diff options
author | Aiden Grossman <aidengrossman@google.com> | 2025-09-04 18:18:05 +0000 |
---|---|---|
committer | Aiden Grossman <aidengrossman@google.com> | 2025-09-04 18:18:05 +0000 |
commit | a65f3d9c492cd7802ec7d27335b0bdd9318799d5 (patch) | |
tree | 41b7d3b108ad67e85587e97997a64ede5b565e7a | |
parent | 6a7ad7dc05980490ca2cb1b01eabb755594623d3 (diff) | |
parent | 46a3b4d5dc6dd9449ec7c0c9065552368cdf41d6 (diff) | |
download | llvm-users/boomanaiden154/main.clang-remove-shell-requirements-from-tests.zip llvm-users/boomanaiden154/main.clang-remove-shell-requirements-from-tests.tar.gz llvm-users/boomanaiden154/main.clang-remove-shell-requirements-from-tests.tar.bz2 |
[𝘀𝗽𝗿] changes introduced through rebaseusers/boomanaiden154/main.clang-remove-shell-requirements-from-tests
Created using spr 1.3.6
[skip ci]
118 files changed, 3349 insertions, 1838 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.h b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.h index 6364813..c91f5f5 100644 --- a/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/ReplaceAutoPtrCheck.h @@ -42,7 +42,7 @@ class ReplaceAutoPtrCheck : public ClangTidyCheck { public: ReplaceAutoPtrCheck(StringRef Name, ClangTidyContext *Context); bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { - return LangOpts.CPlusPlus; + return LangOpts.CPlusPlus11; } void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override; diff --git a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.h b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.h index 76c52b2..7a9bbbe 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/UseAutoCheck.h @@ -17,7 +17,7 @@ class UseAutoCheck : public ClangTidyCheck { public: UseAutoCheck(StringRef Name, ClangTidyContext *Context); bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { - return LangOpts.CPlusPlus; + return LangOpts.CPlusPlus11; } void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override; diff --git a/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.h b/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.h index 64f60351..dc3e7124 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/UseEqualsDeleteCheck.h @@ -23,7 +23,7 @@ class UseEqualsDeleteCheck : public ClangTidyCheck { public: UseEqualsDeleteCheck(StringRef Name, ClangTidyContext *Context); bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { - return LangOpts.CPlusPlus; + return LangOpts.CPlusPlus11; } void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override; diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h index f1591ba..4c02f8c 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h @@ -17,9 +17,7 @@ class UseNullptrCheck : public ClangTidyCheck { public: UseNullptrCheck(StringRef Name, ClangTidyContext *Context); bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { - // FIXME this should be CPlusPlus11 but that causes test cases to - // erroneously fail. - return LangOpts.CPlusPlus || LangOpts.C23; + return LangOpts.CPlusPlus11 || LangOpts.C23; } void storeOptions(ClangTidyOptions::OptionMap &Opts) override; void registerMatchers(ast_matchers::MatchFinder *Finder) override; diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-basic.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-basic.cpp index 2579099..b9ffeec 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-basic.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-basic.cpp @@ -1,9 +1,4 @@ -// RUN: %check_clang_tidy -std=c++98 %s modernize-use-nullptr %t -- -- -Wno-non-literal-null-conversion -// -// Some parts of the test (e.g. assignment of `const int` to `int *`) fail in -// C++11, so we need to run the test in C++98 mode. -// -// FIXME: Make the test work in all language modes. +// RUN: %check_clang_tidy %s modernize-use-nullptr %t -- -- -fno-delayed-template-parsing const unsigned int g_null = 0; #define NULL 0 @@ -23,11 +18,7 @@ void test_assignment() { p2 = p1; // CHECK-FIXES: p2 = p1; - const int null = 0; - int *p3 = null; - // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr - // CHECK-FIXES: int *p3 = nullptr; - + int *p3; p3 = NULL; // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr // CHECK-FIXES: p3 = nullptr; @@ -35,14 +26,11 @@ void test_assignment() { int *p4 = p3; // CHECK-FIXES: int *p4 = p3; - p4 = null; - // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use nullptr - // CHECK-FIXES: p4 = nullptr; - int i1 = 0; int i2 = NULL; + const int null = 0; int i3 = null; int *p5, *p6, *p7; @@ -70,47 +58,13 @@ int *Foo::m_p2 = NULL; // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use nullptr // CHECK-FIXES: int *Foo::m_p2 = nullptr; -template <typename T> -struct Bar { - Bar(T *p) : m_p(p) { - m_p = static_cast<T*>(NULL); - // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr - // CHECK-FIXES: m_p = static_cast<T*>(nullptr); - - m_p = static_cast<T*>(reinterpret_cast<int*>((void*)NULL)); - // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr - // CHECK-FIXES: m_p = static_cast<T*>(nullptr); - - m_p = static_cast<T*>(p ? p : static_cast<void*>(g_null)); - // CHECK-MESSAGES: :[[@LINE-1]]:54: warning: use nullptr - // CHECK-FIXES: m_p = static_cast<T*>(p ? p : static_cast<void*>(nullptr)); - - T *p2 = static_cast<T*>(reinterpret_cast<int*>((void*)NULL)); - // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr - // CHECK-FIXES: T *p2 = static_cast<T*>(nullptr); - - m_p = NULL; - // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use nullptr - // CHECK-FIXES: m_p = nullptr; - - int i = static_cast<int>(0.f); - T *i2 = static_cast<int>(0.f); - // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr - // CHECK-FIXES: T *i2 = nullptr; - } - - T *m_p; -}; - struct Baz { Baz() : i(0) {} int i; }; void test_cxx_cases() { - Foo f(g_null); - // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr - // CHECK-FIXES: Foo f(nullptr); + Foo f; f.bar(NULL); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr @@ -122,10 +76,6 @@ void test_cxx_cases() { // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use nullptr // CHECK-FIXES: f.m_p1 = nullptr; - Bar<int> b(g_null); - // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use nullptr - // CHECK-FIXES: Bar<int> b(nullptr); - Baz b2; int Baz::*memptr(0); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use nullptr @@ -144,10 +94,6 @@ void test_function_default_param2(void *p = NULL); // CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr // CHECK-FIXES: void test_function_default_param2(void *p = nullptr); -void test_function_default_param3(void *p = g_null); -// CHECK-MESSAGES: :[[@LINE-1]]:45: warning: use nullptr -// CHECK-FIXES: void test_function_default_param3(void *p = nullptr); - void test_function(int *p) {} void test_function_no_ptr_param(int i) {} @@ -161,10 +107,6 @@ void test_function_call() { // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr // CHECK-FIXES: test_function(nullptr); - test_function(g_null); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use nullptr - // CHECK-FIXES: test_function(nullptr); - test_function_no_ptr_param(0); } @@ -180,51 +122,33 @@ void *test_function_return2() { // CHECK-FIXES: return nullptr; } -long *test_function_return3() { - return g_null; - // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr - // CHECK-FIXES: return nullptr; -} - -int test_function_return4() { +int test_function_return3() { return 0; } -int test_function_return5() { +int test_function_return4() { return NULL; } -int test_function_return6() { +int test_function_return5() { return g_null; } -int *test_function_return_cast1() { - return(int)0; - // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use nullptr - // CHECK-FIXES: return nullptr; -} - -int *test_function_return_cast2() { +int *test_function_return_cast() { #define RET return - RET(int)0; - // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use nullptr + RET 0; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use nullptr // CHECK-FIXES: RET nullptr; #undef RET } // Test parentheses expressions resulting in a nullptr. -int *test_parentheses_expression1() { +int *test_parentheses_expression() { return(0); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr // CHECK-FIXES: return(nullptr); } -int *test_parentheses_expression2() { - return(int(0.f)); - // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use nullptr - // CHECK-FIXES: return(nullptr); -} - int *test_nested_parentheses_expression() { return((((0)))); // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use nullptr @@ -244,7 +168,7 @@ void *test_parentheses_explicit_cast_sequence1() { } void *test_parentheses_explicit_cast_sequence2() { - return(static_cast<void*>(reinterpret_cast<int*>((float*)int(0.f)))); + return(static_cast<void*>(reinterpret_cast<int*>((float*)(0)))); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr // CHECK-FIXES: return(static_cast<void*>(nullptr)); } @@ -313,19 +237,13 @@ void test_const_pointers() { const int *const_p2 = NULL; // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr // CHECK-FIXES: const int *const_p2 = nullptr; - const int *const_p3 = (int)0; - // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr - // CHECK-FIXES: const int *const_p3 = nullptr; - const int *const_p4 = (int)0.0f; - // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use nullptr - // CHECK-FIXES: const int *const_p4 = nullptr; - const int *const_p5 = (int*)0; + const int *const_p3 = (int*)0; // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use nullptr - // CHECK-FIXES: const int *const_p5 = (int*)nullptr; + // CHECK-FIXES: const int *const_p3 = (int*)nullptr; int *t; - const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(0)); + const int *const_p4 = static_cast<int*>(t ? t : static_cast<int*>(0)); // CHECK-MESSAGES: :[[@LINE-1]]:69: warning: use nullptr - // CHECK-FIXES: const int *const_p6 = static_cast<int*>(t ? t : static_cast<int*>(nullptr)); + // CHECK-FIXES: const int *const_p4 = static_cast<int*>(t ? t : static_cast<int*>(nullptr)); } void test_nested_implicit_cast_expr() { @@ -348,7 +266,21 @@ void test_nested_implicit_cast_expr() { template<typename T> class A { public: - A(T *p = NULL) {} + A(T *p = NULL) { + Ptr = static_cast<T*>(NULL); + + Ptr = static_cast<T*>(reinterpret_cast<int*>((void*)NULL)); + // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: use nullptr + // CHECK-FIXES: Ptr = static_cast<T*>(nullptr); + // FIXME: a better fix-it is: Ptr = nullptr; + + T *p2 = static_cast<T*>(reinterpret_cast<int*>((void*)NULL)); + // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use nullptr + // CHECK-FIXES: T *p2 = static_cast<T*>(nullptr); + // FIXME: a better fix-it is: T *p2 = nullptr; + + Ptr = NULL; + } void f() { Ptr = NULL; diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py index 812ad2c..3398823 100644 --- a/clang/bindings/python/clang/cindex.py +++ b/clang/bindings/python/clang/cindex.py @@ -110,6 +110,7 @@ if TYPE_CHECKING: "tuple[str, Optional[list[Any]], Any]", "tuple[str, Optional[list[Any]], Any, Callable[..., Any]]", ] + CObjP: TypeAlias = _Pointer[Any] TSeq = TypeVar("TSeq", covariant=True) @@ -2981,25 +2982,25 @@ SPELLING_CACHE = { class CompletionChunk: class Kind: - def __init__(self, name): + def __init__(self, name: str): self.name = name - def __str__(self): + def __str__(self) -> str: return self.name - def __repr__(self): + def __repr__(self) -> str: return "<ChunkKind: %s>" % self - def __init__(self, completionString, key): + def __init__(self, completionString: CObjP, key: int): self.cs = completionString self.key = key self.__kindNumberCache = -1 - def __repr__(self): + def __repr__(self) -> str: return "{'" + self.spelling + "', " + str(self.kind) + "}" @CachedProperty - def spelling(self): + def spelling(self) -> str: if self.__kindNumber in SPELLING_CACHE: return SPELLING_CACHE[self.__kindNumber] return _CXString.from_result( @@ -3010,7 +3011,7 @@ class CompletionChunk: # apparently still significantly faster. Please profile carefully if you # would like to add CachedProperty back. @property - def __kindNumber(self): + def __kindNumber(self) -> int: if self.__kindNumberCache == -1: self.__kindNumberCache = conf.lib.clang_getCompletionChunkKind( self.cs, self.key @@ -3018,30 +3019,30 @@ class CompletionChunk: return self.__kindNumberCache @CachedProperty - def kind(self): + def kind(self) -> Kind: return completionChunkKindMap[self.__kindNumber] @CachedProperty - def string(self): + def string(self) -> CompletionString | None: res = conf.lib.clang_getCompletionChunkCompletionString(self.cs, self.key) if not res: return None return CompletionString(res) - def isKindOptional(self): + def isKindOptional(self) -> bool: return self.__kindNumber == 0 - def isKindTypedText(self): + def isKindTypedText(self) -> bool: return self.__kindNumber == 1 - def isKindPlaceHolder(self): + def isKindPlaceHolder(self) -> bool: return self.__kindNumber == 3 - def isKindInformative(self): + def isKindInformative(self) -> bool: return self.__kindNumber == 4 - def isKindResultType(self): + def isKindResultType(self) -> bool: return self.__kindNumber == 15 @@ -3081,14 +3082,14 @@ class CompletionString(ClangObject): def __repr__(self): return "<Availability: %s>" % self - def __len__(self): + def __len__(self) -> int: return self.num_chunks @CachedProperty - def num_chunks(self): + def num_chunks(self) -> int: return conf.lib.clang_getNumCompletionChunks(self.obj) # type: ignore [no-any-return] - def __getitem__(self, key): + def __getitem__(self, key: int) -> CompletionChunk: if self.num_chunks <= key: raise IndexError return CompletionChunk(self.obj, key) @@ -3096,24 +3097,24 @@ class CompletionString(ClangObject): if TYPE_CHECKING: # Defining __getitem__ and __len__ is enough to make an iterable # but the typechecker doesn't understand that. - def __iter__(self): + def __iter__(self) -> Iterator[CompletionChunk]: for i in range(len(self)): yield self[i] @property - def priority(self): + def priority(self) -> int: return conf.lib.clang_getCompletionPriority(self.obj) # type: ignore [no-any-return] @property - def availability(self): + def availability(self) -> CompletionChunk.Kind: res = conf.lib.clang_getCompletionAvailability(self.obj) return availabilityKinds[res] @property - def briefComment(self): + def briefComment(self) -> str: return _CXString.from_result(conf.lib.clang_getCompletionBriefComment(self.obj)) - def __repr__(self): + def __repr__(self) -> str: return ( " | ".join([str(a) for a in self]) + " || Priority: " @@ -3136,25 +3137,28 @@ availabilityKinds = { class CodeCompletionResult(Structure): _fields_ = [("cursorKind", c_int), ("completionString", c_object_p)] - def __repr__(self): + def __repr__(self) -> str: return str(CompletionString(self.completionString)) @property - def kind(self): + def kind(self) -> CursorKind: return CursorKind.from_id(self.cursorKind) @property - def string(self): + def string(self) -> CompletionString: return CompletionString(self.completionString) class CCRStructure(Structure): _fields_ = [("results", POINTER(CodeCompletionResult)), ("numResults", c_int)] - def __len__(self): + results: NoSliceSequence[CodeCompletionResult] + numResults: int + + def __len__(self) -> int: return self.numResults - def __getitem__(self, key): + def __getitem__(self, key: int) -> CodeCompletionResult: if len(self) <= key: raise IndexError @@ -3162,18 +3166,18 @@ class CCRStructure(Structure): class CodeCompletionResults(ClangObject): - def __init__(self, ptr): + def __init__(self, ptr: _Pointer[CCRStructure]): assert isinstance(ptr, POINTER(CCRStructure)) and ptr self.ptr = self._as_parameter_ = ptr - def from_param(self): + def from_param(self) -> _Pointer[CCRStructure]: return self._as_parameter_ - def __del__(self): + def __del__(self) -> None: conf.lib.clang_disposeCodeCompleteResults(self) @property - def results(self): + def results(self) -> CCRStructure: return self.ptr.contents @property diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 9767fde..ad190ea 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -875,12 +875,14 @@ of different sizes and signs is forbidden in binary and ternary builtins. for the comparison. T __builtin_elementwise_fshl(T x, T y, T z) perform a funnel shift left. Concatenate x and y (x is the most integer types significant bits of the wide value), the combined value is shifted - left by z, and the most significant bits are extracted to produce + left by z (modulo the bit width of the original arguments), + and the most significant bits are extracted to produce a result that is the same size as the original arguments. T __builtin_elementwise_fshr(T x, T y, T z) perform a funnel shift right. Concatenate x and y (x is the most integer types significant bits of the wide value), the combined value is shifted - right by z, and the least significant bits are extracted to produce + right by z (modulo the bit width of the original arguments), + and the least significant bits are extracted to produce a result that is the same size as the original arguments. T __builtin_elementwise_ctlz(T x[, T y]) return the number of leading 0 bits in the first argument. If integer types the first argument is 0 and an optional second argument is provided, diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b510fa50..bec001b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -84,6 +84,9 @@ C++ Specific Potentially Breaking Changes static_assert((b.*mp)() == 1); // newly rejected static_assert((c.*mp)() == 1); // accepted +- ``VarTemplateSpecializationDecl::getTemplateArgsAsWritten()`` method now + returns ``nullptr`` for implicitly instantiated declarations. + ABI Changes in This Version --------------------------- @@ -338,6 +341,8 @@ Bug Fixes to C++ Support - Fix the parsing of variadic member functions when the ellipis immediately follows a default argument.(#GH153445) - Fixed a bug that caused ``this`` captured by value in a lambda with a dependent explicit object parameter to not be instantiated properly. (#GH154054) +- Fixed a crash when implicit conversions from initialize list to arrays of + unknown bound during constant evaluation. (#GH151716) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index af0e824..27fc6f0 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -1540,13 +1540,13 @@ def ElementwiseSubSat : Builtin { def ElementwiseFshl : Builtin { let Spellings = ["__builtin_elementwise_fshl"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } def ElementwiseFshr : Builtin { let Spellings = ["__builtin_elementwise_fshr"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 059ea4e0..88b67ee 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11668,7 +11668,8 @@ public: DeclResult CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs); + const TemplateArgumentListInfo &TemplateArgs, + bool SetWrittenArgs); /// Form a reference to the specialization of the given variable template /// corresponding to the specified argument list, or a null-but-valid result @@ -14028,7 +14029,6 @@ public: VarTemplateSpecializationDecl *BuildVarTemplateInstantiation( VarTemplateDecl *VarTemplate, VarDecl *FromVar, const TemplateArgumentList *PartialSpecArgs, - const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl<TemplateArgument> &Converted, SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs = nullptr, diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index fe90707..115c19d 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -723,9 +723,8 @@ enum class TemplateSubstitutionKind : char { bool SubstQualifier(const TagDecl *OldDecl, TagDecl *NewDecl); - Decl *VisitVarTemplateSpecializationDecl( + VarTemplateSpecializationDecl *VisitVarTemplateSpecializationDecl( VarTemplateDecl *VarTemplate, VarDecl *FromVar, - const TemplateArgumentListInfo &TemplateArgsInfo, ArrayRef<TemplateArgument> Converted, VarTemplateSpecializationDecl *PrevDecl = nullptr); diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 8c2b711..ff6ef5a 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2829,6 +2829,65 @@ static bool interp__builtin_select(InterpState &S, CodePtr OpPC, return true; } +static bool interp__builtin_elementwise_fsh(InterpState &S, CodePtr OpPC, + const CallExpr *Call, + unsigned BuiltinID) { + assert(Call->getNumArgs() == 3); + + QualType Arg0Type = Call->getArg(0)->getType(); + QualType Arg1Type = Call->getArg(1)->getType(); + QualType Arg2Type = Call->getArg(2)->getType(); + + // Non-vector integer types. + if (!Arg0Type->isVectorType()) { + const APSInt &Shift = + popToAPSInt(S.Stk, *S.getContext().classify(Arg2Type)); + const APSInt &Lo = popToAPSInt(S.Stk, *S.getContext().classify(Arg1Type)); + const APSInt &Hi = popToAPSInt(S.Stk, *S.getContext().classify(Arg0Type)); + APSInt Result; + if (BuiltinID == Builtin::BI__builtin_elementwise_fshl) + Result = APSInt(llvm::APIntOps::fshl(Hi, Lo, Shift), Hi.isUnsigned()); + else if (BuiltinID == Builtin::BI__builtin_elementwise_fshr) + Result = APSInt(llvm::APIntOps::fshr(Hi, Lo, Shift), Hi.isUnsigned()); + else + llvm_unreachable("Wrong builtin ID"); + pushInteger(S, Result, Call->getType()); + return true; + } + + // Vector type. + const auto *VecT = Arg0Type->castAs<VectorType>(); + const PrimType &ElemT = *S.getContext().classify(VecT->getElementType()); + unsigned NumElems = VecT->getNumElements(); + + const Pointer &VecShift = S.Stk.pop<Pointer>(); + const Pointer &VecLo = S.Stk.pop<Pointer>(); + const Pointer &VecHi = S.Stk.pop<Pointer>(); + const Pointer &Dst = S.Stk.peek<Pointer>(); + for (unsigned I = 0; I != NumElems; ++I) { + APSInt Hi; + APSInt Lo; + APSInt Shift; + INT_TYPE_SWITCH_NO_BOOL(ElemT, { + Hi = VecHi.elem<T>(I).toAPSInt(); + Lo = VecLo.elem<T>(I).toAPSInt(); + Shift = VecShift.elem<T>(I).toAPSInt(); + }); + APSInt Result; + if (BuiltinID == Builtin::BI__builtin_elementwise_fshl) + Result = APSInt(llvm::APIntOps::fshl(Hi, Lo, Shift), Hi.isUnsigned()); + else if (BuiltinID == Builtin::BI__builtin_elementwise_fshr) + Result = APSInt(llvm::APIntOps::fshr(Hi, Lo, Shift), Hi.isUnsigned()); + else + llvm_unreachable("Wrong builtin ID"); + INT_TYPE_SWITCH_NO_BOOL(ElemT, + { Dst.elem<T>(I) = static_cast<T>(Result); }); + } + Dst.initializeAllElements(); + + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, uint32_t BuiltinID) { if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID)) @@ -3393,6 +3452,10 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case X86::BI__builtin_ia32_selectpd_512: return interp__builtin_select(S, OpPC, Call); + case Builtin::BI__builtin_elementwise_fshl: + case Builtin::BI__builtin_elementwise_fshr: + return interp__builtin_elementwise_fsh(S, OpPC, Call, BuiltinID); + default: S.FFDiag(S.Current->getLocation(OpPC), diag::note_invalid_subexpr_in_const_expr) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 66362d4..6c6909e 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -4030,10 +4030,12 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, LastField = nullptr; if (ObjType->isArrayType()) { // Next subobject is an array element. - const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(ObjType); - assert(CAT && "vla in literal type?"); + const ArrayType *AT = Info.Ctx.getAsArrayType(ObjType); + assert((isa<ConstantArrayType>(AT) || isa<IncompleteArrayType>(AT)) && + "vla in literal type?"); uint64_t Index = Sub.Entries[I].getAsArrayIndex(); - if (CAT->getSize().ule(Index)) { + if (const auto *CAT = dyn_cast<ConstantArrayType>(AT); + CAT && CAT->getSize().ule(Index)) { // Note, it should not be possible to form a pointer with a valid // designator which points more than one past the end of the array. if (Info.getLangOpts().CPlusPlus11) @@ -4044,12 +4046,13 @@ findSubobject(EvalInfo &Info, const Expr *E, const CompleteObject &Obj, return handler.failed(); } - ObjType = CAT->getElementType(); + ObjType = AT->getElementType(); if (O->getArrayInitializedElts() > Index) O = &O->getArrayInitializedElt(Index); else if (!isRead(handler.AccessKind)) { - if (!CheckArraySize(Info, CAT, E->getExprLoc())) + if (const auto *CAT = dyn_cast<ConstantArrayType>(AT); + CAT && !CheckArraySize(Info, CAT, E->getExprLoc())) return handler.failed(); expandArray(*O, Index); @@ -12105,6 +12108,40 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { } return Success(APValue(ResultElements.data(), ResultElements.size()), E); } + + case Builtin::BI__builtin_elementwise_fshl: + case Builtin::BI__builtin_elementwise_fshr: { + APValue SourceHi, SourceLo, SourceShift; + if (!EvaluateAsRValue(Info, E->getArg(0), SourceHi) || + !EvaluateAsRValue(Info, E->getArg(1), SourceLo) || + !EvaluateAsRValue(Info, E->getArg(2), SourceShift)) + return false; + + QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType(); + if (!DestEltTy->isIntegerType()) + return false; + + unsigned SourceLen = SourceHi.getVectorLength(); + SmallVector<APValue> ResultElements; + ResultElements.reserve(SourceLen); + for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) { + const APSInt &Hi = SourceHi.getVectorElt(EltNum).getInt(); + const APSInt &Lo = SourceLo.getVectorElt(EltNum).getInt(); + const APSInt &Shift = SourceShift.getVectorElt(EltNum).getInt(); + switch (E->getBuiltinCallee()) { + case Builtin::BI__builtin_elementwise_fshl: + ResultElements.push_back(APValue( + APSInt(llvm::APIntOps::fshl(Hi, Lo, Shift), Hi.isUnsigned()))); + break; + case Builtin::BI__builtin_elementwise_fshr: + ResultElements.push_back(APValue( + APSInt(llvm::APIntOps::fshr(Hi, Lo, Shift), Hi.isUnsigned()))); + break; + } + } + + return Success(APValue(ResultElements.data(), ResultElements.size()), E); + } } } @@ -14058,6 +14095,25 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, APInt Result = std::min(LHS, RHS); return Success(APSInt(Result, !LHS.isSigned()), E); } + case Builtin::BI__builtin_elementwise_fshl: + case Builtin::BI__builtin_elementwise_fshr: { + APSInt Hi, Lo, Shift; + if (!EvaluateInteger(E->getArg(0), Hi, Info) || + !EvaluateInteger(E->getArg(1), Lo, Info) || + !EvaluateInteger(E->getArg(2), Shift, Info)) + return false; + + switch (BuiltinOp) { + case Builtin::BI__builtin_elementwise_fshl: { + APSInt Result(llvm::APIntOps::fshl(Hi, Lo, Shift), Hi.isUnsigned()); + return Success(Result, E); + } + case Builtin::BI__builtin_elementwise_fshr: { + APSInt Result(llvm::APIntOps::fshr(Hi, Lo, Shift), Hi.isUnsigned()); + return Success(Result, E); + } + } + } case Builtin::BIstrlen: case Builtin::BIwcslen: // A call to strlen is not a constant expression. diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 4a31a13..aedfc5e 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1126,8 +1126,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, return ExprError(); } - DeclResult VDecl = CheckVarTemplateId(VarTempl, TemplateKWLoc, - MemberNameInfo.getLoc(), *TemplateArgs); + DeclResult VDecl = + CheckVarTemplateId(VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(), + *TemplateArgs, /*SetWrittenArgs=*/false); if (VDecl.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3d8416a..3533871 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4542,7 +4542,8 @@ static bool IsLibstdcxxStdFormatKind(Preprocessor &PP, VarDecl *Var) { DeclResult Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation TemplateNameLoc, - const TemplateArgumentListInfo &TemplateArgs) { + const TemplateArgumentListInfo &TemplateArgs, + bool SetWrittenArgs) { assert(Template && "A variable template id without template?"); // Check that the template argument list is well-formed for this template. @@ -4725,10 +4726,12 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, // in DoMarkVarDeclReferenced(). // FIXME: LateAttrs et al.? VarTemplateSpecializationDecl *Decl = BuildVarTemplateInstantiation( - Template, InstantiationPattern, PartialSpecArgs, TemplateArgs, - CTAI.CanonicalConverted, TemplateNameLoc /*, LateAttrs, StartingScope*/); + Template, InstantiationPattern, PartialSpecArgs, CTAI.CanonicalConverted, + TemplateNameLoc /*, LateAttrs, StartingScope*/); if (!Decl) return true; + if (SetWrittenArgs) + Decl->setTemplateArgsAsWritten(TemplateArgs); if (AmbiguousPartialSpec) { // Partial ordering did not produce a clear winner. Complain. @@ -4760,7 +4763,7 @@ ExprResult Sema::CheckVarTemplateId( const TemplateArgumentListInfo *TemplateArgs) { DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(), - *TemplateArgs); + *TemplateArgs, /*SetWrittenArgs=*/false); if (Decl.isInvalid()) return ExprError(); @@ -10707,8 +10710,9 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, TemplateArgumentListInfo TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId); - DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc, - D.getIdentifierLoc(), TemplateArgs); + DeclResult Res = + CheckVarTemplateId(PrevTemplate, TemplateLoc, D.getIdentifierLoc(), + TemplateArgs, /*SetWrittenArgs=*/true); if (Res.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index ee1b520..910f99d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4542,14 +4542,17 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( PrevDecl->getPointOfInstantiation(), Ignored)) return nullptr; - return VisitVarTemplateSpecializationDecl(InstVarTemplate, D, - VarTemplateArgsInfo, - CTAI.CanonicalConverted, PrevDecl); + if (VarTemplateSpecializationDecl *VTSD = VisitVarTemplateSpecializationDecl( + InstVarTemplate, D, CTAI.CanonicalConverted, PrevDecl)) { + VTSD->setTemplateArgsAsWritten(VarTemplateArgsInfo); + return VTSD; + } + return nullptr; } -Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( +VarTemplateSpecializationDecl * +TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( VarTemplateDecl *VarTemplate, VarDecl *D, - const TemplateArgumentListInfo &TemplateArgsInfo, ArrayRef<TemplateArgument> Converted, VarTemplateSpecializationDecl *PrevDecl) { @@ -4570,7 +4573,6 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( VarTemplateSpecializationDecl *Var = VarTemplateSpecializationDecl::Create( SemaRef.Context, Owner, D->getInnerLocStart(), D->getLocation(), VarTemplate, DI->getType(), DI, D->getStorageClass(), Converted); - Var->setTemplateArgsAsWritten(TemplateArgsInfo); if (!PrevDecl) { void *InsertPos = nullptr; VarTemplate->findSpecialization(Converted, InsertPos); @@ -5880,7 +5882,6 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( VarTemplateDecl *VarTemplate, VarDecl *FromVar, const TemplateArgumentList *PartialSpecArgs, - const TemplateArgumentListInfo &TemplateArgsInfo, SmallVectorImpl<TemplateArgument> &Converted, SourceLocation PointOfInstantiation, LateInstantiatedAttrVec *LateAttrs, LocalInstantiationScope *StartingScope) { @@ -5922,9 +5923,8 @@ VarTemplateSpecializationDecl *Sema::BuildVarTemplateInstantiation( // TODO: Set LateAttrs and StartingScope ... - return cast_or_null<VarTemplateSpecializationDecl>( - Instantiator.VisitVarTemplateSpecializationDecl( - VarTemplate, FromVar, TemplateArgsInfo, Converted)); + return Instantiator.VisitVarTemplateSpecializationDecl(VarTemplate, FromVar, + Converted); } VarTemplateSpecializationDecl *Sema::CompleteVarTemplateSpecializationDecl( @@ -6340,10 +6340,15 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, TemplateArgInfo.addArgument(Arg); } - Var = cast_or_null<VarDecl>(Instantiator.VisitVarTemplateSpecializationDecl( - VarSpec->getSpecializedTemplate(), Def, TemplateArgInfo, - VarSpec->getTemplateArgs().asArray(), VarSpec)); + VarTemplateSpecializationDecl *VTSD = + Instantiator.VisitVarTemplateSpecializationDecl( + VarSpec->getSpecializedTemplate(), Def, + VarSpec->getTemplateArgs().asArray(), VarSpec); + Var = VTSD; + if (Var) { + VTSD->setTemplateArgsAsWritten(TemplateArgInfo); + llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> PatternPtr = VarSpec->getSpecializedTemplateOrPartial(); diff --git a/clang/test/CodeGen/instrument-objc-method.m b/clang/test/CodeGen/instrument-objc-method.m index 34b4f84..5956274 100644 --- a/clang/test/CodeGen/instrument-objc-method.m +++ b/clang/test/CodeGen/instrument-objc-method.m @@ -1,29 +1,24 @@ -// RUN: %clang_cc1 -disable-llvm-passes -triple x86_64-apple-darwin10 -debug-info-kind=standalone -emit-llvm -o - %s -finstrument-functions | FileCheck -check-prefix=PREINLINE %s -// RUN: %clang_cc1 -disable-llvm-passes -triple x86_64-apple-darwin10 -debug-info-kind=standalone -emit-llvm -o - %s -finstrument-function-entry-bare | FileCheck -check-prefix=BARE %s +// RUN: %clang_cc1 -disable-llvm-passes -triple x86_64-apple-darwin10 -debug-info-kind=standalone -emit-llvm -o - %s -finstrument-functions | FileCheck --check-prefix=PREINLINE --implicit-check-not="__cyg_profile_func_enter" %s +// RUN: %clang_cc1 -disable-llvm-passes -triple x86_64-apple-darwin10 -debug-info-kind=standalone -emit-llvm -o - %s -finstrument-function-entry-bare | FileCheck --check-prefix=BARE --implicit-check-not="__cyg_profile_func_enter" %s @interface ObjCClass @end @implementation ObjCClass -// PREINLINE: @"\01+[ObjCClass initialize]"{{\(.*\)}} #0 -// BARE: @"\01+[ObjCClass initialize]"{{\(.*\)}} #0 +// PREINLINE: define {{.*}}@"\01+[ObjCClass initialize]"{{\(.*\)}} #[[#ATTR:]] +// BARE: define {{.*}}@"\01+[ObjCClass initialize]"{{\(.*\)}} #[[#ATTR:]] + (void)initialize { } -// BARE: @"\01+[ObjCClass load]"{{\(.*\)}} #1 + (void)load __attribute__((no_instrument_function)) { } -// PREINLINE: @"\01-[ObjCClass dealloc]"{{\(.*\)}} #1 -// BARE: @"\01-[ObjCClass dealloc]"{{\(.*\)}} #1 - (void)dealloc __attribute__((no_instrument_function)) { } -// PREINLINE: attributes #0 = { {{.*}}"instrument-function-entry"="__cyg_profile_func_enter" -// PREINLINE-NOT: attributes #0 = { {{.*}}"instrument-function-entry"="__cyg_profile_func_enter_bare" -// PREINLINE-NOT: attributes #2 = { {{.*}}"__cyg_profile_func_enter" -// BARE: attributes #0 = { {{.*}}"instrument-function-entry-inlined"="__cyg_profile_func_enter_bare" -// BARE-NOT: attributes #0 = { {{.*}}"__cyg_profile_func_enter" -// BARE-NOT: attributes #2 = { {{.*}}"__cyg_profile_func_enter_bare" +// PREINLINE: attributes #[[#ATTR]] = +// PREINLINE-SAME: "instrument-function-entry"="__cyg_profile_func_enter" +// BARE: attributes #[[#ATTR]] = +// BARE-SAME: "instrument-function-entry-inlined"="__cyg_profile_func_enter_bare" @end diff --git a/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp b/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp index a29f4d7..007b47c4 100644 --- a/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp +++ b/clang/test/CodeGenCXX/cxx20-p0388-unbound-ary.cpp @@ -32,4 +32,19 @@ void foo(int a) { f({a}); } +constexpr int gh151716() { + int(&&g)[]{0,1,2}; + return g[2]; +} +// CHECK-LABEL: @_ZN3One10gh151716_fEv +// CHECK-NEXT: entry: +// CHECK-NEXT: %v = alloca i32, align 4 +// CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr nonnull %v) +// CHECK-NEXT: store volatile i32 2, ptr %v, align 4 +// CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr nonnull %v) +// CHECK-NEXT: ret void +void gh151716_f() { + volatile const int v = gh151716(); +} + } // namespace One diff --git a/clang/test/CodeGenObjCXX/address-safety-attr.mm b/clang/test/CodeGenObjCXX/address-safety-attr.mm index 1b6f0e8..8a7462d 100644 --- a/clang/test/CodeGenObjCXX/address-safety-attr.mm +++ b/clang/test/CodeGenObjCXX/address-safety-attr.mm @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck -check-prefix=WITHOUT %s -// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=address | FileCheck -check-prefix=ASAN %s +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s --implicit-check-not=sanitize_address +// RUN: %clang_cc1 -emit-llvm -o - %s -fsanitize=address | FileCheck %s --check-prefixes=CHECK,ASAN @interface MyClass + (int) addressSafety:(int*)a; @@ -7,15 +7,14 @@ @implementation MyClass -// WITHOUT: +[MyClass load]{{.*}}#0 -// ASAN: +[MyClass load]{{.*}}#0 +// ASAN: ; Function Attrs: +// ASAN-SAME: sanitize_address +// CHECK-LABEL: define {{.*}}+[MyClass load] +(void) load { } -// WITHOUT: +[MyClass addressSafety:]{{.*}}#0 -// ASAN: +[MyClass addressSafety:]{{.*}}#0 +// ASAN: ; Function Attrs: +// ASAN-SAME: sanitize_address +// CHECK-LABEL: define {{.*}}+[MyClass addressSafety:] + (int) addressSafety:(int*)a { return *a; } @end - -// ASAN: attributes #0 = {{.*}}sanitize_address -// WITHOUT-NOT: attributes #0 = {{.*}}sanitize_address diff --git a/clang/test/Sema/constant-builtins-vector.cpp b/clang/test/Sema/constant-builtins-vector.cpp index 17fa958..714a7fb 100644 --- a/clang/test/Sema/constant-builtins-vector.cpp +++ b/clang/test/Sema/constant-builtins-vector.cpp @@ -961,3 +961,51 @@ static_assert(fmaDouble1[3] == 26.0); constexpr float fmaArray[] = {2.0f, 2.0f, 2.0f, 2.0f}; constexpr float fmaResult = __builtin_elementwise_fma(fmaArray[1], fmaArray[2], fmaArray[3]); static_assert(fmaResult == 6.0f, ""); + +static_assert(__builtin_elementwise_fshl((unsigned char)255, (unsigned char)0, (unsigned char)8) == (unsigned char)255); +static_assert(__builtin_elementwise_fshl((char)127, (char)0, (char)8) == (char)127); +static_assert(__builtin_elementwise_fshl((unsigned char)0, (unsigned char)255, (unsigned char)8) == (unsigned char)0); +static_assert(__builtin_elementwise_fshl((char)0, (char)127, (char)8) == (char)0); +static_assert(__builtin_elementwise_fshr((unsigned char)255, (unsigned char)0, (unsigned char)8) == (unsigned char)0); +static_assert(__builtin_elementwise_fshr((char)127, (char)0, (char)8) == (char)0); +static_assert(__builtin_elementwise_fshr((unsigned char)0, (unsigned char)255, (unsigned char)8) == (unsigned char)255); +static_assert(__builtin_elementwise_fshr((char)0, (char)127, (char)8) == (char)127); +static_assert(__builtin_elementwise_fshl((unsigned int)4294967295, (unsigned int)0, (unsigned int)32) == (unsigned int)4294967295); +static_assert(__builtin_elementwise_fshl((int)2147483647, (int)0, (int)32) == (int)2147483647); +static_assert(__builtin_elementwise_fshl((unsigned int)0, (unsigned int)4294967295, (unsigned int)32) == (unsigned int)0); +static_assert(__builtin_elementwise_fshl((int)0, (int)2147483647, (int)32) == (int)0); +static_assert(__builtin_elementwise_fshr((unsigned int)4294967295, (unsigned int)0, (unsigned int)32) == (unsigned int)0); +static_assert(__builtin_elementwise_fshr((int)2147483647, (int)0, (int)32) == (int)0); +static_assert(__builtin_elementwise_fshr((unsigned int)0, (unsigned int)4294967295, (unsigned int)32) == (unsigned int)4294967295); +static_assert(__builtin_elementwise_fshr((int)0, (int)2147483647, (int)32) == (int)2147483647); +static_assert(__builtin_elementwise_fshl((unsigned long long)18446744073709551615ULL, (unsigned long long)0, (unsigned long long)64) == (unsigned long long)18446744073709551615ULL); +static_assert(__builtin_elementwise_fshl((long long)9223372036854775807, (long long)0, (long long)64) == (long long)9223372036854775807); +static_assert(__builtin_elementwise_fshl((unsigned long long)0, (unsigned long long)18446744073709551615ULL, (unsigned long long)64) == (unsigned long long)0); +static_assert(__builtin_elementwise_fshl((long long)0, (long long)9223372036854775807, (long long)64) == (long long)0); +static_assert(__builtin_elementwise_fshr((unsigned long long)18446744073709551615ULL, (unsigned long long)0, (unsigned long long)64) == (unsigned long long)0); +static_assert(__builtin_elementwise_fshr((long long)9223372036854775807, (long long)0, (long long)64) == (long long)0); +static_assert(__builtin_elementwise_fshr((unsigned long long)0, (unsigned long long)18446744073709551615ULL, (unsigned long long)64) == (unsigned long long)18446744073709551615ULL); +static_assert(__builtin_elementwise_fshr((long long)0, (long long)9223372036854775807, (long long)64) == (long long)9223372036854775807); +static_assert(__builtin_elementwise_fshl((short) 1, (short) 2, (short) 3) == (short)8); +static_assert(__builtin_elementwise_fshl((short) 2, (short) 1, (short) 3) == (short)16); +static_assert(__builtin_elementwise_fshl(1, 2 , 2) == 4); +static_assert(__builtin_elementwise_fshl(2L, 1L , 2L) == 8L); +static_assert(__builtin_elementwise_fshr((unsigned char)1, (unsigned char)2, (unsigned char)3) == (unsigned char)32); +constexpr vector4uchar v4s_fshl_var = + __builtin_elementwise_fshl((vector4uchar){255, 15, 0, 2}, + (vector4uchar){0, 15, 255, 1}, + (vector4uchar){15, 11, 8, 3}); +static_assert(v4s_fshl_var[0] == 128); +static_assert(v4s_fshl_var[1] == 120); +static_assert(v4s_fshl_var[2] == 0); +static_assert(v4s_fshl_var[3] == 16); +constexpr vector4uchar v4s_fshr_var = + __builtin_elementwise_fshr((vector4uchar){255, 15, 0, 1}, + (vector4uchar){0, 15, 255, 2}, + (vector4uchar){15, 11, 8, 3}); +static_assert(v4s_fshr_var[0] == 254); +static_assert(v4s_fshr_var[1] == 225); +static_assert(v4s_fshr_var[2] == 255); +static_assert(v4s_fshr_var[3] == 32); +static_assert(__builtin_elementwise_fshl(v4s_fshl_var[0], v4s_fshl_var[1], v4s_fshl_var[2]) == 128); +static_assert(__builtin_elementwise_fshr(v4s_fshr_var[0], v4s_fshr_var[1], v4s_fshr_var[2]) == 253); diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp index 4c83ff9..e76edbf 100644 --- a/clang/unittests/AST/DeclTest.cpp +++ b/clang/unittests/AST/DeclTest.cpp @@ -586,3 +586,22 @@ namespace x::y { ASSERT_NE(FD, nullptr); ASSERT_EQ(FD->getQualifiedNameAsString(), "x::y::Foo::Foo<T>"); } + +TEST(Decl, NoWrittenArgsInImplicitlyInstantiatedVarSpec) { + const char *Code = R"cpp( + template <typename> + int VarTpl; + + void fn() { + (void)VarTpl<char>; + } + )cpp"; + + auto AST = tooling::buildASTFromCode(Code); + ASTContext &Ctx = AST->getASTContext(); + + const auto *VTSD = selectFirst<VarTemplateSpecializationDecl>( + "id", match(varDecl(isTemplateInstantiation()).bind("id"), Ctx)); + ASSERT_NE(VTSD, nullptr); + EXPECT_EQ(VTSD->getTemplateArgsAsWritten(), nullptr); +} diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index 44a8a2e..3dfbaed 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -375,6 +375,23 @@ def hlfir_CmpCharOp : hlfir_Op<"cmpchar", let hasVerifier = 1; } +def hlfir_CharTrimOp + : hlfir_Op< + "char_trim", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> { + let summary = "trim character"; + let description = [{ Trim a character string. }]; + + let arguments = (ins AnyScalarCharacterEntity:$chr); + + let results = (outs AnyScalarCharacterExpr); + + let assemblyFormat = [{ + $chr attr-dict `:` functional-type(operands, results) + }]; + + let builders = [OpBuilder<(ins "mlir::Value":$chr)>]; +} + def hlfir_AllOp : hlfir_Op<"all", [DeclareOpInterfaceMethods<MemoryEffectsOpInterface>]> { let summary = "ALL transformational intrinsic"; let description = [{ diff --git a/flang/lib/Lower/HlfirIntrinsics.cpp b/flang/lib/Lower/HlfirIntrinsics.cpp index 39595d6..b9731e9 100644 --- a/flang/lib/Lower/HlfirIntrinsics.cpp +++ b/flang/lib/Lower/HlfirIntrinsics.cpp @@ -159,6 +159,18 @@ protected: hlfir::CharExtremumPredicate pred; }; +class HlfirCharTrimLowering : public HlfirTransformationalIntrinsic { +public: + HlfirCharTrimLowering(fir::FirOpBuilder &builder, mlir::Location loc) + : HlfirTransformationalIntrinsic(builder, loc) {} + +protected: + mlir::Value + lowerImpl(const Fortran::lower::PreparedActualArguments &loweredActuals, + const fir::IntrinsicArgumentLoweringRules *argLowering, + mlir::Type stmtResultType) override; +}; + class HlfirCShiftLowering : public HlfirTransformationalIntrinsic { public: using HlfirTransformationalIntrinsic::HlfirTransformationalIntrinsic; @@ -421,6 +433,15 @@ mlir::Value HlfirCharExtremumLowering::lowerImpl( return createOp<hlfir::CharExtremumOp>(pred, mlir::ValueRange{operands}); } +mlir::Value HlfirCharTrimLowering::lowerImpl( + const Fortran::lower::PreparedActualArguments &loweredActuals, + const fir::IntrinsicArgumentLoweringRules *argLowering, + mlir::Type stmtResultType) { + auto operands = getOperandVector(loweredActuals, argLowering); + assert(operands.size() == 1); + return createOp<hlfir::CharTrimOp>(operands[0]); +} + mlir::Value HlfirCShiftLowering::lowerImpl( const Fortran::lower::PreparedActualArguments &loweredActuals, const fir::IntrinsicArgumentLoweringRules *argLowering, @@ -555,6 +576,9 @@ std::optional<hlfir::EntityWithAttributes> Fortran::lower::lowerHlfirIntrinsic( return HlfirCharExtremumLowering{builder, loc, hlfir::CharExtremumPredicate::max} .lower(loweredActuals, argLowering, stmtResultType); + if (name == "trim") + return HlfirCharTrimLowering{builder, loc}.lower( + loweredActuals, argLowering, stmtResultType); } return std::nullopt; } diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index 629b97a..2971a72 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -856,6 +856,28 @@ void hlfir::CmpCharOp::getEffects( } //===----------------------------------------------------------------------===// +// CharTrimOp +//===----------------------------------------------------------------------===// + +void hlfir::CharTrimOp::build(mlir::OpBuilder &builder, + mlir::OperationState &result, mlir::Value chr) { + unsigned kind = getCharacterKind(chr.getType()); + auto resultType = hlfir::ExprType::get( + builder.getContext(), hlfir::ExprType::Shape{}, + fir::CharacterType::get(builder.getContext(), kind, + fir::CharacterType::unknownLen()), + /*polymorphic=*/false); + build(builder, result, resultType, chr); +} + +void hlfir::CharTrimOp::getEffects( + llvm::SmallVectorImpl< + mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>> + &effects) { + getIntrinsicEffects(getOperation(), effects); +} + +//===----------------------------------------------------------------------===// // NumericalReductionOp //===----------------------------------------------------------------------===// diff --git a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp index 8b6c7de..a913cfa 100644 --- a/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp +++ b/flang/lib/Optimizer/HLFIR/Transforms/LowerHLFIRIntrinsics.cpp @@ -585,6 +585,34 @@ class CmpCharOpConversion : public HlfirIntrinsicConversion<hlfir::CmpCharOp> { } }; +class CharTrimOpConversion + : public HlfirIntrinsicConversion<hlfir::CharTrimOp> { + using HlfirIntrinsicConversion<hlfir::CharTrimOp>::HlfirIntrinsicConversion; + + llvm::LogicalResult + matchAndRewrite(hlfir::CharTrimOp trim, + mlir::PatternRewriter &rewriter) const override { + fir::FirOpBuilder builder{rewriter, trim.getOperation()}; + const mlir::Location &loc = trim->getLoc(); + + llvm::SmallVector<IntrinsicArgument, 1> inArgs; + mlir::Value chr = trim.getChr(); + inArgs.push_back({chr, chr.getType()}); + + auto *argLowering = fir::getIntrinsicArgumentLowering("trim"); + llvm::SmallVector<fir::ExtendedValue, 1> args = + lowerArguments(trim, inArgs, rewriter, argLowering); + + mlir::Type resultType = hlfir::getFortranElementType(trim.getType()); + + auto [resultExv, mustBeFreed] = + fir::genIntrinsicCall(builder, loc, "trim", resultType, args); + + processReturnValue(trim, resultExv, mustBeFreed, builder, rewriter); + return mlir::success(); + } +}; + class LowerHLFIRIntrinsics : public hlfir::impl::LowerHLFIRIntrinsicsBase<LowerHLFIRIntrinsics> { public: @@ -592,14 +620,14 @@ public: mlir::ModuleOp module = this->getOperation(); mlir::MLIRContext *context = &getContext(); mlir::RewritePatternSet patterns(context); - patterns.insert<MatmulOpConversion, MatmulTransposeOpConversion, - AllOpConversion, AnyOpConversion, SumOpConversion, - ProductOpConversion, TransposeOpConversion, - CountOpConversion, DotProductOpConversion, - MaxvalOpConversion, MinvalOpConversion, MinlocOpConversion, - MaxlocOpConversion, ArrayShiftOpConversion<hlfir::CShiftOp>, - ArrayShiftOpConversion<hlfir::EOShiftOp>, - ReshapeOpConversion, CmpCharOpConversion>(context); + patterns.insert< + MatmulOpConversion, MatmulTransposeOpConversion, AllOpConversion, + AnyOpConversion, SumOpConversion, ProductOpConversion, + TransposeOpConversion, CountOpConversion, DotProductOpConversion, + MaxvalOpConversion, MinvalOpConversion, MinlocOpConversion, + MaxlocOpConversion, ArrayShiftOpConversion<hlfir::CShiftOp>, + ArrayShiftOpConversion<hlfir::EOShiftOp>, ReshapeOpConversion, + CmpCharOpConversion, CharTrimOpConversion>(context); // While conceptually this pass is performing dialect conversion, we use // pattern rewrites here instead of dialect conversion because this pass diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp index 6cc3290..7c2777b 100644 --- a/flang/lib/Optimizer/Passes/Pipelines.cpp +++ b/flang/lib/Optimizer/Passes/Pipelines.cpp @@ -217,9 +217,6 @@ void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm, pm.addPass(fir::createSimplifyFIROperations( {/*preferInlineImplementation=*/pc.OptLevel.isOptimizingForSpeed()})); - if (pc.AliasAnalysis && !disableFirAliasTags && !useOldAliasTags) - pm.addPass(fir::createAddAliasTags()); - addNestedPassToAllTopLevelOperations<PassConstructor>( pm, fir::createStackReclaim); // convert control flow to CFG form @@ -345,6 +342,9 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig config, llvm::StringRef inputFilename) { fir::addBoxedProcedurePass(pm); + if (config.OptLevel.isOptimizingForSpeed() && config.AliasAnalysis && + !disableFirAliasTags && !useOldAliasTags) + pm.addPass(fir::createAddAliasTags()); addNestedPassToAllTopLevelOperations<PassConstructor>( pm, fir::createAbstractResultOpt); addPassToGPUModuleOperations<PassConstructor>(pm, diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index 0bcd055..e85a772 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -109,7 +109,6 @@ end program ! O2-NEXT: OptimizeArrayRepacking ! ALL-NEXT: LowerRepackArraysPass ! ALL-NEXT: SimplifyFIROperations -! O2-NEXT: AddAliasTags ! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] ! ALL-NEXT: 'fir.global' Pipeline @@ -134,6 +133,7 @@ end program ! O2-NEXT: 'func.func' Pipeline ! O2-NEXT: SetRuntimeCallAttributes ! ALL-NEXT: BoxedProcedurePass +! O2-NEXT: AddAliasTags ! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'gpu.module', 'omp.declare_reduction', 'omp.private'] ! ALL-NEXT: 'fir.global' Pipeline diff --git a/flang/test/Driver/tco-test-gen.fir b/flang/test/Driver/tco-test-gen.fir index 0bc8ed6..b39295d 100644 --- a/flang/test/Driver/tco-test-gen.fir +++ b/flang/test/Driver/tco-test-gen.fir @@ -1,8 +1,8 @@ -// RUN: tco -emit-final-mlir --force-no-alias=false %s | FileCheck %s --check-prefixes=CHECK,AA,CMPLX -// RUN: tco -emit-final-mlir --force-no-alias=false -enable-aa=false %s | FileCheck %s --check-prefixes=CHECK,NOAA,CMPLX -// RUN: tco -emit-final-mlir --force-no-alias=false -simplify-mlir %s | FileCheck %s --check-prefixes=CHECK,AA,SIMPLE -// RUN: tco -emit-final-mlir --force-no-alias=false -enable-aa=false -simplify-mlir %s | FileCheck %s --check-prefixes=CHECK,NOAA,SIMPLE -// RUN: tco -test-gen --force-no-alias=false %s | FileCheck %s --check-prefixes=CHECK,NOAA,SIMPLE +// RUN: tco -emit-final-mlir %s | FileCheck %s --check-prefixes=CHECK,AA,CMPLX +// RUN: tco -emit-final-mlir -enable-aa=false %s | FileCheck %s --check-prefixes=CHECK,NOAA,CMPLX +// RUN: tco -emit-final-mlir -simplify-mlir %s | FileCheck %s --check-prefixes=CHECK,AA,SIMPLE +// RUN: tco -emit-final-mlir -enable-aa=false -simplify-mlir %s | FileCheck %s --check-prefixes=CHECK,NOAA,SIMPLE +// RUN: tco -test-gen %s | FileCheck %s --check-prefixes=CHECK,NOAA,SIMPLE // Just a dummy function that exhibits all of the things we want to turn on and off func.func @_QPtest(%arg0: !fir.ref<i32> {fir.bindc_name = "num"}, %arg1: !fir.ref<i32> {fir.bindc_name = "lb"}, %arg2: !fir.ref<i32> {fir.bindc_name = "ub"}, %arg3: !fir.ref<i32> {fir.bindc_name = "step"}) { @@ -37,10 +37,10 @@ func.func @_QPtest(%arg0: !fir.ref<i32> {fir.bindc_name = "num"}, %arg1: !fir.re } // CHECK-LABEL: llvm.func @_QPtest( -// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr {fir.bindc_name = "num", llvm.nocapture}, -// CHECK-SAME: %[[ARG1:.*]]: !llvm.ptr {fir.bindc_name = "lb", llvm.nocapture}, -// CHECK-SAME: %[[ARG2:.*]]: !llvm.ptr {fir.bindc_name = "ub", llvm.nocapture}, -// CHECK-SAME: %[[ARG3:.*]]: !llvm.ptr {fir.bindc_name = "step", llvm.nocapture}) { +// CHECK-SAME: %[[ARG0:.*]]: !llvm.ptr {fir.bindc_name = "num", llvm.noalias, llvm.nocapture}, +// CHECK-SAME: %[[ARG1:.*]]: !llvm.ptr {fir.bindc_name = "lb", llvm.noalias, llvm.nocapture}, +// CHECK-SAME: %[[ARG2:.*]]: !llvm.ptr {fir.bindc_name = "ub", llvm.noalias, llvm.nocapture}, +// CHECK-SAME: %[[ARG3:.*]]: !llvm.ptr {fir.bindc_name = "step", llvm.noalias, llvm.nocapture}) { // CMPLX: %[[VAL_0:.*]] = llvm.mlir.constant(1 : i64) : i64 // CMPLX: %[[VAL_1:.*]] = llvm.alloca %[[VAL_0]] x i32 {bindc_name = "i"} : (i64) -> !llvm.ptr diff --git a/flang/test/Fir/basic-program.fir b/flang/test/Fir/basic-program.fir index c9fe53b..0a31397 100644 --- a/flang/test/Fir/basic-program.fir +++ b/flang/test/Fir/basic-program.fir @@ -107,7 +107,6 @@ func.func @_QQmain() { // PASSES-NEXT: OptimizeArrayRepacking // PASSES-NEXT: LowerRepackArraysPass // PASSES-NEXT: SimplifyFIROperations -// PASSES-NEXT: AddAliasTags // PASSES-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] // PASSES-NEXT: 'fir.global' Pipeline @@ -132,6 +131,7 @@ func.func @_QQmain() { // PASSES-NEXT: 'func.func' Pipeline // PASSES-NEXT: SetRuntimeCallAttributes // PASSES-NEXT: BoxedProcedurePass +// PASSES-NEXT: AddAliasTags // PASSES-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'gpu.module', 'omp.declare_reduction', 'omp.private'] // PASSES-NEXT: 'fir.global' Pipeline diff --git a/flang/test/Fir/struct-passing-x86-64-byval.fir b/flang/test/Fir/struct-passing-x86-64-byval.fir index e22c3a2..997d293 100644 --- a/flang/test/Fir/struct-passing-x86-64-byval.fir +++ b/flang/test/Fir/struct-passing-x86-64-byval.fir @@ -1,7 +1,7 @@ // Test X86-64 ABI rewrite of struct passed by value (BIND(C), VALUE derived types). // This test test cases where the struct must be passed on the stack according // to the System V ABI. -// RUN: tco --target=x86_64-unknown-linux-gnu --force-no-alias %s | FileCheck %s +// RUN: tco --target=x86_64-unknown-linux-gnu %s | FileCheck %s module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-linux-gnu"} { diff --git a/flang/test/Fir/target-rewrite-complex-10-x86.fir b/flang/test/Fir/target-rewrite-complex-10-x86.fir index d54f98b..5f917ee 100644 --- a/flang/test/Fir/target-rewrite-complex-10-x86.fir +++ b/flang/test/Fir/target-rewrite-complex-10-x86.fir @@ -1,6 +1,6 @@ // Test COMPLEX(10) passing and returning on X86 // RUN: fir-opt --target-rewrite="target=x86_64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=AMD64 -// RUN: tco -target="x86_64-unknown-linux-gnu" --force-no-alias %s | FileCheck %s --check-prefix=AMD64_LLVM +// RUN: tco -target="x86_64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=AMD64_LLVM module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-linux-gnu"} { diff --git a/flang/test/Fir/target.fir b/flang/test/Fir/target.fir index b04e23a..e119064 100644 --- a/flang/test/Fir/target.fir +++ b/flang/test/Fir/target.fir @@ -1,4 +1,4 @@ -// RUN: tco --target=i386-unknown-linux-gnu --force-no-alias %s | FileCheck %s --check-prefix=I32 +// RUN: tco --target=i386-unknown-linux-gnu %s | FileCheck %s --check-prefix=I32 // RUN: tco --target=x86_64-unknown-linux-gnu %s | FileCheck %s --check-prefix=X64 // RUN: tco --target=aarch64-unknown-linux-gnu %s | FileCheck %s --check-prefix=AARCH64 // RUN: tco --target=powerpc64le-unknown-linux-gnu %s | FileCheck %s --check-prefix=PPC diff --git a/flang/test/HLFIR/trim.fir b/flang/test/HLFIR/trim.fir new file mode 100644 index 0000000..8cf4a6d --- /dev/null +++ b/flang/test/HLFIR/trim.fir @@ -0,0 +1,42 @@ +// RUN: fir-opt --lower-hlfir-intrinsics %s | FileCheck %s + +// CHECK-LABEL: func.func @_QPtrim_test( +// CHECK-SAME: %[[ARG0:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) { +// CHECK: %[[VAL_0:.*]] = arith.constant true +// CHECK: %[[VAL_2:.*]] = arith.constant 0 : index +// CHECK: %[[VAL_3:.*]] = arith.constant 8 : index +// CHECK: %[[VAL_4:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>> +// CHECK: %[[VAL_5:.*]] = fir.dummy_scope : !fir.dscope +// CHECK: %[[VAL_6:.*]]:2 = fir.unboxchar %[[ARG0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) +// CHECK: %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_6]]#0 typeparams %[[VAL_6]]#1 dummy_scope %[[VAL_5]] {uniq_name = "_QFtrim_testEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +// CHECK: %[[VAL_8:.*]] = fir.alloca !fir.char<1,8> {bindc_name = "tc", uniq_name = "_QFtrim_testEtc"} +// CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] typeparams %[[VAL_3]] {uniq_name = "_QFtrim_testEtc"} : (!fir.ref<!fir.char<1,8>>, index) -> (!fir.ref<!fir.char<1,8>>, !fir.ref<!fir.char<1,8>>) +// CHECK: %[[VAL_10:.*]] = fir.embox %[[VAL_7]]#1 typeparams %[[VAL_6]]#1 : (!fir.ref<!fir.char<1,?>>, index) -> !fir.box<!fir.char<1,?>> +// CHECK: %[[VAL_11:.*]] = fir.zero_bits !fir.heap<!fir.char<1,?>> +// CHECK: %[[VAL_12:.*]] = fir.embox %[[VAL_11]] typeparams %[[VAL_2]] : (!fir.heap<!fir.char<1,?>>, index) -> !fir.box<!fir.heap<!fir.char<1,?>>> +// CHECK: fir.store %[[VAL_12]] to %[[VAL_4]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> +// CHECK: %[[VAL_14:.*]] = fir.convert %[[VAL_4]] : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) -> !fir.ref<!fir.box<none>> +// CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_10]] : (!fir.box<!fir.char<1,?>>) -> !fir.box<none> +// CHECK: fir.call @_FortranATrim(%[[VAL_14]], %[[VAL_15]], %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> () +// CHECK: %[[VAL_17:.*]] = fir.load %[[VAL_4]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> +// CHECK: %[[VAL_18:.*]] = fir.box_elesize %[[VAL_17]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> index +// CHECK: %[[VAL_19:.*]] = fir.box_addr %[[VAL_17]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>> +// CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_19]] typeparams %[[VAL_18]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.heap<!fir.char<1,?>>) +// CHECK: %[[VAL_21:.*]] = hlfir.as_expr %[[VAL_20]]#0 move %[[VAL_0]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>> +// CHECK: hlfir.assign %[[VAL_21]] to %[[VAL_9]]#0 : !hlfir.expr<!fir.char<1,?>>, !fir.ref<!fir.char<1,8>> +// CHECK: hlfir.destroy %[[VAL_21]] : !hlfir.expr<!fir.char<1,?>> +// CHECK: return +// CHECK: } + +func.func @_QPtrim_test(%arg0: !fir.boxchar<1> {fir.bindc_name = "c"}) { + %0 = fir.dummy_scope : !fir.dscope + %1:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) + %2:2 = hlfir.declare %1#0 typeparams %1#1 dummy_scope %0 {uniq_name = "_QFtrim_testEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) + %c8 = arith.constant 8 : index + %3 = fir.alloca !fir.char<1,8> {bindc_name = "tc", uniq_name = "_QFtrim_testEtc"} + %4:2 = hlfir.declare %3 typeparams %c8 {uniq_name = "_QFtrim_testEtc"} : (!fir.ref<!fir.char<1,8>>, index) -> (!fir.ref<!fir.char<1,8>>, !fir.ref<!fir.char<1,8>>) + %5 = hlfir.char_trim %2#0 : (!fir.boxchar<1>) -> !hlfir.expr<!fir.char<1,?>> + hlfir.assign %5 to %4#0 : !hlfir.expr<!fir.char<1,?>>, !fir.ref<!fir.char<1,8>> + hlfir.destroy %5 : !hlfir.expr<!fir.char<1,?>> + return +} diff --git a/flang/test/Integration/cold_array_repacking.f90 b/flang/test/Integration/cold_array_repacking.f90 index 2f5fe2b..2a3769e 100644 --- a/flang/test/Integration/cold_array_repacking.f90 +++ b/flang/test/Integration/cold_array_repacking.f90 @@ -1,9 +1,9 @@ ! Check that the branch weights used by the array repacking ! are propagated all the way to LLVM IR: -! RUN: %flang_fc1 -frepack-arrays -mmlir --force-no-alias=false -emit-llvm %s -o - | FileCheck %s +! RUN: %flang_fc1 -frepack-arrays -emit-llvm %s -o - | FileCheck %s ! CHECK-LABEL: define void @test_( -! CHECK-SAME: ptr [[TMP0:%.*]]) +! CHECK-SAME: ptr noalias [[TMP0:%.*]]) ! CHECK: [[TMP4:%.*]] = ptrtoint ptr [[TMP0]] to i64 ! CHECK: [[TMP5:%.*]] = icmp ne i64 [[TMP4]], 0 ! CHECK: br i1 [[TMP5]], label %[[BB6:.*]], label %[[BB46:.*]] diff --git a/flang/test/Integration/complex-div-to-llvm-kind10.f90 b/flang/test/Integration/complex-div-to-llvm-kind10.f90 index 5f7b070..7211fed 100644 --- a/flang/test/Integration/complex-div-to-llvm-kind10.f90 +++ b/flang/test/Integration/complex-div-to-llvm-kind10.f90 @@ -1,12 +1,12 @@ ! Test lowering complex division to llvm ir according to options ! REQUIRES: target=x86_64{{.*}} -! RUN: %flang -fcomplex-arithmetic=improved -mmlir --force-no-alias=false -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD -! RUN: %flang -fcomplex-arithmetic=basic -mmlir --force-no-alias=false -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC +! RUN: %flang -fcomplex-arithmetic=improved -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD +! RUN: %flang -fcomplex-arithmetic=basic -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC ! CHECK-LABEL: @div_test_extended -! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]]) +! CHECK-SAME: ptr noalias %[[RET:.*]], ptr noalias %[[LHS:.*]], ptr noalias %[[RHS:.*]]) ! CHECK: %[[LOAD_LHS:.*]] = load { x86_fp80, x86_fp80 }, ptr %[[LHS]], align 16 ! CHECK: %[[LOAD_RHS:.*]] = load { x86_fp80, x86_fp80 }, ptr %[[RHS]], align 16 ! CHECK: %[[LHS_REAL:.*]] = extractvalue { x86_fp80, x86_fp80 } %[[LOAD_LHS]], 0 diff --git a/flang/test/Integration/complex-div-to-llvm-kind16.f90 b/flang/test/Integration/complex-div-to-llvm-kind16.f90 index de67942..7bd5021 100644 --- a/flang/test/Integration/complex-div-to-llvm-kind16.f90 +++ b/flang/test/Integration/complex-div-to-llvm-kind16.f90 @@ -1,12 +1,12 @@ ! Test lowering complex division to llvm ir according to options ! REQUIRES: flang-supports-f128-math -! RUN: %flang -fcomplex-arithmetic=improved -mmlir --force-no-alias=false -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD -! RUN: %flang -fcomplex-arithmetic=basic -mmlir --force-no-alias=false -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC +! RUN: %flang -fcomplex-arithmetic=improved -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD +! RUN: %flang -fcomplex-arithmetic=basic -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC ! CHECK-LABEL: @div_test_quad -! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]]) +! CHECK-SAME: ptr noalias %[[RET:.*]], ptr noalias %[[LHS:.*]], ptr noalias %[[RHS:.*]]) ! CHECK: %[[LOAD_LHS:.*]] = load { fp128, fp128 }, ptr %[[LHS]], align 16 ! CHECK: %[[LOAD_RHS:.*]] = load { fp128, fp128 }, ptr %[[RHS]], align 16 ! CHECK: %[[LHS_REAL:.*]] = extractvalue { fp128, fp128 } %[[LOAD_LHS]], 0 diff --git a/flang/test/Integration/complex-div-to-llvm.f90 b/flang/test/Integration/complex-div-to-llvm.f90 index 51342da..6bce17a 100644 --- a/flang/test/Integration/complex-div-to-llvm.f90 +++ b/flang/test/Integration/complex-div-to-llvm.f90 @@ -1,11 +1,11 @@ ! Test lowering complex division to llvm ir according to options -! RUN: %flang -fcomplex-arithmetic=improved -mmlir --force-no-alias=false -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD -! RUN: %flang -fcomplex-arithmetic=basic -mmlir --force-no-alias=false -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC +! RUN: %flang -fcomplex-arithmetic=improved -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,IMPRVD +! RUN: %flang -fcomplex-arithmetic=basic -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,BASIC ! CHECK-LABEL: @div_test_half -! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]]) +! CHECK-SAME: ptr noalias %[[RET:.*]], ptr noalias %[[LHS:.*]], ptr noalias %[[RHS:.*]]) ! CHECK: %[[LOAD_LHS:.*]] = load { half, half }, ptr %[[LHS]], align 2 ! CHECK: %[[LOAD_RHS:.*]] = load { half, half }, ptr %[[RHS]], align 2 ! CHECK: %[[LHS_REAL:.*]] = extractvalue { half, half } %[[LOAD_LHS]], 0 @@ -131,7 +131,7 @@ end subroutine div_test_half ! CHECK-LABEL: @div_test_bfloat -! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]]) +! CHECK-SAME: ptr noalias %[[RET:.*]], ptr noalias %[[LHS:.*]], ptr noalias %[[RHS:.*]]) ! CHECK: %[[LOAD_LHS:.*]] = load { bfloat, bfloat }, ptr %[[LHS]], align 2 ! CHECK: %[[LOAD_RHS:.*]] = load { bfloat, bfloat }, ptr %[[RHS]], align 2 ! CHECK: %[[LHS_REAL:.*]] = extractvalue { bfloat, bfloat } %[[LOAD_LHS]], 0 @@ -257,7 +257,7 @@ end subroutine div_test_bfloat ! CHECK-LABEL: @div_test_single -! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]]) +! CHECK-SAME: ptr noalias %[[RET:.*]], ptr noalias %[[LHS:.*]], ptr noalias %[[RHS:.*]]) ! CHECK: %[[LOAD_LHS:.*]] = load { float, float }, ptr %[[LHS]], align 4 ! CHECK: %[[LOAD_RHS:.*]] = load { float, float }, ptr %[[RHS]], align 4 ! CHECK: %[[LHS_REAL:.*]] = extractvalue { float, float } %[[LOAD_LHS]], 0 @@ -383,7 +383,7 @@ end subroutine div_test_single ! CHECK-LABEL: @div_test_double -! CHECK-SAME: ptr %[[RET:.*]], ptr %[[LHS:.*]], ptr %[[RHS:.*]]) +! CHECK-SAME: ptr noalias %[[RET:.*]], ptr noalias %[[LHS:.*]], ptr noalias %[[RHS:.*]]) ! CHECK: %[[LOAD_LHS:.*]] = load { double, double }, ptr %[[LHS]], align 8 ! CHECK: %[[LOAD_RHS:.*]] = load { double, double }, ptr %[[RHS]], align 8 ! CHECK: %[[LHS_REAL:.*]] = extractvalue { double, double } %[[LOAD_LHS]], 0 diff --git a/flang/test/Lower/HLFIR/trim.f90 b/flang/test/Lower/HLFIR/trim.f90 new file mode 100644 index 0000000..d09e6c5 --- /dev/null +++ b/flang/test/Lower/HLFIR/trim.f90 @@ -0,0 +1,32 @@ +! RUN: %flang_fc1 -emit-hlfir %s -o - | FileCheck %s + +! CHECK-LABEL: func.func @_QPtrim_test( +! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "c"}) { +! CHECK: %[[VAL_1:.*]] = fir.dummy_scope : !fir.dscope +! CHECK-NEXT: %[[VAL_2:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index) +! CHECK-NEXT: %[[VAL_3:.*]]:2 = hlfir.declare %[[VAL_2]]#0 typeparams %[[VAL_2]]#1 dummy_scope %[[VAL_1]] {uniq_name = "_QFtrim_testEc"} : (!fir.ref<!fir.char<1,?>>, index, !fir.dscope) -> (!fir.boxchar<1>, !fir.ref<!fir.char<1,?>>) +! CHECK-NEXT: %[[VAL_4:.*]] = arith.constant 8 : index +! CHECK-NEXT: %[[VAL_5:.*]] = fir.alloca !fir.char<1,8> {bindc_name = "tc", uniq_name = "_QFtrim_testEtc"} +! CHECK-NEXT: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] typeparams %[[VAL_4]] {uniq_name = "_QFtrim_testEtc"} : (!fir.ref<!fir.char<1,8>>, index) -> (!fir.ref<!fir.char<1,8>>, !fir.ref<!fir.char<1,8>>) +! CHECK-NEXT: %[[VAL_7:.*]] = hlfir.char_trim %[[VAL_3]]#0 : (!fir.boxchar<1>) -> !hlfir.expr<!fir.char<1,?>> +! CHECK-NEXT: hlfir.assign %[[VAL_7]] to %[[VAL_6]]#0 : !hlfir.expr<!fir.char<1,?>>, !fir.ref<!fir.char<1,8>> +! CHECK-NEXT: hlfir.destroy %[[VAL_7]] : !hlfir.expr<!fir.char<1,?>> +! CHECK-NEXT: return +! CHECK-NEXT: } +subroutine trim_test(c) + character(*) :: c + character(8) :: tc + + tc = trim(c) +end subroutine + +! Test trim with fixed length character. +! The length of the returned character type must be unknown. +! CHECK-LABEL: func.func @_QPtrim_test2( +! CHECK: hlfir.char_trim %{{.*}}#0 : (!fir.ref<!fir.char<1,8>>) -> !hlfir.expr<!fir.char<1,?>> +subroutine trim_test2(c) + character(8) :: c + character(8) :: tc + + tc = trim(c) +end subroutine diff --git a/flang/test/Lower/OpenMP/target-data-skip-mapper-calls.f90 b/flang/test/Lower/OpenMP/target-data-skip-mapper-calls.f90 index 63ec865..d1d441d 100644 --- a/flang/test/Lower/OpenMP/target-data-skip-mapper-calls.f90 +++ b/flang/test/Lower/OpenMP/target-data-skip-mapper-calls.f90 @@ -1,12 +1,12 @@ -!RUN: %flang_fc1 -emit-llvm -fopenmp -mmlir --force-no-alias=false %s -o - | FileCheck %s --check-prefix=NORT -!RUN: %flang_fc1 -emit-llvm -fopenmp -mmlir --force-no-alias=false %s -o - | FileCheck %s --check-prefix=LLVM +!RUN: %flang_fc1 -emit-llvm -fopenmp %s -o - | FileCheck %s --check-prefix=NORT +!RUN: %flang_fc1 -emit-llvm -fopenmp %s -o - | FileCheck %s --check-prefix=LLVM !Make sure that there are no calls to the mapper. !NORT-NOT: call{{.*}}__tgt_target_data_begin_mapper !NORT-NOT: call{{.*}}__tgt_target_data_end_mapper !Make sure we generate the body -!LLVM: define internal void @_QFPf(ptr %[[A0:[0-9]+]], ptr %[[A1:[0-9]+]]) +!LLVM: define internal void @_QFPf(ptr noalias %[[A0:[0-9]+]], ptr noalias %[[A1:[0-9]+]]) !LLVM: %[[V0:[0-9]+]] = load i32, ptr %[[A0]], align 4 !LLVM: %[[V1:[0-9]+]] = load i32, ptr %[[A1]], align 4 !LLVM: %[[V2:[0-9]+]] = add i32 %[[V0]], %[[V1]] diff --git a/flang/test/Lower/volatile-string.f90 b/flang/test/Lower/volatile-string.f90 index f263db7..38c29b4 100644 --- a/flang/test/Lower/volatile-string.f90 +++ b/flang/test/Lower/volatile-string.f90 @@ -22,67 +22,56 @@ contains end program ! CHECK-LABEL: func.func @_QQmain() attributes {fir.bindc_name = "P"} { -! CHECK: %[[VAL_0:.*]] = arith.constant 11 : i32 -! CHECK: %[[VAL_1:.*]] = arith.constant 0 : index -! CHECK: %[[VAL_2:.*]] = arith.constant true -! CHECK: %[[VAL_3:.*]] = arith.constant 10 : i32 -! CHECK: %[[VAL_4:.*]] = arith.constant 3 : i32 -! CHECK: %[[VAL_5:.*]] = arith.constant false -! CHECK: %[[VAL_6:.*]] = arith.constant 1 : index -! CHECK: %[[VAL_7:.*]] = arith.constant 3 : index -! CHECK: %[[VAL_8:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,?>>> -! CHECK: %[[VAL_9:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,3>>> -! CHECK: %[[VAL_10:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} -! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) -! CHECK: %[[VAL_12:.*]] = fir.alloca !fir.char<1,3> {bindc_name = "nonvolatile_string", uniq_name = "_QFEnonvolatile_string"} -! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] typeparams %[[VAL_7]] {uniq_name = "_QFEnonvolatile_string"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>) -! CHECK: %[[VAL_14:.*]] = fir.address_of(@_QFEstring) : !fir.ref<!fir.char<1,3>> -! CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_14]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<!fir.char<1,3>, volatile> -! CHECK: %[[VAL_16:.*]]:2 = hlfir.declare %[[VAL_15]] typeparams %[[VAL_7]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEstring"} : (!fir.ref<!fir.char<1,3>, volatile>, index) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>) -! CHECK: %[[VAL_17:.*]] = fir.volatile_cast %[[VAL_16]]#0 : (!fir.ref<!fir.char<1,3>, volatile>) -> !fir.ref<!fir.char<1,3>> -! CHECK: %[[VAL_18:.*]] = fir.emboxchar %[[VAL_17]], %[[VAL_7]] : (!fir.ref<!fir.char<1,3>>, index) -> !fir.boxchar<1> -! CHECK: fir.call @_QFPassign_same_length(%[[VAL_18]]) fastmath<contract> : (!fir.boxchar<1>) -> () -! CHECK: fir.call @_QFPassign_different_length(%[[VAL_18]]) fastmath<contract> : (!fir.boxchar<1>) -> () -! CHECK: %[[VAL_19:.*]] = fir.address_of(@_QQclX6F) : !fir.ref<!fir.char<1>> -! CHECK: %[[VAL_20:.*]]:2 = hlfir.declare %[[VAL_19]] typeparams %[[VAL_6]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX6F"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>) -! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_17]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<i8> -! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_7]] : (index) -> i64 -! CHECK: %[[VAL_23:.*]] = fir.convert %[[VAL_20]]#0 : (!fir.ref<!fir.char<1>>) -> !fir.ref<i8> -! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_6]] : (index) -> i64 -! CHECK: %[[VAL_25:.*]] = fir.call @_FortranAIndex1(%[[VAL_21]], %[[VAL_22]], %[[VAL_23]], %[[VAL_24]], %[[VAL_5]]) fastmath<contract> : (!fir.ref<i8>, i64, !fir.ref<i8>, i64, i1) -> i64 -! CHECK: %[[VAL_26:.*]] = fir.convert %[[VAL_25]] : (i64) -> i32 -! CHECK: hlfir.assign %[[VAL_26]] to %[[VAL_11]]#0 : i32, !fir.ref<i32> -! CHECK: hlfir.assign %[[VAL_4]] to %[[VAL_11]]#0 : i32, !fir.ref<i32> -! CHECK: %[[VAL_27:.*]] = fir.embox %[[VAL_16]]#0 : (!fir.ref<!fir.char<1,3>, volatile>) -> !fir.box<!fir.char<1,3>, volatile> -! CHECK: %[[VAL_28:.*]] = fir.zero_bits !fir.heap<!fir.char<1,3>> -! CHECK: %[[VAL_29:.*]] = fir.embox %[[VAL_28]] : (!fir.heap<!fir.char<1,3>>) -> !fir.box<!fir.heap<!fir.char<1,3>>> -! CHECK: fir.store %[[VAL_29]] to %[[VAL_9]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>> -! CHECK: %[[VAL_30:.*]] = fir.address_of( -! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_9]] : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>) -> !fir.ref<!fir.box<none>> -! CHECK: %[[VAL_32:.*]] = fir.volatile_cast %[[VAL_27]] : (!fir.box<!fir.char<1,3>, volatile>) -> !fir.box<!fir.char<1,3>> -! CHECK: %[[VAL_33:.*]] = fir.convert %[[VAL_32]] : (!fir.box<!fir.char<1,3>>) -> !fir.box<none> -! CHECK: %[[VAL_34:.*]] = fir.convert %[[VAL_30]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8> -! CHECK: fir.call @_FortranAAdjustl(%[[VAL_31]], %[[VAL_33]], %[[VAL_34]], %[[VAL_3]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> () -! CHECK: %[[VAL_35:.*]] = fir.load %[[VAL_9]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>> -! CHECK: %[[VAL_36:.*]] = fir.box_elesize %[[VAL_35]] : (!fir.box<!fir.heap<!fir.char<1,3>>>) -> index -! CHECK: %[[VAL_37:.*]] = fir.box_addr %[[VAL_35]] : (!fir.box<!fir.heap<!fir.char<1,3>>>) -> !fir.heap<!fir.char<1,3>> -! CHECK: %[[VAL_38:.*]]:2 = hlfir.declare %[[VAL_37]] typeparams %[[VAL_36]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,3>>, index) -> (!fir.heap<!fir.char<1,3>>, !fir.heap<!fir.char<1,3>>) -! CHECK: %[[VAL_39:.*]] = hlfir.as_expr %[[VAL_38]]#0 move %[[VAL_2]] : (!fir.heap<!fir.char<1,3>>, i1) -> !hlfir.expr<!fir.char<1,3>> -! CHECK: hlfir.assign %[[VAL_39]] to %[[VAL_16]]#0 : !hlfir.expr<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>, volatile> -! CHECK: hlfir.destroy %[[VAL_39]] : !hlfir.expr<!fir.char<1,3>> -! CHECK: %[[VAL_40:.*]] = fir.zero_bits !fir.heap<!fir.char<1,?>> -! CHECK: %[[VAL_41:.*]] = fir.embox %[[VAL_40]] typeparams %[[VAL_1]] : (!fir.heap<!fir.char<1,?>>, index) -> !fir.box<!fir.heap<!fir.char<1,?>>> -! CHECK: fir.store %[[VAL_41]] to %[[VAL_8]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> -! CHECK: %[[VAL_42:.*]] = fir.convert %[[VAL_8]] : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>>) -> !fir.ref<!fir.box<none>> -! CHECK: fir.call @_FortranATrim(%[[VAL_42]], %[[VAL_33]], %[[VAL_34]], %[[VAL_0]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> () -! CHECK: %[[VAL_43:.*]] = fir.load %[[VAL_8]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,?>>>> -! CHECK: %[[VAL_44:.*]] = fir.box_elesize %[[VAL_43]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> index -! CHECK: %[[VAL_45:.*]] = fir.box_addr %[[VAL_43]] : (!fir.box<!fir.heap<!fir.char<1,?>>>) -> !fir.heap<!fir.char<1,?>> -! CHECK: %[[VAL_46:.*]]:2 = hlfir.declare %[[VAL_45]] typeparams %[[VAL_44]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,?>>, index) -> (!fir.boxchar<1>, !fir.heap<!fir.char<1,?>>) -! CHECK: %[[VAL_47:.*]] = hlfir.as_expr %[[VAL_46]]#0 move %[[VAL_2]] : (!fir.boxchar<1>, i1) -> !hlfir.expr<!fir.char<1,?>> -! CHECK: hlfir.assign %[[VAL_47]] to %[[VAL_13]]#0 : !hlfir.expr<!fir.char<1,?>>, !fir.ref<!fir.char<1,3>> -! CHECK: hlfir.destroy %[[VAL_47]] : !hlfir.expr<!fir.char<1,?>> -! CHECK: hlfir.assign %[[VAL_16]]#0 to %[[VAL_13]]#0 : !fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>> +! CHECK: %[[VAL_0:.*]] = arith.constant true +! CHECK: %[[VAL_1:.*]] = arith.constant 10 : i32 +! CHECK: %[[VAL_2:.*]] = arith.constant 3 : i32 +! CHECK: %[[VAL_3:.*]] = arith.constant false +! CHECK: %[[VAL_4:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_5:.*]] = arith.constant 3 : index +! CHECK: %[[VAL_6:.*]] = fir.alloca !fir.box<!fir.heap<!fir.char<1,3>>> +! CHECK: %[[VAL_7:.*]] = fir.dummy_scope : !fir.dscope +! CHECK: %[[VAL_8:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFEi"} +! CHECK: %[[VAL_9:.*]]:2 = hlfir.declare %[[VAL_8]] {uniq_name = "_QFEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>) +! CHECK: %[[VAL_10:.*]] = fir.alloca !fir.char<1,3> {bindc_name = "nonvolatile_string", uniq_name = "_QFEnonvolatile_string"} +! CHECK: %[[VAL_11:.*]]:2 = hlfir.declare %[[VAL_10]] typeparams %[[VAL_5]] {uniq_name = "_QFEnonvolatile_string"} : (!fir.ref<!fir.char<1,3>>, index) -> (!fir.ref<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>>) +! CHECK: %[[VAL_12:.*]] = fir.address_of(@_QFEstring) : !fir.ref<!fir.char<1,3>> +! CHECK: %[[VAL_13:.*]] = fir.volatile_cast %[[VAL_12]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<!fir.char<1,3>, volatile> +! CHECK: %[[VAL_14:.*]]:2 = hlfir.declare %[[VAL_13]] typeparams %[[VAL_5]] {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QFEstring"} : (!fir.ref<!fir.char<1,3>, volatile>, index) -> (!fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>, volatile>) +! CHECK: %[[VAL_15:.*]] = fir.volatile_cast %[[VAL_14]]#0 : (!fir.ref<!fir.char<1,3>, volatile>) -> !fir.ref<!fir.char<1,3>> +! CHECK: %[[VAL_16:.*]] = fir.emboxchar %[[VAL_15]], %[[VAL_5]] : (!fir.ref<!fir.char<1,3>>, index) -> !fir.boxchar<1> +! CHECK: fir.call @_QFPassign_same_length(%[[VAL_16]]) fastmath<contract> : (!fir.boxchar<1>) -> () +! CHECK: fir.call @_QFPassign_different_length(%[[VAL_16]]) fastmath<contract> : (!fir.boxchar<1>) -> () +! CHECK: %[[VAL_17:.*]] = fir.address_of(@_QQclX6F) : !fir.ref<!fir.char<1>> +! CHECK: %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_17]] typeparams %[[VAL_4]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQclX6F"} : (!fir.ref<!fir.char<1>>, index) -> (!fir.ref<!fir.char<1>>, !fir.ref<!fir.char<1>>) +! CHECK: %[[VAL_19:.*]] = fir.convert %[[VAL_15]] : (!fir.ref<!fir.char<1,3>>) -> !fir.ref<i8> +! CHECK: %[[VAL_20:.*]] = fir.convert %[[VAL_5]] : (index) -> i64 +! CHECK: %[[VAL_21:.*]] = fir.convert %[[VAL_18]]#0 : (!fir.ref<!fir.char<1>>) -> !fir.ref<i8> +! CHECK: %[[VAL_22:.*]] = fir.convert %[[VAL_4]] : (index) -> i64 +! CHECK: %[[VAL_23:.*]] = fir.call @_FortranAIndex1(%[[VAL_19]], %[[VAL_20]], %[[VAL_21]], %[[VAL_22]], %[[VAL_3]]) fastmath<contract> : (!fir.ref<i8>, i64, !fir.ref<i8>, i64, i1) -> i64 +! CHECK: %[[VAL_24:.*]] = fir.convert %[[VAL_23]] : (i64) -> i32 +! CHECK: hlfir.assign %[[VAL_24]] to %[[VAL_9]]#0 : i32, !fir.ref<i32> +! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_9]]#0 : i32, !fir.ref<i32> +! CHECK: %[[VAL_25:.*]] = fir.embox %[[VAL_14]]#0 : (!fir.ref<!fir.char<1,3>, volatile>) -> !fir.box<!fir.char<1,3>, volatile> +! CHECK: %[[VAL_26:.*]] = fir.zero_bits !fir.heap<!fir.char<1,3>> +! CHECK: %[[VAL_27:.*]] = fir.embox %[[VAL_26]] : (!fir.heap<!fir.char<1,3>>) -> !fir.box<!fir.heap<!fir.char<1,3>>> +! CHECK: fir.store %[[VAL_27]] to %[[VAL_6]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>> +! CHECK: %[[VAL_28:.*]] = fir.address_of( +! CHECK: %[[VAL_29:.*]] = fir.convert %[[VAL_6]] : (!fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>>) -> !fir.ref<!fir.box<none>> +! CHECK: %[[VAL_30:.*]] = fir.volatile_cast %[[VAL_25]] : (!fir.box<!fir.char<1,3>, volatile>) -> !fir.box<!fir.char<1,3>> +! CHECK: %[[VAL_31:.*]] = fir.convert %[[VAL_30]] : (!fir.box<!fir.char<1,3>>) -> !fir.box<none> +! CHECK: %[[VAL_32:.*]] = fir.convert %[[VAL_28]] : (!fir.ref<!fir.char<1,{{.*}}>>) -> !fir.ref<i8> +! CHECK: fir.call @_FortranAAdjustl(%[[VAL_29]], %[[VAL_31]], %[[VAL_32]], %[[VAL_1]]) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.ref<i8>, i32) -> () +! CHECK: %[[VAL_33:.*]] = fir.load %[[VAL_6]] : !fir.ref<!fir.box<!fir.heap<!fir.char<1,3>>>> +! CHECK: %[[VAL_34:.*]] = fir.box_elesize %[[VAL_33]] : (!fir.box<!fir.heap<!fir.char<1,3>>>) -> index +! CHECK: %[[VAL_35:.*]] = fir.box_addr %[[VAL_33]] : (!fir.box<!fir.heap<!fir.char<1,3>>>) -> !fir.heap<!fir.char<1,3>> +! CHECK: %[[VAL_36:.*]]:2 = hlfir.declare %[[VAL_35]] typeparams %[[VAL_34]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.heap<!fir.char<1,3>>, index) -> (!fir.heap<!fir.char<1,3>>, !fir.heap<!fir.char<1,3>>) +! CHECK: %[[VAL_37:.*]] = hlfir.as_expr %[[VAL_36]]#0 move %[[VAL_0]] : (!fir.heap<!fir.char<1,3>>, i1) -> !hlfir.expr<!fir.char<1,3>> +! CHECK: hlfir.assign %[[VAL_37]] to %[[VAL_14]]#0 : !hlfir.expr<!fir.char<1,3>>, !fir.ref<!fir.char<1,3>, volatile> +! CHECK: hlfir.destroy %[[VAL_37]] : !hlfir.expr<!fir.char<1,3>> +! CHECK: %[[VAL_38:.*]] = hlfir.char_trim %[[VAL_14]]#0 : (!fir.ref<!fir.char<1,3>, volatile>) -> !hlfir.expr<!fir.char<1,?>> +! CHECK: hlfir.assign %[[VAL_38]] to %[[VAL_11]]#0 : !hlfir.expr<!fir.char<1,?>>, !fir.ref<!fir.char<1,3>> +! CHECK: hlfir.destroy %[[VAL_38]] : !hlfir.expr<!fir.char<1,?>> +! CHECK: hlfir.assign %[[VAL_14]]#0 to %[[VAL_11]]#0 : !fir.ref<!fir.char<1,3>, volatile>, !fir.ref<!fir.char<1,3>> ! CHECK: return ! CHECK: } diff --git a/libc/src/__support/StringUtil/platform_errors.h b/libc/src/__support/StringUtil/platform_errors.h index 32e8414..5f83865 100644 --- a/libc/src/__support/StringUtil/platform_errors.h +++ b/libc/src/__support/StringUtil/platform_errors.h @@ -9,7 +9,7 @@ #ifndef LLVM_LIBC_SRC___SUPPORT_STRINGUTIL_PLATFORM_ERRORS_H #define LLVM_LIBC_SRC___SUPPORT_STRINGUTIL_PLATFORM_ERRORS_H -#if defined(__linux__) || defined(__Fuchsia__) +#if defined(__linux__) || defined(__Fuchsia__) || defined(__EMSCRIPTEN__) #include "tables/linux_platform_errors.h" #else #include "tables/minimal_platform_errors.h" diff --git a/libc/src/__support/macros/properties/architectures.h b/libc/src/__support/macros/properties/architectures.h index ecc9319..21e9bc4 100644 --- a/libc/src/__support/macros/properties/architectures.h +++ b/libc/src/__support/macros/properties/architectures.h @@ -41,6 +41,10 @@ #define LIBC_TARGET_ARCH_IS_ARM #endif +#if defined(__wasm__) +#define LIBC_TARGET_ARCH_IS_WASM +#endif + #if defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64) #define LIBC_TARGET_ARCH_IS_AARCH64 #endif diff --git a/libc/src/setjmp/wasm/sigsetjmp.cpp b/libc/src/setjmp/wasm/sigsetjmp.cpp new file mode 100644 index 0000000..e9dfb3f --- /dev/null +++ b/libc/src/setjmp/wasm/sigsetjmp.cpp @@ -0,0 +1,18 @@ +//===-- Implementation of sigsetjmp ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "src/setjmp/sigsetjmp.h" +#include "hdr/offsetof_macros.h" +#include "src/__support/common.h" + +namespace LIBC_NAMESPACE_DECL { +[[gnu::returns_twice]] int sigsetjmp(jmp_buf sigjmp_buf, + [[maybe_unused]] int savesigs) { + return setjmp(sigjmp_buf); +} +} // namespace LIBC_NAMESPACE_DECL diff --git a/libc/src/stdlib/exit.cpp b/libc/src/stdlib/exit.cpp index ef3b8dd..f26d48a 100644 --- a/libc/src/stdlib/exit.cpp +++ b/libc/src/stdlib/exit.cpp @@ -24,8 +24,12 @@ extern "C" [[gnu::weak]] void __cxa_thread_finalize(); // TODO: use recursive mutex to protect this routine. [[noreturn]] LLVM_LIBC_FUNCTION(void, exit, (int status)) { +// FIXME: The NVPTX target does not support external weak symbols correctly +// despite being an ELF platform. Disable pending a future split. +#if !defined(LIBC_TARGET_ARCH_IS_NVPTX) if (__cxa_thread_finalize) __cxa_thread_finalize(); +#endif __cxa_finalize(nullptr); internal::exit(status); } diff --git a/libcxx/test/extensions/clang/clang_modules_include.gen.py b/libcxx/test/extensions/clang/clang_modules_include.gen.py index 379ac22..2866104 100644 --- a/libcxx/test/extensions/clang/clang_modules_include.gen.py +++ b/libcxx/test/extensions/clang/clang_modules_include.gen.py @@ -10,9 +10,32 @@ # This is important notably because the LLDB data formatters use # libc++ headers with modules enabled. -# RUN: %{python} %s %{libcxx-dir}/utils +# Older macOS SDKs were not properly modularized, which causes issues with localization. +# This feature should instead be based on the SDK version. +# UNSUPPORTED: stdlib=system && target={{.+}}-apple-macosx13{{.*}} + +# GCC doesn't support -fcxx-modules +# UNSUPPORTED: gcc + +# The Windows headers don't appear to be compatible with modules +# UNSUPPORTED: windows +# UNSUPPORTED: buildhost=windows + +# The Android headers don't appear to be compatible with modules yet +# UNSUPPORTED: LIBCXX-ANDROID-FIXME + +# TODO: Investigate this failure +# UNSUPPORTED: LIBCXX-FREEBSD-FIXME + +# TODO: Investigate why this doesn't work on Picolibc once the locale base API is refactored +# UNSUPPORTED: LIBCXX-PICOLIBC-FIXME + +# TODO: Fix seemingly circular inclusion or <wchar.h> on AIX +# UNSUPPORTED: LIBCXX-AIX-FIXME -# block Lit from interpreting a RUN/XFAIL/etc inside the generation script +# UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME + +# RUN: %{python} %s %{libcxx-dir}/utils # END. import sys @@ -29,31 +52,6 @@ for header in public_headers: //--- {header}.compile.pass.cpp // RUN: %{{cxx}} %s %{{flags}} %{{compile_flags}} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only -// Older macOS SDKs were not properly modularized, which causes issues with localization. -// This feature should instead be based on the SDK version. -// UNSUPPORTED: stdlib=system && target={{{{.+}}}}-apple-macosx13{{{{.*}}}} - -// GCC doesn't support -fcxx-modules -// UNSUPPORTED: gcc - -// The Windows headers don't appear to be compatible with modules -// UNSUPPORTED: windows -// UNSUPPORTED: buildhost=windows - -// The Android headers don't appear to be compatible with modules yet -// UNSUPPORTED: LIBCXX-ANDROID-FIXME - -// TODO: Investigate this failure -// UNSUPPORTED: LIBCXX-FREEBSD-FIXME - -// TODO: Investigate why this doesn't work on Picolibc once the locale base API is refactored -// UNSUPPORTED: LIBCXX-PICOLIBC-FIXME - -// TODO: Fix seemingly circular inclusion or <wchar.h> on AIX -// UNSUPPORTED: LIBCXX-AIX-FIXME - -// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME - {lit_header_restrictions.get(header, '')} {lit_header_undeprecations.get(header, '')} @@ -68,30 +66,6 @@ print( // REQUIRES: clang-modules-build -// Older macOS SDKs were not properly modularized, which causes issues with localization. -// This feature should instead be based on the SDK version. -// UNSUPPORTED: stdlib=system && target={{{{.+}}}}-apple-macosx13{{{{.*}}}} - -// GCC doesn't support -fcxx-modules -// UNSUPPORTED: gcc - -// The Windows headers don't appear to be compatible with modules -// UNSUPPORTED: windows -// UNSUPPORTED: buildhost=windows - -// The Android headers don't appear to be compatible with modules yet -// UNSUPPORTED: LIBCXX-ANDROID-FIXME - -// TODO: Investigate this failure -// UNSUPPORTED: LIBCXX-FREEBSD-FIXME - -// TODO: Investigate why this doesn't work on Picolibc once the locale base API is refactored -// UNSUPPORTED: LIBCXX-PICOLIBC-FIXME - -// TODO: Fix seemingly circular inclusion or <wchar.h> on AIX -// UNSUPPORTED: LIBCXX-AIX-FIXME - @import std; - """ ) diff --git a/libcxx/test/extensions/posix/xopen_source.gen.py b/libcxx/test/extensions/posix/xopen_source.gen.py index 9d8c623..ec0d981 100644 --- a/libcxx/test/extensions/posix/xopen_source.gen.py +++ b/libcxx/test/extensions/posix/xopen_source.gen.py @@ -12,6 +12,18 @@ # # https://llvm.org/PR117630 +# Some parts of the code like <fstream> use non-standard functions in their implementation, +# and these functions are not provided when _XOPEN_SOURCE is set to older values. This +# breaks when building with modules even when we don't use the offending headers directly. +# UNSUPPORTED: clang-modules-build + +# The AIX localization support uses some functions as part of their headers that require a +# recent value of _XOPEN_SOURCE. +# UNSUPPORTED: LIBCXX-AIX-FIXME + +# This test fails on FreeBSD for an unknown reason. +# UNSUPPORTED: LIBCXX-FREEBSD-FIXME + # RUN: %{python} %s %{libcxx-dir}/utils # END. @@ -33,19 +45,6 @@ for header in public_headers: print( f"""\ //--- {header}.xopen_source_{version}.compile.pass.cpp - -// Some parts of the code like <fstream> use non-standard functions in their implementation, -// and these functions are not provided when _XOPEN_SOURCE is set to older values. This -// breaks when building with modules even when we don't use the offending headers directly. -// UNSUPPORTED: clang-modules-build - -// The AIX localization support uses some functions as part of their headers that require a -// recent value of _XOPEN_SOURCE. -// UNSUPPORTED: LIBCXX-AIX-FIXME - -// This test fails on FreeBSD for an unknown reason. -// UNSUPPORTED: LIBCXX-FREEBSD-FIXME - {lit_header_restrictions.get(header, '')} {lit_header_undeprecations.get(header, '')} diff --git a/libcxx/test/libcxx-03/clang_tidy.gen.py b/libcxx/test/libcxx-03/clang_tidy.gen.py index dbab2875..5926f52 100644 --- a/libcxx/test/libcxx-03/clang_tidy.gen.py +++ b/libcxx/test/libcxx-03/clang_tidy.gen.py @@ -6,12 +6,17 @@ # # ===----------------------------------------------------------------------===## - # Run our custom libc++ clang-tidy checks on all public headers. -# RUN: %{python} %s %{libcxx-dir}/utils +# REQUIRES: has-clang-tidy + +# The frozen headers should not be updated to the latest libc++ style, so don't test. +# UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME -# block Lit from interpreting a RUN/XFAIL/etc inside the generation script +# The GCC compiler flags are not always compatible with clang-tidy. +# UNSUPPORTED: gcc + +# RUN: %{python} %s %{libcxx-dir}/utils # END. import sys @@ -21,15 +26,6 @@ from libcxx.header_information import lit_header_restrictions, lit_header_undepr for header in public_headers: print(f"""\ //--- {header}.sh.cpp - -// REQUIRES: has-clang-tidy - -// The frozen headers should not be updated to the latest libc++ style, so don't test. -// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME - -// The GCC compiler flags are not always compatible with clang-tidy. -// UNSUPPORTED: gcc - {lit_header_restrictions.get(header, '')} {lit_header_undeprecations.get(header, '')} diff --git a/libcxx/test/libcxx/clang_tidy.gen.py b/libcxx/test/libcxx/clang_tidy.gen.py index 1663f5c..16c90c3 100644 --- a/libcxx/test/libcxx/clang_tidy.gen.py +++ b/libcxx/test/libcxx/clang_tidy.gen.py @@ -6,12 +6,14 @@ # # ===----------------------------------------------------------------------===## - # Run our custom libc++ clang-tidy checks on all public headers. -# RUN: %{python} %s %{libcxx-dir}/utils +# REQUIRES: has-clang-tidy -# block Lit from interpreting a RUN/XFAIL/etc inside the generation script +# The GCC compiler flags are not always compatible with clang-tidy. +# UNSUPPORTED: gcc + +# RUN: %{python} %s %{libcxx-dir}/utils # END. import sys @@ -21,12 +23,6 @@ from libcxx.header_information import lit_header_restrictions, lit_header_undepr for header in public_headers: print(f"""\ //--- {header}.sh.cpp - -// REQUIRES: has-clang-tidy - -// The GCC compiler flags are not always compatible with clang-tidy. -// UNSUPPORTED: gcc - {lit_header_restrictions.get(header, '')} {lit_header_undeprecations.get(header, '')} diff --git a/libcxx/test/libcxx/transitive_includes.gen.py b/libcxx/test/libcxx/transitive_includes.gen.py index f01dbac..6ed35af 100644 --- a/libcxx/test/libcxx/transitive_includes.gen.py +++ b/libcxx/test/libcxx/transitive_includes.gen.py @@ -17,8 +17,6 @@ # to avoid breaking users at every release. # RUN: %{python} %s %{libcxx-dir}/utils - -# block Lit from interpreting a RUN/XFAIL/etc inside the generation script # END. import sys diff --git a/libcxx/test/selftest/gen.cpp/unsupported.gen.cpp b/libcxx/test/selftest/gen.cpp/unsupported.gen.cpp new file mode 100644 index 0000000..6f35939 --- /dev/null +++ b/libcxx/test/selftest/gen.cpp/unsupported.gen.cpp @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// Make sure we can mark a gen-test as UNSUPPORTED + +// We use C++03 as a random feature that we know exists. The goal is to make +// this test always unsupported. +// UNSUPPORTED: c++03 +// REQUIRES: c++03 + +// Note that an unsupported gen-test should still contain some commands, otherwise +// what are we generating? They are never executed, though. +// RUN: something-definitely-invalid diff --git a/libcxx/test/std/double_include.gen.py b/libcxx/test/std/double_include.gen.py index fcf3b9a..f019710 100644 --- a/libcxx/test/std/double_include.gen.py +++ b/libcxx/test/std/double_include.gen.py @@ -8,9 +8,10 @@ # Test that we can include each header in two TU's and link them together. -# RUN: %{python} %s %{libcxx-dir}/utils +# We're using compiler-specific flags in this test +# REQUIRES: (gcc || clang) -# Block Lit from interpreting a RUN/XFAIL/etc inside the generation script. +# RUN: %{python} %s %{libcxx-dir}/utils # END. import sys @@ -28,9 +29,6 @@ for header in public_headers: {lit_header_restrictions.get(header, '')} {lit_header_undeprecations.get(header, '')} -// We're using compiler-specific flags in this test -// REQUIRES: (gcc || clang) - // RUN: %{{cxx}} -c %s -o %t.first.o %{{flags}} %{{compile_flags}} // RUN: %{{cxx}} -c %s -o %t.second.o -DWITH_MAIN %{{flags}} %{{compile_flags}} // RUN: %{{cxx}} -o %t.exe %t.first.o %t.second.o %{{flags}} %{{link_flags}} diff --git a/libcxx/test/std/header_inclusions.gen.py b/libcxx/test/std/header_inclusions.gen.py index 8ff9381..cebff94 100644 --- a/libcxx/test/std/header_inclusions.gen.py +++ b/libcxx/test/std/header_inclusions.gen.py @@ -9,6 +9,11 @@ # Test that all headers include all the other headers they're supposed to, as # prescribed by the Standard. +# UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME + +# TODO: This is currently a libc++-specific way of testing the includes, but is a requirement for all implementation +# REQUIRES: stdlib=libc++ + # RUN: %{python} %s %{libcxx-dir}/utils # END. @@ -46,11 +51,6 @@ for header in public_headers: print( f"""\ //--- {header}.compile.pass.cpp -// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME - -// TODO: This is currently a libc++-specific way of testing the includes, but is a requirement for all implementation -// REQUIRES: stdlib=libc++ - {lit_header_restrictions.get(header, '')} {lit_header_undeprecations.get(header, '')} diff --git a/libcxx/test/std/iterators/iterator.range/mandatory_inclusions.gen.py b/libcxx/test/std/iterators/iterator.range/mandatory_inclusions.gen.py index 46290b1..34ede10 100644 --- a/libcxx/test/std/iterators/iterator.range/mandatory_inclusions.gen.py +++ b/libcxx/test/std/iterators/iterator.range/mandatory_inclusions.gen.py @@ -12,6 +12,8 @@ # <list>, <map>, <regex>, <set>, <span>, <string>, <string_view>, <unordered_map>, # <unordered_set>, <vector>. +# UNSUPPORTED: c++03 + # RUN: %{python} %s %{libcxx-dir}/utils # END. @@ -53,7 +55,6 @@ for header in headers: //--- {header}.pass.cpp {lit_header_restrictions.get(header, '')} {lit_header_undeprecations.get(header, '')} -// UNSUPPORTED: c++03 #include <{header}> #include <cassert> diff --git a/libcxx/utils/libcxx/test/format.py b/libcxx/utils/libcxx/test/format.py index 59d0fff..a0b7b5b 100644 --- a/libcxx/utils/libcxx/test/format.py +++ b/libcxx/utils/libcxx/test/format.py @@ -34,11 +34,14 @@ def _checkBaseSubstitutions(substitutions): def _executeScriptInternal(test, litConfig, commands): """ - Returns (stdout, stderr, exitCode, timeoutInfo, parsedCommands) + Returns (stdout, stderr, exitCode, timeoutInfo, parsedCommands), or an appropriate lit.Test.Result + in case of an error while parsing the script. TODO: This really should be easier to access from Lit itself """ parsedCommands = parseScript(test, preamble=commands) + if isinstance(parsedCommands, lit.Test.Result): + return parsedCommands _, tmpBase = _getTempPaths(test) execDir = os.path.dirname(test.getExecPath()) @@ -65,7 +68,8 @@ def parseScript(test, preamble): """ Extract the script from a test, with substitutions applied. - Returns a list of commands ready to be executed. + Returns a list of commands ready to be executed, or an appropriate lit.Test.Result in case of error + while parsing the script (this includes the script being unsupported). - test The lit.Test to parse. @@ -350,6 +354,8 @@ class CxxStandardLibraryTest(lit.formats.FileBasedTest): if "enable-benchmarks=run" in test.config.available_features: steps += ["%dbg(EXECUTED AS) %{exec} %t.exe --benchmark_out=%T/benchmark-result.json --benchmark_out_format=json"] return self._executeShTest(test, litConfig, steps) + elif re.search('[.]gen[.][^.]+$', filename): # This only happens when a generator test is not supported + return self._executeShTest(test, litConfig, []) else: return lit.Test.Result( lit.Test.UNRESOLVED, "Unknown test suffix for '{}'".format(filename) @@ -381,11 +387,19 @@ class CxxStandardLibraryTest(lit.formats.FileBasedTest): generatorExecDir = os.path.dirname(testSuite.getExecPath(pathInSuite)) os.makedirs(generatorExecDir, exist_ok=True) - # Run the generator test + # Run the generator test. It's possible for this to fail for two reasons: the generator test + # is unsupported or the generator ran but failed at runtime -- handle both. In the first case, + # we return the generator test itself, since it should produce the same result when run after + # test suite generation. In the second case, it's a true error so we report it. steps = [] # Steps must already be in the script - (out, err, exitCode, _, _) = _executeScriptInternal(generator, litConfig, steps) + result = _executeScriptInternal(generator, litConfig, steps) + if isinstance(result, lit.Test.Result): + yield generator + return + + (out, err, exitCode, _, _) = result if exitCode != 0: - raise RuntimeError(f"Error while trying to generate gen test\nstdout:\n{out}\n\nstderr:\n{err}") + raise RuntimeError(f"Error while trying to generate gen test {'/'.join(pathInSuite)}\nstdout:\n{out}\n\nstderr:\n{err}") # Split the generated output into multiple files and generate one test for each file for subfile, content in self._splitFile(out): diff --git a/lldb/bindings/interface/SBStructuredDataExtensions.i b/lldb/bindings/interface/SBStructuredDataExtensions.i index ca3d096..af76cfc 100644 --- a/lldb/bindings/interface/SBStructuredDataExtensions.i +++ b/lldb/bindings/interface/SBStructuredDataExtensions.i @@ -3,16 +3,119 @@ STRING_EXTENSION_OUTSIDE(SBStructuredData) %extend lldb::SBStructuredData { #ifdef SWIGPYTHON %pythoncode%{ - def __int__(self): - return self.GetSignedInteger() - def __len__(self): '''Return the number of element in a lldb.SBStructuredData object.''' return self.GetSize() def __iter__(self): '''Iterate over all the elements in a lldb.SBStructuredData object.''' - return lldb_iter(self, 'GetSize', 'GetItemAtIndex') + data_type = self.GetType() + if data_type == eStructuredDataTypeArray: + for i in range(self.GetSize()): + yield self.GetItemAtIndex(i).dynamic + return + elif data_type == eStructuredDataTypeDictionary: + keys = SBStringList() + self.GetKeys(keys) + return iter(keys) + else: + raise TypeError(f"cannot iterate {self.type_name(data_type)} type") + + def __getitem__(self, key): + data_type = self.GetType() + if data_type == eStructuredDataTypeArray: + if not isinstance(key, int): + raise TypeError("subscript index must be an integer") + count = len(self) + if -count <= key < count: + key %= count + return self.GetItemAtIndex(key).dynamic + raise IndexError("index out of range") + elif data_type == eStructuredDataTypeDictionary: + if not isinstance(key, str): + raise TypeError("subscript key must be a string") + return self.GetValueForKey(key).dynamic + else: + raise TypeError(f"cannot subscript {self.type_name(data_type)} type") + + def __str__(self): + data_type = self.GetType() + if data_type in ( + eStructuredDataTypeString, + eStructuredDataTypeInteger, + eStructuredDataTypeSignedInteger, + eStructuredDataTypeFloat, + ): + return str(self.dynamic) + else: + return repr(self) + + def __int__(self): + data_type = self.GetType() + if data_type in ( + eStructuredDataTypeInteger, + eStructuredDataTypeSignedInteger, + ): + return self.dynamic + else: + raise TypeError(f"cannot convert {self.type_name(data_type)} to int") + + def __float__(self): + data_type = self.GetType() + if data_type in ( + eStructuredDataTypeFloat, + eStructuredDataTypeInteger, + eStructuredDataTypeSignedInteger, + ): + return float(self.dynamic) + else: + raise TypeError(f"cannot convert {self.type_name(data_type)} to float") + + @property + def dynamic(self): + data_type = self.GetType() + if data_type == eStructuredDataTypeNull: + return None + elif data_type == eStructuredDataTypeBoolean: + return self.GetBooleanValue() + elif data_type == eStructuredDataTypeInteger: + return self.GetUnsignedIntegerValue() + elif data_type == eStructuredDataTypeSignedInteger: + return self.GetSignedIntegerValue() + elif data_type == eStructuredDataTypeFloat: + return self.GetFloatValue() + elif data_type == eStructuredDataTypeString: + size = len(self) or 1023 + return self.GetStringValue(size + 1) + elif data_type == eStructuredDataTypeGeneric: + return self.GetGenericValue() + else: + return self + + @staticmethod + def type_name(t): + if t == eStructuredDataTypeNull: + return "null" + elif t == eStructuredDataTypeBoolean: + return "boolean" + elif t == eStructuredDataTypeInteger: + return "integer" + elif t == eStructuredDataTypeSignedInteger: + return "integer" + elif t == eStructuredDataTypeFloat: + return "float" + elif t == eStructuredDataTypeString: + return "string" + elif t == eStructuredDataTypeArray: + return "array" + elif t == eStructuredDataTypeDictionary: + return "dictionary" + elif t == eStructuredDataTypeGeneric: + return "generic" + elif t == eStructuredDataTypeInvalid: + return "invalid" + else: + raise TypeError(f"unknown structured data type: {t}") %} #endif } diff --git a/lldb/include/lldb/Host/JSONTransport.h b/lldb/include/lldb/Host/JSONTransport.h index 0be60a8..210f33e 100644 --- a/lldb/include/lldb/Host/JSONTransport.h +++ b/lldb/include/lldb/Host/JSONTransport.h @@ -100,7 +100,8 @@ public: virtual llvm::Expected<MainLoop::ReadHandleUP> RegisterMessageHandler(MainLoop &loop, MessageHandler &handler) = 0; -protected: + // FIXME: Refactor mcp::Server to not directly access log on the transport. + // protected: template <typename... Ts> inline auto Logv(const char *Fmt, Ts &&...Vals) { Log(llvm::formatv(Fmt, std::forward<Ts>(Vals)...).str()); } @@ -139,9 +140,7 @@ public: /// detail. static constexpr size_t kReadBufferSize = 1024; -protected: - virtual llvm::Expected<std::vector<std::string>> Parse() = 0; - virtual std::string Encode(const llvm::json::Value &message) = 0; + // FIXME: Write should be protected. llvm::Error Write(const llvm::json::Value &message) { this->Logv("<-- {0}", message); std::string output = Encode(message); @@ -149,6 +148,10 @@ protected: return m_out->Write(output.data(), bytes_written).takeError(); } +protected: + virtual llvm::Expected<std::vector<std::string>> Parse() = 0; + virtual std::string Encode(const llvm::json::Value &message) = 0; + llvm::SmallString<kReadBufferSize> m_buffer; private: diff --git a/lldb/include/lldb/Protocol/MCP/Server.h b/lldb/include/lldb/Protocol/MCP/Server.h index c6e78a9..254b7d9 100644 --- a/lldb/include/lldb/Protocol/MCP/Server.h +++ b/lldb/include/lldb/Protocol/MCP/Server.h @@ -14,33 +14,17 @@ #include "lldb/Protocol/MCP/Protocol.h" #include "lldb/Protocol/MCP/Resource.h" #include "lldb/Protocol/MCP/Tool.h" +#include "lldb/Protocol/MCP/Transport.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Error.h" -#include <mutex> +#include "llvm/Support/JSON.h" +#include <functional> +#include <memory> +#include <string> +#include <vector> namespace lldb_protocol::mcp { -class MCPTransport - : public lldb_private::JSONRPCTransport<Request, Response, Notification> { -public: - using LogCallback = std::function<void(llvm::StringRef message)>; - - MCPTransport(lldb::IOObjectSP in, lldb::IOObjectSP out, - std::string client_name, LogCallback log_callback = {}) - : JSONRPCTransport(in, out), m_client_name(std::move(client_name)), - m_log_callback(log_callback) {} - virtual ~MCPTransport() = default; - - void Log(llvm::StringRef message) override { - if (m_log_callback) - m_log_callback(llvm::formatv("{0}: {1}", m_client_name, message).str()); - } - -private: - std::string m_client_name; - LogCallback m_log_callback; -}; - /// Information about this instance of lldb's MCP server for lldb-mcp to use to /// coordinate connecting an lldb-mcp client. struct ServerInfo { diff --git a/lldb/include/lldb/Protocol/MCP/Transport.h b/lldb/include/lldb/Protocol/MCP/Transport.h new file mode 100644 index 0000000..47c2ccf --- /dev/null +++ b/lldb/include/lldb/Protocol/MCP/Transport.h @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PROTOCOL_MCP_TRANSPORT_H +#define LLDB_PROTOCOL_MCP_TRANSPORT_H + +#include "lldb/Host/JSONTransport.h" +#include "lldb/Protocol/MCP/Protocol.h" +#include "lldb/lldb-forward.h" +#include "llvm/ADT/FunctionExtras.h" +#include "llvm/ADT/StringRef.h" + +namespace lldb_protocol::mcp { + +/// Generic transport that uses the MCP protocol. +using MCPTransport = lldb_private::Transport<Request, Response, Notification>; + +/// Generic logging callback, to allow the MCP server / client / transport layer +/// to be independent of the lldb log implementation. +using LogCallback = llvm::unique_function<void(llvm::StringRef message)>; + +class Transport final + : public lldb_private::JSONRPCTransport<Request, Response, Notification> { +public: + Transport(lldb::IOObjectSP in, lldb::IOObjectSP out, + LogCallback log_callback = {}); + virtual ~Transport() = default; + + /// Transport is not copyable. + /// @{ + Transport(const Transport &) = delete; + void operator=(const Transport &) = delete; + /// @} + + void Log(llvm::StringRef message) override; + +private: + LogCallback m_log_callback; +}; + +} // namespace lldb_protocol::mcp + +#endif diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index fbf1285..3b8d6a8 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -79,7 +79,7 @@ static lldb_private::RegisterInfo g_register_infos_mte[] = { DEFINE_EXTENSION_REG(mte_ctrl)}; static lldb_private::RegisterInfo g_register_infos_tls[] = { - DEFINE_EXTENSION_REG(tpidr), + DEFINE_EXTENSION_REG_GENERIC(tpidr, LLDB_REGNUM_GENERIC_TP), // Only present when SME is present DEFINE_EXTENSION_REG(tpidr2)}; diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h index c9c4d7c..829fa07 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h +++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_arm64.h @@ -456,6 +456,7 @@ static uint32_t g_d29_invalidates[] = {fpu_v29, fpu_s29, LLDB_INVALID_REGNUM}; static uint32_t g_d30_invalidates[] = {fpu_v30, fpu_s30, LLDB_INVALID_REGNUM}; static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; +// clang-format off // Generates register kinds array with DWARF, EH frame and generic kind #define MISC_KIND(reg, type, generic_kind) \ { \ @@ -470,6 +471,11 @@ static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; LLDB_INVALID_REGNUM, lldb_kind \ } +#define GENERIC_KIND(genenric_kind) \ + { \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, genenric_kind, \ + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM \ + } // Generates register kinds array for registers with only lldb kind #define KIND_ALL_INVALID \ { \ @@ -484,8 +490,6 @@ static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; #define MISC_FPU_KIND(lldb_kind) LLDB_KIND(lldb_kind) #define MISC_EXC_KIND(lldb_kind) LLDB_KIND(lldb_kind) -// clang-format off - // Defines a 64-bit general purpose register #define DEFINE_GPR64(reg, generic_kind) \ { \ @@ -540,6 +544,12 @@ static uint32_t g_d31_invalidates[] = {fpu_v31, fpu_s31, LLDB_INVALID_REGNUM}; #reg, nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex, \ KIND_ALL_INVALID, nullptr, nullptr, nullptr, \ } + +#define DEFINE_EXTENSION_REG_GENERIC(reg, generic_kind) \ + { \ + #reg, nullptr, 8, 0, lldb::eEncodingUint, lldb::eFormatHex, \ + GENERIC_KIND(generic_kind), nullptr, nullptr, nullptr, \ + } static lldb_private::RegisterInfo g_register_infos_arm64_le[] = { // DEFINE_GPR64(name, GENERIC KIND) diff --git a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp index 12cb257..2b004c1 100644 --- a/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp +++ b/lldb/source/Plugins/Protocol/MCP/ProtocolServerMCP.cpp @@ -70,9 +70,9 @@ void ProtocolServerMCP::AcceptCallback(std::unique_ptr<Socket> socket) { LLDB_LOG(log, "New MCP client connected: {0}", client_name); lldb::IOObjectSP io_sp = std::move(socket); - auto transport_up = std::make_unique<lldb_protocol::mcp::MCPTransport>( - io_sp, io_sp, std::move(client_name), [&](llvm::StringRef message) { - LLDB_LOG(GetLog(LLDBLog::Host), "{0}", message); + auto transport_up = std::make_unique<lldb_protocol::mcp::Transport>( + io_sp, io_sp, [client_name](llvm::StringRef message) { + LLDB_LOG(GetLog(LLDBLog::Host), "{0}: {1}", client_name, message); }); auto instance_up = std::make_unique<lldb_protocol::mcp::Server>( std::string(kName), std::string(kVersion), std::move(transport_up), diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 16ca90a..6768a94 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1655,22 +1655,62 @@ void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter) { clang->GetNativePDBParser()->Dump(s, filter); } -void SymbolFileNativePDB::CacheFunctionNames() { - if (!m_func_full_names.IsEmpty()) +void SymbolFileNativePDB::CacheGlobalBaseNames() { + if (!m_func_full_names.IsEmpty() || !m_global_variable_base_names.IsEmpty()) return; // (segment, code offset) -> gid - std::map<std::pair<uint16_t, uint32_t>, uint32_t> addr_ids; + std::map<std::pair<uint16_t, uint32_t>, uint32_t> func_addr_ids; - // First, find all function references in the globals table. + // First, look through all items in the globals table. for (const uint32_t gid : m_index->globals().getGlobalsTable()) { - CVSymbol ref_sym = m_index->symrecords().readRecord(gid); - auto kind = ref_sym.kind(); + CVSymbol sym = m_index->symrecords().readRecord(gid); + auto kind = sym.kind(); + + // If this is a global variable, we only need to look at the name + llvm::StringRef name; + switch (kind) { + case SymbolKind::S_GDATA32: + case SymbolKind::S_LDATA32: { + DataSym data = + llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym)); + name = data.Name; + break; + } + case SymbolKind::S_GTHREAD32: + case SymbolKind::S_LTHREAD32: { + ThreadLocalDataSym data = llvm::cantFail( + SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym)); + name = data.Name; + break; + } + case SymbolKind::S_CONSTANT: { + ConstantSym data = + llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym)); + name = data.Name; + break; + } + default: + break; + } + + if (!name.empty()) { + llvm::StringRef base = MSVCUndecoratedNameParser::DropScope(name); + if (base.empty()) + base = name; + + m_global_variable_base_names.Append(ConstString(base), gid); + continue; + } + if (kind != S_PROCREF && kind != S_LPROCREF) continue; + // For functions, we need to follow the reference to the procedure and look + // at the type + ProcRefSym ref = - llvm::cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(ref_sym)); + llvm::cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(sym)); if (ref.Name.empty()) continue; @@ -1694,7 +1734,7 @@ void SymbolFileNativePDB::CacheFunctionNames() { // The function/procedure symbol only contains the demangled name. // The mangled names are in the publics table. Save the address of this // function to lookup the mangled name later. - addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid); + func_addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid); llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(proc.Name); if (basename.empty()) @@ -1729,8 +1769,8 @@ void SymbolFileNativePDB::CacheFunctionNames() { continue; // Check if this symbol is for one of our functions. - auto it = addr_ids.find({pub.Segment, pub.Offset}); - if (it != addr_ids.end()) + auto it = func_addr_ids.find({pub.Segment, pub.Offset}); + if (it != func_addr_ids.end()) m_func_full_names.Append(ConstString(pub.Name), it->second); } @@ -1741,31 +1781,35 @@ void SymbolFileNativePDB::CacheFunctionNames() { m_func_method_names.SizeToFit(); m_func_base_names.Sort(std::less<uint32_t>()); m_func_base_names.SizeToFit(); + m_global_variable_base_names.Sort(std::less<uint32_t>()); + m_global_variable_base_names.SizeToFit(); } void SymbolFileNativePDB::FindGlobalVariables( ConstString name, const CompilerDeclContext &parent_decl_ctx, uint32_t max_matches, VariableList &variables) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; - std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName( - name.GetStringRef(), m_index->symrecords()); - for (const SymbolAndOffset &result : results) { - switch (result.second.kind()) { - case SymbolKind::S_GDATA32: - case SymbolKind::S_LDATA32: - case SymbolKind::S_GTHREAD32: - case SymbolKind::S_LTHREAD32: - case SymbolKind::S_CONSTANT: { - PdbGlobalSymId global(result.first, false); - if (VariableSP var = GetOrCreateGlobalVariable(global)) - variables.AddVariable(var); - break; - } - default: + CacheGlobalBaseNames(); + + std::vector<uint32_t> results; + m_global_variable_base_names.GetValues(name, results); + + size_t n_matches = 0; + for (uint32_t gid : results) { + PdbGlobalSymId global(gid, false); + + if (parent_decl_ctx.IsValid() && + GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx) continue; - } + + VariableSP var = GetOrCreateGlobalVariable(global); + if (!var) + continue; + variables.AddVariable(var); + + if (++n_matches >= max_matches) + break; } } @@ -1783,7 +1827,7 @@ void SymbolFileNativePDB::FindFunctions( name_type_mask & eFunctionNameTypeBase || name_type_mask & eFunctionNameTypeMethod)) return; - CacheFunctionNames(); + CacheGlobalBaseNames(); std::set<uint32_t> resolved_ids; // avoid duplicate lookups auto resolve_from = [&](UniqueCStringMap<uint32_t> &Names) { diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index cfa0041..095b40c 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -260,7 +260,10 @@ private: std::vector<CompilerContext> GetContextForType(llvm::codeview::TypeIndex ti); - void CacheFunctionNames(); + /// Caches the basenames of symbols found in the globals stream. + /// + /// This includes functions and global variables + void CacheGlobalBaseNames(); void CacheUdtDeclarations(); llvm::Expected<Declaration> ResolveUdtDeclaration(PdbTypeSymId type_id); @@ -306,6 +309,9 @@ private: lldb_private::UniqueCStringMap<uint32_t> m_func_base_names; /// method basename -> Global ID(s) lldb_private::UniqueCStringMap<uint32_t> m_func_method_names; + + /// global variable basename -> Global ID(s) + lldb_private::UniqueCStringMap<uint32_t> m_global_variable_base_names; }; } // namespace npdb diff --git a/lldb/source/Protocol/MCP/CMakeLists.txt b/lldb/source/Protocol/MCP/CMakeLists.txt index a4f270a..5258cb6 100644 --- a/lldb/source/Protocol/MCP/CMakeLists.txt +++ b/lldb/source/Protocol/MCP/CMakeLists.txt @@ -3,6 +3,7 @@ add_lldb_library(lldbProtocolMCP NO_PLUGIN_DEPENDENCIES Protocol.cpp Server.cpp Tool.cpp + Transport.cpp LINK_COMPONENTS Support diff --git a/lldb/source/Protocol/MCP/Transport.cpp b/lldb/source/Protocol/MCP/Transport.cpp new file mode 100644 index 0000000..cccdc3b --- /dev/null +++ b/lldb/source/Protocol/MCP/Transport.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Protocol/MCP/Transport.h" +#include "llvm/ADT/StringRef.h" +#include <utility> + +using namespace lldb_protocol::mcp; +using namespace llvm; + +Transport::Transport(lldb::IOObjectSP in, lldb::IOObjectSP out, + LogCallback log_callback) + : JSONRPCTransport(in, out), m_log_callback(std::move(log_callback)) {} + +void Transport::Log(StringRef message) { + if (m_log_callback) + m_log_callback(message); +} diff --git a/lldb/test/API/linux/aarch64/tls_registers/TestAArch64LinuxTLSRegisters.py b/lldb/test/API/linux/aarch64/tls_registers/TestAArch64LinuxTLSRegisters.py index ec8eb1c..2fa963e 100644 --- a/lldb/test/API/linux/aarch64/tls_registers/TestAArch64LinuxTLSRegisters.py +++ b/lldb/test/API/linux/aarch64/tls_registers/TestAArch64LinuxTLSRegisters.py @@ -53,6 +53,8 @@ class AArch64LinuxTLSRegisters(TestBase): tls_reg.IsValid(), "{} register not found.".format(register) ) self.assertEqual(tls_reg.GetValueAsUnsigned(), values[register]) + if register == "tpidr": + self.expect("reg read tp", substrs=[hex(values[register])]) def check_tls_reg(self, registers): self.setup(registers) diff --git a/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py b/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py index 99f88d3..b12f4da 100644 --- a/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py +++ b/lldb/test/API/python_api/sbstructureddata/TestStructuredDataAPI.py @@ -48,10 +48,11 @@ class TestStructuredDataAPI(TestBase): s.Clear() error = example.GetDescription(s) self.assertSuccess(error, "GetDescription works") + # Ensure str() doesn't raise an exception. + self.assertTrue(str(example)) if not "key_float" in s.GetData(): self.fail("FAILED: could not find key_float in description output") - dict_struct = lldb.SBStructuredData() dict_struct = example.GetValueForKey("key_dict") # Tests for dictionary data type @@ -113,18 +114,22 @@ class TestStructuredDataAPI(TestBase): self.assertSuccess(example.SetFromJSON("1")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeInteger) self.assertEqual(example.GetIntegerValue(), 1) + self.assertEqual(int(example), 1) self.assertSuccess(example.SetFromJSON("4.19")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeFloat) self.assertEqual(example.GetFloatValue(), 4.19) + self.assertEqual(float(example), 4.19) self.assertSuccess(example.SetFromJSON('"Bonjour, 123!"')) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeString) self.assertEqual(example.GetStringValue(42), "Bonjour, 123!") + self.assertEqual(str(example), "Bonjour, 123!") self.assertSuccess(example.SetFromJSON("true")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeBoolean) self.assertTrue(example.GetBooleanValue()) + self.assertTrue(example) self.assertSuccess(example.SetFromJSON("null")) self.assertEqual(example.GetType(), lldb.eStructuredDataTypeNull) @@ -187,38 +192,35 @@ class TestStructuredDataAPI(TestBase): self.assertEqual(sb_data, example_arr) def invalid_struct_test(self, example): - invalid_struct = lldb.SBStructuredData() invalid_struct = example.GetValueForKey("invalid_key") if invalid_struct.IsValid(): self.fail("An invalid object should have been returned") # Check Type API - if not invalid_struct.GetType() == lldb.eStructuredDataTypeInvalid: + if invalid_struct.GetType() != lldb.eStructuredDataTypeInvalid: self.fail("Wrong type returned: " + str(invalid_struct.GetType())) def dictionary_struct_test(self, example): # Check API returning a valid SBStructuredData of 'dictionary' type - dict_struct = lldb.SBStructuredData() dict_struct = example.GetValueForKey("key_dict") if not dict_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not dict_struct.GetType() == lldb.eStructuredDataTypeDictionary: + if dict_struct.GetType() != lldb.eStructuredDataTypeDictionary: self.fail("Wrong type returned: " + str(dict_struct.GetType())) # Check Size API for 'dictionary' type - if not dict_struct.GetSize() == 6: + if dict_struct.GetSize() != 6: self.fail("Wrong no of elements returned: " + str(dict_struct.GetSize())) def string_struct_test(self, dict_struct): - string_struct = lldb.SBStructuredData() string_struct = dict_struct.GetValueForKey("key_string") if not string_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not string_struct.GetType() == lldb.eStructuredDataTypeString: + if string_struct.GetType() != lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) # Check API returning 'string' value @@ -238,18 +240,17 @@ class TestStructuredDataAPI(TestBase): # Check a valid SBStructuredData containing an unsigned integer. # We intentionally make this larger than what an int64_t can hold but # still small enough to fit a uint64_t - uint_struct = lldb.SBStructuredData() uint_struct = dict_struct.GetValueForKey("key_uint") if not uint_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not uint_struct.GetType() == lldb.eStructuredDataTypeInteger: + if uint_struct.GetType() != lldb.eStructuredDataTypeInteger: self.fail("Wrong type returned: " + str(uint_struct.GetType())) # Check API returning unsigned integer value output = uint_struct.GetUnsignedIntegerValue() - if not output == 0xFFFFFFFF00000000: + if output != 0xFFFFFFFF00000000: self.fail("wrong output: " + str(output)) # Calling wrong API on a SBStructuredData @@ -262,18 +263,17 @@ class TestStructuredDataAPI(TestBase): # Check a valid SBStructuredData containing an signed integer. # We intentionally make this smaller than what an uint64_t can hold but # still small enough to fit a int64_t - sint_struct = lldb.SBStructuredData() sint_struct = dict_struct.GetValueForKey("key_sint") if not sint_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not sint_struct.GetType() == lldb.eStructuredDataTypeSignedInteger: + if sint_struct.GetType() != lldb.eStructuredDataTypeSignedInteger: self.fail("Wrong type returned: " + str(sint_struct.GetType())) # Check API returning signed integer value output = sint_struct.GetSignedIntegerValue() - if not output == -42: + if output != -42: self.fail("wrong output: " + str(output)) # Calling wrong API on a SBStructuredData @@ -283,28 +283,26 @@ class TestStructuredDataAPI(TestBase): self.fail("Valid string " + output + " returned for an integer object") def double_struct_test(self, dict_struct): - floating_point_struct = lldb.SBStructuredData() floating_point_struct = dict_struct.GetValueForKey("key_float") if not floating_point_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not floating_point_struct.GetType() == lldb.eStructuredDataTypeFloat: + if floating_point_struct.GetType() != lldb.eStructuredDataTypeFloat: self.fail("Wrong type returned: " + str(floating_point_struct.GetType())) # Check API returning 'double' value output = floating_point_struct.GetFloatValue() - if not output == 2.99: + if output != 2.99: self.fail("wrong output: " + str(output)) def bool_struct_test(self, dict_struct): - bool_struct = lldb.SBStructuredData() bool_struct = dict_struct.GetValueForKey("key_bool") if not bool_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not bool_struct.GetType() == lldb.eStructuredDataTypeBoolean: + if bool_struct.GetType() != lldb.eStructuredDataTypeBoolean: self.fail("Wrong type returned: " + str(bool_struct.GetType())) # Check API returning 'bool' value @@ -314,17 +312,16 @@ class TestStructuredDataAPI(TestBase): def array_struct_test(self, dict_struct): # Check API returning a valid SBStructuredData of 'array' type - array_struct = lldb.SBStructuredData() array_struct = dict_struct.GetValueForKey("key_array") if not array_struct.IsValid(): self.fail("A valid object should have been returned") # Check Type API - if not array_struct.GetType() == lldb.eStructuredDataTypeArray: + if array_struct.GetType() != lldb.eStructuredDataTypeArray: self.fail("Wrong type returned: " + str(array_struct.GetType())) # Check Size API for 'array' type - if not array_struct.GetSize() == 2: + if array_struct.GetSize() != 2: self.fail("Wrong no of elements returned: " + str(array_struct.GetSize())) # Check API returning a valid SBStructuredData for different 'array' @@ -332,17 +329,73 @@ class TestStructuredDataAPI(TestBase): string_struct = array_struct.GetItemAtIndex(0) if not string_struct.IsValid(): self.fail("A valid object should have been returned") - if not string_struct.GetType() == lldb.eStructuredDataTypeString: + if string_struct.GetType() != lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) output = string_struct.GetStringValue(5) - if not output == "23": + if output != "23": self.fail("wrong output: " + str(output)) string_struct = array_struct.GetItemAtIndex(1) if not string_struct.IsValid(): self.fail("A valid object should have been returned") - if not string_struct.GetType() == lldb.eStructuredDataTypeString: + if string_struct.GetType() != lldb.eStructuredDataTypeString: self.fail("Wrong type returned: " + str(string_struct.GetType())) output = string_struct.GetStringValue(5) - if not output == "arr": + if output != "arr": self.fail("wrong output: " + str(output)) + + def test_round_trip_scalars(self): + for original in (0, 11, -1, 0.0, 4.5, -0.25): + constructor = type(original) + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(original)) + round_tripped = constructor(data) + self.assertEqual(round_tripped, original) + + def test_dynamic(self): + for original in (0, 11, -1, 0.0, 4.5, -0.25, "", "dirk", True, False): + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(original)) + self.assertEqual(data.dynamic, original) + + def test_round_trip_int(self): + for original in (0, 11, -1): + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(original)) + self.assertEqual(int(data), int(original)) + + def test_round_trip_float(self): + for original in (0, 11, -1, 0.0, 4.5, -0.25): + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(original)) + self.assertEqual(float(data), float(original)) + + def test_iterate_array(self): + array = [0, 1, 2] + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(array)) + for value in data: + self.assertEqual(value, array.pop(0)) + + def test_iterate_dictionary(self): + dictionary = {"0": 0, "1": 1, "2": 2} + keys = set(dictionary.keys()) + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(dictionary)) + for key in data: + self.assertIn(key, keys) + keys.remove(key) + + def test_getitem_array(self): + array = [1, 2, 3] + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(array)) + for i in range(len(array)): + self.assertEqual(data[i], array[i]) + + def test_getitem_dictionary(self): + dictionary = {"one": 1, "two": 2, "three": 3} + data = lldb.SBStructuredData() + data.SetFromJSON(json.dumps(dictionary)) + for key in dictionary: + self.assertEqual(data[key], dictionary[key]) diff --git a/lldb/test/Shell/Host/TestCustomShell.test b/lldb/test/Shell/Host/TestCustomShell.test index 0e948a1..5d3e901 100644 --- a/lldb/test/Shell/Host/TestCustomShell.test +++ b/lldb/test/Shell/Host/TestCustomShell.test @@ -6,7 +6,7 @@ # XFAIL: system-openbsd # RUN: %clang_host %S/Inputs/simple.c -g -o %t.out -# RUN: SHELL=bogus not %lldb %t.out -b -o 'process launch -X 1 --' 2>&1 | FileCheck %s --check-prefix ERROR +# RUN: env SHELL=bogus not %lldb %t.out -b -o 'process launch -X 1 --' 2>&1 | FileCheck %s --check-prefix ERROR # RUN: env -i ASAN_OPTIONS='detect_container_overflow=0' %lldb %t.out -b -o 'process launch -X 1 --' 2>&1 | FileCheck %s # ERROR: error: shell expansion failed diff --git a/lldb/test/Shell/SymbolFile/DWARF/deterministic-build.cpp b/lldb/test/Shell/SymbolFile/DWARF/deterministic-build.cpp index 9e79f23..13fe389 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/deterministic-build.cpp +++ b/lldb/test/Shell/SymbolFile/DWARF/deterministic-build.cpp @@ -3,9 +3,8 @@ // requires the ld64 linker, which clang invokes by default. // REQUIRES: system-darwin // RUN: %clang_host %s -g -c -o %t.o -// RUN: ZERO_AR_DATE=1 %clang_host %t.o -g -o %t +// RUN: env ZERO_AR_DATE=1 %clang_host %t.o -g -o %t // RUN: %lldb %t -o "breakpoint set -f %s -l 11" -o run -o exit | FileCheck %s // CHECK: stop reason = breakpoint - int main() { return 0; } diff --git a/lldb/test/Shell/SymbolFile/PDB/expressions.test b/lldb/test/Shell/SymbolFile/PDB/expressions.test index 1932be7..33b02e2 100644 --- a/lldb/test/Shell/SymbolFile/PDB/expressions.test +++ b/lldb/test/Shell/SymbolFile/PDB/expressions.test @@ -1,6 +1,7 @@ REQUIRES: target-windows, msvc RUN: %build --compiler=msvc --nodefaultlib --output=%t.exe %S/Inputs/ExpressionsTest.cpp -RUN: not %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s +RUN: env LLDB_USE_NATIVE_PDB_READER=0 not %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 not %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s // Check the variable value through `expression` CHECK: (lldb) expression result diff --git a/lldb/test/Shell/SymbolFile/add-dsym.test b/lldb/test/Shell/SymbolFile/add-dsym.test index 52d1a13..9695ddc 100644 --- a/lldb/test/Shell/SymbolFile/add-dsym.test +++ b/lldb/test/Shell/SymbolFile/add-dsym.test @@ -4,5 +4,5 @@ # HELP: Syntax: add-dsym <cmd-options> <filename> # RUN: yaml2obj %S/Inputs/a.yaml -o %t.out -# RUN: LLDB_APPLE_DSYMFORUUID_EXECUTABLE=%S/Inputs/dsymforuuid.sh %lldb %t.out -o 'add-dsym -u 41945CA4-5D9D-3CDE-82B4-37E4C09750B5' 2>&1 | FileCheck %s +# RUN: env LLDB_APPLE_DSYMFORUUID_EXECUTABLE=%S/Inputs/dsymforuuid.sh %lldb %t.out -o 'add-dsym -u 41945CA4-5D9D-3CDE-82B4-37E4C09750B5' 2>&1 | FileCheck %s # CHECK: UUID information was not found diff --git a/lldb/tools/lldb-mcp/lldb-mcp.cpp b/lldb/tools/lldb-mcp/lldb-mcp.cpp index 1f82af9..6c4ebba 100644 --- a/lldb/tools/lldb-mcp/lldb-mcp.cpp +++ b/lldb/tools/lldb-mcp/lldb-mcp.cpp @@ -67,9 +67,10 @@ int main(int argc, char *argv[]) { [](MainLoopBase &loop) { loop.RequestTermination(); }); }); - auto transport_up = std::make_unique<lldb_protocol::mcp::MCPTransport>( - input, output, std::string(client_name), - [&](llvm::StringRef message) { llvm::errs() << message << '\n'; }); + auto transport_up = std::make_unique<lldb_protocol::mcp::Transport>( + input, output, [&](llvm::StringRef message) { + llvm::errs() << formatv("{0}: {1}", client_name, message) << '\n'; + }); auto instance_up = std::make_unique<lldb_protocol::mcp::Server>( std::string(kName), std::string(kVersion), std::move(transport_up), loop); diff --git a/lldb/unittests/Protocol/ProtocolMCPServerTest.cpp b/lldb/unittests/Protocol/ProtocolMCPServerTest.cpp index 9fa4461..f686255 100644 --- a/lldb/unittests/Protocol/ProtocolMCPServerTest.cpp +++ b/lldb/unittests/Protocol/ProtocolMCPServerTest.cpp @@ -21,6 +21,7 @@ #include "lldb/Protocol/MCP/Resource.h" #include "lldb/Protocol/MCP/Server.h" #include "lldb/Protocol/MCP/Tool.h" +#include "lldb/Protocol/MCP/Transport.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Support/JSON.h" @@ -36,19 +37,6 @@ using namespace lldb_private; using namespace lldb_protocol::mcp; namespace { -class TestMCPTransport final : public MCPTransport { -public: - TestMCPTransport(lldb::IOObjectSP in, lldb::IOObjectSP out) - : lldb_protocol::mcp::MCPTransport(in, out, "unittest") {} - - using MCPTransport::Write; - - void Log(llvm::StringRef message) override { - log_messages.emplace_back(message); - } - - std::vector<std::string> log_messages; -}; class TestServer : public Server { public: @@ -134,7 +122,7 @@ class ProtocolServerMCPTest : public PipePairTest { public: SubsystemRAII<FileSystem, HostInfo, Socket> subsystems; - std::unique_ptr<TestMCPTransport> transport_up; + std::unique_ptr<lldb_protocol::mcp::Transport> transport_up; std::unique_ptr<TestServer> server_up; MainLoop loop; MockMessageHandler<Request, Response, Notification> message_handler; @@ -163,7 +151,7 @@ public: void SetUp() override { PipePairTest::SetUp(); - transport_up = std::make_unique<TestMCPTransport>( + transport_up = std::make_unique<lldb_protocol::mcp::Transport>( std::make_shared<NativeFile>(input.GetReadFileDescriptor(), File::eOpenOptionReadOnly, NativeFile::Unowned), @@ -173,7 +161,7 @@ public: server_up = std::make_unique<TestServer>( "lldb-mcp", "0.1.0", - std::make_unique<TestMCPTransport>( + std::make_unique<lldb_protocol::mcp::Transport>( std::make_shared<NativeFile>(output.GetReadFileDescriptor(), File::eOpenOptionReadOnly, NativeFile::Unowned), diff --git a/llvm/docs/CodeGenerator.rst b/llvm/docs/CodeGenerator.rst index eda8bf6..7486054 100644 --- a/llvm/docs/CodeGenerator.rst +++ b/llvm/docs/CodeGenerator.rst @@ -90,8 +90,8 @@ This design has two important implications. The first is that LLVM can support completely non-traditional code generation targets. For example, the C backend does not require register allocation, instruction selection, or any of the other standard components provided by the system. As such, it only implements these -two interfaces, and does its own thing. Note that C backend was removed from the -trunk since LLVM 3.1 release. Another example of a code generator like this is a +two interfaces, and does its own thing. Note that the C backend was removed from the +trunk in the LLVM 3.1 release. Another example of a code generator like this is a (purely hypothetical) backend that converts LLVM to the GCC RTL form and uses GCC to emit machine code for a target. @@ -565,7 +565,7 @@ Conceptually a MI bundle is a MI with a number of other MIs nested within: MI bundle support does not change the physical representations of MachineBasicBlock and MachineInstr. All the MIs (including top level and nested ones) are stored as sequential list of MIs. The "bundled" MIs are marked with -the 'InsideBundle' flag. A top level MI with the special BUNDLE opcode is used +the 'InsideBundle' flag. A top-level MI with the special BUNDLE opcode is used to represent the start of a bundle. It's legal to mix BUNDLE MIs with individual MIs that are not inside bundles nor represent bundles. @@ -575,7 +575,7 @@ The MachineBasicBlock iterator has been modified to skip over bundled MIs to enforce the bundle-as-a-single-unit concept. An alternative iterator instr_iterator has been added to MachineBasicBlock to allow passes to iterate over all of the MIs in a MachineBasicBlock, including those which are nested -inside bundles. The top level BUNDLE instruction must have the correct set of +inside bundles. The top-level BUNDLE instruction must have the correct set of register MachineOperand's that represent the cumulative inputs and outputs of the bundled MIs. @@ -602,7 +602,7 @@ level, devoid of "high level" information like "constant pools", "jump tables", "global variables" or anything like that. At this level, LLVM handles things like label names, machine instructions, and sections in the object file. The code in this layer is used for a number of important purposes: the tail end of -the code generator uses it to write a .s or .o file, and it is also used by the +the code generator uses it to write a ``.s`` or ``.o`` file, and it is also used by the llvm-mc tool to implement standalone machine code assemblers and disassemblers. This section describes some of the important classes. There are also a number @@ -615,8 +615,8 @@ The ``MCStreamer`` API ---------------------- MCStreamer is best thought of as an assembler API. It is an abstract API which -is *implemented* in different ways (e.g. to output a .s file, output an ELF .o -file, etc) but whose API correspond directly to what you see in a .s file. +is *implemented* in different ways (e.g. to output a ``.s`` file, output an ELF ``.o`` +file, etc) but whose API corresponds directly to what you see in a ``.s`` file. MCStreamer has one method per directive, such as EmitLabel, EmitSymbolAttribute, switchSection, emitValue (for .byte, .word), etc, which directly correspond to assembly level directives. It also has an EmitInstruction method, which is used @@ -629,7 +629,7 @@ higher level LLVM IR and Machine* constructs down to the MC layer, emitting directives through MCStreamer. On the implementation side of MCStreamer, there are two major implementations: -one for writing out a .s file (MCAsmStreamer), and one for writing out a .o +one for writing out a ``.s`` file (MCAsmStreamer), and one for writing out a ``.o`` file (MCObjectStreamer). MCAsmStreamer is a straightforward implementation that prints out a directive for each method (e.g. ``EmitValue -> .byte``), but MCObjectStreamer implements a full assembler. @@ -639,7 +639,7 @@ Each target that needs it defines a class that inherits from it and is a lot like MCStreamer itself: It has one method per directive and two classes that inherit from it, a target object streamer and a target asm streamer. The target asm streamer just prints it (``emitFnStart -> .fnstart``), and the object -streamer implement the assembler logic for it. +streamer implements the assembler logic for it. To make llvm use these classes, the target initialization must call TargetRegistry::RegisterAsmStreamer and TargetRegistry::RegisterMCObjectStreamer @@ -667,7 +667,7 @@ MCSymbols are created by MCContext and uniqued there. This means that MCSymbols can be compared for pointer equivalence to find out if they are the same symbol. Note that pointer inequality does not guarantee the labels will end up at different addresses though. It's perfectly legal to output something like this -to the .s file: +to the ``.s`` file: :: @@ -685,7 +685,7 @@ subclassed by object file specific implementations (e.g. ``MCSectionMachO``, ``MCSectionCOFF``, ``MCSectionELF``) and these are created and uniqued by MCContext. The MCStreamer has a notion of the current section, which can be changed with the SwitchToSection method (which corresponds to a ".section" -directive in a .s file). +directive in a ``.s`` file). .. _MCInst: @@ -887,7 +887,7 @@ bundled into a single scheduling-unit node, and with immediate operands and other nodes that aren't relevant for scheduling omitted. The option ``-filter-view-dags`` allows to select the name of the basic block -that you are interested to visualize and filters all the previous +that you are interested in visualizing and filters all the previous ``view-*-dags`` options. .. _Build initial DAG: @@ -944,7 +944,7 @@ The Legalize phase is in charge of converting a DAG to only use the operations that are natively supported by the target. Targets often have weird constraints, such as not supporting every operation on -every supported datatype (e.g. X86 does not support byte conditional moves and +every supported data type (e.g. X86 does not support byte conditional moves and PowerPC does not support sign-extending loads from a 16-bit memory location). Legalize takes care of this by open-coding another sequence of operations to emulate the operation ("expansion"), by promoting one type to a larger type that @@ -1077,7 +1077,7 @@ for your target. It has the following strengths: if your patterns make sense or not. * It can handle arbitrary constraints on operands for the pattern match. In - particular, it is straight-forward to say things like "match any immediate + particular, it is straightforward to say things like "match any immediate that is a 13-bit sign-extended value". For examples, see the ``immSExt16`` and related ``tblgen`` classes in the PowerPC backend. @@ -1615,7 +1615,7 @@ Since the MC layer works at the level of abstraction of object files, it doesn't have a notion of functions, global variables etc. Instead, it thinks about labels, directives, and instructions. A key class used at this time is the MCStreamer class. This is an abstract API that is implemented in different ways -(e.g. to output a .s file, output an ELF .o file, etc) that is effectively an +(e.g. to output a ``.s`` file, output an ELF ``.o`` file, etc) that is effectively an "assembler API". MCStreamer has one method per directive, such as EmitLabel, EmitSymbolAttribute, switchSection, etc, which directly correspond to assembly level directives. @@ -1648,7 +1648,7 @@ three important things that you have to implement for your target: Finally, at your choosing, you can also implement a subclass of MCCodeEmitter which lowers MCInst's into machine code bytes and relocations. This is -important if you want to support direct .o file emission, or would like to +important if you want to support direct ``.o`` file emission, or would like to implement an assembler for your target. Emitting function stack size information @@ -1678,7 +1678,7 @@ Instructions in a VLIW target can typically be mapped to multiple functional units. During the process of packetizing, the compiler must be able to reason about whether an instruction can be added to a packet. This decision can be complex since the compiler has to examine all possible mappings of instructions -to functional units. Therefore to alleviate compilation-time complexity, the +to functional units. Therefore, to alleviate compilation-time complexity, the VLIW packetizer parses the instruction classes of a target and generates tables at compiler build time. These tables can then be queried by the provided machine-independent API to determine if an instruction can be accommodated in a @@ -1729,7 +1729,7 @@ Instruction Alias Processing ---------------------------- Once the instruction is parsed, it enters the MatchInstructionImpl function. -The MatchInstructionImpl function performs alias processing and then does actual +The MatchInstructionImpl function performs alias processing and then performs actual matching. Alias processing is the phase that canonicalizes different lexical forms of the @@ -1934,7 +1934,7 @@ following constraints are met: * Caller and callee have matching return type or the callee result is not used. -* If any of the callee arguments are being passed in stack, they must be +* If any of the callee arguments are being passed on the stack, they must be available in caller's own incoming argument stack and the frame offsets must be the same. @@ -2074,7 +2074,7 @@ character per operand with an optional special size. For example: The PowerPC backend ------------------- -The PowerPC code generator lives in the lib/Target/PowerPC directory. The code +The PowerPC code generator lives in the ``lib/Target/PowerPC`` directory. The code generation is retargetable to several variations or *subtargets* of the PowerPC ISA; including ppc32, ppc64 and altivec. @@ -2140,7 +2140,7 @@ previous frame pointer (r31.) The entries in the linkage area are the size of a GPR, thus the linkage area is 24 bytes long in 32-bit mode and 48 bytes in 64-bit mode. -32 bit linkage area: +32-bit linkage area: :raw-html:`<table border="1" cellspacing="0">` :raw-html:`<tr>` @@ -2169,7 +2169,7 @@ GPR, thus the linkage area is 24 bytes long in 32-bit mode and 48 bytes in :raw-html:`</tr>` :raw-html:`</table>` -64 bit linkage area: +64-bit linkage area: :raw-html:`<table border="1" cellspacing="0">` :raw-html:`<tr>` diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst index eefd76d..b055327 100644 --- a/llvm/docs/GlobalISel/GenericOpcode.rst +++ b/llvm/docs/GlobalISel/GenericOpcode.rst @@ -1150,6 +1150,15 @@ An alignment value of `0` or `1` means no specific alignment. %8:_(p0) = G_DYN_STACKALLOC %7(s64), 32 +G_FREEZE +^^^^^^^^ + +G_FREEZE is used to stop propagation of undef and poison values. + +.. code-block:: none + + %1:_(s32) = G_FREEZE %0(s32) + Optimization Hints ------------------ diff --git a/llvm/include/llvm/ADT/DenseMapInfo.h b/llvm/include/llvm/ADT/DenseMapInfo.h index ec7a116..b91a908 100644 --- a/llvm/include/llvm/ADT/DenseMapInfo.h +++ b/llvm/include/llvm/ADT/DenseMapInfo.h @@ -179,41 +179,35 @@ template <typename... Ts> struct DenseMapInfo<std::tuple<Ts...>> { return Tuple(DenseMapInfo<Ts>::getTombstoneKey()...); } - template <unsigned I> - static unsigned getHashValueImpl(const Tuple &values, std::false_type) { - using EltType = std::tuple_element_t<I, Tuple>; - std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd; - return detail::combineHashValue( - DenseMapInfo<EltType>::getHashValue(std::get<I>(values)), - getHashValueImpl<I + 1>(values, atEnd)); - } - - template <unsigned I> - static unsigned getHashValueImpl(const Tuple &, std::true_type) { - return 0; + template <unsigned I> static unsigned getHashValueImpl(const Tuple &values) { + if constexpr (I == sizeof...(Ts)) { + return 0; + } else { + using EltType = std::tuple_element_t<I, Tuple>; + return detail::combineHashValue( + DenseMapInfo<EltType>::getHashValue(std::get<I>(values)), + getHashValueImpl<I + 1>(values)); + } } static unsigned getHashValue(const std::tuple<Ts...> &values) { - std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd; - return getHashValueImpl<0>(values, atEnd); + return getHashValueImpl<0>(values); } template <unsigned I> - static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs, std::false_type) { - using EltType = std::tuple_element_t<I, Tuple>; - std::integral_constant<bool, I + 1 == sizeof...(Ts)> atEnd; - return DenseMapInfo<EltType>::isEqual(std::get<I>(lhs), std::get<I>(rhs)) && - isEqualImpl<I + 1>(lhs, rhs, atEnd); - } - - template <unsigned I> - static bool isEqualImpl(const Tuple &, const Tuple &, std::true_type) { - return true; + static bool isEqualImpl(const Tuple &lhs, const Tuple &rhs) { + if constexpr (I == sizeof...(Ts)) { + return true; + } else { + using EltType = std::tuple_element_t<I, Tuple>; + return DenseMapInfo<EltType>::isEqual(std::get<I>(lhs), + std::get<I>(rhs)) && + isEqualImpl<I + 1>(lhs, rhs); + } } static bool isEqual(const Tuple &lhs, const Tuple &rhs) { - std::integral_constant<bool, 0 == sizeof...(Ts)> atEnd; - return isEqualImpl<0>(lhs, rhs, atEnd); + return isEqualImpl<0>(lhs, rhs); } }; diff --git a/llvm/include/llvm/ADT/EnumeratedArray.h b/llvm/include/llvm/ADT/EnumeratedArray.h index fd0700c..93e1327 100644 --- a/llvm/include/llvm/ADT/EnumeratedArray.h +++ b/llvm/include/llvm/ADT/EnumeratedArray.h @@ -57,8 +57,7 @@ public: } ValueType &operator[](Enumeration Index) { return const_cast<ValueType &>( - static_cast<const EnumeratedArray<ValueType, Enumeration, LargestEnum, - IndexType, Size> &>(*this)[Index]); + static_cast<const EnumeratedArray &>(*this)[Index]); } IndexType size() const { return Size; } bool empty() const { return size() == 0; } diff --git a/llvm/include/llvm/Analysis/HashRecognize.h b/llvm/include/llvm/Analysis/HashRecognize.h index 0361dfc..6dea3d2 100644 --- a/llvm/include/llvm/Analysis/HashRecognize.h +++ b/llvm/include/llvm/Analysis/HashRecognize.h @@ -20,18 +20,12 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/Value.h" -#include "llvm/Support/KnownBits.h" #include <variant> namespace llvm { class LPMUpdater; -/// A tuple of bits that are expected to be zero, number N of them expected to -/// be zero, with a boolean indicating whether it's the top or bottom N bits -/// expected to be zero. -using ErrBits = std::tuple<KnownBits, unsigned, bool>; - /// A custom std::array with 256 entries, that also has a print function. struct CRCTable : public std::array<APInt, 256> { void print(raw_ostream &OS) const; @@ -85,7 +79,7 @@ public: HashRecognize(const Loop &L, ScalarEvolution &SE); // The main analysis entry points. - std::variant<PolynomialInfo, ErrBits, StringRef> recognizeCRC() const; + std::variant<PolynomialInfo, StringRef> recognizeCRC() const; std::optional<PolynomialInfo> getResult() const; // Auxilary entry point after analysis to interleave the generating polynomial diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index d68be03..2cb7890 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -2284,6 +2284,14 @@ m_ZExtOrSExtOrSelf(const OpTy &Op) { } template <typename OpTy> +inline match_combine_or<match_combine_or<CastInst_match<OpTy, ZExtInst>, + CastInst_match<OpTy, TruncInst>>, + OpTy> +m_ZExtOrTruncOrSelf(const OpTy &Op) { + return m_CombineOr(m_CombineOr(m_ZExt(Op), m_Trunc(Op)), Op); +} + +template <typename OpTy> inline CastInst_match<OpTy, UIToFPInst> m_UIToFP(const OpTy &Op) { return CastInst_match<OpTy, UIToFPInst>(Op); } diff --git a/llvm/include/llvm/Support/ReverseIteration.h b/llvm/include/llvm/Support/ReverseIteration.h index 9e94118..1a42ff3 100644 --- a/llvm/include/llvm/Support/ReverseIteration.h +++ b/llvm/include/llvm/Support/ReverseIteration.h @@ -6,8 +6,7 @@ namespace llvm { -template<class T = void *> -bool shouldReverseIterate() { +template <class T = void *> constexpr bool shouldReverseIterate() { #if LLVM_ENABLE_REVERSE_ITERATION return detail::IsPointerLike<T>::value; #else diff --git a/llvm/lib/Analysis/HashRecognize.cpp b/llvm/lib/Analysis/HashRecognize.cpp index 92c9e37..5b3448f 100644 --- a/llvm/lib/Analysis/HashRecognize.cpp +++ b/llvm/lib/Analysis/HashRecognize.cpp @@ -73,202 +73,31 @@ using namespace SCEVPatternMatch; #define DEBUG_TYPE "hash-recognize" -// KnownBits for a PHI node. There are at most two PHI nodes, corresponding to -// the Simple Recurrence and Conditional Recurrence. The IndVar PHI is not -// relevant. -using KnownPhiMap = SmallDenseMap<const PHINode *, KnownBits, 2>; - -// A pair of a PHI node along with its incoming value from within a loop. -using PhiStepPair = std::pair<const PHINode *, const Instruction *>; - -/// A much simpler version of ValueTracking, in that it computes KnownBits of -/// values, except that it computes the evolution of KnownBits in a loop with a -/// given trip count, and predication is specialized for a significant-bit -/// check. -class ValueEvolution { - const unsigned TripCount; - const bool ByteOrderSwapped; - APInt GenPoly; - StringRef ErrStr; - - // Compute the KnownBits of a BinaryOperator. - KnownBits computeBinOp(const BinaryOperator *I); - - // Compute the KnownBits of an Instruction. - KnownBits computeInstr(const Instruction *I); - - // Compute the KnownBits of a Value. - KnownBits compute(const Value *V); - -public: - // ValueEvolution is meant to be constructed with the TripCount of the loop, - // and a boolean indicating whether the polynomial algorithm is big-endian - // (for the significant-bit check). - ValueEvolution(unsigned TripCount, bool ByteOrderSwapped); - - // Given a list of PHI nodes along with their incoming value from within the - // loop, computeEvolutions computes the KnownBits of each of the PHI nodes on - // the final iteration. Returns true on success and false on error. - bool computeEvolutions(ArrayRef<PhiStepPair> PhiEvolutions); - - // In case ValueEvolution encounters an error, this is meant to be used for a - // precise error message. - StringRef getError() const { return ErrStr; } - - // A set of Instructions visited by ValueEvolution. The only unvisited - // instructions will be ones not on the use-def chain of the PHIs' evolutions. +/// Checks if there's a stray instruction in the loop \p L outside of the +/// use-def chains from \p Roots, or if we escape the loop during the use-def +/// walk. +static bool containsUnreachable(const Loop &L, + ArrayRef<const Instruction *> Roots) { SmallPtrSet<const Instruction *, 16> Visited; + BasicBlock *Latch = L.getLoopLatch(); - // The computed KnownBits for each PHI node, which is populated after - // computeEvolutions is called. - KnownPhiMap KnownPhis; -}; - -ValueEvolution::ValueEvolution(unsigned TripCount, bool ByteOrderSwapped) - : TripCount(TripCount), ByteOrderSwapped(ByteOrderSwapped) {} - -KnownBits ValueEvolution::computeBinOp(const BinaryOperator *I) { - KnownBits KnownL(compute(I->getOperand(0))); - KnownBits KnownR(compute(I->getOperand(1))); - - switch (I->getOpcode()) { - case Instruction::BinaryOps::And: - return KnownL & KnownR; - case Instruction::BinaryOps::Or: - return KnownL | KnownR; - case Instruction::BinaryOps::Xor: - return KnownL ^ KnownR; - case Instruction::BinaryOps::Shl: { - auto *OBO = cast<OverflowingBinaryOperator>(I); - return KnownBits::shl(KnownL, KnownR, OBO->hasNoUnsignedWrap(), - OBO->hasNoSignedWrap()); - } - case Instruction::BinaryOps::LShr: - return KnownBits::lshr(KnownL, KnownR); - case Instruction::BinaryOps::AShr: - return KnownBits::ashr(KnownL, KnownR); - case Instruction::BinaryOps::Add: { - auto *OBO = cast<OverflowingBinaryOperator>(I); - return KnownBits::add(KnownL, KnownR, OBO->hasNoUnsignedWrap(), - OBO->hasNoSignedWrap()); - } - case Instruction::BinaryOps::Sub: { - auto *OBO = cast<OverflowingBinaryOperator>(I); - return KnownBits::sub(KnownL, KnownR, OBO->hasNoUnsignedWrap(), - OBO->hasNoSignedWrap()); - } - case Instruction::BinaryOps::Mul: { - Value *Op0 = I->getOperand(0); - Value *Op1 = I->getOperand(1); - bool SelfMultiply = Op0 == Op1 && isGuaranteedNotToBeUndef(Op0); - return KnownBits::mul(KnownL, KnownR, SelfMultiply); - } - case Instruction::BinaryOps::UDiv: - return KnownBits::udiv(KnownL, KnownR); - case Instruction::BinaryOps::SDiv: - return KnownBits::sdiv(KnownL, KnownR); - case Instruction::BinaryOps::URem: - return KnownBits::urem(KnownL, KnownR); - case Instruction::BinaryOps::SRem: - return KnownBits::srem(KnownL, KnownR); - default: - ErrStr = "Unknown BinaryOperator"; - unsigned BitWidth = I->getType()->getScalarSizeInBits(); - return {BitWidth}; - } -} - -KnownBits ValueEvolution::computeInstr(const Instruction *I) { - unsigned BitWidth = I->getType()->getScalarSizeInBits(); - - // computeInstr is the only entry-point that needs to update the Visited set. - Visited.insert(I); + SmallVector<const Instruction *, 16> Worklist(Roots); + while (!Worklist.empty()) { + const Instruction *I = Worklist.pop_back_val(); + Visited.insert(I); - // We look up in the map that contains the KnownBits of the PHI from the - // previous iteration. - if (const PHINode *P = dyn_cast<PHINode>(I)) - return KnownPhis.lookup_or(P, BitWidth); + if (isa<PHINode>(I)) + continue; - // Compute the KnownBits for a Select(Cmp()), forcing it to take the branch - // that is predicated on the (least|most)-significant-bit check. - CmpPredicate Pred; - Value *L, *R; - Instruction *TV, *FV; - if (match(I, m_Select(m_ICmp(Pred, m_Value(L), m_Value(R)), m_Instruction(TV), - m_Instruction(FV)))) { - Visited.insert(cast<Instruction>(I->getOperand(0))); - - // We need to check LCR against [0, 2) in the little-endian case, because - // the RCR check is insufficient: it is simply [0, 1). - if (!ByteOrderSwapped) { - KnownBits KnownL = compute(L); - unsigned ICmpBW = KnownL.getBitWidth(); - auto LCR = ConstantRange::fromKnownBits(KnownL, false); - auto CheckLCR = ConstantRange(APInt::getZero(ICmpBW), APInt(ICmpBW, 2)); - if (LCR != CheckLCR) { - ErrStr = "Bad LHS of significant-bit-check"; - return {BitWidth}; + for (const Use &U : I->operands()) { + if (auto *UI = dyn_cast<Instruction>(U)) { + if (!L.contains(UI)) + return true; + Worklist.push_back(UI); } } - - // Check that the predication is on (most|least) significant bit. - KnownBits KnownR = compute(R); - unsigned ICmpBW = KnownR.getBitWidth(); - auto RCR = ConstantRange::fromKnownBits(KnownR, false); - auto AllowedR = ConstantRange::makeAllowedICmpRegion(Pred, RCR); - ConstantRange CheckRCR(APInt::getZero(ICmpBW), - ByteOrderSwapped ? APInt::getSignedMinValue(ICmpBW) - : APInt(ICmpBW, 1)); - - // We only compute KnownBits of either TV or FV, as the other value would - // just be a bit-shift as checked by isBigEndianBitShift. - if (AllowedR == CheckRCR) { - Visited.insert(FV); - return compute(TV); - } - if (AllowedR.inverse() == CheckRCR) { - Visited.insert(TV); - return compute(FV); - } - - ErrStr = "Bad RHS of significant-bit-check"; - return {BitWidth}; } - - if (auto *BO = dyn_cast<BinaryOperator>(I)) - return computeBinOp(BO); - - switch (I->getOpcode()) { - case Instruction::CastOps::Trunc: - return compute(I->getOperand(0)).trunc(BitWidth); - case Instruction::CastOps::ZExt: - return compute(I->getOperand(0)).zext(BitWidth); - case Instruction::CastOps::SExt: - return compute(I->getOperand(0)).sext(BitWidth); - default: - ErrStr = "Unknown Instruction"; - return {BitWidth}; - } -} - -KnownBits ValueEvolution::compute(const Value *V) { - if (auto *CI = dyn_cast<ConstantInt>(V)) - return KnownBits::makeConstant(CI->getValue()); - - if (auto *I = dyn_cast<Instruction>(V)) - return computeInstr(I); - - ErrStr = "Unknown Value"; - unsigned BitWidth = V->getType()->getScalarSizeInBits(); - return {BitWidth}; -} - -bool ValueEvolution::computeEvolutions(ArrayRef<PhiStepPair> PhiEvolutions) { - for (unsigned I = 0; I < TripCount; ++I) - for (auto [Phi, Step] : PhiEvolutions) - KnownPhis.emplace_or_assign(Phi, computeInstr(Step)); - - return ErrStr.empty(); + return std::distance(Latch->begin(), Latch->end()) != Visited.size(); } /// A structure that can hold either a Simple Recurrence or a Conditional @@ -320,6 +149,62 @@ private: Instruction::BinaryOps BOWithConstOpToMatch = Instruction::BinaryOpsEnd); }; +/// Check the well-formedness of the (most|least) significant bit check given \p +/// ConditionalRecurrence, \p SimpleRecurrence, depending on \p +/// ByteOrderSwapped. We check that ConditionalRecurrence.Step is a +/// Select(Cmp()) where the compare is `>= 0` in the big-endian case, and `== 0` +/// in the little-endian case (or the inverse, in which case the branches of the +/// compare are swapped). We check that the LHS is (ConditionalRecurrence.Phi +/// [xor SimpleRecurrence.Phi]) in the big-endian case, and additionally check +/// for an AND with one in the little-endian case. We then check AllowedByR +/// against CheckAllowedByR, which is [0, smin) in the big-endian case, and is +/// [0, 1) in the little-endian case. CheckAllowedByR checks for +/// significant-bit-clear, and we match the corresponding arms of the select +/// against bit-shift and bit-shift-and-xor-gen-poly. +static bool +isSignificantBitCheckWellFormed(const RecurrenceInfo &ConditionalRecurrence, + const RecurrenceInfo &SimpleRecurrence, + bool ByteOrderSwapped) { + auto *SI = cast<SelectInst>(ConditionalRecurrence.Step); + CmpPredicate Pred; + const Value *L; + const APInt *R; + Instruction *TV, *FV; + if (!match(SI, m_Select(m_ICmp(Pred, m_Value(L), m_APInt(R)), + m_Instruction(TV), m_Instruction(FV)))) + return false; + + // Match predicate with or without a SimpleRecurrence (the corresponding data + // is LHSAux). + auto MatchPred = m_CombineOr( + m_Specific(ConditionalRecurrence.Phi), + m_c_Xor(m_ZExtOrTruncOrSelf(m_Specific(ConditionalRecurrence.Phi)), + m_ZExtOrTruncOrSelf(m_Specific(SimpleRecurrence.Phi)))); + bool LWellFormed = ByteOrderSwapped ? match(L, MatchPred) + : match(L, m_c_And(MatchPred, m_One())); + if (!LWellFormed) + return false; + + KnownBits KnownR = KnownBits::makeConstant(*R); + unsigned BW = KnownR.getBitWidth(); + auto RCR = ConstantRange::fromKnownBits(KnownR, false); + auto AllowedByR = ConstantRange::makeAllowedICmpRegion(Pred, RCR); + ConstantRange CheckAllowedByR(APInt::getZero(BW), + ByteOrderSwapped ? APInt::getSignedMinValue(BW) + : APInt(BW, 1)); + + BinaryOperator *BitShift = ConditionalRecurrence.BO; + if (AllowedByR == CheckAllowedByR) + return TV == BitShift && + match(FV, m_c_Xor(m_Specific(BitShift), + m_SpecificInt(*ConditionalRecurrence.ExtraConst))); + if (AllowedByR.inverse() == CheckAllowedByR) + return FV == BitShift && + match(TV, m_c_Xor(m_Specific(BitShift), + m_SpecificInt(*ConditionalRecurrence.ExtraConst))); + return false; +} + /// Wraps llvm::matchSimpleRecurrence. Match a simple first order recurrence /// cycle of the form: /// @@ -336,8 +221,11 @@ private: /// %BO = binop %step, %rec /// bool RecurrenceInfo::matchSimpleRecurrence(const PHINode *P) { - Phi = P; - return llvm::matchSimpleRecurrence(Phi, BO, Start, Step); + if (llvm::matchSimpleRecurrence(P, BO, Start, Step)) { + Phi = P; + return true; + } + return false; } /// Digs for a recurrence starting with \p V hitting the PHI node in a use-def @@ -459,26 +347,6 @@ PolynomialInfo::PolynomialInfo(unsigned TripCount, Value *LHS, const APInt &RHS, : TripCount(TripCount), LHS(LHS), RHS(RHS), ComputedValue(ComputedValue), ByteOrderSwapped(ByteOrderSwapped), LHSAux(LHSAux) {} -/// In the big-endian case, checks the bottom N bits against CheckFn, and that -/// the rest are unknown. In the little-endian case, checks the top N bits -/// against CheckFn, and that the rest are unknown. Callers usually call this -/// function with N = TripCount, and CheckFn checking that the remainder bits of -/// the CRC polynomial division are zero. -static bool checkExtractBits(const KnownBits &Known, unsigned N, - function_ref<bool(const KnownBits &)> CheckFn, - bool ByteOrderSwapped) { - // Check that the entire thing is a constant. - if (N == Known.getBitWidth()) - return CheckFn(Known.extractBits(N, 0)); - - // Check that the {top, bottom} N bits are not unknown and that the {bottom, - // top} N bits are known. - unsigned BitPos = ByteOrderSwapped ? 0 : Known.getBitWidth() - N; - unsigned SwappedBitPos = ByteOrderSwapped ? N : 0; - return CheckFn(Known.extractBits(N, BitPos)) && - Known.extractBits(Known.getBitWidth() - N, SwappedBitPos).isUnknown(); -} - /// Generate a lookup table of 256 entries by interleaving the generating /// polynomial. The optimization technique of table-lookup for CRC is also /// called the Sarwate algorithm. @@ -511,8 +379,6 @@ CRCTable HashRecognize::genSarwateTable(const APInt &GenPoly, /// Checks that \p P1 and \p P2 are used together in an XOR in the use-def chain /// of \p SI's condition, ignoring any casts. The purpose of this function is to /// ensure that LHSAux from the SimpleRecurrence is used correctly in the CRC -/// computation. We cannot check the correctness of casts at this point, and -/// rely on the KnownBits propagation to check correctness of the CRC /// computation. /// /// In other words, it checks for the following pattern: @@ -540,8 +406,8 @@ static bool isConditionalOnXorOfPHIs(const SelectInst *SI, const PHINode *P1, continue; // If we match an XOR of the two PHIs ignoring casts, we're done. - if (match(I, m_c_Xor(m_CastOrSelf(m_Specific(P1)), - m_CastOrSelf(m_Specific(P2))))) + if (match(I, m_c_Xor(m_ZExtOrTruncOrSelf(m_Specific(P1)), + m_ZExtOrTruncOrSelf(m_Specific(P2))))) return true; // Continue along the use-def chain. @@ -570,10 +436,8 @@ static std::optional<bool> isBigEndianBitShift(Value *V, ScalarEvolution &SE) { } /// The main entry point for analyzing a loop and recognizing the CRC algorithm. -/// Returns a PolynomialInfo on success, and either an ErrBits or a StringRef on -/// failure. -std::variant<PolynomialInfo, ErrBits, StringRef> -HashRecognize::recognizeCRC() const { +/// Returns a PolynomialInfo on success, and a StringRef on failure. +std::variant<PolynomialInfo, StringRef> HashRecognize::recognizeCRC() const { if (!L.isInnermost()) return "Loop is not innermost"; BasicBlock *Latch = L.getLoopLatch(); @@ -637,36 +501,19 @@ HashRecognize::recognizeCRC() const { "Expected ExtraConst in conditional recurrence"); const APInt &GenPoly = *ConditionalRecurrence.ExtraConst; - // PhiEvolutions are pairs of PHINodes along with their incoming value from - // within the loop, which we term as their step. Note that in the case of a - // Simple Recurrence, Step is an operand of the BO, while in a Conditional - // Recurrence, it is a SelectInst. - SmallVector<PhiStepPair, 2> PhiEvolutions; - PhiEvolutions.emplace_back(ConditionalRecurrence.Phi, ComputedValue); + if (!isSignificantBitCheckWellFormed(ConditionalRecurrence, SimpleRecurrence, + *ByteOrderSwapped)) + return "Malformed significant-bit check"; + + SmallVector<const Instruction *> Roots( + {ComputedValue, + cast<Instruction>(IndVar->getIncomingValueForBlock(Latch)), + L.getLatchCmpInst(), Latch->getTerminator()}); if (SimpleRecurrence) - PhiEvolutions.emplace_back(SimpleRecurrence.Phi, SimpleRecurrence.BO); - - ValueEvolution VE(TC, *ByteOrderSwapped); - if (!VE.computeEvolutions(PhiEvolutions)) - return VE.getError(); - KnownBits ResultBits = VE.KnownPhis.at(ConditionalRecurrence.Phi); - - // There must be exactly four unvisited instructions, corresponding to the - // IndVar PHI. Any other unvisited instructions from the KnownBits propagation - // can complicate the optimization, which replaces the entire loop with the - // table-lookup version of the hash algorithm. - std::initializer_list<const Instruction *> AugmentVisited = { - IndVar, Latch->getTerminator(), L.getLatchCmpInst(), - cast<Instruction>(IndVar->getIncomingValueForBlock(Latch))}; - VE.Visited.insert_range(AugmentVisited); - if (std::distance(Latch->begin(), Latch->end()) != VE.Visited.size()) + Roots.push_back(SimpleRecurrence.BO); + if (containsUnreachable(L, Roots)) return "Found stray unvisited instructions"; - unsigned N = std::min(TC, ResultBits.getBitWidth()); - auto IsZero = [](const KnownBits &K) { return K.isZero(); }; - if (!checkExtractBits(ResultBits, N, IsZero, *ByteOrderSwapped)) - return ErrBits(ResultBits, TC, *ByteOrderSwapped); - return PolynomialInfo(TC, LHS, GenPoly, ComputedValue, *ByteOrderSwapped, LHSAux); } @@ -693,13 +540,6 @@ void HashRecognize::print(raw_ostream &OS) const { OS << "Did not find a hash algorithm\n"; if (std::holds_alternative<StringRef>(Ret)) OS << "Reason: " << std::get<StringRef>(Ret) << "\n"; - if (std::holds_alternative<ErrBits>(Ret)) { - auto [Actual, Iter, ByteOrderSwapped] = std::get<ErrBits>(Ret); - OS << "Reason: Expected " << (ByteOrderSwapped ? "bottom " : "top ") - << Iter << " bits zero ("; - Actual.print(OS); - OS << ")\n"; - } return; } diff --git a/llvm/lib/Target/AArch64/CMakeLists.txt b/llvm/lib/Target/AArch64/CMakeLists.txt index 803943f..833ce48 100644 --- a/llvm/lib/Target/AArch64/CMakeLists.txt +++ b/llvm/lib/Target/AArch64/CMakeLists.txt @@ -7,7 +7,9 @@ tablegen(LLVM AArch64GenAsmWriter.inc -gen-asm-writer) tablegen(LLVM AArch64GenAsmWriter1.inc -gen-asm-writer -asmwriternum=1) tablegen(LLVM AArch64GenCallingConv.inc -gen-callingconv) tablegen(LLVM AArch64GenDAGISel.inc -gen-dag-isel) -tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler) +tablegen(LLVM AArch64GenDisassemblerTables.inc -gen-disassembler + -ignore-non-decodable-operands + -ignore-fully-defined-operands) tablegen(LLVM AArch64GenFastISel.inc -gen-fast-isel) tablegen(LLVM AArch64GenGlobalISel.inc -gen-global-isel) tablegen(LLVM AArch64GenO0PreLegalizeGICombiner.inc -gen-global-isel-combiner diff --git a/llvm/lib/Target/AMDGPU/CMakeLists.txt b/llvm/lib/Target/AMDGPU/CMakeLists.txt index 05295ae..a915c40 100644 --- a/llvm/lib/Target/AMDGPU/CMakeLists.txt +++ b/llvm/lib/Target/AMDGPU/CMakeLists.txt @@ -7,7 +7,9 @@ tablegen(LLVM AMDGPUGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM AMDGPUGenCallingConv.inc -gen-callingconv) tablegen(LLVM AMDGPUGenDAGISel.inc -gen-dag-isel) tablegen(LLVM AMDGPUGenDisassemblerTables.inc -gen-disassembler - --specialize-decoders-per-bitwidth) + --specialize-decoders-per-bitwidth + -ignore-non-decodable-operands + -ignore-fully-defined-operands) tablegen(LLVM AMDGPUGenInstrInfo.inc -gen-instr-info) tablegen(LLVM AMDGPUGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM AMDGPUGenMCPseudoLowering.inc -gen-pseudo-lowering) diff --git a/llvm/lib/Target/ARM/CMakeLists.txt b/llvm/lib/Target/ARM/CMakeLists.txt index a39629b..fa778ca 100644 --- a/llvm/lib/Target/ARM/CMakeLists.txt +++ b/llvm/lib/Target/ARM/CMakeLists.txt @@ -6,7 +6,8 @@ tablegen(LLVM ARMGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM ARMGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM ARMGenCallingConv.inc -gen-callingconv) tablegen(LLVM ARMGenDAGISel.inc -gen-dag-isel) -tablegen(LLVM ARMGenDisassemblerTables.inc -gen-disassembler) +tablegen(LLVM ARMGenDisassemblerTables.inc -gen-disassembler + -ignore-non-decodable-operands) tablegen(LLVM ARMGenFastISel.inc -gen-fast-isel) tablegen(LLVM ARMGenGlobalISel.inc -gen-global-isel) tablegen(LLVM ARMGenInstrInfo.inc -gen-instr-info) diff --git a/llvm/lib/Target/AVR/AVRInstrFormats.td b/llvm/lib/Target/AVR/AVRInstrFormats.td index e1e65b5..eb4daf7 100644 --- a/llvm/lib/Target/AVR/AVRInstrFormats.td +++ b/llvm/lib/Target/AVR/AVRInstrFormats.td @@ -79,6 +79,7 @@ class FRdRr<bits<4> opcode, bits<2> f, dag outs, dag ins, string asmstr, //===----------------------------------------------------------------------===// class FZRd<bits<3> t, dag outs, dag ins, string asmstr, list<dag> pattern> : AVRInst16<outs, ins, asmstr, pattern> { + bits<0> z; bits<5> rd; let Inst{15 - 12} = 0b1001; diff --git a/llvm/lib/Target/AVR/AVRInstrInfo.td b/llvm/lib/Target/AVR/AVRInstrInfo.td index 958e138..70efda4 100644 --- a/llvm/lib/Target/AVR/AVRInstrInfo.td +++ b/llvm/lib/Target/AVR/AVRInstrInfo.td @@ -1230,7 +1230,9 @@ let Uses = [R1, R0] in { let Defs = [R31R30] in def SPMZPi : F16<0b1001010111111000, (outs), (ins ZREG:$z), "spm $z+", []>, - Requires<[HasSPMX]>; + Requires<[HasSPMX]> { + bits<0> z; + } } // Read data from IO location operations. diff --git a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp index 56b3cf7..d874697 100644 --- a/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp +++ b/llvm/lib/Target/AVR/Disassembler/AVRDisassembler.cpp @@ -91,6 +91,12 @@ static DecodeStatus DecodeLD8RegisterClass(MCInst &Inst, unsigned RegNo, return MCDisassembler::Success; } +static DecodeStatus DecodeZREGRegisterClass(MCInst &Inst, + const MCDisassembler *Decoder) { + Inst.addOperand(MCOperand::createReg(AVR::R31R30)); + return MCDisassembler::Success; +} + static DecodeStatus decodeFIOARr(MCInst &Inst, unsigned Insn, uint64_t Address, const MCDisassembler *Decoder) { unsigned addr = 0; diff --git a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp index 4812191..5adffee 100644 --- a/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp +++ b/llvm/lib/Target/AVR/MCTargetDesc/AVRInstPrinter.cpp @@ -101,23 +101,6 @@ const char *AVRInstPrinter::getPrettyRegisterName(MCRegister Reg, void AVRInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { const MCOperandInfo &MOI = this->MII.get(MI->getOpcode()).operands()[OpNo]; - if (MOI.RegClass == AVR::ZREGRegClassID) { - // Special case for the Z register, which sometimes doesn't have an operand - // in the MCInst. - O << "Z"; - return; - } - - if (OpNo >= MI->size()) { - // Not all operands are correctly disassembled at the moment. This means - // that some machine instructions won't have all the necessary operands - // set. - // To avoid asserting, print <unknown> instead until the necessary support - // has been implemented. - O << "<unknown>"; - return; - } - const MCOperand &Op = MI->getOperand(OpNo); if (Op.isReg()) { diff --git a/llvm/lib/Target/BPF/CMakeLists.txt b/llvm/lib/Target/BPF/CMakeLists.txt index eade4ca..678cb42 100644 --- a/llvm/lib/Target/BPF/CMakeLists.txt +++ b/llvm/lib/Target/BPF/CMakeLists.txt @@ -6,7 +6,8 @@ tablegen(LLVM BPFGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM BPFGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM BPFGenCallingConv.inc -gen-callingconv) tablegen(LLVM BPFGenDAGISel.inc -gen-dag-isel) -tablegen(LLVM BPFGenDisassemblerTables.inc -gen-disassembler) +tablegen(LLVM BPFGenDisassemblerTables.inc -gen-disassembler + -ignore-non-decodable-operands) tablegen(LLVM BPFGenInstrInfo.inc -gen-instr-info) tablegen(LLVM BPFGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM BPFGenRegisterInfo.inc -gen-register-info) diff --git a/llvm/lib/Target/CSKY/CMakeLists.txt b/llvm/lib/Target/CSKY/CMakeLists.txt index 4b900bc..101b34e 100644 --- a/llvm/lib/Target/CSKY/CMakeLists.txt +++ b/llvm/lib/Target/CSKY/CMakeLists.txt @@ -7,7 +7,8 @@ tablegen(LLVM CSKYGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM CSKYGenCallingConv.inc -gen-callingconv) tablegen(LLVM CSKYGenCompressInstEmitter.inc -gen-compress-inst-emitter) tablegen(LLVM CSKYGenDAGISel.inc -gen-dag-isel) -tablegen(LLVM CSKYGenDisassemblerTables.inc -gen-disassembler) +tablegen(LLVM CSKYGenDisassemblerTables.inc -gen-disassembler + -ignore-non-decodable-operands) tablegen(LLVM CSKYGenInstrInfo.inc -gen-instr-info) tablegen(LLVM CSKYGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM CSKYGenMCPseudoLowering.inc -gen-pseudo-lowering) diff --git a/llvm/lib/Target/Hexagon/CMakeLists.txt b/llvm/lib/Target/Hexagon/CMakeLists.txt index d758260..b615536 100644 --- a/llvm/lib/Target/Hexagon/CMakeLists.txt +++ b/llvm/lib/Target/Hexagon/CMakeLists.txt @@ -7,7 +7,8 @@ tablegen(LLVM HexagonGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM HexagonGenCallingConv.inc -gen-callingconv) tablegen(LLVM HexagonGenDAGISel.inc -gen-dag-isel) tablegen(LLVM HexagonGenDFAPacketizer.inc -gen-dfa-packetizer) -tablegen(LLVM HexagonGenDisassemblerTables.inc -gen-disassembler) +tablegen(LLVM HexagonGenDisassemblerTables.inc -gen-disassembler + -ignore-non-decodable-operands) tablegen(LLVM HexagonGenInstrInfo.inc -gen-instr-info) tablegen(LLVM HexagonGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM HexagonGenRegisterInfo.inc -gen-register-info) diff --git a/llvm/lib/Target/Hexagon/HexagonDepInstrFormats.td b/llvm/lib/Target/Hexagon/HexagonDepInstrFormats.td index 75e87c9..661b948 100644 --- a/llvm/lib/Target/Hexagon/HexagonDepInstrFormats.td +++ b/llvm/lib/Target/Hexagon/HexagonDepInstrFormats.td @@ -3049,7 +3049,6 @@ class Enc_cf1927 : OpcodeHexagon { class Enc_d0fe02 : OpcodeHexagon { bits <5> Rxx32; let Inst{20-16} = Rxx32{4-0}; - bits <0> sgp10; } class Enc_d15d19 : OpcodeHexagon { bits <1> Mu2; diff --git a/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp b/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp index d3ad653..4992f1a 100644 --- a/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp +++ b/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp @@ -107,6 +107,18 @@ static DecodeStatus DecodeFPCSCRegisterClass(MCInst &Inst, uint64_t RegNo, } #define DecodeFPICRegisterClass DecodeFPCSCRegisterClass +static DecodeStatus DecodeCCRCRegisterClass(MCInst &Inst, + const MCDisassembler *Decoder) { + Inst.addOperand(MCOperand::createReg(M68k::CCR)); + return DecodeStatus::Success; +} + +static DecodeStatus DecodeSRCRegisterClass(MCInst &Inst, + const MCDisassembler *Decoder) { + Inst.addOperand(MCOperand::createReg(M68k::SR)); + return DecodeStatus::Success; +} + static DecodeStatus DecodeImm32(MCInst &Inst, uint64_t Imm, uint64_t Address, const void *Decoder) { Inst.addOperand(MCOperand::createImm(M68k::swapWord<uint32_t>(Imm))); diff --git a/llvm/lib/Target/Mips/CMakeLists.txt b/llvm/lib/Target/Mips/CMakeLists.txt index 21d1765..4a2277e 100644 --- a/llvm/lib/Target/Mips/CMakeLists.txt +++ b/llvm/lib/Target/Mips/CMakeLists.txt @@ -6,7 +6,8 @@ tablegen(LLVM MipsGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM MipsGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM MipsGenCallingConv.inc -gen-callingconv) tablegen(LLVM MipsGenDAGISel.inc -gen-dag-isel) -tablegen(LLVM MipsGenDisassemblerTables.inc -gen-disassembler) +tablegen(LLVM MipsGenDisassemblerTables.inc -gen-disassembler + -ignore-non-decodable-operands) tablegen(LLVM MipsGenFastISel.inc -gen-fast-isel) tablegen(LLVM MipsGenGlobalISel.inc -gen-global-isel) tablegen(LLVM MipsGenPostLegalizeGICombiner.inc -gen-global-isel-combiner diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td index 9359311..269d303 100644 --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -1984,7 +1984,7 @@ def : Pat<(int_ppc_darnraw), (DARN 2)>; class X_RA5_RB5<bits<6> opcode, bits<10> xo, string opc, RegisterOperand ty, InstrItinClass itin, list<dag> pattern> - : X_L1_RS5_RS5<opcode, xo, (outs), (ins ty:$RA, ty:$RB, u1imm:$L), + : X_L1_RS5_RS5<opcode, xo, (outs), (ins ty:$RA, ty:$RB), !strconcat(opc, " $RA, $RB"), itin, pattern>{ let L = 1; } diff --git a/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/llvm/lib/Target/PowerPC/PPCInstrFormats.td index b4b475b4..fba1c66 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrFormats.td +++ b/llvm/lib/Target/PowerPC/PPCInstrFormats.td @@ -18,7 +18,7 @@ class I<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin> bit PPC64 = 0; // Default value, override with isPPC64 let Namespace = "PPC"; - let Inst{0-5} = opcode; + let Inst{0...5} = opcode; let OutOperandList = OOL; let InOperandList = IOL; let AsmString = asmstr; @@ -34,7 +34,7 @@ class I<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin> let TSFlags{0} = PPC970_First; let TSFlags{1} = PPC970_Single; let TSFlags{2} = PPC970_Cracked; - let TSFlags{5-3} = PPC970_Unit; + let TSFlags{5...3} = PPC970_Unit; // Indicate that this instruction is of type X-Form Load or Store bits<1> XFormMemOp = 0; @@ -99,8 +99,8 @@ class I2<bits<6> opcode1, bits<6> opcode2, dag OOL, dag IOL, string asmstr, bit PPC64 = 0; // Default value, override with isPPC64 let Namespace = "PPC"; - let Inst{0-5} = opcode1; - let Inst{32-37} = opcode2; + let Inst{0...5} = opcode1; + let Inst{32...37} = opcode2; let OutOperandList = OOL; let InOperandList = IOL; let AsmString = asmstr; @@ -116,7 +116,7 @@ class I2<bits<6> opcode1, bits<6> opcode2, dag OOL, dag IOL, string asmstr, let TSFlags{0} = PPC970_First; let TSFlags{1} = PPC970_Single; let TSFlags{2} = PPC970_Cracked; - let TSFlags{5-3} = PPC970_Unit; + let TSFlags{5...3} = PPC970_Unit; // Fields used for relation models. string BaseName = ""; @@ -135,7 +135,7 @@ class IForm<bits<6> opcode, bit aa, bit lk, dag OOL, dag IOL, string asmstr, let Pattern = pattern; bits<24> LI; - let Inst{6-29} = LI; + let Inst{6...29} = LI; let Inst{30} = aa; let Inst{31} = lk; } @@ -148,12 +148,12 @@ class BForm<bits<6> opcode, bit aa, bit lk, dag OOL, dag IOL, string asmstr> bits<14> BD; bits<5> BI; - let BI{0-1} = BIBO{5-6}; - let BI{2-4} = CR{0-2}; + let BI{0...1} = BIBO{5...6}; + let BI{2...4} = CR{0...2}; - let Inst{6-10} = BIBO{4-0}; - let Inst{11-15} = BI; - let Inst{16-29} = BD; + let Inst{6...10} = BIBO{4...0}; + let Inst{11...15} = BI; + let Inst{16...29} = BD; let Inst{30} = aa; let Inst{31} = lk; } @@ -161,8 +161,8 @@ class BForm<bits<6> opcode, bit aa, bit lk, dag OOL, dag IOL, string asmstr> class BForm_1<bits<6> opcode, bits<5> bo, bit aa, bit lk, dag OOL, dag IOL, string asmstr> : BForm<opcode, aa, lk, OOL, IOL, asmstr> { - let BIBO{4-0} = bo; - let BIBO{6-5} = 0; + let BIBO{4...0} = bo; + let BIBO{6...5} = 0; let CR = 0; } @@ -171,9 +171,9 @@ class BForm_2<bits<6> opcode, bits<5> bo, bits<5> bi, bit aa, bit lk, : I<opcode, OOL, IOL, asmstr, IIC_BrB> { bits<14> BD; - let Inst{6-10} = bo; - let Inst{11-15} = bi; - let Inst{16-29} = BD; + let Inst{6...10} = bo; + let Inst{11...15} = bi; + let Inst{16...29} = BD; let Inst{30} = aa; let Inst{31} = lk; } @@ -185,9 +185,9 @@ class BForm_3<bits<6> opcode, bit aa, bit lk, bits<5> BI; bits<14> BD; - let Inst{6-10} = BO; - let Inst{11-15} = BI; - let Inst{16-29} = BD; + let Inst{6...10} = BO; + let Inst{11...15} = BI; + let Inst{16...29} = BD; let Inst{30} = aa; let Inst{31} = lk; } @@ -200,10 +200,10 @@ class BForm_3_at<bits<6> opcode, bit aa, bit lk, bits<5> BI; bits<14> BD; - let Inst{6-8} = BO{4-2}; - let Inst{9-10} = at; - let Inst{11-15} = BI; - let Inst{16-29} = BD; + let Inst{6...8} = BO{4...2}; + let Inst{9...10} = at; + let Inst{11...15} = BI; + let Inst{16...29} = BD; let Inst{30} = aa; let Inst{31} = lk; } @@ -215,9 +215,9 @@ BForm_4<bits<6> opcode, bits<5> bo, bit aa, bit lk, bits<5> BI; bits<14> BD; - let Inst{6-10} = bo; - let Inst{11-15} = BI; - let Inst{16-29} = BD; + let Inst{6...10} = bo; + let Inst{11...15} = BI; + let Inst{16...29} = BD; let Inst{30} = aa; let Inst{31} = lk; } @@ -231,7 +231,7 @@ class SCForm<bits<6> opcode, bits<1> xo1, bits<1> xo2, let Pattern = pattern; - let Inst{20-26} = LEV; + let Inst{20...26} = LEV; let Inst{30} = xo1; let Inst{31} = xo2; } @@ -246,9 +246,9 @@ class DForm_base<bits<6> opcode, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RST; - let Inst{11-15} = RA; - let Inst{16-31} = D; + let Inst{6...10} = RST; + let Inst{11...15} = RA; + let Inst{16...31} = D; } class DForm_1<bits<6> opcode, dag OOL, dag IOL, string asmstr, @@ -273,9 +273,9 @@ class DForm_2_r0<bits<6> opcode, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RST; - let Inst{11-15} = 0; - let Inst{16-31} = D; + let Inst{6...10} = RST; + let Inst{11...15} = 0; + let Inst{16...31} = D; } class DForm_4<bits<6> opcode, dag OOL, dag IOL, string asmstr, @@ -287,9 +287,9 @@ class DForm_4<bits<6> opcode, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RST; - let Inst{11-15} = RA; - let Inst{16-31} = D; + let Inst{6...10} = RST; + let Inst{11...15} = RA; + let Inst{16...31} = D; } class DForm_4_zero<bits<6> opcode, dag OOL, dag IOL, string asmstr, @@ -321,13 +321,13 @@ class IForm_and_DForm_1<bits<6> opcode1, bit aa, bit lk, bits<6> opcode2, let Pattern = pattern; bits<24> LI; - let Inst{6-29} = LI; + let Inst{6...29} = LI; let Inst{30} = aa; let Inst{31} = lk; - let Inst{38-42} = RST; - let Inst{43-47} = RA; - let Inst{48-63} = D; + let Inst{38...42} = RST; + let Inst{43...47} = RA; + let Inst{48...63} = D; } // This is used to emit BL8+NOP. @@ -349,11 +349,11 @@ class DForm_5<bits<6> opcode, dag OOL, dag IOL, string asmstr, bits<5> RA; bits<16> D; - let Inst{6-8} = BF; + let Inst{6...8} = BF; let Inst{9} = 0; let Inst{10} = L; - let Inst{11-15} = RA; - let Inst{16-31} = D; + let Inst{11...15} = RA; + let Inst{16...31} = D; } class DForm_5_ext<bits<6> opcode, dag OOL, dag IOL, string asmstr, @@ -383,10 +383,10 @@ class DSForm_1<bits<6> opcode, bits<2> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RST; - let Inst{11-15} = RA; - let Inst{16-29} = D; - let Inst{30-31} = xo; + let Inst{6...10} = RST; + let Inst{11...15} = RA; + let Inst{16...29} = D; + let Inst{30...31} = xo; } // ISA V3.0B 1.6.6 DX-Form @@ -398,10 +398,10 @@ class DXForm<bits<6> opcode, bits<5> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = D{5-1}; // d1 - let Inst{16-25} = D{15-6}; // d0 - let Inst{26-30} = xo; + let Inst{6...10} = RT; + let Inst{11...15} = D{5...1}; // d1 + let Inst{16...25} = D{15...6}; // d0 + let Inst{26...30} = xo; let Inst{31} = D{0}; // d2 } @@ -415,11 +415,11 @@ class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = RA; - let Inst{16-27} = DQ; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = RA; + let Inst{16...27} = DQ; let Inst{28} = XT{5}; - let Inst{29-31} = xo; + let Inst{29...31} = xo; } class DQForm_RTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL, @@ -431,10 +431,10 @@ class DQForm_RTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL, bits<12> DQ; let Pattern = pattern; - let Inst{6-10} = RTp{4-0}; - let Inst{11-15} = RA; - let Inst{16-27} = DQ; - let Inst{28-31} = xo; + let Inst{6...10} = RTp{4...0}; + let Inst{11...15} = RA; + let Inst{16...27} = DQ; + let Inst{28...31} = xo; } // 1.7.6 X-Form @@ -449,10 +449,10 @@ class XForm_base_r3xo<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asms bit RC = 0; // set by isRecordForm - let Inst{6-10} = RST; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{6...10} = RST; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -475,7 +475,7 @@ class XForm_tlbilx<bits<10> xo, dag OOL, dag IOL, string asmstr, class XForm_attn<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin> : I<opcode, OOL, IOL, asmstr, itin> { - let Inst{21-30} = xo; + let Inst{21...30} = xo; } // This is the same as XForm_base_r3xo, but the first two operands are swapped @@ -490,10 +490,10 @@ class XForm_base_r3xo_swapped bit RC = 0; // set by isRecordForm - let Inst{6-10} = RST; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{6...10} = RST; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -528,10 +528,10 @@ class XForm_tlbws<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RST; - let Inst{11-15} = RA; + let Inst{6...10} = RST; + let Inst{11...15} = RA; let Inst{20} = WS; - let Inst{21-30} = xo; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -570,12 +570,12 @@ class XForm_16<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<5> RA; bits<5> RB; - let Inst{6-8} = BF; + let Inst{6...8} = BF; let Inst{9} = 0; let Inst{10} = L; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -587,10 +587,10 @@ class XForm_icbt<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<5> RB; let Inst{6} = 0; - let Inst{7-10} = CT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{7...10} = CT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -600,9 +600,9 @@ class XForm_sr<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<5> RS; bits<4> SR; - let Inst{6-10} = RS; - let Inst{12-15} = SR; - let Inst{21-30} = xo; + let Inst{6...10} = RS; + let Inst{12...15} = SR; + let Inst{21...30} = xo; } class XForm_mbar<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, @@ -610,8 +610,8 @@ class XForm_mbar<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, : I<opcode, OOL, IOL, asmstr, itin> { bits<5> MO; - let Inst{6-10} = MO; - let Inst{21-30} = xo; + let Inst{6...10} = MO; + let Inst{21...30} = xo; } class XForm_srin<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, @@ -620,9 +620,9 @@ class XForm_srin<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<5> RS; bits<5> RB; - let Inst{6-10} = RS; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{6...10} = RS; + let Inst{16...20} = RB; + let Inst{21...30} = xo; } class XForm_mtmsr<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, @@ -631,9 +631,9 @@ class XForm_mtmsr<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<5> RS; bits<1> L; - let Inst{6-10} = RS; + let Inst{6...10} = RS; let Inst{15} = L; - let Inst{21-30} = xo; + let Inst{21...30} = xo; } class XForm_16_ext<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, @@ -649,11 +649,11 @@ class XForm_17<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<5> RA; bits<5> RB; - let Inst{6-8} = BF; - let Inst{9-10} = 0; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{6...8} = BF; + let Inst{9...10} = 0; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -673,10 +673,10 @@ class XForm_18<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = FRT; - let Inst{11-15} = FRA; - let Inst{16-20} = FRB; - let Inst{21-30} = xo; + let Inst{6...10} = FRT; + let Inst{11...15} = FRA; + let Inst{16...20} = FRB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -696,11 +696,11 @@ class XForm_20<bits<6> opcode, bits<6> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = FRT; - let Inst{11-15} = FRA; - let Inst{16-20} = FRB; - let Inst{21-24} = tttt; - let Inst{25-30} = xo; + let Inst{6...10} = FRT; + let Inst{11...15} = FRA; + let Inst{16...20} = FRB; + let Inst{21...24} = tttt; + let Inst{25...30} = xo; let Inst{31} = 0; } @@ -708,10 +708,10 @@ class XForm_24<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, InstrItinClass itin, list<dag> pattern> : I<opcode, OOL, IOL, asmstr, itin> { let Pattern = pattern; - let Inst{6-10} = 31; - let Inst{11-15} = 0; - let Inst{16-20} = 0; - let Inst{21-30} = xo; + let Inst{6...10} = 31; + let Inst{11...15} = 0; + let Inst{16...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -721,11 +721,11 @@ class XForm_24_sync<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, bits<2> L; let Pattern = pattern; - let Inst{6-8} = 0; - let Inst{9-10} = L; - let Inst{11-15} = 0; - let Inst{16-20} = 0; - let Inst{21-30} = xo; + let Inst{6...8} = 0; + let Inst{9...10} = L; + let Inst{11...15} = 0; + let Inst{16...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -736,12 +736,12 @@ class XForm_IMM2_IMM2<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, bits<2> PL; let Pattern = pattern; - let Inst{6-8} = 0; - let Inst{9-10} = L; - let Inst{11-13} = 0; - let Inst{14-15} = PL; - let Inst{16-20} = 0; - let Inst{21-30} = xo; + let Inst{6...8} = 0; + let Inst{9...10} = L; + let Inst{11...13} = 0; + let Inst{14...15} = PL; + let Inst{16...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -752,12 +752,12 @@ class XForm_IMM3_IMM2<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, bits<2> SC; let Pattern = pattern; - let Inst{6-7} = 0; - let Inst{8-10} = L; - let Inst{11-13} = 0; - let Inst{14-15} = SC; - let Inst{16-20} = 0; - let Inst{21-30} = xo; + let Inst{6...7} = 0; + let Inst{8...10} = L; + let Inst{11...13} = 0; + let Inst{14...15} = SC; + let Inst{16...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -803,9 +803,9 @@ class XForm_42<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm - let Inst{6-10} = RST; - let Inst{11-20} = 0; - let Inst{21-30} = xo; + let Inst{6...10} = RST; + let Inst{11...20} = 0; + let Inst{21...30} = xo; let Inst{31} = RC; } class XForm_43<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, @@ -816,9 +816,9 @@ class XForm_43<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm - let Inst{6-10} = FM; - let Inst{11-20} = 0; - let Inst{21-30} = xo; + let Inst{6...10} = FM; + let Inst{11...20} = 0; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -828,11 +828,11 @@ class XForm_44<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<5> RT; bits<3> BFA; - let Inst{6-10} = RT; - let Inst{11-13} = BFA; - let Inst{14-15} = 0; - let Inst{16-20} = 0; - let Inst{21-30} = xo; + let Inst{6...10} = RT; + let Inst{11...13} = BFA; + let Inst{14...15} = 0; + let Inst{16...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -842,11 +842,11 @@ class XForm_45<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<5> RT; bits<2> L; - let Inst{6-10} = RT; - let Inst{11-13} = 0; - let Inst{14-15} = L; - let Inst{16-20} = 0; - let Inst{21-30} = xo; + let Inst{6...10} = RT; + let Inst{11...13} = 0; + let Inst{14...15} = L; + let Inst{16...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -856,11 +856,11 @@ class X_FRT5_XO2_XO3_XO10<bits<6> opcode, bits<2> xo1, bits<3> xo2, bits<10> xo, : XForm_base_r3xo<opcode, xo, OOL, IOL, asmstr, itin, pattern> { let Pattern = pattern; - let Inst{6-10} = RST; - let Inst{11-12} = xo1; - let Inst{13-15} = xo2; - let Inst{16-20} = 0; - let Inst{21-30} = xo; + let Inst{6...10} = RST; + let Inst{11...12} = xo1; + let Inst{13...15} = xo2; + let Inst{16...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -871,11 +871,11 @@ class X_FRT5_XO2_XO3_FRB5_XO10<bits<6> opcode, bits<2> xo1, bits<3> xo2, let Pattern = pattern; bits<5> FRB; - let Inst{6-10} = RST; - let Inst{11-12} = xo1; - let Inst{13-15} = xo2; - let Inst{16-20} = FRB; - let Inst{21-30} = xo; + let Inst{6...10} = RST; + let Inst{11...12} = xo1; + let Inst{13...15} = xo2; + let Inst{16...20} = FRB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -886,12 +886,12 @@ class X_FRT5_XO2_XO3_DRM3_XO10<bits<6> opcode, bits<2> xo1, bits<3> xo2, let Pattern = pattern; bits<3> DRM; - let Inst{6-10} = RST; - let Inst{11-12} = xo1; - let Inst{13-15} = xo2; - let Inst{16-17} = 0; - let Inst{18-20} = DRM; - let Inst{21-30} = xo; + let Inst{6...10} = RST; + let Inst{11...12} = xo1; + let Inst{13...15} = xo2; + let Inst{16...17} = 0; + let Inst{18...20} = DRM; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -902,12 +902,12 @@ class X_FRT5_XO2_XO3_RM2_X10<bits<6> opcode, bits<2> xo1, bits<3> xo2, let Pattern = pattern; bits<2> RM; - let Inst{6-10} = RST; - let Inst{11-12} = xo1; - let Inst{13-15} = xo2; - let Inst{16-18} = 0; - let Inst{19-20} = RM; - let Inst{21-30} = xo; + let Inst{6...10} = RST; + let Inst{11...12} = xo1; + let Inst{13...15} = xo2; + let Inst{16...18} = 0; + let Inst{19...20} = RM; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -934,10 +934,10 @@ class XForm_htm0<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, bit RC = 1; - let Inst{6-9} = 0; + let Inst{6...9} = 0; let Inst{10} = R; - let Inst{11-20} = 0; - let Inst{21-30} = xo; + let Inst{11...20} = 0; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -949,8 +949,8 @@ class XForm_htm1<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, bit RC = 1; let Inst{6} = A; - let Inst{7-20} = 0; - let Inst{21-30} = xo; + let Inst{7...20} = 0; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -961,10 +961,10 @@ class XForm_htm2<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm - let Inst{7-9} = 0; + let Inst{7...9} = 0; let Inst{10} = L; - let Inst{11-20} = 0; - let Inst{21-30} = xo; + let Inst{11...20} = 0; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -975,9 +975,9 @@ class XForm_htm3<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; - let Inst{6-8} = BF; - let Inst{9-20} = 0; - let Inst{21-30} = xo; + let Inst{6...8} = BF; + let Inst{9...20} = 0; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -992,12 +992,12 @@ class X_BF3_L1_RS5_RS5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-8} = BF; + let Inst{6...8} = BF; let Inst{9} = 0; let Inst{10} = L; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1011,11 +1011,11 @@ class X_BF3_RS5_RS5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-8} = BF; - let Inst{9-10} = 0; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{6...8} = BF; + let Inst{9...10} = 0; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1035,10 +1035,10 @@ class X_BF3_DCMX7_RS5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-8} = BF; - let Inst{9-15} = DCMX; - let Inst{16-20} = VB; - let Inst{21-30} = xo; + let Inst{6...8} = BF; + let Inst{9...15} = DCMX; + let Inst{16...20} = VB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1050,10 +1050,10 @@ class X_RD6_IMM8<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-12} = 0; - let Inst{13-20} = IMM8; - let Inst{21-30} = xo; + let Inst{6...10} = XT{4...0}; + let Inst{11...12} = 0; + let Inst{13...20} = IMM8; + let Inst{21...30} = xo; let Inst{31} = XT{5}; } @@ -1092,10 +1092,10 @@ class XX1Form<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = XT{5}; } @@ -1117,10 +1117,10 @@ class XX2Form<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = 0; - let Inst{16-20} = XB{4-0}; - let Inst{21-29} = xo; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = 0; + let Inst{16...20} = XB{4...0}; + let Inst{21...29} = xo; let Inst{30} = XB{5}; let Inst{31} = XT{5}; } @@ -1133,10 +1133,10 @@ class XX2Form_1<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-8} = CR; - let Inst{9-15} = 0; - let Inst{16-20} = XB{4-0}; - let Inst{21-29} = xo; + let Inst{6...8} = CR; + let Inst{9...15} = 0; + let Inst{16...20} = XB{4...0}; + let Inst{21...29} = xo; let Inst{30} = XB{5}; let Inst{31} = 0; } @@ -1150,11 +1150,11 @@ class XX2Form_2<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-13} = 0; - let Inst{14-15} = D; - let Inst{16-20} = XB{4-0}; - let Inst{21-29} = xo; + let Inst{6...10} = XT{4...0}; + let Inst{11...13} = 0; + let Inst{14...15} = D; + let Inst{16...20} = XB{4...0}; + let Inst{21...29} = xo; let Inst{30} = XB{5}; let Inst{31} = XT{5}; } @@ -1168,10 +1168,10 @@ class XX2_RD6_UIM5_RS6<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = UIM5; - let Inst{16-20} = XB{4-0}; - let Inst{21-29} = xo; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = UIM5; + let Inst{16...20} = XB{4...0}; + let Inst{21...29} = xo; let Inst{30} = XB{5}; let Inst{31} = XT{5}; } @@ -1185,10 +1185,10 @@ class XX2_RD5_XO5_RS6<bits<6> opcode, bits<5> xo2, bits<9> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = xo2; - let Inst{16-20} = XB{4-0}; - let Inst{21-29} = xo; + let Inst{6...10} = RT; + let Inst{11...15} = xo2; + let Inst{16...20} = XB{4...0}; + let Inst{21...29} = xo; let Inst{30} = XB{5}; let Inst{31} = 0; } @@ -1202,10 +1202,10 @@ class XX2_RD6_XO5_RS6<bits<6> opcode, bits<5> xo2, bits<9> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = xo2; - let Inst{16-20} = XB{4-0}; - let Inst{21-29} = xo; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = xo2; + let Inst{16...20} = XB{4...0}; + let Inst{21...29} = xo; let Inst{30} = XB{5}; let Inst{31} = XT{5}; } @@ -1219,10 +1219,10 @@ class XX2_BF3_DCMX7_RS6<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-8} = BF; - let Inst{9-15} = DCMX; - let Inst{16-20} = XB{4-0}; - let Inst{21-29} = xo; + let Inst{6...8} = BF; + let Inst{9...15} = DCMX; + let Inst{16...20} = XB{4...0}; + let Inst{21...29} = xo; let Inst{30} = XB{5}; let Inst{31} = 0; } @@ -1237,12 +1237,12 @@ class XX2_RD6_DCMX7_RS6<bits<6> opcode, bits<4> xo1, bits<3> xo2, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = DCMX{4-0}; - let Inst{16-20} = XB{4-0}; - let Inst{21-24} = xo1; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = DCMX{4...0}; + let Inst{16...20} = XB{4...0}; + let Inst{21...24} = xo1; let Inst{25} = DCMX{6}; - let Inst{26-28} = xo2; + let Inst{26...28} = xo2; let Inst{29} = DCMX{5}; let Inst{30} = XB{5}; let Inst{31} = XT{5}; @@ -1257,10 +1257,10 @@ class XForm_XD6_RA5_RB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-10} = D{4-0}; // D - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{6...10} = D{4...0}; // D + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = D{5}; // DX } @@ -1273,11 +1273,11 @@ class XForm_BF3_UIM6_FRB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-8} = BF; + let Inst{6...8} = BF; let Inst{9} = 0; - let Inst{10-15} = UIM; - let Inst{16-20} = FRB; - let Inst{21-30} = xo; + let Inst{10...15} = UIM; + let Inst{16...20} = FRB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1292,11 +1292,11 @@ class XForm_SP2_FRTB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asms bit RC = 0; // set by isRecordForm - let Inst{6 - 10} = FRT; - let Inst{11 - 12} = SP; - let Inst{13 - 15} = 0; - let Inst{16 - 20} = FRB; - let Inst{21 - 30} = xo; + let Inst{6...10} = FRT; + let Inst{11...12} = SP; + let Inst{13...15} = 0; + let Inst{16...20} = FRB; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -1311,11 +1311,11 @@ class XForm_S1_FRTB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, bit RC = 0; // set by isRecordForm - let Inst{6 - 10} = FRT; + let Inst{6...10} = FRT; let Inst{11} = S; - let Inst{12 - 15} = 0; - let Inst{16 - 20} = FRB; - let Inst{21 - 30} = xo; + let Inst{12...15} = 0; + let Inst{16...20} = FRB; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -1328,10 +1328,10 @@ class XX3Form<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = XA{4-0}; - let Inst{16-20} = XB{4-0}; - let Inst{21-28} = xo; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = XA{4...0}; + let Inst{16...20} = XB{4...0}; + let Inst{21...28} = xo; let Inst{29} = XA{5}; let Inst{30} = XB{5}; let Inst{31} = XT{5}; @@ -1353,11 +1353,11 @@ class XX3Form_1<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-8} = CR; - let Inst{9-10} = 0; - let Inst{11-15} = XA{4-0}; - let Inst{16-20} = XB{4-0}; - let Inst{21-28} = xo; + let Inst{6...8} = CR; + let Inst{9...10} = 0; + let Inst{11...15} = XA{4...0}; + let Inst{16...20} = XB{4...0}; + let Inst{21...28} = xo; let Inst{29} = XA{5}; let Inst{30} = XB{5}; let Inst{31} = 0; @@ -1373,12 +1373,12 @@ class XX3Form_2<bits<6> opcode, bits<5> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = XA{4-0}; - let Inst{16-20} = XB{4-0}; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = XA{4...0}; + let Inst{16...20} = XB{4...0}; let Inst{21} = 0; - let Inst{22-23} = D; - let Inst{24-28} = xo; + let Inst{22...23} = D; + let Inst{24...28} = xo; let Inst{29} = XA{5}; let Inst{30} = XB{5}; let Inst{31} = XT{5}; @@ -1395,11 +1395,11 @@ class XX3Form_Rc<bits<6> opcode, bits<7> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = XA{4-0}; - let Inst{16-20} = XB{4-0}; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = XA{4...0}; + let Inst{16...20} = XB{4...0}; let Inst{21} = RC; - let Inst{22-28} = xo; + let Inst{22...28} = xo; let Inst{29} = XA{5}; let Inst{30} = XB{5}; let Inst{31} = XT{5}; @@ -1415,11 +1415,11 @@ class XX4Form<bits<6> opcode, bits<2> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = XA{4-0}; - let Inst{16-20} = XB{4-0}; - let Inst{21-25} = XC{4-0}; - let Inst{26-27} = xo; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = XA{4...0}; + let Inst{16...20} = XB{4...0}; + let Inst{21...25} = XC{4...0}; + let Inst{26...27} = xo; let Inst{28} = XC{5}; let Inst{29} = XA{5}; let Inst{30} = XB{5}; @@ -1435,10 +1435,10 @@ class DCB_Form<bits<10> xo, bits<5> immfield, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = immfield; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{6...10} = immfield; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1451,10 +1451,10 @@ class DCB_Form_hint<bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = TH; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{6...10} = TH; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1469,11 +1469,11 @@ class DSS_Form<bits<1> T, bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; let Inst{6} = T; - let Inst{7-8} = 0; - let Inst{9-10} = STRM; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{7...8} = 0; + let Inst{9...10} = STRM; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1487,10 +1487,10 @@ class XLForm_1<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = CRD; - let Inst{11-15} = CRA; - let Inst{16-20} = CRB; - let Inst{21-30} = xo; + let Inst{6...10} = CRD; + let Inst{11...15} = CRA; + let Inst{16...20} = CRB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1527,10 +1527,10 @@ class XLForm_1_ext<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = CRD; - let Inst{11-15} = CRD; - let Inst{16-20} = CRD; - let Inst{21-30} = xo; + let Inst{6...10} = CRD; + let Inst{11...15} = CRD; + let Inst{16...20} = CRD; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1543,11 +1543,11 @@ class XLForm_2<bits<6> opcode, bits<10> xo, bit lk, dag OOL, dag IOL, string asm let Pattern = pattern; - let Inst{6-10} = BO; - let Inst{11-15} = BI; - let Inst{16-18} = 0; - let Inst{19-20} = BH; - let Inst{21-30} = xo; + let Inst{6...10} = BO; + let Inst{11...15} = BI; + let Inst{16...18} = 0; + let Inst{19...20} = BH; + let Inst{21...30} = xo; let Inst{31} = lk; } @@ -1557,9 +1557,9 @@ class XLForm_2_br<bits<6> opcode, bits<10> xo, bit lk, bits<7> BIBO; // 2 bits of BI and 5 bits of BO. bits<3> CR; - let BO = BIBO{4-0}; - let BI{0-1} = BIBO{5-6}; - let BI{2-4} = CR{0-2}; + let BO = BIBO{4...0}; + let BI{0...1} = BIBO{5...6}; + let BI{2...4} = CR{0...2}; let BH = 0; } @@ -1584,12 +1584,12 @@ class XLForm_3<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<3> BF; bits<3> BFA; - let Inst{6-8} = BF; - let Inst{9-10} = 0; - let Inst{11-13} = BFA; - let Inst{14-15} = 0; - let Inst{16-20} = 0; - let Inst{21-30} = xo; + let Inst{6...8} = BF; + let Inst{9...10} = 0; + let Inst{11...13} = BFA; + let Inst{14...15} = 0; + let Inst{16...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1602,13 +1602,13 @@ class XLForm_4<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; - let Inst{6-8} = BF; - let Inst{9-10} = 0; - let Inst{11-14} = 0; + let Inst{6...8} = BF; + let Inst{9...10} = 0; + let Inst{11...14} = 0; let Inst{15} = W; - let Inst{16-19} = U; + let Inst{16...19} = U; let Inst{20} = 0; - let Inst{21-30} = xo; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -1619,9 +1619,9 @@ class XLForm_S<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-19} = 0; + let Inst{6...19} = 0; let Inst{20} = S; - let Inst{21-30} = xo; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1640,17 +1640,17 @@ class XLForm_2_and_DSForm_1<bits<6> opcode1, bits<10> xo1, bit lk, let Pattern = pattern; - let Inst{6-10} = BO; - let Inst{11-15} = BI; - let Inst{16-18} = 0; - let Inst{19-20} = BH; - let Inst{21-30} = xo1; + let Inst{6...10} = BO; + let Inst{11...15} = BI; + let Inst{16...18} = 0; + let Inst{19...20} = BH; + let Inst{21...30} = xo1; let Inst{31} = lk; - let Inst{38-42} = RST; - let Inst{43-47} = RA; - let Inst{48-61} = D; - let Inst{62-63} = xo2; + let Inst{38...42} = RST; + let Inst{43...47} = RA; + let Inst{48...61} = D; + let Inst{62...63} = xo2; } class XLForm_2_ext_and_DSForm_1<bits<6> opcode1, bits<10> xo1, @@ -1677,16 +1677,16 @@ class XLForm_2_ext_and_DForm_1<bits<6> opcode1, bits<10> xo1, bits<5> bo, let Pattern = pattern; - let Inst{6-10} = bo; - let Inst{11-15} = bi; - let Inst{16-18} = 0; - let Inst{19-20} = 0; // Unused (BH) - let Inst{21-30} = xo1; + let Inst{6...10} = bo; + let Inst{11...15} = bi; + let Inst{16...18} = 0; + let Inst{19...20} = 0; // Unused (BH) + let Inst{21...30} = xo1; let Inst{31} = lk; - let Inst{38-42} = RST; - let Inst{43-47} = RA; - let Inst{48-63} = D; + let Inst{38...42} = RST; + let Inst{43...47} = RA; + let Inst{48...63} = D; } // 1.7.8 XFX-Form @@ -1696,7 +1696,7 @@ class XFXForm_1<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<5> RST; bits<10> SPR; - let Inst{6-10} = RST; + let Inst{6...10} = RST; let Inst{11} = SPR{4}; let Inst{12} = SPR{3}; let Inst{13} = SPR{2}; @@ -1707,7 +1707,7 @@ class XFXForm_1<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, let Inst{18} = SPR{7}; let Inst{19} = SPR{6}; let Inst{20} = SPR{5}; - let Inst{21-30} = xo; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1722,9 +1722,9 @@ class XFXForm_3<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, : I<opcode, OOL, IOL, asmstr, itin> { bits<5> RT; - let Inst{6-10} = RT; - let Inst{11-20} = 0; - let Inst{21-30} = xo; + let Inst{6...10} = RT; + let Inst{11...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1735,9 +1735,9 @@ class XFXForm_3p<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<10> imm; let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-20} = imm; - let Inst{21-30} = xo; + let Inst{6...10} = RT; + let Inst{11...20} = imm; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1747,11 +1747,11 @@ class XFXForm_5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<8> FXM; bits<5> RST; - let Inst{6-10} = RST; + let Inst{6...10} = RST; let Inst{11} = 0; - let Inst{12-19} = FXM; + let Inst{12...19} = FXM; let Inst{20} = 0; - let Inst{21-30} = xo; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1761,11 +1761,11 @@ class XFXForm_5a<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, bits<5> RST; bits<8> FXM; - let Inst{6-10} = RST; + let Inst{6...10} = RST; let Inst{11} = 1; - let Inst{12-19} = FXM; + let Inst{12...19} = FXM; let Inst{20} = 0; - let Inst{21-30} = xo; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -1782,10 +1782,10 @@ class XFLForm<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; let Inst{6} = 0; - let Inst{7-14} = FM; + let Inst{7...14} = FM; let Inst{15} = 0; - let Inst{16-20} = RT; - let Inst{21-30} = xo; + let Inst{16...20} = RT; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -1801,10 +1801,10 @@ class XFLForm_1<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; let Inst{6} = L; - let Inst{7-14} = FLM; + let Inst{7...14} = FLM; let Inst{15} = W; - let Inst{16-20} = FRB; - let Inst{21-30} = xo; + let Inst{16...20} = FRB; + let Inst{21...30} = xo; let Inst{31} = RC; } @@ -1819,10 +1819,10 @@ class XSForm_1<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm let Pattern = pattern; - let Inst{6-10} = RS; - let Inst{11-15} = RA; - let Inst{16-20} = SH{4,3,2,1,0}; - let Inst{21-29} = xo; + let Inst{6...10} = RS; + let Inst{11...15} = RA; + let Inst{16...20} = SH{4,3,2,1,0}; + let Inst{21...29} = xo; let Inst{30} = SH{5}; let Inst{31} = RC; } @@ -1839,11 +1839,11 @@ class XOForm_1<bits<6> opcode, bits<9> xo, bit oe, dag OOL, dag IOL, string asms bit RC = 0; // set by isRecordForm - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; let Inst{21} = oe; - let Inst{22-30} = xo; + let Inst{22...30} = xo; let Inst{31} = RC; } @@ -1866,11 +1866,11 @@ class AForm_1<bits<6> opcode, bits<5> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm - let Inst{6-10} = FRT; - let Inst{11-15} = FRA; - let Inst{16-20} = FRB; - let Inst{21-25} = FRC; - let Inst{26-30} = xo; + let Inst{6...10} = FRT; + let Inst{11...15} = FRA; + let Inst{16...20} = FRB; + let Inst{21...25} = FRC; + let Inst{26...30} = xo; let Inst{31} = RC; } @@ -1896,11 +1896,11 @@ class AForm_4<bits<6> opcode, bits<5> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-25} = COND; - let Inst{26-30} = xo; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...25} = COND; + let Inst{26...30} = xo; let Inst{31} = 0; } @@ -1918,11 +1918,11 @@ class MForm_1<bits<6> opcode, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm - let Inst{6-10} = RS; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-25} = MB; - let Inst{26-30} = ME; + let Inst{6...10} = RS; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...25} = MB; + let Inst{26...30} = ME; let Inst{31} = RC; } @@ -1939,11 +1939,11 @@ class MForm_2<bits<6> opcode, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm - let Inst{6-10} = RS; - let Inst{11-15} = RA; - let Inst{16-20} = SH; - let Inst{21-25} = MB; - let Inst{26-30} = ME; + let Inst{6...10} = RS; + let Inst{11...15} = RA; + let Inst{16...20} = SH; + let Inst{21...25} = MB; + let Inst{26...30} = ME; let Inst{31} = RC; } @@ -1960,11 +1960,11 @@ class MDForm_1<bits<6> opcode, bits<3> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm - let Inst{6-10} = RS; - let Inst{11-15} = RA; - let Inst{16-20} = SH{4,3,2,1,0}; - let Inst{21-26} = MBE{4,3,2,1,0,5}; - let Inst{27-29} = xo; + let Inst{6...10} = RS; + let Inst{11...15} = RA; + let Inst{16...20} = SH{4,3,2,1,0}; + let Inst{21...26} = MBE{4,3,2,1,0,5}; + let Inst{27...29} = xo; let Inst{30} = SH{5}; let Inst{31} = RC; } @@ -1981,11 +1981,11 @@ class MDSForm_1<bits<6> opcode, bits<4> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm - let Inst{6-10} = RS; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-26} = MBE{4,3,2,1,0,5}; - let Inst{27-30} = xo; + let Inst{6...10} = RS; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...26} = MBE{4,3,2,1,0,5}; + let Inst{27...30} = xo; let Inst{31} = RC; } @@ -2003,11 +2003,11 @@ class VAForm_1<bits<6> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-25} = RC; - let Inst{26-31} = xo; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...25} = RC; + let Inst{26...31} = xo; } // VAForm_1a - DABC ordering. @@ -2021,11 +2021,11 @@ class VAForm_1a<bits<6> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-25} = RC; - let Inst{26-31} = xo; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...25} = RC; + let Inst{26...31} = xo; } class VAForm_2<bits<6> xo, dag OOL, dag IOL, string asmstr, @@ -2038,12 +2038,12 @@ class VAForm_2<bits<6> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; let Inst{21} = 0; - let Inst{22-25} = SH; - let Inst{26-31} = xo; + let Inst{22...25} = SH; + let Inst{26...31} = xo; } // E-2 VX-Form @@ -2056,10 +2056,10 @@ class VXForm_1<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = VD; - let Inst{11-15} = VA; - let Inst{16-20} = VB; - let Inst{21-31} = xo; + let Inst{6...10} = VD; + let Inst{11...15} = VA; + let Inst{16...20} = VB; + let Inst{21...31} = xo; } class VXForm_setzero<bits<11> xo, dag OOL, dag IOL, string asmstr, @@ -2078,10 +2078,10 @@ class VXForm_2<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = VD; - let Inst{11-15} = 0; - let Inst{16-20} = VB; - let Inst{21-31} = xo; + let Inst{6...10} = VD; + let Inst{11...15} = 0; + let Inst{16...20} = VB; + let Inst{21...31} = xo; } class VXForm_3<bits<11> xo, dag OOL, dag IOL, string asmstr, @@ -2092,10 +2092,10 @@ class VXForm_3<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = VD; - let Inst{11-15} = IMM; - let Inst{16-20} = 0; - let Inst{21-31} = xo; + let Inst{6...10} = VD; + let Inst{11...15} = IMM; + let Inst{16...20} = 0; + let Inst{21...31} = xo; } /// VXForm_4 - VX instructions with "VD,0,0" register fields, like mfvscr. @@ -2106,10 +2106,10 @@ class VXForm_4<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = VD; - let Inst{11-15} = 0; - let Inst{16-20} = 0; - let Inst{21-31} = xo; + let Inst{6...10} = VD; + let Inst{11...15} = 0; + let Inst{16...20} = 0; + let Inst{21...31} = xo; } /// VXForm_5 - VX instructions with "0,0,VB" register fields, like mtvscr. @@ -2120,10 +2120,10 @@ class VXForm_5<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = 0; - let Inst{11-15} = 0; - let Inst{16-20} = VB; - let Inst{21-31} = xo; + let Inst{6...10} = 0; + let Inst{11...15} = 0; + let Inst{16...20} = VB; + let Inst{21...31} = xo; } // e.g. [PO VRT EO VRB XO] @@ -2135,10 +2135,10 @@ class VXForm_RD5_XO5_RS5<bits<11> xo, bits<5> eo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-10} = VD; - let Inst{11-15} = eo; - let Inst{16-20} = VB; - let Inst{21-31} = xo; + let Inst{6...10} = VD; + let Inst{11...15} = eo; + let Inst{16...20} = VB; + let Inst{21...31} = xo; } /// VXForm_CR - VX crypto instructions with "VRT, VRA, ST, SIX" @@ -2152,11 +2152,11 @@ class VXForm_CR<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = VD; - let Inst{11-15} = VA; + let Inst{6...10} = VD; + let Inst{11...15} = VA; let Inst{16} = ST; - let Inst{17-20} = SIX; - let Inst{21-31} = xo; + let Inst{17...20} = SIX; + let Inst{21...31} = xo; } /// VXForm_BX - VX crypto instructions with "VRT, VRA, 0 - like vsbox" @@ -2168,10 +2168,10 @@ class VXForm_BX<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = VD; - let Inst{11-15} = VA; - let Inst{16-20} = 0; - let Inst{21-31} = xo; + let Inst{6...10} = VD; + let Inst{11...15} = VA; + let Inst{16...20} = 0; + let Inst{21...31} = xo; } // E-4 VXR-Form @@ -2185,11 +2185,11 @@ class VXRForm_1<bits<10> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = VD; - let Inst{11-15} = VA; - let Inst{16-20} = VB; + let Inst{6...10} = VD; + let Inst{11...15} = VA; + let Inst{16...20} = VB; let Inst{21} = RC; - let Inst{22-31} = xo; + let Inst{22...31} = xo; } // VX-Form: [PO VRT EO VRB 1 PS XO] @@ -2203,12 +2203,12 @@ class VX_RD5_EO5_RS5_PS1_XO9<bits<5> eo, bits<9> xo, let Pattern = pattern; - let Inst{6-10} = VD; - let Inst{11-15} = eo; - let Inst{16-20} = VB; + let Inst{6...10} = VD; + let Inst{11...15} = eo; + let Inst{16...20} = VB; let Inst{21} = 1; let Inst{22} = PS; - let Inst{23-31} = xo; + let Inst{23...31} = xo; } // VX-Form: [PO VRT VRA VRB 1 PS XO] or [PO VRT VRA VRB 1 / XO] @@ -2222,12 +2222,12 @@ class VX_RD5_RSp5_PS1_XO9<bits<9> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = VD; - let Inst{11-15} = VA; - let Inst{16-20} = VB; + let Inst{6...10} = VD; + let Inst{11...15} = VA; + let Inst{16...20} = VB; let Inst{21} = 1; let Inst{22} = PS; - let Inst{23-31} = xo; + let Inst{23...31} = xo; } class Z22Form_BF3_FRA5_DCM6<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, @@ -2240,11 +2240,11 @@ class Z22Form_BF3_FRA5_DCM6<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-8} = BF; - let Inst{9-10} = 0; - let Inst{11-15} = FRA; - let Inst{16-21} = DCM; - let Inst{22-30} = xo; + let Inst{6...8} = BF; + let Inst{9...10} = 0; + let Inst{11...15} = FRA; + let Inst{16...21} = DCM; + let Inst{22...30} = xo; let Inst{31} = 0; } @@ -2260,10 +2260,10 @@ class Z22Form_FRTA5_SH6<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, bit RC = 0; // set by isRecordForm - let Inst{6 - 10} = FRT; - let Inst{11 - 15} = FRA; - let Inst{16 - 21} = SH; - let Inst{22 - 30} = xo; + let Inst{6...10} = FRT; + let Inst{11...15} = FRA; + let Inst{16...21} = SH; + let Inst{22...30} = xo; let Inst{31} = RC; } @@ -2279,12 +2279,12 @@ class Z23Form_8<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, string asmstr, bit RC = 0; // set by isRecordForm - let Inst{6-10} = VRT; - let Inst{11-14} = 0; + let Inst{6...10} = VRT; + let Inst{11...14} = 0; let Inst{15} = R; - let Inst{16-20} = VRB; - let Inst{21-22} = idx; - let Inst{23-30} = xo; + let Inst{16...20} = VRB; + let Inst{21...22} = idx; + let Inst{23...30} = xo; let Inst{31} = RC; } @@ -2298,11 +2298,11 @@ class Z23Form_RTAB5_CY2<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-22} = CY; - let Inst{23-30} = xo; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...22} = CY; + let Inst{23...30} = xo; let Inst{31} = 0; } @@ -2318,11 +2318,11 @@ class Z23Form_FRTAB5_RMC2<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, bit RC = 0; // set by isRecordForm - let Inst{6 - 10} = FRT; - let Inst{11 - 15} = FRA; - let Inst{16 - 20} = FRB; - let Inst{21 - 22} = RMC; - let Inst{23 - 30} = xo; + let Inst{6...10} = FRT; + let Inst{11...15} = FRA; + let Inst{16...20} = FRB; + let Inst{21...22} = RMC; + let Inst{23...30} = xo; let Inst{31} = RC; } @@ -2345,12 +2345,12 @@ class Z23Form_FRTB5_R1_RMC2<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, bit RC = 0; // set by isRecordForm - let Inst{6 - 10} = FRT; - let Inst{11 - 14} = 0; + let Inst{6...10} = FRT; + let Inst{11...14} = 0; let Inst{15} = R; - let Inst{16 - 20} = FRB; - let Inst{21 - 22} = RMC; - let Inst{23 - 30} = xo; + let Inst{16...20} = FRB; + let Inst{21...22} = RMC; + let Inst{23...30} = xo; let Inst{31} = RC; } @@ -2362,7 +2362,7 @@ class PPCEmitTimePseudo<dag OOL, dag IOL, string asmstr, list<dag> pattern> let isCodeGenOnly = 1; let PPC64 = 0; let Pattern = pattern; - let Inst{31-0} = 0; + let Inst{31...0} = 0; let hasNoSchedulingInfo = 1; } diff --git a/llvm/lib/Target/PowerPC/PPCInstrFuture.td b/llvm/lib/Target/PowerPC/PPCInstrFuture.td index 7277e36..8cf5c85 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrFuture.td +++ b/llvm/lib/Target/PowerPC/PPCInstrFuture.td @@ -23,11 +23,11 @@ class XOForm_RTAB5_L1<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, bit RC = 0; // set by isRecordForm - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; let Inst{21} = L; - let Inst{22-30} = xo; + let Inst{22...30} = xo; let Inst{31} = RC; } @@ -52,10 +52,10 @@ class VXForm_VRTB5<bits<11> xo, bits<5> R, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6 -10} = VRT; - let Inst{11 -15} = R; - let Inst{16 -20} = VRB; - let Inst{21 -31} = xo; + let Inst{6...10} = VRT; + let Inst{11...15} = R; + let Inst{16...20} = VRB; + let Inst{21...31} = xo; } class VXForm_VRTB5_UIM2<bits<11> xo, bits<3> R, dag OOL, dag IOL, string asmstr, @@ -67,11 +67,11 @@ class VXForm_VRTB5_UIM2<bits<11> xo, bits<3> R, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6 -10} = VRT; - let Inst{11 -13} = R; - let Inst{14 -15} = UIM; - let Inst{16 -20} = VRB; - let Inst{21 -31} = xo; + let Inst{6...10} = VRT; + let Inst{11...13} = R; + let Inst{14...15} = UIM; + let Inst{16...20} = VRB; + let Inst{21...31} = xo; } class VXForm_VRTB5_UIM1<bits<11> xo, bits<4> R, dag OOL, dag IOL, string asmstr, @@ -83,11 +83,11 @@ class VXForm_VRTB5_UIM1<bits<11> xo, bits<4> R, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6 -10} = VRT; - let Inst{11 -14} = R; + let Inst{6...10} = VRT; + let Inst{11...14} = R; let Inst{15} = UIM; - let Inst{16 -20} = VRB; - let Inst{21 -31} = xo; + let Inst{16...20} = VRB; + let Inst{21...31} = xo; } class VXForm_VRTB5_UIM3<bits<11> xo, bits<2> R, dag OOL, dag IOL, string asmstr, @@ -99,11 +99,11 @@ class VXForm_VRTB5_UIM3<bits<11> xo, bits<2> R, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6 -10} = VRT; - let Inst{11 -12} = R; - let Inst{13 -15} = UIM; - let Inst{16 -20} = VRB; - let Inst{21 -31} = xo; + let Inst{6...10} = VRT; + let Inst{11...12} = R; + let Inst{13...15} = UIM; + let Inst{16...20} = VRB; + let Inst{21...31} = xo; } class VXForm_VRTAB5<bits<11> xo, dag OOL, dag IOL, string asmstr, @@ -114,10 +114,10 @@ class VXForm_VRTAB5<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6 -10} = VRT; - let Inst{11 -15} = VRA; - let Inst{16 -20} = VRB; - let Inst{21 -31} = xo; + let Inst{6...10} = VRT; + let Inst{11...15} = VRA; + let Inst{16...20} = VRB; + let Inst{21...31} = xo; } let Predicates = [IsISAFuture] in { diff --git a/llvm/lib/Target/PowerPC/PPCInstrFutureMMA.td b/llvm/lib/Target/PowerPC/PPCInstrFutureMMA.td index a3a75c0..8848957 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrFutureMMA.td +++ b/llvm/lib/Target/PowerPC/PPCInstrFutureMMA.td @@ -22,13 +22,13 @@ class XX3Form_AT3_XABp5_P1<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6 -8} = AT{2 -0}; - let Inst{9 -10} = 0; - let Inst{11 -14} = XAp{3 -0}; + let Inst{6...8} = AT{2...0}; + let Inst{9...10} = 0; + let Inst{11...14} = XAp{3...0}; let Inst{15} = P; - let Inst{16 -19} = XBp{3 -0}; + let Inst{16...19} = XBp{3...0}; let Inst{20} = 0; - let Inst{21 -28} = xo; + let Inst{21...28} = xo; let Inst{29} = XAp{4}; let Inst{30} = XBp{4}; let Inst{31} = 0; @@ -43,12 +43,12 @@ class XX2Form_AT3_XBp5_P2<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6 -8} = AT{2 -0}; - let Inst{9 -14} = 0; + let Inst{6...8} = AT{2...0}; + let Inst{9...14} = 0; let Inst{15} = P{0}; - let Inst{16 -19} = XBp{3 -0}; + let Inst{16...19} = XBp{3...0}; let Inst{20} = P{1}; - let Inst{21 -29} = xo; + let Inst{21...29} = xo; let Inst{30} = XBp{4}; let Inst{31} = 0; } @@ -61,12 +61,12 @@ class XForm_ATB3<bits<6> opcode, bits<5> o, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6 -8} = AT{2 -0}; - let Inst{9 -10} = 0; - let Inst{11 -15} = o; - let Inst{16 -18} = AB{2 -0}; - let Inst{19 -20} = 0; - let Inst{21 -30} = xo; + let Inst{6...8} = AT{2...0}; + let Inst{9...10} = 0; + let Inst{11...15} = o; + let Inst{16...18} = AB{2...0}; + let Inst{19...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -79,12 +79,12 @@ class XX3Form_AT3_XAp5B6<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6 -8} = AT; - let Inst{9 -10} = 0; - let Inst{11 -14} = XAp{3 -0}; + let Inst{6...8} = AT; + let Inst{9...10} = 0; + let Inst{11...14} = XAp{3...0}; let Inst{15} = 0; - let Inst{16 -20} = XB{4 -0}; - let Inst{21 -28} = xo; + let Inst{16...20} = XB{4...0}; + let Inst{21...28} = xo; let Inst{29} = XAp{4}; let Inst{30} = XB{5}; let Inst{31} = 0; @@ -104,20 +104,20 @@ class MMIRR_XX3Form_X8YP4_XAp5B6<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6 -7} = 3; - let Inst{8 -11} = 9; - let Inst{12 -15} = 0; - let Inst{16 -19} = PMSK; - let Inst{20 -27} = XMSK; - let Inst{28 -31} = YMSK; + let Inst{6...7} = 3; + let Inst{8...11} = 9; + let Inst{12...15} = 0; + let Inst{16...19} = PMSK; + let Inst{20...27} = XMSK; + let Inst{28...31} = YMSK; // The instruction. - let Inst{38 -40} = AT; - let Inst{41 -42} = 0; - let Inst{43 -46} = XAp{3 -0}; + let Inst{38...40} = AT; + let Inst{41...42} = 0; + let Inst{43...46} = XAp{3...0}; let Inst{47} = 0; - let Inst{48 -52} = XB{4 -0}; - let Inst{53 -60} = xo; + let Inst{48...52} = XB{4...0}; + let Inst{53...60} = xo; let Inst{61} = XAp{4}; let Inst{62} = XB{5}; let Inst{63} = 0; @@ -137,21 +137,21 @@ class MMIRR_XX3Form_X8Y4P2_XAp5B6<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6 -7} = 3; - let Inst{8 -11} = 9; - let Inst{12 -15} = 0; - let Inst{16 -17} = PMSK; - let Inst{18 -19} = 0; - let Inst{20 -27} = XMSK; - let Inst{28 -31} = YMSK; + let Inst{6...7} = 3; + let Inst{8...11} = 9; + let Inst{12...15} = 0; + let Inst{16...17} = PMSK; + let Inst{18...19} = 0; + let Inst{20...27} = XMSK; + let Inst{28...31} = YMSK; // The instruction. - let Inst{38 -40} = AT; - let Inst{41 -42} = 0; - let Inst{43 -46} = XAp{3 -0}; + let Inst{38...40} = AT; + let Inst{41...42} = 0; + let Inst{43...46} = XAp{3...0}; let Inst{47} = 0; - let Inst{48 -52} = XB{4 -0}; - let Inst{53 -60} = xo; + let Inst{48...52} = XB{4...0}; + let Inst{53...60} = xo; let Inst{61} = XAp{4}; let Inst{62} = XB{5}; let Inst{63} = 0; @@ -358,13 +358,13 @@ class XForm_AT3_T1_AB3<bits<6> opcode, bits<5> o, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6 -8} = AT{2 -0}; + let Inst{6...8} = AT{2...0}; let Inst{9} = 0; let Inst{10} = T; - let Inst{11 -15} = o; - let Inst{16 -18} = AB{2 -0}; - let Inst{19 -20} = 0; - let Inst{21 -30} = xo; + let Inst{11...15} = o; + let Inst{16...18} = AB{2...0}; + let Inst{19...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -376,11 +376,11 @@ class XForm_ATp2_SR5<bits<6> opcode, bits<5> o, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6 -7} = ATp{1 -0}; - let Inst{8 -10} = 0; - let Inst{11 -15} = o; - let Inst{16 -20} = SR{4 -0}; - let Inst{21 -30} = xo; + let Inst{6...7} = ATp{1...0}; + let Inst{8...10} = 0; + let Inst{11...15} = o; + let Inst{16...20} = SR{4...0}; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -395,13 +395,13 @@ class XX2Form_AT3_XB6_ID2_E1_BL2<bits<6> opcode, bits<9> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6 -8} = AT{2 -0}; - let Inst{9 -10} = 0; - let Inst{11 -12} = ID{1 -0}; + let Inst{6...8} = AT{2...0}; + let Inst{9...10} = 0; + let Inst{11...12} = ID{1...0}; let Inst{13} = E; - let Inst{14 -15} = BL{1 -0}; - let Inst{16 -20} = XB{4 -0}; - let Inst{21 -29} = xo; + let Inst{14...15} = BL{1...0}; + let Inst{16...20} = XB{4...0}; + let Inst{21...29} = xo; let Inst{30} = XB{5}; let Inst{31} = 0; } diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 7cea9a1..c12cf85 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -4275,7 +4275,7 @@ def WRTEEI: I<31, (outs), (ins i1imm:$E), "wrteei $E", IIC_SprMTMSR>, bits<1> E; let Inst{16} = E; - let Inst{21-30} = 163; + let Inst{21...30} = 163; } def DCCCI : XForm_tlb<454, (outs), (ins gprc:$RA, gprc:$RB), diff --git a/llvm/lib/Target/PowerPC/PPCInstrP10.td b/llvm/lib/Target/PowerPC/PPCInstrP10.td index 3a9b64c8..149a44d 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrP10.td +++ b/llvm/lib/Target/PowerPC/PPCInstrP10.td @@ -125,8 +125,8 @@ class PI<bits<6> pref, bits<6> opcode, dag OOL, dag IOL, string asmstr, let InOperandList = IOL; let AsmString = asmstr; let Itinerary = itin; - let Inst{0-5} = pref; - let Inst{32-37} = opcode; + let Inst{0...5} = pref; + let Inst{32...37} = opcode; bits<1> PPC970_First = 0; bits<1> PPC970_Single = 0; @@ -138,7 +138,7 @@ class PI<bits<6> pref, bits<6> opcode, dag OOL, dag IOL, string asmstr, let TSFlags{0} = PPC970_First; let TSFlags{1} = PPC970_Single; let TSFlags{2} = PPC970_Cracked; - let TSFlags{5-3} = PPC970_Unit; + let TSFlags{5...3} = PPC970_Unit; bits<1> Prefixed = 1; // This is a prefixed instruction. let TSFlags{7} = Prefixed; @@ -167,11 +167,11 @@ class VXForm_VTB5_RC<bits<10> xo, bits<5> R, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = VT; - let Inst{11-15} = R; - let Inst{16-20} = VB; + let Inst{6...10} = VT; + let Inst{11...15} = R; + let Inst{16...20} = VB; let Inst{21} = RC; - let Inst{22-31} = xo; + let Inst{22...31} = xo; } // Multiclass definition to account for record and non-record form @@ -200,16 +200,16 @@ class MLS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr, let Pattern = pattern; // The prefix. - let Inst{6-7} = 2; - let Inst{8-10} = 0; + let Inst{6...7} = 2; + let Inst{8...10} = 0; let Inst{11} = PCRel; - let Inst{12-13} = 0; - let Inst{14-31} = D{33-16}; // d0 + let Inst{12...13} = 0; + let Inst{14...31} = D{33...16}; // d0 // The instruction. - let Inst{38-42} = RST{4-0}; - let Inst{43-47} = RA; - let Inst{48-63} = D{15-0}; // d1 + let Inst{38...42} = RST{4...0}; + let Inst{43...47} = RA; + let Inst{48...63} = D{15...0}; // d1 } class MLS_DForm_R_SI34_RTA5<bits<6> opcode, dag OOL, dag IOL, string asmstr, @@ -222,16 +222,16 @@ class MLS_DForm_R_SI34_RTA5<bits<6> opcode, dag OOL, dag IOL, string asmstr, let Pattern = pattern; // The prefix. - let Inst{6-7} = 2; - let Inst{8-10} = 0; + let Inst{6...7} = 2; + let Inst{8...10} = 0; let Inst{11} = PCRel; - let Inst{12-13} = 0; - let Inst{14-31} = SI{33-16}; + let Inst{12...13} = 0; + let Inst{14...31} = SI{33...16}; // The instruction. - let Inst{38-42} = RT; - let Inst{43-47} = RA; - let Inst{48-63} = SI{15-0}; + let Inst{38...42} = RT; + let Inst{43...47} = RA; + let Inst{48...63} = SI{15...0}; } class MLS_DForm_SI34_RT5<bits<6> opcode, dag OOL, dag IOL, string asmstr, @@ -243,16 +243,16 @@ class MLS_DForm_SI34_RT5<bits<6> opcode, dag OOL, dag IOL, string asmstr, let Pattern = pattern; // The prefix. - let Inst{6-7} = 2; - let Inst{8-10} = 0; + let Inst{6...7} = 2; + let Inst{8...10} = 0; let Inst{11} = 0; - let Inst{12-13} = 0; - let Inst{14-31} = SI{33-16}; + let Inst{12...13} = 0; + let Inst{14...31} = SI{33...16}; // The instruction. - let Inst{38-42} = RT; - let Inst{43-47} = 0; - let Inst{48-63} = SI{15-0}; + let Inst{38...42} = RT; + let Inst{43...47} = 0; + let Inst{48...63} = SI{15...0}; } multiclass MLS_DForm_R_SI34_RTA5_p<bits<6> opcode, dag OOL, dag IOL, @@ -274,15 +274,15 @@ class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr, let Pattern = pattern; // The prefix. - let Inst{6-10} = 0; + let Inst{6...10} = 0; let Inst{11} = PCRel; - let Inst{12-13} = 0; - let Inst{14-31} = D{33-16}; // d0 + let Inst{12...13} = 0; + let Inst{14...31} = D{33...16}; // d0 // The instruction. - let Inst{38-42} = RST{4-0}; - let Inst{43-47} = RA; - let Inst{48-63} = D{15-0}; // d1 + let Inst{38...42} = RST{4...0}; + let Inst{43...47} = RA; + let Inst{48...63} = D{15...0}; // d1 } // 8LS:D-Form: [ 1 0 0 // R // d0 @@ -298,18 +298,18 @@ class 8LS_DForm_R_SI34_XT6_RA5_MEM<bits<5> opcode, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6-7} = 0; + let Inst{6...7} = 0; let Inst{8} = 0; - let Inst{9-10} = 0; // reserved + let Inst{9...10} = 0; // reserved let Inst{11} = PCRel; - let Inst{12-13} = 0; // reserved - let Inst{14-31} = D{33-16}; // d0 + let Inst{12...13} = 0; // reserved + let Inst{14...31} = D{33...16}; // d0 // The instruction. let Inst{37} = XST{5}; - let Inst{38-42} = XST{4-0}; - let Inst{43-47} = RA; - let Inst{48-63} = D{15-0}; // d1 + let Inst{38...42} = XST{4...0}; + let Inst{43...47} = RA; + let Inst{48...63} = D{15...0}; // d1 } // X-Form: [PO T IMM VRB XO TX] @@ -321,10 +321,10 @@ class XForm_XT6_IMM5_VB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, bits<5> IMM; let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = IMM; - let Inst{16-20} = VRB; - let Inst{21-30} = xo; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = IMM; + let Inst{16...20} = VRB; + let Inst{21...30} = xo; let Inst{31} = XT{5}; } @@ -341,19 +341,19 @@ class 8RR_XX4Form_IMM8_XTAB6<bits<6> opcode, bits<2> xo, let Pattern = pattern; // The prefix. - let Inst{6-7} = 1; + let Inst{6...7} = 1; let Inst{8} = 0; - let Inst{9-11} = 0; - let Inst{12-13} = 0; - let Inst{14-23} = 0; - let Inst{24-31} = IMM; + let Inst{9...11} = 0; + let Inst{12...13} = 0; + let Inst{14...23} = 0; + let Inst{24...31} = IMM; // The instruction. - let Inst{38-42} = XT{4-0}; - let Inst{43-47} = XA{4-0}; - let Inst{48-52} = XB{4-0}; - let Inst{53-57} = XC{4-0}; - let Inst{58-59} = xo; + let Inst{38...42} = XT{4...0}; + let Inst{43...47} = XA{4...0}; + let Inst{48...52} = XB{4...0}; + let Inst{53...57} = XC{4...0}; + let Inst{58...59} = xo; let Inst{60} = XC{5}; let Inst{61} = XA{5}; let Inst{62} = XB{5}; @@ -369,11 +369,11 @@ class VXForm_RD5_N3_VB5<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RD; - let Inst{11-12} = 0; - let Inst{13-15} = N; - let Inst{16-20} = VB; - let Inst{21-31} = xo; + let Inst{6...10} = RD; + let Inst{11...12} = 0; + let Inst{13...15} = N; + let Inst{16...20} = VB; + let Inst{21...31} = xo; } @@ -401,11 +401,11 @@ class VXForm_BF3_VAB5<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-8} = BF; - let Inst{9-10} = 0; - let Inst{11-15} = VA; - let Inst{16-20} = VB; - let Inst{21-31} = xo; + let Inst{6...8} = BF; + let Inst{9...10} = 0; + let Inst{11...15} = VA; + let Inst{16...20} = VB; + let Inst{21...31} = xo; } // VN-Form: [PO VRT VRA VRB PS SD XO] @@ -420,12 +420,12 @@ class VNForm_VTAB5_SD3<bits<6> xo, bits<2> ps, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = VRT; - let Inst{11-15} = VRA; - let Inst{16-20} = VRB; - let Inst{21-22} = ps; - let Inst{23-25} = SD; - let Inst{26-31} = xo; + let Inst{6...10} = VRT; + let Inst{11...15} = VRA; + let Inst{16...20} = VRB; + let Inst{21...22} = ps; + let Inst{23...25} = SD; + let Inst{26...31} = xo; } class VXForm_RD5_MP_VB5<bits<11> xo, bits<4> eo, dag OOL, dag IOL, @@ -437,11 +437,11 @@ class VXForm_RD5_MP_VB5<bits<11> xo, bits<4> eo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-10} = RD; - let Inst{11-14} = eo; + let Inst{6...10} = RD; + let Inst{11...14} = eo; let Inst{15} = MP; - let Inst{16-20} = VB; - let Inst{21-31} = xo; + let Inst{16...20} = VB; + let Inst{21...31} = xo; } // 8RR:D-Form: [ 1 1 0 // // imm0 @@ -456,17 +456,17 @@ class 8RR_DForm_IMM32_XT6<bits<6> opcode, bits<4> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6-7} = 1; - let Inst{8-11} = 0; - let Inst{12-13} = 0; // reserved - let Inst{14-15} = 0; // reserved - let Inst{16-31} = IMM32{31-16}; + let Inst{6...7} = 1; + let Inst{8...11} = 0; + let Inst{12...13} = 0; // reserved + let Inst{14...15} = 0; // reserved + let Inst{16...31} = IMM32{31...16}; // The instruction. - let Inst{38-42} = XT{4-0}; - let Inst{43-46} = xo; + let Inst{38...42} = XT{4...0}; + let Inst{43...46} = xo; let Inst{47} = XT{5}; - let Inst{48-63} = IMM32{15-0}; + let Inst{48...63} = IMM32{15...0}; } // 8RR:D-Form: [ 1 1 0 // // imm0 @@ -482,18 +482,18 @@ class 8RR_DForm_IMM32_XT6_IX<bits<6> opcode, bits<3> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6-7} = 1; - let Inst{8-11} = 0; - let Inst{12-13} = 0; // reserved - let Inst{14-15} = 0; // reserved - let Inst{16-31} = IMM32{31-16}; + let Inst{6...7} = 1; + let Inst{8...11} = 0; + let Inst{12...13} = 0; // reserved + let Inst{14...15} = 0; // reserved + let Inst{16...31} = IMM32{31...16}; // The instruction. - let Inst{38-42} = XT{4-0}; - let Inst{43-45} = xo; + let Inst{38...42} = XT{4...0}; + let Inst{43...45} = xo; let Inst{46} = IX; let Inst{47} = XT{5}; - let Inst{48-63} = IMM32{15-0}; + let Inst{48...63} = IMM32{15...0}; } class 8RR_XX4Form_XTABC6<bits<6> opcode, bits<2> xo, dag OOL, dag IOL, @@ -507,17 +507,17 @@ class 8RR_XX4Form_XTABC6<bits<6> opcode, bits<2> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6-7} = 1; - let Inst{8-11} = 0; - let Inst{12-13} = 0; - let Inst{14-31} = 0; + let Inst{6...7} = 1; + let Inst{8...11} = 0; + let Inst{12...13} = 0; + let Inst{14...31} = 0; // The instruction. - let Inst{38-42} = XT{4-0}; - let Inst{43-47} = XA{4-0}; - let Inst{48-52} = XB{4-0}; - let Inst{53-57} = XC{4-0}; - let Inst{58-59} = xo; + let Inst{38...42} = XT{4...0}; + let Inst{43...47} = XA{4...0}; + let Inst{48...52} = XB{4...0}; + let Inst{53...57} = XC{4...0}; + let Inst{58...59} = xo; let Inst{60} = XC{5}; let Inst{61} = XA{5}; let Inst{62} = XB{5}; @@ -537,18 +537,18 @@ class 8RR_XX4Form_IMM3_XTABC6<bits<6> opcode, bits<2> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6-7} = 1; - let Inst{8-11} = 0; - let Inst{12-13} = 0; - let Inst{14-28} = 0; - let Inst{29-31} = IMM; + let Inst{6...7} = 1; + let Inst{8...11} = 0; + let Inst{12...13} = 0; + let Inst{14...28} = 0; + let Inst{29...31} = IMM; // The instruction. - let Inst{38-42} = XT{4-0}; - let Inst{43-47} = XA{4-0}; - let Inst{48-52} = XB{4-0}; - let Inst{53-57} = XC{4-0}; - let Inst{58-59} = xo; + let Inst{38...42} = XT{4...0}; + let Inst{43...47} = XA{4...0}; + let Inst{48...52} = XB{4...0}; + let Inst{53...57} = XC{4...0}; + let Inst{58...59} = xo; let Inst{60} = XC{5}; let Inst{61} = XA{5}; let Inst{62} = XB{5}; @@ -565,11 +565,11 @@ class XX2_BF3_XO5_XB6_XO9<bits<6> opcode, bits<5> xo2, bits<9> xo, dag OOL, let Pattern = pattern; - let Inst{6-8} = BF; - let Inst{9-10} = 0; - let Inst{11-15} = xo2; - let Inst{16-20} = XB{4-0}; - let Inst{21-29} = xo; + let Inst{6...8} = BF; + let Inst{9...10} = 0; + let Inst{11...15} = xo2; + let Inst{16...20} = XB{4...0}; + let Inst{21...29} = xo; let Inst{30} = XB{5}; let Inst{31} = 0; } @@ -863,11 +863,11 @@ class DQForm_XTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-9} = XTp{3-0}; + let Inst{6...9} = XTp{3...0}; let Inst{10} = XTp{4}; - let Inst{11-15} = RA; - let Inst{16-27} = DQ; - let Inst{28-31} = xo; + let Inst{11...15} = RA; + let Inst{16...27} = DQ; + let Inst{28...31} = xo; } class XForm_XTp5_XAB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, @@ -878,11 +878,11 @@ class XForm_XTp5_XAB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL, bits<5> RB; let Pattern = pattern; - let Inst{6-9} = XTp{3-0}; + let Inst{6...9} = XTp{3...0}; let Inst{10} = XTp{4}; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-30} = xo; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -896,16 +896,16 @@ class 8LS_DForm_R_XTp5_SI34_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr, let Pattern = pattern; // The prefix. - let Inst{6-10} = 0; + let Inst{6...10} = 0; let Inst{11} = PCRel; - let Inst{12-13} = 0; - let Inst{14-31} = D{33-16}; // Imm18 + let Inst{12...13} = 0; + let Inst{14...31} = D{33...16}; // Imm18 // The instruction. - let Inst{38-41} = XTp{3-0}; + let Inst{38...41} = XTp{3...0}; let Inst{42} = XTp{4}; - let Inst{43-47} = RA; - let Inst{48-63} = D{15-0}; + let Inst{43...47} = RA; + let Inst{48...63} = D{15...0}; } multiclass 8LS_DForm_R_XTp5_SI34_MEM_p<bits<6> opcode, dag OOL, @@ -935,11 +935,11 @@ class XForm_AT3<bits<6> opcode, bits<5> xo2, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-8} = AT; - let Inst{9-10} = 0; - let Inst{11-15} = xo2; - let Inst{16-20} = 0; - let Inst{21-30} = xo; + let Inst{6...8} = AT; + let Inst{9...10} = 0; + let Inst{11...15} = xo2; + let Inst{16...20} = 0; + let Inst{21...30} = xo; let Inst{31} = 0; } @@ -952,10 +952,10 @@ class XForm_XT6_IMM5<bits<6> opcode, bits<5> eo, bits<10> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-10} = XT{4-0}; - let Inst{11-15} = eo; - let Inst{16-20} = UIM; - let Inst{21-30} = xo; + let Inst{6...10} = XT{4...0}; + let Inst{11...15} = eo; + let Inst{16...20} = UIM; + let Inst{21...30} = xo; let Inst{31} = XT{5}; } @@ -969,11 +969,11 @@ class XX3Form_AT3_XAB6<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; - let Inst{6-8} = AT; - let Inst{9-10} = 0; - let Inst{11-15} = XA{4-0}; - let Inst{16-20} = XB{4-0}; - let Inst{21-28} = xo; + let Inst{6...8} = AT; + let Inst{9...10} = 0; + let Inst{11...15} = XA{4...0}; + let Inst{16...20} = XB{4...0}; + let Inst{21...28} = xo; let Inst{29} = XA{5}; let Inst{30} = XB{5}; let Inst{31} = 0; @@ -993,20 +993,20 @@ class MMIRR_XX3Form_XY4P2_XAB6<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6-7} = 3; - let Inst{8-11} = 9; - let Inst{12-15} = 0; - let Inst{16-17} = PMSK; - let Inst{18-23} = 0; - let Inst{24-27} = XMSK; - let Inst{28-31} = YMSK; + let Inst{6...7} = 3; + let Inst{8...11} = 9; + let Inst{12...15} = 0; + let Inst{16...17} = PMSK; + let Inst{18...23} = 0; + let Inst{24...27} = XMSK; + let Inst{28...31} = YMSK; // The instruction. - let Inst{38-40} = AT; - let Inst{41-42} = 0; - let Inst{43-47} = XA{4-0}; - let Inst{48-52} = XB{4-0}; - let Inst{53-60} = xo; + let Inst{38...40} = AT; + let Inst{41...42} = 0; + let Inst{43...47} = XA{4...0}; + let Inst{48...52} = XB{4...0}; + let Inst{53...60} = xo; let Inst{61} = XA{5}; let Inst{62} = XB{5}; let Inst{63} = 0; @@ -1025,18 +1025,18 @@ class MMIRR_XX3Form_XY4_XAB6<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6-7} = 3; - let Inst{8-11} = 9; - let Inst{12-23} = 0; - let Inst{24-27} = XMSK; - let Inst{28-31} = YMSK; + let Inst{6...7} = 3; + let Inst{8...11} = 9; + let Inst{12...23} = 0; + let Inst{24...27} = XMSK; + let Inst{28...31} = YMSK; // The instruction. - let Inst{38-40} = AT; - let Inst{41-42} = 0; - let Inst{43-47} = XA{4-0}; - let Inst{48-52} = XB{4-0}; - let Inst{53-60} = xo; + let Inst{38...40} = AT; + let Inst{41...42} = 0; + let Inst{43...47} = XA{4...0}; + let Inst{48...52} = XB{4...0}; + let Inst{53...60} = xo; let Inst{61} = XA{5}; let Inst{62} = XB{5}; let Inst{63} = 0; @@ -1055,19 +1055,19 @@ class MMIRR_XX3Form_X4Y2_XAB6<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6-7} = 3; - let Inst{8-11} = 9; - let Inst{12-23} = 0; - let Inst{24-27} = XMSK; - let Inst{28-29} = YMSK; - let Inst{30-31} = 0; + let Inst{6...7} = 3; + let Inst{8...11} = 9; + let Inst{12...23} = 0; + let Inst{24...27} = XMSK; + let Inst{28...29} = YMSK; + let Inst{30...31} = 0; // The instruction. - let Inst{38-40} = AT; - let Inst{41-42} = 0; - let Inst{43-47} = XA{4-0}; - let Inst{48-52} = XB{4-0}; - let Inst{53-60} = xo; + let Inst{38...40} = AT; + let Inst{41...42} = 0; + let Inst{43...47} = XA{4...0}; + let Inst{48...52} = XB{4...0}; + let Inst{53...60} = xo; let Inst{61} = XA{5}; let Inst{62} = XB{5}; let Inst{63} = 0; @@ -1087,19 +1087,19 @@ class MMIRR_XX3Form_XY4P8_XAB6<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6-7} = 3; - let Inst{8-11} = 9; - let Inst{12-15} = 0; - let Inst{16-23} = PMSK; - let Inst{24-27} = XMSK; - let Inst{28-31} = YMSK; + let Inst{6...7} = 3; + let Inst{8...11} = 9; + let Inst{12...15} = 0; + let Inst{16...23} = PMSK; + let Inst{24...27} = XMSK; + let Inst{28...31} = YMSK; // The instruction. - let Inst{38-40} = AT; - let Inst{41-42} = 0; - let Inst{43-47} = XA{4-0}; - let Inst{48-52} = XB{4-0}; - let Inst{53-60} = xo; + let Inst{38...40} = AT; + let Inst{41...42} = 0; + let Inst{43...47} = XA{4...0}; + let Inst{48...52} = XB{4...0}; + let Inst{53...60} = xo; let Inst{61} = XA{5}; let Inst{62} = XB{5}; let Inst{63} = 0; @@ -1119,20 +1119,20 @@ class MMIRR_XX3Form_XYP4_XAB6<bits<6> opcode, bits<8> xo, dag OOL, dag IOL, let Pattern = pattern; // The prefix. - let Inst{6-7} = 3; - let Inst{8-11} = 9; - let Inst{12-15} = 0; - let Inst{16-19} = PMSK; - let Inst{20-23} = 0; - let Inst{24-27} = XMSK; - let Inst{28-31} = YMSK; + let Inst{6...7} = 3; + let Inst{8...11} = 9; + let Inst{12...15} = 0; + let Inst{16...19} = PMSK; + let Inst{20...23} = 0; + let Inst{24...27} = XMSK; + let Inst{28...31} = YMSK; // The instruction. - let Inst{38-40} = AT; - let Inst{41-42} = 0; - let Inst{43-47} = XA{4-0}; - let Inst{48-52} = XB{4-0}; - let Inst{53-60} = xo; + let Inst{38...40} = AT; + let Inst{41...42} = 0; + let Inst{43...47} = XA{4...0}; + let Inst{48...52} = XB{4...0}; + let Inst{53...60} = xo; let Inst{61} = XA{5}; let Inst{62} = XB{5}; let Inst{63} = 0; diff --git a/llvm/lib/Target/PowerPC/PPCInstrSPE.td b/llvm/lib/Target/PowerPC/PPCInstrSPE.td index e91cae3..5104cc6 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrSPE.td +++ b/llvm/lib/Target/PowerPC/PPCInstrSPE.td @@ -20,10 +20,10 @@ class EFXForm_1<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-31} = xo; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...31} = xo; } class EFXForm_2<bits<11> xo, dag OOL, dag IOL, string asmstr, @@ -45,11 +45,11 @@ class EFXForm_3<bits<11> xo, dag OOL, dag IOL, string asmstr, bits<5> RA; bits<5> RB; - let Inst{6-8} = crD; - let Inst{9-10} = 0; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-31} = xo; + let Inst{6...8} = crD; + let Inst{9...10} = 0; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...31} = xo; } class EVXForm_1<bits<11> xo, dag OOL, dag IOL, string asmstr, @@ -61,10 +61,10 @@ class EVXForm_1<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-31} = xo; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...31} = xo; } class EVXForm_2<bits<11> xo, dag OOL, dag IOL, string asmstr, @@ -88,11 +88,11 @@ class EVXForm_3<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-8} = crD; - let Inst{9-10} = 0; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-31} = xo; + let Inst{6...8} = crD; + let Inst{9...10} = 0; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...31} = xo; } class EVXForm_4<bits<8> xo, dag OOL, dag IOL, string asmstr, @@ -105,11 +105,11 @@ class EVXForm_4<bits<8> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = RB; - let Inst{21-28} = xo; - let Inst{29-31} = crD; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = RB; + let Inst{21...28} = xo; + let Inst{29...31} = crD; } class EVXForm_D<bits<11> xo, dag OOL, dag IOL, string asmstr, @@ -121,10 +121,10 @@ class EVXForm_D<bits<11> xo, dag OOL, dag IOL, string asmstr, let Pattern = pattern; - let Inst{6-10} = RT; - let Inst{11-15} = RA; - let Inst{16-20} = D; - let Inst{21-31} = xo; + let Inst{6...10} = RT; + let Inst{11...15} = RA; + let Inst{16...20} = D; + let Inst{21...31} = xo; } let DecoderNamespace = "SPE", Predicates = [HasSPE] in { diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt index 531238a..0ff178e 100644 --- a/llvm/lib/Target/RISCV/CMakeLists.txt +++ b/llvm/lib/Target/RISCV/CMakeLists.txt @@ -88,6 +88,7 @@ add_llvm_target(RISCVCodeGen GlobalISel IPO MC + Passes RISCVDesc RISCVInfo Scalar diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp index b1b7ea5..89df9d8 100644 --- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp +++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp @@ -46,8 +46,6 @@ public: raw_ostream &CStream) const override; private: - void addSPOperands(MCInst &MI) const; - DecodeStatus getInstruction48(MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address, raw_ostream &CStream) const; @@ -196,6 +194,12 @@ static DecodeStatus DecodeFPR128RegisterClass(MCInst &Inst, uint32_t RegNo, return MCDisassembler::Success; } +static DecodeStatus DecodeSPRegisterClass(MCInst &Inst, + const MCDisassembler *Decoder) { + Inst.addOperand(MCOperand::createReg(RISCV::X2)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeGPRNoX0RegisterClass(MCInst &Inst, uint32_t RegNo, uint64_t Address, const MCDisassembler *Decoder) { @@ -600,15 +604,6 @@ static DecodeStatus decodeXTHeadMemPair(MCInst &Inst, uint32_t Insn, #include "RISCVGenDisassemblerTables.inc" -// Add implied SP operand for C.*SP compressed instructions. The SP operand -// isn't explicitly encoded in the instruction. -void RISCVDisassembler::addSPOperands(MCInst &MI) const { - const MCInstrDesc &MCID = MCII->get(MI.getOpcode()); - for (unsigned i = 0; i < MCID.getNumOperands(); i++) - if (MCID.operands()[i].RegClass == RISCV::SPRegClassID) - MI.insert(MI.begin() + i, MCOperand::createReg(RISCV::X2)); -} - namespace { struct DecoderListEntry { @@ -774,12 +769,8 @@ DecodeStatus RISCVDisassembler::getInstruction16(MCInst &MI, uint64_t &Size, LLVM_DEBUG(dbgs() << "Trying " << Entry.Desc << " table:\n"); DecodeStatus Result = decodeInstruction(Entry.Table, MI, Insn, Address, this, STI); - if (Result == MCDisassembler::Fail) - continue; - - addSPOperands(MI); - - return Result; + if (Result != MCDisassembler::Fail) + return Result; } return MCDisassembler::Fail; diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormatsC.td b/llvm/lib/Target/RISCV/RISCVInstrFormatsC.td index 209c3fa..4c7cd05 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrFormatsC.td +++ b/llvm/lib/Target/RISCV/RISCVInstrFormatsC.td @@ -54,7 +54,6 @@ class RVInst16CSS<bits<3> funct3, bits<2> opcode, dag outs, dag ins, : RVInst16<outs, ins, opcodestr, argstr, [], InstFormatCSS> { bits<10> imm; bits<5> rs2; - bits<5> rs1; let Inst{15-13} = funct3; let Inst{12-7} = imm{5-0}; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td index bfc766d..9fc7366 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoC.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoC.td @@ -230,13 +230,17 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in class CStackLoad<bits<3> funct3, string OpcodeStr, DAGOperand cls, DAGOperand opnd> : RVInst16CI<funct3, 0b10, (outs cls:$rd), (ins SPMem:$rs1, opnd:$imm), - OpcodeStr, "$rd, ${imm}(${rs1})">; + OpcodeStr, "$rd, ${imm}(${rs1})"> { + bits<0> rs1; +} let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in class CStackStore<bits<3> funct3, string OpcodeStr, DAGOperand cls, DAGOperand opnd> : RVInst16CSS<funct3, 0b10, (outs), (ins cls:$rs2, SPMem:$rs1, opnd:$imm), - OpcodeStr, "$rs2, ${imm}(${rs1})">; + OpcodeStr, "$rs2, ${imm}(${rs1})"> { + bits<0> rs1; +} let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in class CLoad_ri<bits<3> funct3, string OpcodeStr, diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXwch.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXwch.td index a43cbad..bb1862c 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXwch.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXwch.td @@ -106,6 +106,7 @@ def QK_C_LBUSP : QKStackInst<0b00, (outs GPRC:$rd_rs2), (ins SPMem:$rs1, uimm4:$imm), "qk.c.lbusp", "$rd_rs2, ${imm}(${rs1})">, Sched<[WriteLDB, ReadMemBase]> { + bits<0> rs1; bits<4> imm; let Inst{10-7} = imm; } @@ -115,6 +116,7 @@ def QK_C_SBSP : QKStackInst<0b10, (outs), uimm4:$imm), "qk.c.sbsp", "$rd_rs2, ${imm}(${rs1})">, Sched<[WriteSTB, ReadStoreData, ReadMemBase]> { + bits<0> rs1; bits<4> imm; let Inst{10-7} = imm; } @@ -124,6 +126,7 @@ def QK_C_LHUSP : QKStackInst<0b01, (outs GPRC:$rd_rs2), (ins SPMem:$rs1, uimm5_lsb0:$imm), "qk.c.lhusp", "$rd_rs2, ${imm}(${rs1})">, Sched<[WriteLDH, ReadMemBase]> { + bits<0> rs1; bits<5> imm; let Inst{10-8} = imm{3-1}; let Inst{7} = imm{4}; @@ -133,6 +136,7 @@ def QK_C_SHSP : QKStackInst<0b11, (outs), (ins GPRC:$rd_rs2, SPMem:$rs1, uimm5_lsb0:$imm), "qk.c.shsp", "$rd_rs2, ${imm}(${rs1})">, Sched<[WriteSTH, ReadStoreData, ReadMemBase]> { + bits<0> rs1; bits<5> imm; let Inst{10-8} = imm{3-1}; let Inst{7} = imm{4}; diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp index d70b1d0..460bb33 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp @@ -652,7 +652,8 @@ void RISCVPassConfig::addPostRegAlloc() { void RISCVTargetMachine::registerPassBuilderCallbacks(PassBuilder &PB) { PB.registerLateLoopOptimizationsEPCallback([=](LoopPassManager &LPM, OptimizationLevel Level) { - LPM.addPass(LoopIdiomVectorizePass(LoopIdiomVectorizeStyle::Predicated)); + if (Level != OptimizationLevel::O0) + LPM.addPass(LoopIdiomVectorizePass(LoopIdiomVectorizeStyle::Predicated)); }); } diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp index b94ed7d..2cfd70a 100644 --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -3397,8 +3397,8 @@ DIExpression *llvm::getExpressionForConstant(DIBuilder &DIB, const Constant &C, if (FP && Ty.isFloatingPointTy() && Ty.getScalarSizeInBits() <= 64) { const APFloat &APF = FP->getValueAPF(); APInt const &API = APF.bitcastToAPInt(); - if (auto Temp = API.getZExtValue()) - return DIB.createConstantValueExpression(static_cast<uint64_t>(Temp)); + if (uint64_t Temp = API.getZExtValue()) + return DIB.createConstantValueExpression(Temp); return DIB.createConstantValueExpression(*API.getRawData()); } diff --git a/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll b/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll index fe140d0..432a4d7 100644 --- a/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll +++ b/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll @@ -427,6 +427,53 @@ exit: ; preds = %loop ret i32 %crc.next } +define i16 @crc16.be.tc8.zext.data(i8 %msg, i16 %checksum) { +; CHECK-LABEL: 'crc16.be.tc8.zext.data' +; CHECK-NEXT: Found big-endian CRC-16 loop with trip count 8 +; CHECK-NEXT: Initial CRC: i16 %checksum +; CHECK-NEXT: Generating polynomial: 258 +; CHECK-NEXT: Computed CRC: %crc.next = select i1 %check.sb, i16 %crc.shl, i16 %crc.xor +; CHECK-NEXT: Auxiliary data: i8 %msg +; CHECK-NEXT: Computed CRC lookup table: +; CHECK-NEXT: 0 258 516 774 1032 1290 1548 1806 2064 2322 2580 2838 3096 3354 3612 3870 +; CHECK-NEXT: 4128 4386 4644 4902 5160 5418 5676 5934 6192 6450 6708 6966 7224 7482 7740 7998 +; CHECK-NEXT: 8256 8514 8772 9030 9288 9546 9804 10062 10320 10578 10836 11094 11352 11610 11868 12126 +; CHECK-NEXT: 12384 12642 12900 13158 13416 13674 13932 14190 14448 14706 14964 15222 15480 15738 15996 16254 +; CHECK-NEXT: 16512 16770 17028 17286 17544 17802 18060 18318 18576 18834 19092 19350 19608 19866 20124 20382 +; CHECK-NEXT: 20640 20898 21156 21414 21672 21930 22188 22446 22704 22962 23220 23478 23736 23994 24252 24510 +; CHECK-NEXT: 24768 25026 25284 25542 25800 26058 26316 26574 26832 27090 27348 27606 27864 28122 28380 28638 +; CHECK-NEXT: 28896 29154 29412 29670 29928 30186 30444 30702 30960 31218 31476 31734 31992 32250 32508 32766 +; CHECK-NEXT: 33024 32770 33540 33286 34056 33802 34572 34318 35088 34834 35604 35350 36120 35866 36636 36382 +; CHECK-NEXT: 37152 36898 37668 37414 38184 37930 38700 38446 39216 38962 39732 39478 40248 39994 40764 40510 +; CHECK-NEXT: 41280 41026 41796 41542 42312 42058 42828 42574 43344 43090 43860 43606 44376 44122 44892 44638 +; CHECK-NEXT: 45408 45154 45924 45670 46440 46186 46956 46702 47472 47218 47988 47734 48504 48250 49020 48766 +; CHECK-NEXT: 49536 49282 50052 49798 50568 50314 51084 50830 51600 51346 52116 51862 52632 52378 53148 52894 +; CHECK-NEXT: 53664 53410 54180 53926 54696 54442 55212 54958 55728 55474 56244 55990 56760 56506 57276 57022 +; CHECK-NEXT: 57792 57538 58308 58054 58824 58570 59340 59086 59856 59602 60372 60118 60888 60634 61404 61150 +; CHECK-NEXT: 61920 61666 62436 62182 62952 62698 63468 63214 63984 63730 64500 64246 65016 64762 65532 65278 +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ] + %data = phi i8 [ %msg, %entry ], [ %data.next, %loop ] + %crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ] + %data.ext = zext i8 %data to i16 + %xor.crc.data = xor i16 %crc, %data.ext + %check.sb = icmp sge i16 %xor.crc.data, 0 + %crc.shl = shl i16 %crc, 1 + %crc.xor = xor i16 %crc.shl, 258 + %crc.next = select i1 %check.sb, i16 %crc.shl, i16 %crc.xor + %data.next = shl i8 %data, 1 + %iv.next = add nuw nsw i8 %iv, 1 + %exit.cond = icmp samesign ult i8 %iv, 7 + br i1 %exit.cond, label %loop, label %exit + +exit: ; preds = %loop + ret i16 %crc.next +} + ; Negative tests define i16 @not.crc.non.const.tc(i16 %crc.init, i32 %loop.limit) { @@ -649,7 +696,7 @@ exit: ; preds = %loop define i16 @not.crc.wrong.sb.check.const(i8 %msg, i16 %checksum) { ; CHECK-LABEL: 'not.crc.wrong.sb.check.const' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Bad RHS of significant-bit-check +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -676,7 +723,7 @@ exit: ; preds = %loop define i16 @not.crc.wrong.sb.check.pred(i16 %crc.init) { ; CHECK-LABEL: 'not.crc.wrong.sb.check.pred' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Bad RHS of significant-bit-check +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -750,7 +797,7 @@ exit: ; preds = %loop define i32 @not.crc.unknown.icmp.rhs(i32 %checksum, i32 %msg, i32 %unknown) { ; CHECK-LABEL: 'not.crc.unknown.icmp.rhs' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Bad LHS of significant-bit-check +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -777,7 +824,7 @@ exit: ; preds = %loop define i32 @not.crc.unknown.icmp.lhs(i32 %checksum, i32 %msg, i32 %unknown) { ; CHECK-LABEL: 'not.crc.unknown.icmp.lhs' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Bad LHS of significant-bit-check +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -805,7 +852,7 @@ exit: ; preds = %loop define i16 @not.crc.stray.or(i16 %msg, i16 %checksum) { ; CHECK-LABEL: 'not.crc.stray.or' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Bad LHS of significant-bit-check +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -833,7 +880,7 @@ exit: ; preds = %loop define i16 @not.crc.inverse.sb.check(i16 %msg, i16 %checksum) { ; CHECK-LABEL: 'not.crc.inverse.sb.check' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Expected top 16 bits zero (1100000000000001) +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -857,10 +904,10 @@ exit: ; preds = %loop ret i16 %crc.next } -define i16 @crc1.tc8.sb.check.endian.mismatch(i8 %msg, i16 %checksum) { -; CHECK-LABEL: 'crc1.tc8.sb.check.endian.mismatch' +define i16 @not.crc.sb.check.endian.mismatch(i8 %msg, i16 %checksum) { +; CHECK-LABEL: 'not.crc.sb.check.endian.mismatch' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Bad RHS of significant-bit-check +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -888,7 +935,7 @@ exit: ; preds = %loop define i16 @not.crc.init.arg.inverted.select(i16 %crc.init) { ; CHECK-LABEL: 'not.crc.init.arg.inverted.select' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Expected top 8 bits zero (11000000????????) +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -912,7 +959,7 @@ exit: ; preds = %loop define i16 @not.crc.bad.endian.swapped.sb.check(i8 %msg, i16 %checksum) { ; CHECK-LABEL: 'not.crc.bad.endian.swapped.sb.check' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Found stray unvisited instructions +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -1109,7 +1156,7 @@ exit: ; preds = %loop define i16 @not.crc.unknown.value(i16 %msg, i16 %checksum, i16 %corrupt) { ; CHECK-LABEL: 'not.crc.unknown.value' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Unknown Value +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -1134,6 +1181,63 @@ exit: ; preds = %loop ret i16 %crc.next } +define i16 @not.crc.unknown.call.outside.loop(i16 %msg, i16 %checksum) { +; CHECK-LABEL: 'not.crc.unknown.call.outside.loop' +; CHECK-NEXT: Did not find a hash algorithm +; CHECK-NEXT: Reason: Malformed significant-bit check +; +entry: + %corrupt = call i16 @side.effect() + br label %loop + +loop: ; preds = %loop, %entry + %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ] + %crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ] + %data = phi i16 [ %msg, %entry ], [ %data.next, %loop ] + %xor.crc.data = xor i16 %crc, %data + %xor.crc.data.corrupt = mul i16 %xor.crc.data, %corrupt + %and.crc.data = and i16 %xor.crc.data.corrupt, 1 + %data.next = lshr i16 %data, 1 + %check.sb = icmp eq i16 %and.crc.data, 0 + %crc.lshr = lshr i16 %crc, 1 + %crc.xor = xor i16 %crc.lshr, -24575 + %crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %crc.xor + %iv.next = add nuw nsw i8 %iv, 1 + %exit.cond = icmp samesign ult i8 %iv, 15 + br i1 %exit.cond, label %loop, label %exit + +exit: ; preds = %loop + ret i16 %crc.next +} + +define i16 @not.crc.constant.sb.check.corruption(i16 %msg, i16 %checksum) { +; CHECK-LABEL: 'not.crc.constant.sb.check.corruption' +; CHECK-NEXT: Did not find a hash algorithm +; CHECK-NEXT: Reason: Malformed significant-bit check +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ] + %crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ] + %data = phi i16 [ %msg, %entry ], [ %data.next, %loop ] + %xor.crc.data = xor i16 %crc, %data + %xor.crc.data.corrupt = mul i16 %xor.crc.data, 2 + %and.crc.data = and i16 %xor.crc.data.corrupt, 1 + %data.next = lshr i16 %data, 1 + %check.sb = icmp eq i16 %and.crc.data, 0 + %crc.lshr = lshr i16 %crc, 1 + %crc.xor = xor i16 %crc.lshr, -24575 + %crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %crc.xor + %iv.next = add nuw nsw i8 %iv, 1 + %exit.cond = icmp samesign ult i8 %iv, 15 + br i1 %exit.cond, label %loop, label %exit + +exit: ; preds = %loop + ret i16 %crc.next +} + define i16 @not.crc.float.simple.recurrence(float %msg, i16 %checksum) { ; CHECK-LABEL: 'not.crc.float.simple.recurrence' ; CHECK-NEXT: Did not find a hash algorithm @@ -1219,7 +1323,7 @@ declare void @print(i16) define i16 @not.crc.call.sb.check(i16 %crc.init) { ; CHECK-LABEL: 'not.crc.call.sb.check' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Found stray unvisited instructions +; CHECK-NEXT: Reason: Malformed significant-bit check ; entry: br label %loop @@ -1240,4 +1344,108 @@ exit: ; preds = %loop ret i16 %crc.next } +define i16 @not.crc.bad.lhs.sb.check.be(i16 %crc.init) { +; CHECK-LABEL: 'not.crc.bad.lhs.sb.check.be' +; CHECK-NEXT: Did not find a hash algorithm +; CHECK-NEXT: Reason: Malformed significant-bit check +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ] + %crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ] + %crc.shl = shl i16 %crc, 1 + %crc.xor = xor i16 %crc.shl, 4129 + %check.sb = icmp slt i16 %crc.shl, 0 + %crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl + %iv.next = add nuw nsw i32 %iv, 1 + %exit.cond = icmp samesign ult i32 %iv, 7 + br i1 %exit.cond, label %loop, label %exit + +exit: ; preds = %loop + ret i16 %crc.next +} + +define i16 @not.crc.bad.cast.sext(i8 %msg, i16 %checksum) { +; CHECK-LABEL: 'not.crc.bad.cast.sext' +; CHECK-NEXT: Did not find a hash algorithm +; CHECK-NEXT: Reason: Recurrences not intertwined with XOR +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ] + %data = phi i8 [ %msg, %entry ], [ %data.next, %loop ] + %crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ] + %data.ext = sext i8 %data to i16 + %xor.crc.data = xor i16 %crc, %data.ext + %check.sb = icmp sge i16 %xor.crc.data, 0 + %crc.shl = shl i16 %crc, 1 + %crc.xor = xor i16 %crc.shl, 258 + %crc.next = select i1 %check.sb, i16 %crc.shl, i16 %crc.xor + %data.next = shl i8 %data, 1 + %iv.next = add nuw nsw i8 %iv, 1 + %exit.cond = icmp samesign ult i8 %iv, 7 + br i1 %exit.cond, label %loop, label %exit + +exit: ; preds = %loop + ret i16 %crc.next +} + + +define i16 @not.crc.sb.check.patternmatch.fail(i16 %crc.init) { +; CHECK-LABEL: 'not.crc.sb.check.patternmatch.fail' +; CHECK-NEXT: Did not find a hash algorithm +; CHECK-NEXT: Reason: Malformed significant-bit check +; +entry: + br label %loop + +loop: ; preds = %loop, %entry + %iv = phi i16 [ 0, %entry ], [ %iv.next, %loop ] + %crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ] + %crc.shl = shl i16 %crc, 1 + %evil.and.iv = and i16 %iv, 2 + %evil.and.1 = add i16 %evil.and.iv, 1 + %evil.mul = mul i16 %crc.shl, %evil.and.1 + %evil.xor = xor i16 %evil.mul, 4129 + %check.sb = icmp slt i16 %crc, 0 + %crc.next = select i1 %check.sb, i16 %evil.xor, i16 %evil.mul + %iv.next = add nuw nsw i16 %iv, 1 + %exitcond.not = icmp eq i16 %iv.next, 8 + br i1 %exitcond.not, label %exit, label %loop + +exit: ; preds = %loop + ret i16 %crc.next +} + +define i16 @not.crc.sb.check.patternmatch.fail.call.outside.loop(i16 %crc.init) { +; CHECK-LABEL: 'not.crc.sb.check.patternmatch.fail.call.outside.loop' +; CHECK-NEXT: Did not find a hash algorithm +; CHECK-NEXT: Reason: Malformed significant-bit check +; +entry: + %corrupt = call i16 @side.effect() + br label %loop + +loop: ; preds = %loop, %entry + %iv = phi i16 [ 0, %entry ], [ %iv.next, %loop ] + %crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ] + %crc.shl = shl i16 %crc, 1 + %evil.and.corrupt = and i16 %corrupt, 2 + %evil.and.1 = add i16 %evil.and.corrupt, 1 + %evil.mul = mul i16 %crc.shl, %evil.and.1 + %evil.xor = xor i16 %evil.mul, 4129 + %check.sb = icmp slt i16 %crc, 0 + %crc.next = select i1 %check.sb, i16 %evil.xor, i16 %evil.mul + %iv.next = add nuw nsw i16 %iv, 1 + %exitcond.not = icmp eq i16 %iv.next, 8 + br i1 %exitcond.not, label %exit, label %loop + +exit: ; preds = %loop + ret i16 %crc.next +} + declare i16 @side.effect() diff --git a/llvm/test/CodeGen/AArch64/freeze.ll b/llvm/test/CodeGen/AArch64/freeze.ll index 36d88c5..2a33a4c 100644 --- a/llvm/test/CodeGen/AArch64/freeze.ll +++ b/llvm/test/CodeGen/AArch64/freeze.ll @@ -430,6 +430,82 @@ define <8 x i16> @freeze_abds(<8 x i16> %a, <8 x i16> %b) { ret <8 x i16> %r } +; TODO: Unnecessary final and +define <8 x i16> @freeze_uhadd(<8 x i16> %a0, <8 x i16> %a1) { +; CHECK-LABEL: freeze_uhadd: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v2.8h, #15 +; CHECK-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-NEXT: and v1.16b, v1.16b, v2.16b +; CHECK-NEXT: movi v2.8h, #31 +; CHECK-NEXT: uhadd v0.8h, v0.8h, v1.8h +; CHECK-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-NEXT: ret + %m0 = and <8 x i16> %a0, splat (i16 15) + %m1 = and <8 x i16> %a1, splat (i16 15) + %avg = call <8 x i16> @llvm.aarch64.neon.uhadd.v8i16(<8 x i16> %m0, <8 x i16> %m1) + %frozen = freeze <8 x i16> %avg + %masked = and <8 x i16> %frozen, splat (i16 31) + ret <8 x i16> %masked +} + +; TODO: Unnecessary final and +define <8 x i16> @freeze_urhadd(<8 x i16> %a0, <8 x i16> %a1) { +; CHECK-LABEL: freeze_urhadd: +; CHECK: // %bb.0: +; CHECK-NEXT: movi v2.8h, #15 +; CHECK-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-NEXT: and v1.16b, v1.16b, v2.16b +; CHECK-NEXT: movi v2.8h, #31 +; CHECK-NEXT: urhadd v0.8h, v0.8h, v1.8h +; CHECK-NEXT: and v0.16b, v0.16b, v2.16b +; CHECK-NEXT: ret + %m0 = and <8 x i16> %a0, splat (i16 15) + %m1 = and <8 x i16> %a1, splat (i16 15) + %avg = call <8 x i16> @llvm.aarch64.neon.urhadd.v8i16(<8 x i16> %m0, <8 x i16> %m1) + %frozen = freeze <8 x i16> %avg + %masked = and <8 x i16> %frozen, splat (i16 31) + ret <8 x i16> %masked +} + +; TODO: Unnecessary sext_inreg +define <8 x i16> @freeze_shadd(<8 x i8> %a0, <8 x i16> %a1) { +; CHECK-LABEL: freeze_shadd: +; CHECK: // %bb.0: +; CHECK-NEXT: sshll v0.8h, v0.8b, #0 +; CHECK-NEXT: sshr v1.8h, v1.8h, #8 +; CHECK-NEXT: shadd v0.8h, v0.8h, v1.8h +; CHECK-NEXT: shl v0.8h, v0.8h, #8 +; CHECK-NEXT: sshr v0.8h, v0.8h, #8 +; CHECK-NEXT: ret + %x0 = sext <8 x i8> %a0 to <8 x i16> + %x1 = ashr <8 x i16> %a1, splat (i16 8) + %avg = call <8 x i16> @llvm.aarch64.neon.shadd.v8i16(<8 x i16> %x0, <8 x i16> %x1) + %frozen = freeze <8 x i16> %avg + %trunc = trunc <8 x i16> %frozen to <8 x i8> + %sext = sext <8 x i8> %trunc to <8 x i16> + ret <8 x i16> %sext +} + +; TODO: Unnecessary sext_inreg +define <8 x i16> @freeze_srhadd(<8 x i8> %a0, <8 x i16> %a1) { +; CHECK-LABEL: freeze_srhadd: +; CHECK: // %bb.0: +; CHECK-NEXT: sshll v0.8h, v0.8b, #0 +; CHECK-NEXT: sshr v1.8h, v1.8h, #8 +; CHECK-NEXT: srhadd v0.8h, v0.8h, v1.8h +; CHECK-NEXT: shl v0.8h, v0.8h, #8 +; CHECK-NEXT: sshr v0.8h, v0.8h, #8 +; CHECK-NEXT: ret + %x0 = sext <8 x i8> %a0 to <8 x i16> + %x1 = ashr <8 x i16> %a1, splat (i16 8) + %avg = call <8 x i16> @llvm.aarch64.neon.srhadd.v8i16(<8 x i16> %x0, <8 x i16> %x1) + %frozen = freeze <8 x i16> %avg + %trunc = trunc <8 x i16> %frozen to <8 x i8> + %sext = sext <8 x i8> %trunc to <8 x i16> + ret <8 x i16> %sext +} + define i32 @freeze_scmp(i32 %a0) nounwind { ; CHECK-LABEL: freeze_scmp: ; CHECK: // %bb.0: diff --git a/llvm/test/CodeGen/AMDGPU/addsub64_carry.ll b/llvm/test/CodeGen/AMDGPU/addsub64_carry.ll new file mode 100644 index 0000000..d326966 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/addsub64_carry.ll @@ -0,0 +1,396 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +;; Test that carryout from 64-bit add/sub (synthesized from two 32-bit adds/subs) is utilized +;; (i.e. no additional compare is generated). + +; RUN: llc -mtriple=amdgcn-amd-amdpal -mcpu=gfx900 < %s | FileCheck %s + +%struct.uint96 = type { i64, i32 } +%struct.uint64pair = type { i64, i64 } + +declare {i64, i1} @llvm.uadd.with.overflow.i64(i64, i64) +declare {i64, i1} @llvm.usub.with.overflow.i64(i64, i64) + +declare {<2 x i64>, <2 x i1>} @llvm.uadd.with.overflow.v2i64(<2 x i64>, <2 x i64>) +declare {<2 x i64>, <2 x i1>} @llvm.usub.with.overflow.v2i64(<2 x i64>, <2 x i64>) + +define %struct.uint96 @v_add64_32(i64 %val64A, i64 %val64B, i32 %val32) { +; CHECK-LABEL: v_add64_32: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_add_co_u32_e32 v5, vcc, v0, v2 +; CHECK-NEXT: v_addc_co_u32_e32 v6, vcc, v1, v3, vcc +; CHECK-NEXT: v_cmp_lt_u64_e32 vcc, v[5:6], v[0:1] +; CHECK-NEXT: v_mov_b32_e32 v0, v5 +; CHECK-NEXT: v_addc_co_u32_e32 v2, vcc, 0, v4, vcc +; CHECK-NEXT: v_mov_b32_e32 v1, v6 +; CHECK-NEXT: s_setpc_b64 s[30:31] + %sum64 = add i64 %val64A, %val64B + %obit = icmp ult i64 %sum64, %val64A + %obit32 = zext i1 %obit to i32 + %sum32 = add i32 %val32, %obit32 + %.fca.0.insert = insertvalue %struct.uint96 poison, i64 %sum64, 0 + %.fca.1.insert = insertvalue %struct.uint96 %.fca.0.insert, i32 %sum32, 1 + ret %struct.uint96 %.fca.1.insert +} + +define <2 x i64> @v_uadd_v2i64(<2 x i64> %val0, <2 x i64> %val1, ptr %ptrval) { +; CHECK-LABEL: v_uadd_v2i64: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_add_co_u32_e32 v6, vcc, v2, v6 +; CHECK-NEXT: v_addc_co_u32_e32 v7, vcc, v3, v7, vcc +; CHECK-NEXT: v_add_co_u32_e32 v4, vcc, v0, v4 +; CHECK-NEXT: v_addc_co_u32_e32 v5, vcc, v1, v5, vcc +; CHECK-NEXT: v_cmp_lt_u64_e32 vcc, v[4:5], v[0:1] +; CHECK-NEXT: flat_store_dwordx4 v[8:9], v[4:7] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc +; CHECK-NEXT: v_cmp_lt_u64_e32 vcc, v[6:7], v[2:3] +; CHECK-NEXT: v_mov_b32_e32 v1, v0 +; CHECK-NEXT: v_cndmask_b32_e64 v2, 0, -1, vcc +; CHECK-NEXT: v_mov_b32_e32 v3, v2 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] + %pair = call {<2 x i64>, <2 x i1>} @llvm.uadd.with.overflow.v2i64(<2 x i64> %val0, <2 x i64> %val1) + %val = extractvalue {<2 x i64>, <2 x i1>} %pair, 0 + %obit = extractvalue {<2 x i64>, <2 x i1>} %pair, 1 + %res = sext <2 x i1> %obit to <2 x i64> + store <2 x i64> %val, ptr %ptrval + ret <2 x i64> %res +} + +define <2 x i64> @v_usub_v2i64(<2 x i64> %val0, <2 x i64> %val1, ptr %ptrval) { +; CHECK-LABEL: v_usub_v2i64: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_sub_co_u32_e32 v6, vcc, v2, v6 +; CHECK-NEXT: v_subb_co_u32_e32 v7, vcc, v3, v7, vcc +; CHECK-NEXT: v_sub_co_u32_e32 v4, vcc, v0, v4 +; CHECK-NEXT: v_subb_co_u32_e32 v5, vcc, v1, v5, vcc +; CHECK-NEXT: v_cmp_gt_u64_e32 vcc, v[4:5], v[0:1] +; CHECK-NEXT: flat_store_dwordx4 v[8:9], v[4:7] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc +; CHECK-NEXT: v_cmp_gt_u64_e32 vcc, v[6:7], v[2:3] +; CHECK-NEXT: v_mov_b32_e32 v1, v0 +; CHECK-NEXT: v_cndmask_b32_e64 v2, 0, -1, vcc +; CHECK-NEXT: v_mov_b32_e32 v3, v2 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] + %pair = call {<2 x i64>, <2 x i1>} @llvm.usub.with.overflow.v2i64(<2 x i64> %val0, <2 x i64> %val1) + %val = extractvalue {<2 x i64>, <2 x i1>} %pair, 0 + %obit = extractvalue {<2 x i64>, <2 x i1>} %pair, 1 + %res = sext <2 x i1> %obit to <2 x i64> + store <2 x i64> %val, ptr %ptrval + ret <2 x i64> %res +} + +define i64 @v_uadd_i64(i64 %val0, i64 %val1, ptr %ptrval) { +; CHECK-LABEL: v_uadd_i64: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_add_co_u32_e32 v2, vcc, v0, v2 +; CHECK-NEXT: v_addc_co_u32_e32 v3, vcc, v1, v3, vcc +; CHECK-NEXT: v_cmp_lt_u64_e32 vcc, v[2:3], v[0:1] +; CHECK-NEXT: flat_store_dwordx2 v[4:5], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc +; CHECK-NEXT: v_mov_b32_e32 v1, v0 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] + %pair = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %val0, i64 %val1) + %val = extractvalue {i64, i1} %pair, 0 + %obit = extractvalue {i64, i1} %pair, 1 + %res = sext i1 %obit to i64 + store i64 %val, ptr %ptrval + ret i64 %res +} + +define i64 @v_uadd_p1(i64 %val0, i64 %val1, ptr %ptrval) { +; CHECK-LABEL: v_uadd_p1: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_add_co_u32_e32 v0, vcc, 1, v0 +; CHECK-NEXT: v_addc_co_u32_e32 v1, vcc, 0, v1, vcc +; CHECK-NEXT: v_cmp_eq_u64_e32 vcc, 0, v[0:1] +; CHECK-NEXT: flat_store_dwordx2 v[4:5], v[0:1] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc +; CHECK-NEXT: v_mov_b32_e32 v1, v0 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] + %pair = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %val0, i64 1) + %val = extractvalue {i64, i1} %pair, 0 + %obit = extractvalue {i64, i1} %pair, 1 + %res = sext i1 %obit to i64 + store i64 %val, ptr %ptrval + ret i64 %res +} + +define i64 @v_uadd_n1(i64 %val0, i64 %val1, ptr %ptrval) { +; CHECK-LABEL: v_uadd_n1: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_add_co_u32_e32 v2, vcc, -1, v0 +; CHECK-NEXT: v_addc_co_u32_e32 v3, vcc, -1, v1, vcc +; CHECK-NEXT: v_cmp_ne_u64_e32 vcc, 0, v[0:1] +; CHECK-NEXT: flat_store_dwordx2 v[4:5], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc +; CHECK-NEXT: v_mov_b32_e32 v1, v0 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] + %pair = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %val0, i64 -1) + %val = extractvalue {i64, i1} %pair, 0 + %obit = extractvalue {i64, i1} %pair, 1 + %res = sext i1 %obit to i64 + store i64 %val, ptr %ptrval + ret i64 %res +} + +define i64 @v_usub_p1(i64 %val0, i64 %val1, ptr %ptrval) { +; CHECK-LABEL: v_usub_p1: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_add_co_u32_e32 v2, vcc, -1, v0 +; CHECK-NEXT: v_addc_co_u32_e32 v3, vcc, -1, v1, vcc +; CHECK-NEXT: v_cmp_gt_u64_e32 vcc, v[2:3], v[0:1] +; CHECK-NEXT: flat_store_dwordx2 v[4:5], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc +; CHECK-NEXT: v_mov_b32_e32 v1, v0 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] + %pair = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val0, i64 1) + %val = extractvalue {i64, i1} %pair, 0 + %obit = extractvalue {i64, i1} %pair, 1 + %res = sext i1 %obit to i64 + store i64 %val, ptr %ptrval + ret i64 %res +} + +define i64 @v_usub_n1(i64 %val0, i64 %val1, ptr %ptrval) { +; CHECK-LABEL: v_usub_n1: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0) +; CHECK-NEXT: v_add_co_u32_e32 v2, vcc, 1, v0 +; CHECK-NEXT: v_addc_co_u32_e32 v3, vcc, 0, v1, vcc +; CHECK-NEXT: v_cmp_gt_u64_e32 vcc, v[2:3], v[0:1] +; CHECK-NEXT: flat_store_dwordx2 v[4:5], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc +; CHECK-NEXT: v_mov_b32_e32 v1, v0 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: s_setpc_b64 s[30:31] + %pair = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val0, i64 -1) + %val = extractvalue {i64, i1} %pair, 0 + %obit = extractvalue {i64, i1} %pair, 1 + %res = sext i1 %obit to i64 + store i64 %val, ptr %ptrval + ret i64 %res +} + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; test SGPR +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +define amdgpu_ps %struct.uint96 @s_add64_32(i64 inreg %val64A, i64 inreg %val64B, i32 inreg %val32) { +; CHECK-LABEL: s_add64_32: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_add_u32 s6, s0, s2 +; CHECK-NEXT: v_mov_b32_e32 v0, s0 +; CHECK-NEXT: s_addc_u32 s7, s1, s3 +; CHECK-NEXT: v_mov_b32_e32 v1, s1 +; CHECK-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[0:1] +; CHECK-NEXT: s_mov_b32 s0, s6 +; CHECK-NEXT: s_cmp_lg_u64 vcc, 0 +; CHECK-NEXT: s_addc_u32 s2, s4, 0 +; CHECK-NEXT: s_mov_b32 s1, s7 +; CHECK-NEXT: ; return to shader part epilog + %sum64 = add i64 %val64A, %val64B + %obit = icmp ult i64 %sum64, %val64A + %obit32 = zext i1 %obit to i32 + %sum32 = add i32 %val32, %obit32 + %.fca.0.insert = insertvalue %struct.uint96 poison, i64 %sum64, 0 + %.fca.1.insert = insertvalue %struct.uint96 %.fca.0.insert, i32 %sum32, 1 + ret %struct.uint96 %.fca.1.insert +} + +define amdgpu_ps <2 x i64> @s_uadd_v2i64(<2 x i64> inreg %val0, <2 x i64> inreg %val1, ptr %ptrval) { +; CHECK-LABEL: s_uadd_v2i64: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_add_u32 s6, s2, s6 +; CHECK-NEXT: v_mov_b32_e32 v9, s3 +; CHECK-NEXT: s_addc_u32 s7, s3, s7 +; CHECK-NEXT: v_mov_b32_e32 v8, s2 +; CHECK-NEXT: s_add_u32 s4, s0, s4 +; CHECK-NEXT: v_mov_b32_e32 v7, s1 +; CHECK-NEXT: v_cmp_lt_u64_e32 vcc, s[6:7], v[8:9] +; CHECK-NEXT: s_addc_u32 s5, s1, s5 +; CHECK-NEXT: v_mov_b32_e32 v6, s0 +; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, -1, vcc +; CHECK-NEXT: v_cmp_lt_u64_e32 vcc, s[4:5], v[6:7] +; CHECK-NEXT: v_readfirstlane_b32 s2, v8 +; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, -1, vcc +; CHECK-NEXT: v_readfirstlane_b32 s0, v6 +; CHECK-NEXT: v_mov_b32_e32 v2, s4 +; CHECK-NEXT: v_mov_b32_e32 v3, s5 +; CHECK-NEXT: v_mov_b32_e32 v4, s6 +; CHECK-NEXT: v_mov_b32_e32 v5, s7 +; CHECK-NEXT: s_mov_b32 s1, s0 +; CHECK-NEXT: s_mov_b32 s3, s2 +; CHECK-NEXT: flat_store_dwordx4 v[0:1], v[2:5] +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: ; return to shader part epilog + %pair = call {<2 x i64>, <2 x i1>} @llvm.uadd.with.overflow.v2i64(<2 x i64> %val0, <2 x i64> %val1) + %val = extractvalue {<2 x i64>, <2 x i1>} %pair, 0 + %obit = extractvalue {<2 x i64>, <2 x i1>} %pair, 1 + %res = sext <2 x i1> %obit to <2 x i64> + store <2 x i64> %val, ptr %ptrval + ret <2 x i64> %res +} + +define amdgpu_ps <2 x i64> @s_usub_v2i64(<2 x i64> inreg %val0, <2 x i64> inreg %val1, ptr %ptrval) { +; CHECK-LABEL: s_usub_v2i64: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_sub_u32 s6, s2, s6 +; CHECK-NEXT: v_mov_b32_e32 v9, s3 +; CHECK-NEXT: s_subb_u32 s7, s3, s7 +; CHECK-NEXT: v_mov_b32_e32 v8, s2 +; CHECK-NEXT: s_sub_u32 s4, s0, s4 +; CHECK-NEXT: v_mov_b32_e32 v7, s1 +; CHECK-NEXT: v_cmp_gt_u64_e32 vcc, s[6:7], v[8:9] +; CHECK-NEXT: s_subb_u32 s5, s1, s5 +; CHECK-NEXT: v_mov_b32_e32 v6, s0 +; CHECK-NEXT: v_cndmask_b32_e64 v8, 0, -1, vcc +; CHECK-NEXT: v_cmp_gt_u64_e32 vcc, s[4:5], v[6:7] +; CHECK-NEXT: v_readfirstlane_b32 s2, v8 +; CHECK-NEXT: v_cndmask_b32_e64 v6, 0, -1, vcc +; CHECK-NEXT: v_readfirstlane_b32 s0, v6 +; CHECK-NEXT: v_mov_b32_e32 v2, s4 +; CHECK-NEXT: v_mov_b32_e32 v3, s5 +; CHECK-NEXT: v_mov_b32_e32 v4, s6 +; CHECK-NEXT: v_mov_b32_e32 v5, s7 +; CHECK-NEXT: s_mov_b32 s1, s0 +; CHECK-NEXT: s_mov_b32 s3, s2 +; CHECK-NEXT: flat_store_dwordx4 v[0:1], v[2:5] +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: ; return to shader part epilog + %pair = call {<2 x i64>, <2 x i1>} @llvm.usub.with.overflow.v2i64(<2 x i64> %val0, <2 x i64> %val1) + %val = extractvalue {<2 x i64>, <2 x i1>} %pair, 0 + %obit = extractvalue {<2 x i64>, <2 x i1>} %pair, 1 + %res = sext <2 x i1> %obit to <2 x i64> + store <2 x i64> %val, ptr %ptrval + ret <2 x i64> %res +} + +define amdgpu_ps i64 @s_uadd_i64(i64 inreg %val0, i64 inreg %val1, ptr %ptrval) { +; CHECK-LABEL: s_uadd_i64: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_add_u32 s2, s0, s2 +; CHECK-NEXT: v_mov_b32_e32 v3, s1 +; CHECK-NEXT: s_addc_u32 s3, s1, s3 +; CHECK-NEXT: v_mov_b32_e32 v2, s0 +; CHECK-NEXT: v_mov_b32_e32 v5, s3 +; CHECK-NEXT: v_cmp_lt_u64_e32 vcc, s[2:3], v[2:3] +; CHECK-NEXT: v_mov_b32_e32 v4, s2 +; CHECK-NEXT: flat_store_dwordx2 v[0:1], v[4:5] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc +; CHECK-NEXT: v_readfirstlane_b32 s0, v0 +; CHECK-NEXT: s_mov_b32 s1, s0 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: ; return to shader part epilog + %pair = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %val0, i64 %val1) + %val = extractvalue {i64, i1} %pair, 0 + %obit = extractvalue {i64, i1} %pair, 1 + %res = sext i1 %obit to i64 + store i64 %val, ptr %ptrval + ret i64 %res +} + +define amdgpu_ps i64 @s_uadd_p1(i64 inreg %val0, i64 inreg %val1, ptr %ptrval) { +; CHECK-LABEL: s_uadd_p1: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_add_u32 s0, s0, 1 +; CHECK-NEXT: s_addc_u32 s1, s1, 0 +; CHECK-NEXT: s_cmp_eq_u64 s[0:1], 0 +; CHECK-NEXT: v_mov_b32_e32 v3, s1 +; CHECK-NEXT: v_mov_b32_e32 v2, s0 +; CHECK-NEXT: s_cselect_b64 s[0:1], -1, 0 +; CHECK-NEXT: flat_store_dwordx2 v[0:1], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, s[0:1] +; CHECK-NEXT: v_readfirstlane_b32 s0, v0 +; CHECK-NEXT: s_mov_b32 s1, s0 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: ; return to shader part epilog + %pair = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %val0, i64 1) + %val = extractvalue {i64, i1} %pair, 0 + %obit = extractvalue {i64, i1} %pair, 1 + %res = sext i1 %obit to i64 + store i64 %val, ptr %ptrval + ret i64 %res +} + +define amdgpu_ps i64 @s_uadd_n1(i64 inreg %val0, i64 inreg %val1, ptr %ptrval) { +; CHECK-LABEL: s_uadd_n1: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_add_u32 s2, s0, -1 +; CHECK-NEXT: s_addc_u32 s3, s1, -1 +; CHECK-NEXT: s_cmp_lg_u64 s[0:1], 0 +; CHECK-NEXT: v_mov_b32_e32 v2, s2 +; CHECK-NEXT: v_mov_b32_e32 v3, s3 +; CHECK-NEXT: s_cselect_b64 s[0:1], -1, 0 +; CHECK-NEXT: flat_store_dwordx2 v[0:1], v[2:3] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, s[0:1] +; CHECK-NEXT: v_readfirstlane_b32 s0, v0 +; CHECK-NEXT: s_mov_b32 s1, s0 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: ; return to shader part epilog + %pair = call {i64, i1} @llvm.uadd.with.overflow.i64(i64 %val0, i64 -1) + %val = extractvalue {i64, i1} %pair, 0 + %obit = extractvalue {i64, i1} %pair, 1 + %res = sext i1 %obit to i64 + store i64 %val, ptr %ptrval + ret i64 %res +} + +define amdgpu_ps i64 @s_usub_p1(i64 inreg %val0, i64 inreg %val1, ptr %ptrval) { +; CHECK-LABEL: s_usub_p1: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_add_u32 s2, s0, -1 +; CHECK-NEXT: v_mov_b32_e32 v3, s1 +; CHECK-NEXT: s_addc_u32 s3, s1, -1 +; CHECK-NEXT: v_mov_b32_e32 v2, s0 +; CHECK-NEXT: v_mov_b32_e32 v5, s3 +; CHECK-NEXT: v_cmp_gt_u64_e32 vcc, s[2:3], v[2:3] +; CHECK-NEXT: v_mov_b32_e32 v4, s2 +; CHECK-NEXT: flat_store_dwordx2 v[0:1], v[4:5] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc +; CHECK-NEXT: v_readfirstlane_b32 s0, v0 +; CHECK-NEXT: s_mov_b32 s1, s0 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: ; return to shader part epilog + %pair = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val0, i64 1) + %val = extractvalue {i64, i1} %pair, 0 + %obit = extractvalue {i64, i1} %pair, 1 + %res = sext i1 %obit to i64 + store i64 %val, ptr %ptrval + ret i64 %res +} + +define amdgpu_ps i64 @s_usub_n1(i64 inreg %val0, i64 inreg %val1, ptr %ptrval) { +; CHECK-LABEL: s_usub_n1: +; CHECK: ; %bb.0: +; CHECK-NEXT: s_add_u32 s2, s0, 1 +; CHECK-NEXT: v_mov_b32_e32 v3, s1 +; CHECK-NEXT: s_addc_u32 s3, s1, 0 +; CHECK-NEXT: v_mov_b32_e32 v2, s0 +; CHECK-NEXT: v_mov_b32_e32 v5, s3 +; CHECK-NEXT: v_cmp_gt_u64_e32 vcc, s[2:3], v[2:3] +; CHECK-NEXT: v_mov_b32_e32 v4, s2 +; CHECK-NEXT: flat_store_dwordx2 v[0:1], v[4:5] +; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc +; CHECK-NEXT: v_readfirstlane_b32 s0, v0 +; CHECK-NEXT: s_mov_b32 s1, s0 +; CHECK-NEXT: s_waitcnt vmcnt(0) lgkmcnt(0) +; CHECK-NEXT: ; return to shader part epilog + %pair = call {i64, i1} @llvm.usub.with.overflow.i64(i64 %val0, i64 -1) + %val = extractvalue {i64, i1} %pair, 0 + %obit = extractvalue {i64, i1} %pair, 1 + %res = sext i1 %obit to i64 + store i64 %val, ptr %ptrval + ret i64 %res +} diff --git a/llvm/test/CodeGen/RISCV/select-const.ll b/llvm/test/CodeGen/RISCV/select-const.ll index 3d87b7d..5b5548d 100644 --- a/llvm/test/CodeGen/RISCV/select-const.ll +++ b/llvm/test/CodeGen/RISCV/select-const.ll @@ -1077,3 +1077,188 @@ define i32 @sext_or_constant2(i32 signext %x) { %cond = select i1 %cmp, i32 573857, i32 %ext ret i32 %cond } + + +define i32 @select_0_6(i32 signext %x) { +; RV32I-LABEL: select_0_6: +; RV32I: # %bb.0: +; RV32I-NEXT: srai a0, a0, 2 +; RV32I-NEXT: srli a0, a0, 30 +; RV32I-NEXT: slli a0, a0, 1 +; RV32I-NEXT: ret +; +; RV32IF-LABEL: select_0_6: +; RV32IF: # %bb.0: +; RV32IF-NEXT: srai a0, a0, 2 +; RV32IF-NEXT: srli a0, a0, 30 +; RV32IF-NEXT: slli a0, a0, 1 +; RV32IF-NEXT: ret +; +; RV32ZICOND-LABEL: select_0_6: +; RV32ZICOND: # %bb.0: +; RV32ZICOND-NEXT: srli a0, a0, 31 +; RV32ZICOND-NEXT: li a1, 6 +; RV32ZICOND-NEXT: czero.eqz a0, a1, a0 +; RV32ZICOND-NEXT: ret +; +; RV64I-LABEL: select_0_6: +; RV64I: # %bb.0: +; RV64I-NEXT: srai a0, a0, 2 +; RV64I-NEXT: srli a0, a0, 62 +; RV64I-NEXT: slli a0, a0, 1 +; RV64I-NEXT: ret +; +; RV64IFD-LABEL: select_0_6: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: srai a0, a0, 2 +; RV64IFD-NEXT: srli a0, a0, 62 +; RV64IFD-NEXT: slli a0, a0, 1 +; RV64IFD-NEXT: ret +; +; RV64ZICOND-LABEL: select_0_6: +; RV64ZICOND: # %bb.0: +; RV64ZICOND-NEXT: srli a0, a0, 63 +; RV64ZICOND-NEXT: li a1, 6 +; RV64ZICOND-NEXT: czero.eqz a0, a1, a0 +; RV64ZICOND-NEXT: ret + %cmp = icmp sgt i32 %x, -1 + %cond = select i1 %cmp, i32 0, i32 6 + ret i32 %cond +} + +define i32 @select_6_0(i32 signext %x) { +; RV32I-LABEL: select_6_0: +; RV32I: # %bb.0: +; RV32I-NEXT: srli a0, a0, 31 +; RV32I-NEXT: addi a0, a0, -1 +; RV32I-NEXT: andi a0, a0, 6 +; RV32I-NEXT: ret +; +; RV32IF-LABEL: select_6_0: +; RV32IF: # %bb.0: +; RV32IF-NEXT: srli a0, a0, 31 +; RV32IF-NEXT: addi a0, a0, -1 +; RV32IF-NEXT: andi a0, a0, 6 +; RV32IF-NEXT: ret +; +; RV32ZICOND-LABEL: select_6_0: +; RV32ZICOND: # %bb.0: +; RV32ZICOND-NEXT: srli a0, a0, 31 +; RV32ZICOND-NEXT: li a1, 6 +; RV32ZICOND-NEXT: czero.nez a0, a1, a0 +; RV32ZICOND-NEXT: ret +; +; RV64I-LABEL: select_6_0: +; RV64I: # %bb.0: +; RV64I-NEXT: srli a0, a0, 63 +; RV64I-NEXT: addi a0, a0, -1 +; RV64I-NEXT: andi a0, a0, 6 +; RV64I-NEXT: ret +; +; RV64IFD-LABEL: select_6_0: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: srli a0, a0, 63 +; RV64IFD-NEXT: addi a0, a0, -1 +; RV64IFD-NEXT: andi a0, a0, 6 +; RV64IFD-NEXT: ret +; +; RV64ZICOND-LABEL: select_6_0: +; RV64ZICOND: # %bb.0: +; RV64ZICOND-NEXT: srli a0, a0, 63 +; RV64ZICOND-NEXT: li a1, 6 +; RV64ZICOND-NEXT: czero.nez a0, a1, a0 +; RV64ZICOND-NEXT: ret + %cmp = icmp sgt i32 %x, -1 + %cond = select i1 %cmp, i32 6, i32 0 + ret i32 %cond +} + +define i32 @select_0_394(i32 signext %x) { +; RV32I-LABEL: select_0_394: +; RV32I: # %bb.0: +; RV32I-NEXT: srai a0, a0, 31 +; RV32I-NEXT: andi a0, a0, 394 +; RV32I-NEXT: ret +; +; RV32IF-LABEL: select_0_394: +; RV32IF: # %bb.0: +; RV32IF-NEXT: srai a0, a0, 31 +; RV32IF-NEXT: andi a0, a0, 394 +; RV32IF-NEXT: ret +; +; RV32ZICOND-LABEL: select_0_394: +; RV32ZICOND: # %bb.0: +; RV32ZICOND-NEXT: srli a0, a0, 31 +; RV32ZICOND-NEXT: li a1, 394 +; RV32ZICOND-NEXT: czero.eqz a0, a1, a0 +; RV32ZICOND-NEXT: ret +; +; RV64I-LABEL: select_0_394: +; RV64I: # %bb.0: +; RV64I-NEXT: srai a0, a0, 63 +; RV64I-NEXT: andi a0, a0, 394 +; RV64I-NEXT: ret +; +; RV64IFD-LABEL: select_0_394: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: srai a0, a0, 63 +; RV64IFD-NEXT: andi a0, a0, 394 +; RV64IFD-NEXT: ret +; +; RV64ZICOND-LABEL: select_0_394: +; RV64ZICOND: # %bb.0: +; RV64ZICOND-NEXT: srli a0, a0, 63 +; RV64ZICOND-NEXT: li a1, 394 +; RV64ZICOND-NEXT: czero.eqz a0, a1, a0 +; RV64ZICOND-NEXT: ret + %cmp = icmp sgt i32 %x, -1 + %cond = select i1 %cmp, i32 0, i32 394 + ret i32 %cond +} + +define i32 @select_394_0(i32 signext %x) { +; RV32I-LABEL: select_394_0: +; RV32I: # %bb.0: +; RV32I-NEXT: srli a0, a0, 31 +; RV32I-NEXT: addi a0, a0, -1 +; RV32I-NEXT: andi a0, a0, 394 +; RV32I-NEXT: ret +; +; RV32IF-LABEL: select_394_0: +; RV32IF: # %bb.0: +; RV32IF-NEXT: srli a0, a0, 31 +; RV32IF-NEXT: addi a0, a0, -1 +; RV32IF-NEXT: andi a0, a0, 394 +; RV32IF-NEXT: ret +; +; RV32ZICOND-LABEL: select_394_0: +; RV32ZICOND: # %bb.0: +; RV32ZICOND-NEXT: srli a0, a0, 31 +; RV32ZICOND-NEXT: li a1, 394 +; RV32ZICOND-NEXT: czero.nez a0, a1, a0 +; RV32ZICOND-NEXT: ret +; +; RV64I-LABEL: select_394_0: +; RV64I: # %bb.0: +; RV64I-NEXT: srli a0, a0, 63 +; RV64I-NEXT: addi a0, a0, -1 +; RV64I-NEXT: andi a0, a0, 394 +; RV64I-NEXT: ret +; +; RV64IFD-LABEL: select_394_0: +; RV64IFD: # %bb.0: +; RV64IFD-NEXT: srli a0, a0, 63 +; RV64IFD-NEXT: addi a0, a0, -1 +; RV64IFD-NEXT: andi a0, a0, 394 +; RV64IFD-NEXT: ret +; +; RV64ZICOND-LABEL: select_394_0: +; RV64ZICOND: # %bb.0: +; RV64ZICOND-NEXT: srli a0, a0, 63 +; RV64ZICOND-NEXT: li a1, 394 +; RV64ZICOND-NEXT: czero.nez a0, a1, a0 +; RV64ZICOND-NEXT: ret + %cmp = icmp sgt i32 %x, -1 + %cond = select i1 %cmp, i32 394, i32 0 + ret i32 %cond +} diff --git a/llvm/test/TableGen/AsmPredicateCombining.td b/llvm/test/TableGen/AsmPredicateCombining.td index f7c0ae7..c8081a4 100644 --- a/llvm/test/TableGen/AsmPredicateCombining.td +++ b/llvm/test/TableGen/AsmPredicateCombining.td @@ -1,4 +1,4 @@ -// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | \ +// RUN: llvm-tblgen -gen-disassembler -ignore-non-decodable-operands -I %p/../../include %s | \ // RUN: FileCheck --check-prefix=DISASS %s // RUN: llvm-tblgen -gen-asm-matcher -I %p/../../include %s | \ // RUN: FileCheck --check-prefix=MATCHER %s diff --git a/llvm/test/Transforms/LoopVectorize/interleaved-accesses-3.ll b/llvm/test/Transforms/LoopVectorize/interleaved-accesses-3.ll deleted file mode 100644 index 661e8eb..0000000 --- a/llvm/test/Transforms/LoopVectorize/interleaved-accesses-3.ll +++ /dev/null @@ -1,124 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 -; RUN: opt -S -passes=loop-vectorize,instcombine -force-vector-width=4 -force-vector-interleave=1 -enable-interleaved-mem-accesses=true < %s | FileCheck %s - -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" - -; Check that the interleaved-mem-access analysis currently does not create an -; interleave group for access 'a' due to the possible pointer wrap-around. -; -; To begin with, in this test the candidate interleave group can be created -; only when getPtrStride is called with Assume=true. Next, because -; the interleave-group of the loads is not full (has gaps), we also need to check -; for possible pointer wrapping. Here we currently use Assume=false and as a -; result cannot prove the transformation is safe and therefore invalidate the -; candidate interleave group. -; - -; void func(unsigned * __restrict a, unsigned * __restrict b, unsigned char x, unsigned char y) { -; int i = 0; -; for (unsigned char index = x; i < y; index +=2, ++i) -; b[i] = aptr 2; -; -; } - -define void @_Z4funcPjS_hh(ptr noalias nocapture readonly %a, ptr noalias nocapture %b, i8 zeroext %x, i8 zeroext %y) local_unnamed_addr { -; CHECK-LABEL: define void @_Z4funcPjS_hh( -; CHECK-SAME: ptr noalias readonly captures(none) [[A:%.*]], ptr noalias captures(none) [[B:%.*]], i8 zeroext [[X:%.*]], i8 zeroext [[Y:%.*]]) local_unnamed_addr { -; CHECK-NEXT: [[ENTRY:.*:]] -; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i8 [[Y]], 0 -; CHECK-NEXT: br i1 [[CMP9]], label %[[FOR_COND_CLEANUP:.*]], label %[[FOR_BODY_PREHEADER:.*]] -; CHECK: [[FOR_BODY_PREHEADER]]: -; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i8 [[Y]] to i64 -; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i8 [[Y]], 5 -; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]] -; CHECK: [[VECTOR_SCEVCHECK]]: -; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[WIDE_TRIP_COUNT]], -1 -; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i8 -; CHECK-NEXT: [[MUL_RESULT:%.*]] = shl i8 [[TMP1]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = xor i8 [[X]], -1 -; CHECK-NEXT: [[TMP3:%.*]] = icmp ugt i8 [[MUL_RESULT]], [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = icmp ugt i64 [[TMP0]], 127 -; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]] -; CHECK-NEXT: br i1 [[TMP5]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]] -; CHECK: [[VECTOR_PH]]: -; CHECK-NEXT: [[N_MOD_VF:%.*]] = and i64 [[WIDE_TRIP_COUNT]], 3 -; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 -; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP8]], i64 4, i64 [[N_MOD_VF]] -; CHECK-NEXT: [[N_VEC:%.*]] = sub nsw i64 [[WIDE_TRIP_COUNT]], [[TMP7]] -; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i64 [[N_VEC]] to i8 -; CHECK-NEXT: [[TMP6:%.*]] = shl i8 [[DOTCAST]], 1 -; CHECK-NEXT: [[IND_END:%.*]] = add i8 [[X]], [[TMP6]] -; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] -; CHECK: [[VECTOR_BODY]]: -; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] -; CHECK-NEXT: [[DOTCAST3:%.*]] = trunc i64 [[INDEX]] to i8 -; CHECK-NEXT: [[TMP9:%.*]] = shl i8 [[DOTCAST3]], 1 -; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i8 [[X]], [[TMP9]] -; CHECK-NEXT: [[TMP14:%.*]] = zext i8 [[OFFSET_IDX]] to i64 -; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds nuw i32, ptr [[A]], i64 [[TMP14]] -; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <8 x i32>, ptr [[TMP15]], align 4 -; CHECK-NEXT: [[TMP23:%.*]] = shufflevector <8 x i32> [[WIDE_VEC]], <8 x i32> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6> -; CHECK-NEXT: [[TMP24:%.*]] = shl <4 x i32> [[TMP23]], splat (i32 1) -; CHECK-NEXT: [[TMP25:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDEX]] -; CHECK-NEXT: store <4 x i32> [[TMP24]], ptr [[TMP25]], align 4 -; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 -; CHECK-NEXT: [[TMP26:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] -; CHECK-NEXT: br i1 [[TMP26]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] -; CHECK: [[MIDDLE_BLOCK]]: -; CHECK-NEXT: br label %[[SCALAR_PH]] -; CHECK: [[SCALAR_PH]]: -; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[FOR_BODY_PREHEADER]] ], [ 0, %[[VECTOR_SCEVCHECK]] ] -; CHECK-NEXT: [[BC_RESUME_VAL3:%.*]] = phi i8 [ [[IND_END]], %[[MIDDLE_BLOCK]] ], [ [[X]], %[[FOR_BODY_PREHEADER]] ], [ [[X]], %[[VECTOR_SCEVCHECK]] ] -; CHECK-NEXT: br label %[[FOR_BODY:.*]] -; CHECK: [[FOR_COND_CLEANUP_LOOPEXIT:.*]]: -; CHECK-NEXT: br label %[[FOR_COND_CLEANUP]] -; CHECK: [[FOR_COND_CLEANUP]]: -; CHECK-NEXT: ret void -; CHECK: [[FOR_BODY]]: -; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], %[[FOR_BODY]] ], [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ] -; CHECK-NEXT: [[INDEX_011:%.*]] = phi i8 [ [[ADD:%.*]], %[[FOR_BODY]] ], [ [[BC_RESUME_VAL3]], %[[SCALAR_PH]] ] -; CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[INDEX_011]] to i64 -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[A]], i64 [[IDXPROM]] -; CHECK-NEXT: [[TMP27:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[TMP27]], 1 -; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDVARS_IV]] -; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX2]], align 4 -; CHECK-NEXT: [[ADD]] = add i8 [[INDEX_011]], 2 -; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 -; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] -; CHECK-NEXT: br i1 [[EXITCOND]], label %[[FOR_COND_CLEANUP_LOOPEXIT]], label %[[FOR_BODY]], !llvm.loop [[LOOP3:![0-9]+]] -; -entry: - %cmp9 = icmp eq i8 %y, 0 - br i1 %cmp9, label %for.cond.cleanup, label %for.body.preheader - -for.body.preheader: - %wide.trip.count = zext i8 %y to i64 - br label %for.body - -for.cond.cleanup.loopexit: - br label %for.cond.cleanup - -for.cond.cleanup: - ret void - -for.body: - %indvars.iv = phi i64 [ %indvars.iv.next, %for.body ], [ 0, %for.body.preheader ] - %index.011 = phi i8 [ %add, %for.body ], [ %x, %for.body.preheader ] - %idxprom = zext i8 %index.011 to i64 - %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom - %0 = load i32, ptr %arrayidx, align 4 - %mul = shl i32 %0, 1 - %arrayidx2 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv - store i32 %mul, ptr %arrayidx2, align 4 - %add = add i8 %index.011, 2 - %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 - %exitcond = icmp eq i64 %indvars.iv.next, %wide.trip.count - br i1 %exitcond, label %for.cond.cleanup.loopexit, label %for.body -} -;. -; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]], [[META2:![0-9]+]]} -; CHECK: [[META1]] = !{!"llvm.loop.isvectorized", i32 1} -; CHECK: [[META2]] = !{!"llvm.loop.unroll.runtime.disable"} -; CHECK: [[LOOP3]] = distinct !{[[LOOP3]], [[META1]]} -;. diff --git a/llvm/test/Transforms/LoopVectorize/interleaved-accesses-requiring-scev-predicates.ll b/llvm/test/Transforms/LoopVectorize/interleaved-accesses-requiring-scev-predicates.ll new file mode 100644 index 0000000..bb6c47b --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/interleaved-accesses-requiring-scev-predicates.ll @@ -0,0 +1,246 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 5 +; RUN: opt -S -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -enable-interleaved-mem-accesses=true %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +; Check that the interleaved-mem-access analysis currently does not create an +; interleave group for access 'a' due to the possible pointer wrap-around. +; +; To begin with, in this test the candidate interleave group can be created +; only when getPtrStride is called with Assume=true. Next, because +; the interleave-group of the loads is not full (has gaps), we also need to check +; for possible pointer wrapping. Here we currently use Assume=false and as a +; result cannot prove the transformation is safe and therefore invalidate the +; candidate interleave group. +; + +; void func(unsigned * __restrict a, unsigned * __restrict b, unsigned char x, unsigned char y) { +; int i = 0; +; for (unsigned char index = x; i < y; index +=2, ++i) +; b[i] = aptr 2; +; +; } + +define void @wrap_around_scev_check(ptr noalias %a, ptr noalias %b, i8 %x, i8 %y) { +; CHECK-LABEL: define void @wrap_around_scev_check( +; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) { +; CHECK-NEXT: [[ENTRY:.*:]] +; CHECK-NEXT: [[CMP9:%.*]] = icmp eq i8 [[Y]], 0 +; CHECK-NEXT: br i1 [[CMP9]], label %[[EXIT:.*]], label %[[LOOP_PREHEADER:.*]] +; CHECK: [[LOOP_PREHEADER]]: +; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i8 [[Y]] to i64 +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[WIDE_TRIP_COUNT]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]] +; CHECK: [[VECTOR_SCEVCHECK]]: +; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[WIDE_TRIP_COUNT]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[TMP0]] to i8 +; CHECK-NEXT: [[MUL1:%.*]] = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 2, i8 [[TMP1]]) +; CHECK-NEXT: [[MUL_RESULT:%.*]] = extractvalue { i8, i1 } [[MUL1]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = extractvalue { i8, i1 } [[MUL1]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[X]], [[MUL_RESULT]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp ult i8 [[TMP2]], [[X]] +; CHECK-NEXT: [[TMP5:%.*]] = or i1 [[TMP3]], [[TMP4]] +; CHECK-NEXT: [[TMP17:%.*]] = icmp ugt i64 [[TMP0]], 255 +; CHECK-NEXT: [[TMP18:%.*]] = or i1 [[TMP5]], [[TMP17]] +; CHECK-NEXT: br i1 [[TMP18]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[WIDE_TRIP_COUNT]], 4 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP6]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[WIDE_TRIP_COUNT]], [[TMP7]] +; CHECK-NEXT: [[DOTCAST:%.*]] = trunc i64 [[N_VEC]] to i8 +; CHECK-NEXT: [[TMP8:%.*]] = mul i8 [[DOTCAST]], 2 +; CHECK-NEXT: [[TMP9:%.*]] = add i8 [[X]], [[TMP8]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[DOTCAST2:%.*]] = trunc i64 [[INDEX]] to i8 +; CHECK-NEXT: [[TMP10:%.*]] = mul i8 [[DOTCAST2]], 2 +; CHECK-NEXT: [[OFFSET_IDX:%.*]] = add i8 [[X]], [[TMP10]] +; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[OFFSET_IDX]] to i64 +; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[TMP11]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <8 x i32>, ptr [[TMP12]], align 4 +; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <8 x i32> [[WIDE_VEC]], <8 x i32> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6> +; CHECK-NEXT: [[TMP13:%.*]] = shl <4 x i32> [[STRIDED_VEC]], splat (i32 1) +; CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDEX]] +; CHECK-NEXT: store <4 x i32> [[TMP13]], ptr [[TMP14]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP15:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP15]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: br label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[LOOP_PREHEADER]] ], [ 0, %[[VECTOR_SCEVCHECK]] ] +; CHECK-NEXT: [[BC_RESUME_VAL3:%.*]] = phi i8 [ [[TMP9]], %[[MIDDLE_BLOCK]] ], [ [[X]], %[[LOOP_PREHEADER]] ], [ [[X]], %[[VECTOR_SCEVCHECK]] ] +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[INDEX_011:%.*]] = phi i8 [ [[BC_RESUME_VAL3]], %[[SCALAR_PH]] ], [ [[ADD:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[IDXPROM:%.*]] = zext i8 [[INDEX_011]] to i64 +; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[IDXPROM]] +; CHECK-NEXT: [[TMP16:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +; CHECK-NEXT: [[MUL:%.*]] = shl i32 [[TMP16]], 1 +; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]] +; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX2]], align 4 +; CHECK-NEXT: [[ADD]] = add i8 [[INDEX_011]], 2 +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], [[WIDE_TRIP_COUNT]] +; CHECK-NEXT: br i1 [[EXITCOND]], label %[[EXIT_LOOPEXIT:.*]], label %[[LOOP]], !llvm.loop [[LOOP3:![0-9]+]] +; CHECK: [[EXIT_LOOPEXIT]]: +; CHECK-NEXT: br label %[[EXIT]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: ret void +; +entry: + %cmp9 = icmp eq i8 %y, 0 + br i1 %cmp9, label %exit, label %loop.preheader + +loop.preheader: + %wide.trip.count = zext i8 %y to i64 + br label %loop + +loop: + %iv = phi i64 [ 0, %loop.preheader ], [ %iv.next, %loop ] + %index.011 = phi i8 [ %x, %loop.preheader ], [ %add, %loop ] + %idxprom = zext i8 %index.011 to i64 + %arrayidx = getelementptr inbounds i32, ptr %a, i64 %idxprom + %0 = load i32, ptr %arrayidx, align 4 + %mul = shl i32 %0, 1 + %arrayidx2 = getelementptr inbounds i32, ptr %b, i64 %iv + store i32 %mul, ptr %arrayidx2, align 4 + %add = add i8 %index.011, 2 + %iv.next = add nuw nsw i64 %iv, 1 + %exitcond = icmp eq i64 %iv.next, %wide.trip.count + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +; For %gep, we have the following SCEV: ((4 * (zext i4 {0,+,5}<%loop> to i64))<nuw><nsw> + %x). +; Note the i4 bit wide AddRec {0,+,5}. It is known to wrap in the loop with trip count 16. +; FIXME: Currently we incorrectly assume the widened AddRec does not wrap. +define void @wrap_predicate_for_interleave_group_wraps_for_known_trip_count(ptr noalias %x, ptr noalias %out) { +; CHECK-LABEL: define void @wrap_predicate_for_interleave_group_wraps_for_known_trip_count( +; CHECK-SAME: ptr noalias [[X:%.*]], ptr noalias [[OUT:%.*]]) { +; CHECK-NEXT: [[START:.*]]: +; CHECK-NEXT: br i1 false, label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP0:%.*]] = mul nuw nsw i64 [[INDEX]], 5 +; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[TMP0]], 15 +; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds nuw i32, ptr [[X]], i64 [[TMP1]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <20 x i32>, ptr [[TMP2]], align 4 +; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <20 x i32> [[WIDE_VEC]], <20 x i32> poison, <4 x i32> <i32 0, i32 5, i32 10, i32 15> +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds nuw i32, ptr [[OUT]], i64 [[INDEX]] +; CHECK-NEXT: store <4 x i32> [[STRIDED_VEC]], ptr [[TMP3]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[INDEX_NEXT]], 12 +; CHECK-NEXT: br i1 [[TMP4]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: br label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ 12, %[[MIDDLE_BLOCK]] ], [ 0, %[[START]] ] +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[IV_MUL5:%.*]] = mul nuw nsw i64 [[IV]], 5 +; CHECK-NEXT: [[IV_MUL5_MASKED:%.*]] = and i64 [[IV_MUL5]], 15 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[X]], i64 [[IV_MUL5_MASKED]] +; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[GEP]], align 4 +; CHECK-NEXT: [[OUT_I:%.*]] = getelementptr inbounds nuw i32, ptr [[OUT]], i64 [[IV]] +; CHECK-NEXT: store i32 [[V]], ptr [[OUT_I]], align 4 +; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], 16 +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]], !llvm.loop [[LOOP5:![0-9]+]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: ret void +; +start: + br label %loop + +loop: + %iv = phi i64 [ 0, %start ], [ %iv.next, %loop ] + %iv.next = add nuw nsw i64 %iv, 1 + %iv.mul5 = mul nuw nsw i64 %iv, 5 + %iv.mul5.masked = and i64 %iv.mul5, 15 + %gep = getelementptr inbounds nuw i32, ptr %x, i64 %iv.mul5.masked + %v = load i32, ptr %gep, align 4 + %out.i = getelementptr inbounds nuw i32, ptr %out, i64 %iv + store i32 %v, ptr %out.i, align 4 + %exitcond.not = icmp eq i64 %iv.next, 16 + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} + +; For %gep, we have the following SCEV: ((4 * (zext i4 {0,+,3}<%loop> to i64))<nuw><nsw> + %x). +; Note the i4 bit wide AddRec {0,+,3}. It may wrap, depending on the trip count. +define void @wrap_predicate_for_interleave_group_unknown_trip_count(ptr noalias %x, ptr noalias %out, i64 %n) { +; CHECK-LABEL: define void @wrap_predicate_for_interleave_group_unknown_trip_count( +; CHECK-SAME: ptr noalias [[X:%.*]], ptr noalias [[OUT:%.*]], i64 [[N:%.*]]) { +; CHECK-NEXT: [[START:.*]]: +; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ule i64 [[N]], 4 +; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_SCEVCHECK:.*]] +; CHECK: [[VECTOR_SCEVCHECK]]: +; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[N]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i64 [[TMP0]], 15 +; CHECK-NEXT: br i1 [[TMP1]], label %[[SCALAR_PH]], label %[[VECTOR_PH:.*]] +; CHECK: [[VECTOR_PH]]: +; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[N_MOD_VF]], 0 +; CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP2]], i64 4, i64 [[N_MOD_VF]] +; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N]], [[TMP7]] +; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] +; CHECK: [[VECTOR_BODY]]: +; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] +; CHECK-NEXT: [[TMP8:%.*]] = mul nuw nsw i64 [[INDEX]], 3 +; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP8]], 15 +; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds nuw i32, ptr [[X]], i64 [[TMP3]] +; CHECK-NEXT: [[WIDE_VEC:%.*]] = load <12 x i32>, ptr [[TMP4]], align 4 +; CHECK-NEXT: [[STRIDED_VEC:%.*]] = shufflevector <12 x i32> [[WIDE_VEC]], <12 x i32> poison, <4 x i32> <i32 0, i32 3, i32 6, i32 9> +; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds nuw i32, ptr [[OUT]], i64 [[INDEX]] +; CHECK-NEXT: store <4 x i32> [[STRIDED_VEC]], ptr [[TMP5]], align 4 +; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4 +; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] +; CHECK-NEXT: br i1 [[TMP6]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP6:![0-9]+]] +; CHECK: [[MIDDLE_BLOCK]]: +; CHECK-NEXT: br label %[[SCALAR_PH]] +; CHECK: [[SCALAR_PH]]: +; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[N_VEC]], %[[MIDDLE_BLOCK]] ], [ 0, %[[START]] ], [ 0, %[[VECTOR_SCEVCHECK]] ] +; CHECK-NEXT: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[BC_RESUME_VAL]], %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ] +; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1 +; CHECK-NEXT: [[IV_MUL5:%.*]] = mul nuw nsw i64 [[IV]], 3 +; CHECK-NEXT: [[IV_MUL5_MASKED:%.*]] = and i64 [[IV_MUL5]], 15 +; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i32, ptr [[X]], i64 [[IV_MUL5_MASKED]] +; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[GEP]], align 4 +; CHECK-NEXT: [[OUT_I:%.*]] = getelementptr inbounds nuw i32, ptr [[OUT]], i64 [[IV]] +; CHECK-NEXT: store i32 [[V]], ptr [[OUT_I]], align 4 +; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[IV_NEXT]], [[N]] +; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label %[[EXIT:.*]], label %[[LOOP]], !llvm.loop [[LOOP7:![0-9]+]] +; CHECK: [[EXIT]]: +; CHECK-NEXT: ret void +; +start: + br label %loop + +loop: + %iv = phi i64 [ 0, %start ], [ %iv.next, %loop ] + %iv.next = add nuw nsw i64 %iv, 1 + %iv.mul3 = mul nuw nsw i64 %iv, 3 + %iv.mul3.masked = and i64 %iv.mul3, 15 + %gep = getelementptr inbounds nuw i32, ptr %x, i64 %iv.mul3.masked + %v = load i32, ptr %gep, align 4 + %out.i = getelementptr inbounds nuw i32, ptr %out, i64 %iv + store i32 %v, ptr %out.i, align 4 + %exitcond.not = icmp eq i64 %iv.next, %n + br i1 %exitcond.not, label %exit, label %loop + +exit: + ret void +} diff --git a/llvm/utils/TableGen/DecoderEmitter.cpp b/llvm/utils/TableGen/DecoderEmitter.cpp index 339063d..ebb7deb 100644 --- a/llvm/utils/TableGen/DecoderEmitter.cpp +++ b/llvm/utils/TableGen/DecoderEmitter.cpp @@ -104,6 +104,18 @@ static cl::opt<bool> SpecializeDecodersPerBitwidth( "Helps reduce the code size."), cl::init(false), cl::cat(DisassemblerEmitterCat)); +static cl::opt<bool> IgnoreNonDecodableOperands( + "ignore-non-decodable-operands", + cl::desc( + "Do not issue an error if an operand cannot be decoded automatically."), + cl::init(false), cl::cat(DisassemblerEmitterCat)); + +static cl::opt<bool> IgnoreFullyDefinedOperands( + "ignore-fully-defined-operands", + cl::desc( + "Do not automatically decode operands with no '?' in their encoding."), + cl::init(false), cl::cat(DisassemblerEmitterCat)); + STATISTIC(NumEncodings, "Number of encodings considered"); STATISTIC(NumEncodingsLackingDisasm, "Number of encodings without disassembler info"); @@ -149,7 +161,7 @@ struct OperandInfo { std::vector<EncodingField> Fields; std::string Decoder; bool HasCompleteDecoder; - uint64_t InitValue = 0; + std::optional<uint64_t> InitValue; OperandInfo(std::string D, bool HCD) : Decoder(D), HasCompleteDecoder(HCD) {} @@ -1110,11 +1122,29 @@ FilterChooser::getIslands(const KnownBits &EncodingBits) const { void DecoderTableBuilder::emitBinaryParser(raw_ostream &OS, indent Indent, const OperandInfo &OpInfo) const { - bool UseInsertBits = OpInfo.numFields() != 1 || OpInfo.InitValue != 0; + // Special case for 'bits<0>'. + if (OpInfo.Fields.empty() && !OpInfo.InitValue) { + if (IgnoreNonDecodableOperands) + return; + assert(!OpInfo.Decoder.empty()); + // The operand has no encoding, so the corresponding argument is omitted. + // This avoids confusion and allows the function to be overloaded if the + // operand does have an encoding in other instructions. + OS << Indent << "if (!Check(S, " << OpInfo.Decoder << "(MI, Decoder)))\n" + << Indent << " return MCDisassembler::Fail;\n"; + return; + } + + if (OpInfo.Fields.empty() && OpInfo.InitValue && IgnoreFullyDefinedOperands) + return; + + // We need to construct the encoding of the operand from pieces if it is not + // encoded sequentially or has a non-zero constant part in the encoding. + bool UseInsertBits = OpInfo.numFields() > 1 || OpInfo.InitValue.value_or(0); if (UseInsertBits) { OS << Indent << "tmp = 0x"; - OS.write_hex(OpInfo.InitValue); + OS.write_hex(OpInfo.InitValue.value_or(0)); OS << ";\n"; } @@ -1158,8 +1188,7 @@ void DecoderTableBuilder::emitDecoder(raw_ostream &OS, indent Indent, } for (const OperandInfo &Op : Encoding.getOperands()) - if (Op.numFields()) - emitBinaryParser(OS, Indent, Op); + emitBinaryParser(OS, Indent, Op); } unsigned DecoderTableBuilder::getDecoderIndex(unsigned EncodingID) const { @@ -1941,15 +1970,48 @@ static void debugDumpRecord(const Record &Rec) { static void addOneOperandFields(const Record *EncodingDef, const BitsInit &InstBits, std::map<StringRef, StringRef> &TiedNames, - StringRef OpName, OperandInfo &OpInfo) { - // Some bits of the operand may be required to be 1 depending on the - // instruction's encoding. Collect those bits. - if (const RecordVal *EncodedValue = EncodingDef->getValue(OpName)) - if (const BitsInit *OpBits = dyn_cast<BitsInit>(EncodedValue->getValue())) - for (unsigned I = 0; I < OpBits->getNumBits(); ++I) - if (const BitInit *OpBit = dyn_cast<BitInit>(OpBits->getBit(I))) - if (OpBit->getValue()) - OpInfo.InitValue |= 1ULL << I; + const Record *OpRec, StringRef OpName, + OperandInfo &OpInfo) { + // Find a field with the operand's name. + const RecordVal *OpEncodingField = EncodingDef->getValue(OpName); + + // If there is no such field, try tied operand's name. + if (!OpEncodingField) { + if (auto I = TiedNames.find(OpName); I != TiedNames.end()) + OpEncodingField = EncodingDef->getValue(I->second); + + // If still no luck, the old behavior is to not decode this operand + // automatically and let the target do it. This is error-prone, so + // the new behavior is to report an error. + if (!OpEncodingField) { + if (!IgnoreNonDecodableOperands) + PrintError(EncodingDef->getLoc(), + "could not find field for operand '" + OpName + "'"); + return; + } + } + + // Some or all bits of the operand may be required to be 0 or 1 depending + // on the instruction's encoding. Collect those bits. + if (const auto *OpBit = dyn_cast<BitInit>(OpEncodingField->getValue())) { + OpInfo.InitValue = OpBit->getValue(); + return; + } + if (const auto *OpBits = dyn_cast<BitsInit>(OpEncodingField->getValue())) { + if (OpBits->getNumBits() == 0) { + if (OpInfo.Decoder.empty()) { + PrintError(EncodingDef->getLoc(), "operand '" + OpName + "' of type '" + + OpRec->getName() + + "' must have a decoder method"); + } + return; + } + for (unsigned I = 0; I < OpBits->getNumBits(); ++I) { + if (const auto *OpBit = dyn_cast<BitInit>(OpBits->getBit(I))) + OpInfo.InitValue = OpInfo.InitValue.value_or(0) | + static_cast<uint64_t>(OpBit->getValue()) << I; + } + } // Find out where the variable bits of the operand are encoded. The bits don't // have to be consecutive or in ascending order. For example, an operand could @@ -2034,8 +2096,10 @@ void InstructionEncoding::parseFixedLenOperands(const BitsInit &Bits) { // Decode each of the sub-ops separately. for (auto [SubOpName, SubOp] : zip_equal(Op.SubOpNames, Op.MIOperandInfo->getArgs())) { - OperandInfo SubOpInfo = getOpInfo(cast<DefInit>(SubOp)->getDef()); - addOneOperandFields(EncodingDef, Bits, TiedNames, SubOpName, SubOpInfo); + const Record *SubOpRec = cast<DefInit>(SubOp)->getDef(); + OperandInfo SubOpInfo = getOpInfo(SubOpRec); + addOneOperandFields(EncodingDef, Bits, TiedNames, SubOpRec, SubOpName, + SubOpInfo); Operands.push_back(std::move(SubOpInfo)); } continue; @@ -2056,13 +2120,8 @@ void InstructionEncoding::parseFixedLenOperands(const BitsInit &Bits) { } } - addOneOperandFields(EncodingDef, Bits, TiedNames, Op.Name, OpInfo); - // FIXME: it should be an error not to find a definition for a given - // operand, rather than just failing to add it to the resulting - // instruction! (This is a longstanding bug, which will be addressed in an - // upcoming change.) - if (OpInfo.numFields() > 0) - Operands.push_back(std::move(OpInfo)); + addOneOperandFields(EncodingDef, Bits, TiedNames, Op.Rec, Op.Name, OpInfo); + Operands.push_back(std::move(OpInfo)); } } diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td index fa2e10c..dd00d67 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -1000,17 +1000,17 @@ def LLVM_GetActiveLaneMaskOp /// Create a call to Masked Load intrinsic. def LLVM_MaskedLoadOp : LLVM_OneResultIntrOp<"masked.load"> { let arguments = (ins LLVM_AnyPointer:$data, LLVM_VectorOf<I1>:$mask, - Variadic<LLVM_AnyVector>:$pass_thru, I32Attr:$alignment, + Optional<LLVM_AnyVector>:$pass_thru, I32Attr:$alignment, UnitAttr:$nontemporal); let results = (outs LLVM_AnyVector:$res); let assemblyFormat = "operands attr-dict `:` functional-type(operands, results)"; string llvmBuilder = [{ - auto *inst = $pass_thru.empty() ? builder.CreateMaskedLoad( - $_resultType, $data, llvm::Align($alignment), $mask) : + auto *inst = $pass_thru ? builder.CreateMaskedLoad( + $_resultType, $data, llvm::Align($alignment), $mask, $pass_thru) : builder.CreateMaskedLoad( - $_resultType, $data, llvm::Align($alignment), $mask, $pass_thru[0]); + $_resultType, $data, llvm::Align($alignment), $mask); $res = inst; }] #setNonTemporalMetadataCode; string mlirBuilder = [{ diff --git a/offload/DeviceRTL/src/Parallelism.cpp b/offload/DeviceRTL/src/Parallelism.cpp index aa5e740..0ea2f89 100644 --- a/offload/DeviceRTL/src/Parallelism.cpp +++ b/offload/DeviceRTL/src/Parallelism.cpp @@ -103,11 +103,10 @@ uint32_t determineNumberOfThreads(int32_t NumThreadsClause, extern "C" { -[[clang::always_inline]] void -__kmpc_parallel_spmd(IdentTy *ident, int32_t num_threads, void *fn, void **args, - const int64_t nargs, int32_t nt_strict = false, - int32_t nt_severity = severity_fatal, - const char *nt_message = nullptr) { +[[clang::always_inline]] void __kmpc_parallel_spmd_impl( + IdentTy *ident, int32_t num_threads, void *fn, void **args, + const int64_t nargs, int32_t nt_strict = false, + int32_t nt_severity = severity_fatal, const char *nt_message = nullptr) { uint32_t TId = mapping::getThreadIdInBlock(); uint32_t NumThreads = determineNumberOfThreads(num_threads, nt_strict, nt_severity, nt_message); @@ -163,7 +162,22 @@ __kmpc_parallel_spmd(IdentTy *ident, int32_t num_threads, void *fn, void **args, return; } -[[clang::always_inline]] void __kmpc_parallel_51( +[[clang::always_inline]] void __kmpc_parallel_spmd(IdentTy *ident, + int32_t num_threads, + void *fn, void **args, + const int64_t nargs) { + return __kmpc_parallel_spmd_impl(ident, num_threads, fn, args, nargs); +} + +[[clang::always_inline]] void __kmpc_parallel_spmd_60( + IdentTy *ident, int32_t num_threads, void *fn, void **args, + const int64_t nargs, int32_t nt_strict = false, + int32_t nt_severity = severity_fatal, const char *nt_message = nullptr) { + return __kmpc_parallel_spmd_impl(ident, num_threads, fn, args, nargs, + nt_strict, nt_severity, nt_message); +} + +[[clang::always_inline]] void __kmpc_parallel_impl( IdentTy *ident, int32_t, int32_t if_expr, int32_t num_threads, int proc_bind, void *fn, void *wrapper_fn, void **args, int64_t nargs, int32_t nt_strict = false, int32_t nt_severity = severity_fatal, @@ -198,8 +212,11 @@ __kmpc_parallel_spmd(IdentTy *ident, int32_t num_threads, void *fn, void **args, // This was moved to its own routine so it could be called directly // in certain situations to avoid resource consumption of unused // logic in parallel_51. - __kmpc_parallel_spmd(ident, num_threads, fn, args, nargs, nt_strict, - nt_severity, nt_message); + if (nt_strict) + __kmpc_parallel_spmd(ident, num_threads, fn, args, nargs); + else + __kmpc_parallel_spmd_60(ident, num_threads, fn, args, nargs, nt_strict, + nt_severity, nt_message); return; } @@ -308,14 +325,22 @@ __kmpc_parallel_spmd(IdentTy *ident, int32_t num_threads, void *fn, void **args, __kmpc_end_sharing_variables(); } +[[clang::always_inline]] void +__kmpc_parallel_51(IdentTy *ident, int32_t id, int32_t if_expr, + int32_t num_threads, int proc_bind, void *fn, + void *wrapper_fn, void **args, int64_t nargs) { + return __kmpc_parallel_impl(ident, id, if_expr, num_threads, proc_bind, fn, + wrapper_fn, args, nargs); +} + [[clang::always_inline]] void __kmpc_parallel_60( IdentTy *ident, int32_t id, int32_t if_expr, int32_t num_threads, int proc_bind, void *fn, void *wrapper_fn, void **args, int64_t nargs, int32_t nt_strict = false, int32_t nt_severity = severity_fatal, const char *nt_message = nullptr) { - return __kmpc_parallel_51(ident, id, if_expr, num_threads, proc_bind, fn, - wrapper_fn, args, nargs, nt_strict, nt_severity, - nt_message); + return __kmpc_parallel_impl(ident, id, if_expr, num_threads, proc_bind, fn, + wrapper_fn, args, nargs, nt_strict, nt_severity, + nt_message); } [[clang::noinline]] bool __kmpc_kernel_parallel(ParallelRegionFnTy *WorkFn) { |