diff --git a/clang/include/clang/Basic/ObjCRuntime.h b/clang/include/clang/Basic/ObjCRuntime.h index 1c4a69269deea0..26403bfa98c9d6 100644 --- a/clang/include/clang/Basic/ObjCRuntime.h +++ b/clang/include/clang/Basic/ObjCRuntime.h @@ -476,6 +476,10 @@ class ObjCRuntime { friend bool operator!=(const ObjCRuntime &left, const ObjCRuntime &right) { return !(left == right); } + + friend llvm::hash_code hash_value(const ObjCRuntime &OCR) { + return llvm::hash_combine(OCR.getKind(), OCR.getVersion()); + } }; raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f58854cd9e08be..6f6af917e3a31a 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3852,6 +3852,10 @@ std::string CompilerInvocation::getModuleHash() const { for (StringRef Feature : LangOpts->ModuleFeatures) code = hash_combine(code, Feature); + code = hash_combine(code, LangOpts->ObjCRuntime); + const auto &BCN = LangOpts->CommentOpts.BlockCommandNames; + code = hash_combine(code, hash_combine_range(BCN.begin(), BCN.end())); + // Extend the signature with the target options. code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU, TargetOpts->ABI); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 77858b17d62c6d..efaf36a6930618 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -13560,12 +13560,14 @@ static getBaseAlignmentAndOffsetFromLValue(const Expr *E, ASTContext &Ctx) { } case Stmt::MemberExprClass: { auto *ME = cast(E); - if (ME->isArrow()) - break; auto *FD = dyn_cast(ME->getMemberDecl()); if (!FD || FD->getType()->isReferenceType()) break; - auto P = getBaseAlignmentAndOffsetFromLValue(ME->getBase(), Ctx); + Optional> P; + if (ME->isArrow()) + P = getBaseAlignmentAndOffsetFromPtr(ME->getBase(), Ctx); + else + P = getBaseAlignmentAndOffsetFromLValue(ME->getBase(), Ctx); if (!P) break; const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(FD->getParent()); @@ -13629,6 +13631,11 @@ static getBaseAlignmentAndOffsetFromPtr(const Expr *E, ASTContext &Ctx) { } break; } + case Stmt::CXXThisExprClass: { + auto *RD = E->getType()->getPointeeType()->getAsCXXRecordDecl(); + CharUnits Alignment = Ctx.getASTRecordLayout(RD).getNonVirtualAlignment(); + return std::make_pair(Alignment, CharUnits::Zero()); + } case Stmt::UnaryOperatorClass: { auto *UO = cast(E); if (UO->getOpcode() == UO_AddrOf) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 0a0bb3952cd891..d885920b6c14e9 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4203,8 +4203,8 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, break; case ICK_Compatible_Conversion: - From = ImpCastExprToType(From, ToType, CK_NoOp, - VK_RValue, /*BasePath=*/nullptr, CCK).get(); + From = ImpCastExprToType(From, ToType, CK_NoOp, From->getValueKind(), + /*BasePath=*/nullptr, CCK).get(); break; case ICK_Writeback_Conversion: @@ -4441,11 +4441,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, break; case ICK_Qualification: { - // The qualification keeps the category of the inner expression, unless the - // target type isn't a reference. - ExprValueKind VK = - ToType->isReferenceType() ? From->getValueKind() : VK_RValue; - + ExprValueKind VK = From->getValueKind(); CastKind CK = CK_NoOp; if (ToType->isReferenceType() && diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d68be854aeeb4b..599e81d1b4d04a 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -4709,7 +4709,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, Sema::ReferenceConversions::NestedQualification) ? ICK_Qualification : ICK_Identity; - ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); + ICS.Standard.setFromType(T2); ICS.Standard.setToType(0, T2); ICS.Standard.setToType(1, T1); ICS.Standard.setToType(2, T1); diff --git a/clang/test/Modules/context-hash.c b/clang/test/Modules/context-hash.c index 33dfb2f15a2ce2..8bb7422f6a54f0 100644 --- a/clang/test/Modules/context-hash.c +++ b/clang/test/Modules/context-hash.c @@ -1,3 +1,6 @@ +// This test verifies that only strict hashing includes search paths and +// diagnostics in the module context hash. + // RUN: rm -rf %t // RUN: %clang_cc1 -fsyntax-only -internal-isystem \ // RUN: %S/Inputs/System/usr/include -fmodules -fimplicit-module-maps \ @@ -20,8 +23,25 @@ // RUN: echo %t > %t.path // RUN: cat %t.path %t1 %t2 %t3 %t4 | FileCheck %s -// This test verifies that only strict hashing includes search paths and -// diagnostics in the module context hash. +// This tests things verified by ASTReader::checkLanguageOptions that are not +// part of LangOpts.def. + +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -internal-isystem \ +// RUN: %S/Inputs/System/usr/include -fmodules -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t -x objective-c %s -Rmodule-build 2> %t1 +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -internal-isystem \ +// RUN: %S/Inputs/System/usr/include -fmodules -fimplicit-module-maps \ +// RUN: -fobjc-runtime=macosx-1.0.0.0 \ +// RUN: -fmodules-cache-path=%t -x objective-c %s -Rmodule-build 2> %t2 +// RUN: rm -rf %t +// RUN: %clang_cc1 -fsyntax-only -internal-isystem \ +// RUN: %S/Inputs/System/usr/include -fmodules -fimplicit-module-maps \ +// RUN: -fcomment-block-commands=lp,bj \ +// RUN: -fmodules-cache-path=%t -x objective-c %s -Rmodule-build 2> %t3 +// RUN: echo %t > %t.path +// RUN: cat %t.path %t1 %t2 %t3 | FileCheck --check-prefix=LANGOPTS %s #include @@ -32,3 +52,10 @@ // CHECK: cstd-[[AST_HASH]].pcm' // CHECK-NOT: building module 'cstd' as '{{.*[/\\]}}[[CONTEXT_HASH]]{{[/\\]}} // CHECK: cstd-[[AST_HASH]].pcm' + +// LANGOPTS: [[PREFIX:(.*[/\\])+[a-zA-Z0-9.-]+]] +// LANGOPTS: building module 'cstd' as '[[PREFIX]]{{[/\\]}}[[CONTEXT_HASH:[A-Z0-9]+]]{{[/\\]}}cstd-[[AST_HASH:[A-Z0-9]+]].pcm' +// LANGOPTS-NOT: building module 'cstd' as '{{.*[/\\]}}[[CONTEXT_HASH]]{{[/\\]}} +// LANGOPTS: cstd-[[AST_HASH]].pcm' +// LANGOPTS-NOT: building module 'cstd' as '{{.*[/\\]}}[[CONTEXT_HASH]]{{[/\\]}} +// LANGOPTS: cstd-[[AST_HASH]].pcm' diff --git a/clang/test/SemaCXX/references.cpp b/clang/test/SemaCXX/references.cpp index f30e16d990ebea..eaab1ae833e4e6 100644 --- a/clang/test/SemaCXX/references.cpp +++ b/clang/test/SemaCXX/references.cpp @@ -201,3 +201,9 @@ namespace RefCollapseTypePrinting { template void add_rref(); // expected-note {{instantiation of}} template void add_rref(); // expected-note {{instantiation of}} } + +namespace PR45521 { + struct a { template a(const b * const&); }; + int *d; + const a &r = d; +} diff --git a/clang/test/SemaCXX/warn-cast-align.cpp b/clang/test/SemaCXX/warn-cast-align.cpp index 53cd75fb140528..1e84ba9cd67af4 100644 --- a/clang/test/SemaCXX/warn-cast-align.cpp +++ b/clang/test/SemaCXX/warn-cast-align.cpp @@ -44,9 +44,16 @@ void test1(void *P) { c = IntPtr(P); } +struct __attribute__((aligned(16))) AlignedS { + char m[16]; +}; + struct __attribute__((aligned(16))) A { char m0[16]; char m1[16]; + AlignedS *getAlignedS() { + return (AlignedS *)m1; + } }; struct B0 { @@ -92,6 +99,9 @@ struct __attribute__((aligned(16))) D4 : virtual D2 { struct D5 : virtual D0 { char m0[16]; + AlignedS *get() { + return (AlignedS *)m0; // expected-warning {{cast from 'char *' to 'AlignedS *'}} + } }; struct D6 : virtual D5 { diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index aa0df8d5bfdfd0..5e3c901322ec6c 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -505,13 +505,9 @@ set(hexagon_SOURCES hexagon/dfsqrt.S hexagon/divdi3.S hexagon/divsi3.S - hexagon/fabs_opt.S hexagon/fastmath2_dlib_asm.S hexagon/fastmath2_ldlib_asm.S hexagon/fastmath_dlib_asm.S - hexagon/fma_opt.S - hexagon/fmax_opt.S - hexagon/fmin_opt.S hexagon/memcpy_forward_vp4cp4n2.S hexagon/memcpy_likely_aligned.S hexagon/moddi3.S diff --git a/compiler-rt/lib/builtins/hexagon/dffma.S b/compiler-rt/lib/builtins/hexagon/dffma.S index c201d3d8be5e14..843e88b3cab84c 100644 --- a/compiler-rt/lib/builtins/hexagon/dffma.S +++ b/compiler-rt/lib/builtins/hexagon/dffma.S @@ -104,13 +104,11 @@ .type __hexagon_fmadf4,@function .global __hexagon_fmadf5 .type __hexagon_fmadf5,@function - .global fma - .type fma,@function Q6_ALIAS(fmadf5) .p2align 5 __hexagon_fmadf4: __hexagon_fmadf5: -fma: +.Lfma_begin: { P_TMP = dfclass(A,#2) P_TMP = dfclass(B,#2) @@ -561,7 +559,7 @@ fma: B = insert(BTMP,#63,#0) AH -= asl(TMP,#HI_MANTBITS) } - jump fma + jump .Lfma_begin .Lfma_ab_tiny: ATMP = combine(##0x00100000,#0) @@ -569,7 +567,7 @@ fma: A = insert(ATMP,#63,#0) B = insert(ATMP,#63,#0) } - jump fma + jump .Lfma_begin .Lab_inf: { diff --git a/compiler-rt/lib/builtins/hexagon/fabs_opt.S b/compiler-rt/lib/builtins/hexagon/fabs_opt.S deleted file mode 100644 index 6bf9b84b3d209c..00000000000000 --- a/compiler-rt/lib/builtins/hexagon/fabs_opt.S +++ /dev/null @@ -1,36 +0,0 @@ -//===----------------------Hexagon builtin routine ------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -.macro FUNCTION_BEGIN name -.text -.p2align 5 -.globl \name -.type \name, @function -\name: -.endm - -.macro FUNCTION_END name -.size \name, . - \name -.endm - -FUNCTION_BEGIN fabs - { - r1 = clrbit(r1, #31) - jumpr r31 - } -FUNCTION_END fabs - -FUNCTION_BEGIN fabsf - { - r0 = clrbit(r0, #31) - jumpr r31 - } -FUNCTION_END fabsf - - .globl fabsl - .set fabsl, fabs diff --git a/compiler-rt/lib/builtins/hexagon/fma_opt.S b/compiler-rt/lib/builtins/hexagon/fma_opt.S deleted file mode 100644 index 7f566adffd6a47..00000000000000 --- a/compiler-rt/lib/builtins/hexagon/fma_opt.S +++ /dev/null @@ -1,30 +0,0 @@ -//===----------------------Hexagon builtin routine ------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -.macro FUNCTION_BEGIN name -.text -.p2align 5 -.globl \name -.type \name, @function -\name: -.endm - -.macro FUNCTION_END name -.size \name, . - \name -.endm - -FUNCTION_BEGIN fmaf - r2 += sfmpy(r0, r1) - { - r0 = r2 - jumpr r31 - } -FUNCTION_END fmaf - - .globl fmal - .set fmal, fma diff --git a/compiler-rt/lib/builtins/hexagon/fmax_opt.S b/compiler-rt/lib/builtins/hexagon/fmax_opt.S deleted file mode 100644 index 81d711dff8d206..00000000000000 --- a/compiler-rt/lib/builtins/hexagon/fmax_opt.S +++ /dev/null @@ -1,29 +0,0 @@ -//===----------------------Hexagon builtin routine ------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -.macro FUNCTION_BEGIN name -.text -.p2align 5 -.globl \name -.type \name, @function -\name: -.endm - -.macro FUNCTION_END name -.size \name, . - \name -.endm - -FUNCTION_BEGIN fmaxf - { - r0 = sfmax(r0, r1) - jumpr r31 - } -FUNCTION_END fmaxf - - .globl fmaxl - .set fmaxl, fmax diff --git a/compiler-rt/lib/builtins/hexagon/fmin_opt.S b/compiler-rt/lib/builtins/hexagon/fmin_opt.S deleted file mode 100644 index d043f1d7a6987a..00000000000000 --- a/compiler-rt/lib/builtins/hexagon/fmin_opt.S +++ /dev/null @@ -1,29 +0,0 @@ -//===----------------------Hexagon builtin routine ------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -.macro FUNCTION_BEGIN name -.text -.p2align 5 -.globl \name -.type \name, @function -\name: -.endm - -.macro FUNCTION_END name -.size \name, . - \name -.endm - -FUNCTION_BEGIN fminf - { - r0 = sfmin(r0, r1) - jumpr r31 - } -FUNCTION_END fminf - - .globl fminl - .set fminl, fmin diff --git a/flang/include/flang/Evaluate/type.h b/flang/include/flang/Evaluate/type.h index 197fb3291dd428..c62d633563430d 100644 --- a/flang/include/flang/Evaluate/type.h +++ b/flang/include/flang/Evaluate/type.h @@ -146,7 +146,7 @@ class DynamicType { DynamicType ResultTypeForMultiply(const DynamicType &) const; bool IsAssumedLengthCharacter() const; - bool IsUnknownLengthCharacter() const; + bool IsNonConstantLengthCharacter() const; bool IsTypelessIntrinsicArgument() const; constexpr bool IsAssumedType() const { // TYPE(*) return kind_ == AssumedTypeKind; diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp index 5b07eaa454d89a..9b96a479df5977 100644 --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -612,7 +612,9 @@ Expr> FoldOperation( if (iter != scope->end()) { const Symbol &symbol{*iter->second}; const auto *details{symbol.detailsIf()}; - if (details && details->init()) { + if (details && details->init() && + (details->attr() == common::TypeParamAttr::Kind || + IsConstantExpr(*details->init()))) { Expr expr{*details->init()}; return Fold(context, Expr{ diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp index e943b49fcf1b02..90d864466e2dce 100644 --- a/flang/lib/Evaluate/shape.cpp +++ b/flang/lib/Evaluate/shape.cpp @@ -205,7 +205,7 @@ auto GetLowerBoundHelper::operator()(const Symbol &symbol0) -> Result { if (j++ == dimension_) { if (const auto &bound{shapeSpec.lbound().GetExplicit()}) { return Fold(context_, common::Clone(*bound)); - } else if (semantics::IsDescriptor(symbol)) { + } else if (IsDescriptor(symbol)) { return ExtentExpr{DescriptorInquiry{NamedEntity{symbol0}, DescriptorInquiry::Field::LowerBound, dimension_}}; } else { @@ -230,7 +230,7 @@ auto GetLowerBoundHelper::operator()(const Component &component) -> Result { if (j++ == dimension_) { if (const auto &bound{shapeSpec.lbound().GetExplicit()}) { return Fold(context_, common::Clone(*bound)); - } else if (semantics::IsDescriptor(symbol)) { + } else if (IsDescriptor(symbol)) { return ExtentExpr{ DescriptorInquiry{NamedEntity{common::Clone(component)}, DescriptorInquiry::Field::LowerBound, dimension_}}; diff --git a/flang/lib/Evaluate/type.cpp b/flang/lib/Evaluate/type.cpp index 0a823cd20398f5..293cd186481485 100644 --- a/flang/lib/Evaluate/type.cpp +++ b/flang/lib/Evaluate/type.cpp @@ -22,17 +22,21 @@ // IsDescriptor() predicate: true when a symbol is implemented // at runtime with a descriptor. -// TODO there's probably a better place for this predicate than here namespace Fortran::semantics { -static bool IsDescriptor(const ObjectEntityDetails &details) { - if (const auto *type{details.type()}) { +static bool IsDescriptor(const DeclTypeSpec *type) { + if (type) { if (auto dynamicType{evaluate::DynamicType::From(*type)}) { - if (dynamicType->RequiresDescriptor()) { - return true; - } + return dynamicType->RequiresDescriptor(); } } + return false; +} + +static bool IsDescriptor(const ObjectEntityDetails &details) { + if (IsDescriptor(details.type())) { + return true; + } // TODO: Automatic (adjustable) arrays - are they descriptors? for (const ShapeSpec &shapeSpec : details.shape()) { const auto &lb{shapeSpec.lbound().GetExplicit()}; @@ -62,6 +66,7 @@ bool IsDescriptor(const Symbol &symbol) { symbol.attrs().test(Attr::EXTERNAL)) && IsDescriptor(d); }, + [&](const EntityDetails &d) { return IsDescriptor(d.type()); }, [](const AssocEntityDetails &d) { if (const auto &expr{d.expr()}) { if (expr->Rank() > 0) { @@ -149,7 +154,7 @@ bool DynamicType::IsAssumedLengthCharacter() const { charLength_->isAssumed(); } -bool DynamicType::IsUnknownLengthCharacter() const { +bool DynamicType::IsNonConstantLengthCharacter() const { if (category_ != TypeCategory::Character) { return false; } else if (!charLength_) { @@ -471,7 +476,7 @@ DynamicType DynamicType::ResultTypeForMultiply(const DynamicType &that) const { } bool DynamicType::RequiresDescriptor() const { - return IsPolymorphic() || IsUnknownLengthCharacter() || + return IsPolymorphic() || IsNonConstantLengthCharacter() || (derived_ && CountNonConstantLenParameters(*derived_) > 0); } diff --git a/flang/lib/Evaluate/variable.cpp b/flang/lib/Evaluate/variable.cpp index 3a6cf560384c88..8c9bd18285af4e 100644 --- a/flang/lib/Evaluate/variable.cpp +++ b/flang/lib/Evaluate/variable.cpp @@ -8,6 +8,7 @@ #include "flang/Evaluate/variable.h" #include "flang/Common/idioms.h" +#include "flang/Evaluate/check-expression.h" #include "flang/Evaluate/fold.h" #include "flang/Evaluate/tools.h" #include "flang/Parser/char-block.h" @@ -259,16 +260,13 @@ static std::optional> SymbolLEN(const Symbol &sym) { if (const semantics::ParamValue * len{dyType->charLength()}) { if (len->isExplicit()) { if (auto intExpr{len->GetExplicit()}) { - return ConvertToType(*std::move(intExpr)); - } else { - // There was an error constructing this symbol's type. It should - // have a length expression, but we couldn't retrieve it - return std::nullopt; + if (IsConstantExpr(*intExpr)) { + return ConvertToType(*std::move(intExpr)); + } } - } else { - return Expr{ - DescriptorInquiry{NamedEntity{sym}, DescriptorInquiry::Field::Len}}; } + return Expr{ + DescriptorInquiry{NamedEntity{sym}, DescriptorInquiry::Field::Len}}; } } return std::nullopt; diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py index 2b8185a18b77ed..f9975b27c47593 100644 --- a/lldb/packages/Python/lldbsuite/test/dotest.py +++ b/lldb/packages/Python/lldbsuite/test/dotest.py @@ -363,7 +363,10 @@ def parseOptionsAndInitTestdirs(): args.executable) sys.exit(-1) - if args.server: + if args.server and args.out_of_tree_debugserver: + logging.warning('Both --server and --out-of-tree-debugserver are set') + + if args.server and not args.out_of_tree_debugserver: os.environ['LLDB_DEBUGSERVER_PATH'] = args.server if args.excluded: diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h index d8d72cacf226e6..1aca692e30a799 100644 --- a/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/llvm/include/llvm/BinaryFormat/Wasm.h @@ -280,6 +280,7 @@ enum : unsigned { }; enum : unsigned { + WASM_LIMITS_FLAG_NONE = 0x0, WASM_LIMITS_FLAG_HAS_MAX = 0x1, WASM_LIMITS_FLAG_IS_SHARED = 0x2, WASM_LIMITS_FLAG_IS_64 = 0x4, diff --git a/llvm/include/llvm/Support/VersionTuple.h b/llvm/include/llvm/Support/VersionTuple.h index ad89e40f0f1448..6f3711f06f1a05 100644 --- a/llvm/include/llvm/Support/VersionTuple.h +++ b/llvm/include/llvm/Support/VersionTuple.h @@ -14,6 +14,7 @@ #ifndef LLVM_SUPPORT_VERSIONTUPLE_H #define LLVM_SUPPORT_VERSIONTUPLE_H +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/Optional.h" #include #include @@ -144,6 +145,10 @@ class VersionTuple { return !(X < Y); } + friend llvm::hash_code hash_value(const VersionTuple &VT) { + return llvm::hash_combine(VT.Major, VT.Minor, VT.Subminor, VT.Build); + } + /// Retrieve a string representation of the version number. std::string getAsString() const; diff --git a/llvm/include/llvm/Support/X86TargetParser.def b/llvm/include/llvm/Support/X86TargetParser.def index 91feb146baaaf3..9910fd615b1dc2 100644 --- a/llvm/include/llvm/Support/X86TargetParser.def +++ b/llvm/include/llvm/Support/X86TargetParser.def @@ -230,5 +230,6 @@ X86_FEATURE (RETPOLINE_INDIRECT_BRANCHES, "retpoline-indirect-branches") X86_FEATURE (RETPOLINE_INDIRECT_CALLS, "retpoline-indirect-calls") X86_FEATURE (LVI_CFI, "lvi-cfi") X86_FEATURE (LVI_LOAD_HARDENING, "lvi-load-hardening") +X86_FEATURE (SESES, "seses") #undef X86_FEATURE_COMPAT #undef X86_FEATURE diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp index d63fedda3bd13d..2cb57c1d1ccc8c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -913,36 +913,38 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I, // Export the result value if needed const GCResultInst *GCResult = I.getGCResult(); Type *RetTy = I.getActualReturnType(); - if (!RetTy->isVoidTy() && GCResult) { - if (GCResult->getParent() != I.getParent()) { - // Result value will be used in a different basic block so we need to - // export it now. Default exporting mechanism will not work here because - // statepoint call has a different type than the actual call. It means - // that by default llvm will create export register of the wrong type - // (always i32 in our case). So instead we need to create export register - // with correct type manually. - // TODO: To eliminate this problem we can remove gc.result intrinsics - // completely and make statepoint call to return a tuple. - unsigned Reg = FuncInfo.CreateRegs(RetTy); - RegsForValue RFV(*DAG.getContext(), DAG.getTargetLoweringInfo(), - DAG.getDataLayout(), Reg, RetTy, - I.getCallingConv()); - SDValue Chain = DAG.getEntryNode(); - - RFV.getCopyToRegs(ReturnValue, DAG, getCurSDLoc(), Chain, nullptr); - PendingExports.push_back(Chain); - FuncInfo.ValueMap[&I] = Reg; - } else { - // Result value will be used in a same basic block. Don't export it or - // perform any explicit register copies. - // We'll replace the actuall call node shortly. gc_result will grab - // this value. - setValue(&I, ReturnValue); - } - } else { - // The token value is never used from here on, just generate a poison value + + if (RetTy->isVoidTy() || !GCResult) { + // The return value is not needed, just generate a poison value. setValue(&I, DAG.getIntPtrConstant(-1, getCurSDLoc())); + return; + } + + if (GCResult->getParent() == I.getParent()) { + // Result value will be used in a same basic block. Don't export it or + // perform any explicit register copies. The gc_result will simply grab + // this value. + setValue(&I, ReturnValue); + return; } + + // Result value will be used in a different basic block so we need to export + // it now. Default exporting mechanism will not work here because statepoint + // call has a different type than the actual call. It means that by default + // llvm will create export register of the wrong type (always i32 in our + // case). So instead we need to create export register with correct type + // manually. + // TODO: To eliminate this problem we can remove gc.result intrinsics + // completely and make statepoint call to return a tuple. + unsigned Reg = FuncInfo.CreateRegs(RetTy); + RegsForValue RFV(*DAG.getContext(), DAG.getTargetLoweringInfo(), + DAG.getDataLayout(), Reg, RetTy, + I.getCallingConv()); + SDValue Chain = DAG.getEntryNode(); + + RFV.getCopyToRegs(ReturnValue, DAG, getCurSDLoc(), Chain, nullptr); + PendingExports.push_back(Chain); + FuncInfo.ValueMap[&I] = Reg; } void SelectionDAGBuilder::LowerCallSiteWithDeoptBundleImpl( @@ -988,23 +990,23 @@ void SelectionDAGBuilder::LowerCallSiteWithDeoptBundle( void SelectionDAGBuilder::visitGCResult(const GCResultInst &CI) { // The result value of the gc_result is simply the result of the actual // call. We've already emitted this, so just grab the value. - const GCStatepointInst *I = CI.getStatepoint(); - - if (I->getParent() != CI.getParent()) { - // Statepoint is in different basic block so we should have stored call - // result in a virtual register. - // We can not use default getValue() functionality to copy value from this - // register because statepoint and actual call return types can be - // different, and getValue() will use CopyFromReg of the wrong type, - // which is always i32 in our case. - Type *RetTy = I->getActualReturnType(); - SDValue CopyFromReg = getCopyFromRegs(I, RetTy); - - assert(CopyFromReg.getNode()); - setValue(&CI, CopyFromReg); - } else { - setValue(&CI, getValue(I)); + const GCStatepointInst *SI = CI.getStatepoint(); + + if (SI->getParent() == CI.getParent()) { + setValue(&CI, getValue(SI)); + return; } + // Statepoint is in different basic block so we should have stored call + // result in a virtual register. + // We can not use default getValue() functionality to copy value from this + // register because statepoint and actual call return types can be + // different, and getValue() will use CopyFromReg of the wrong type, + // which is always i32 in our case. + Type *RetTy = SI->getActualReturnType(); + SDValue CopyFromReg = getCopyFromRegs(SI, RetTy); + + assert(CopyFromReg.getNode()); + setValue(&CI, CopyFromReg); } void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) { diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index d1290b050ef2cf..f51d908c53e13a 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -1198,7 +1198,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, MemImport.Module = "env"; MemImport.Field = "__linear_memory"; MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY; - MemImport.Memory.Flags = is64Bit() ? wasm::WASM_LIMITS_FLAG_IS_64 : 0; + MemImport.Memory.Flags = is64Bit() ? wasm::WASM_LIMITS_FLAG_IS_64 + : wasm::WASM_LIMITS_FLAG_NONE; Imports.push_back(MemImport); // For now, always emit the table section, since indirect calls are not diff --git a/llvm/lib/Support/X86TargetParser.cpp b/llvm/lib/Support/X86TargetParser.cpp index 261e296b9e5aad..df03f63e720e08 100644 --- a/llvm/lib/Support/X86TargetParser.cpp +++ b/llvm/lib/Support/X86TargetParser.cpp @@ -441,6 +441,7 @@ static constexpr FeatureBitset ImpliedFeaturesRETPOLINE_INDIRECT_BRANCHES = {}; static constexpr FeatureBitset ImpliedFeaturesRETPOLINE_INDIRECT_CALLS = {}; static constexpr FeatureBitset ImpliedFeaturesLVI_CFI = {}; static constexpr FeatureBitset ImpliedFeaturesLVI_LOAD_HARDENING = {}; +static constexpr FeatureBitset ImpliedFeaturesSESES = {}; // XSAVE features are dependent on basic XSAVE. static constexpr FeatureBitset ImpliedFeaturesXSAVEC = FeatureXSAVE; @@ -562,6 +563,7 @@ void llvm::X86::getImpliedFeatures( if (I == std::end(FeatureInfos)) { // FIXME: This shouldn't happen, but may not have all features in the table // yet. + assert(false && "Feature not found in table!"); return; } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index b2e51516b983a0..91fc69b5bc10ea 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -33,6 +33,7 @@ #include "llvm/IR/IntrinsicsRISCV.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -2978,6 +2979,26 @@ bool RISCVTargetLowering::shouldExtendTypeInLibCall(EVT Type) const { return true; } +bool RISCVTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT, + SDValue C) const { + // Check integral scalar types. + if (VT.isScalarInteger()) { + // Do not perform the transformation on riscv32 with the M extension. + if (!Subtarget.is64Bit() && Subtarget.hasStdExtM()) + return false; + if (auto *ConstNode = dyn_cast(C.getNode())) { + if (ConstNode->getAPIntValue().getBitWidth() > 8 * sizeof(int64_t)) + return false; + int64_t Imm = ConstNode->getSExtValue(); + if (isPowerOf2_64(Imm + 1) || isPowerOf2_64(Imm - 1) || + isPowerOf2_64(1 - Imm) || isPowerOf2_64(-1 - Imm)) + return true; + } + } + + return false; +} + #define GET_REGISTER_MATCHER #include "RISCVGenAsmMatcher.inc" diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index 691bb6d75d1399..e420e879efc91e 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -185,6 +185,9 @@ class RISCVTargetLowering : public TargetLowering { bool mayBeEmittedAsTailCall(const CallInst *CI) const override; bool shouldConsiderGEPOffsetSplit() const override { return true; } + bool decomposeMulByConstant(LLVMContext &Context, EVT VT, + SDValue C) const override; + TargetLowering::AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override; Value *emitMaskedAtomicRMWIntrinsic(IRBuilder<> &Builder, AtomicRMWInst *AI, diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp index b65832450828ab..5bb05c6ac3d18d 100644 --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -3760,24 +3760,11 @@ int BoUpSLP::getSpillCost() const { SmallPtrSet LiveValues; Instruction *PrevInst = nullptr; - // The entries in VectorizableTree are not necessarily ordered by their - // position in basic blocks. Collect them and order them by dominance so later - // instructions are guaranteed to be visited first. For instructions in - // different basic blocks, we only scan to the beginning of the block, so - // their order does not matter, as long as all instructions in a basic block - // are grouped together. Using dominance ensures a deterministic order. - SmallVector OrderedScalars; for (const auto &TEPtr : VectorizableTree) { Instruction *Inst = dyn_cast(TEPtr->Scalars[0]); if (!Inst) continue; - OrderedScalars.push_back(Inst); - } - llvm::stable_sort(OrderedScalars, [this](Instruction *A, Instruction *B) { - return !DT->dominates(A, B); - }); - for (Instruction *Inst : OrderedScalars) { if (!PrevInst) { PrevInst = Inst; continue; diff --git a/llvm/test/CodeGen/RISCV/mul.ll b/llvm/test/CodeGen/RISCV/mul.ll index 5808660b57130d..89c4bce122fd2d 100644 --- a/llvm/test/CodeGen/RISCV/mul.ll +++ b/llvm/test/CodeGen/RISCV/mul.ll @@ -79,12 +79,8 @@ define signext i32 @mul(i32 %a, i32 %b) nounwind { define signext i32 @mul_constant(i32 %a) nounwind { ; RV32I-LABEL: mul_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a1, zero, 5 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a1, a0, 2 +; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: mul_constant: @@ -95,19 +91,14 @@ define signext i32 @mul_constant(i32 %a) nounwind { ; ; RV64I-LABEL: mul_constant: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 5 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: sext.w a0, a0 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 2 +; RV64I-NEXT: addw a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: mul_constant: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 5 -; RV64IM-NEXT: mulw a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 2 +; RV64IM-NEXT: addw a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i32 %a, 5 ret i32 %1 @@ -177,13 +168,15 @@ define i64 @mul64(i64 %a, i64 %b) nounwind { define i64 @mul64_constant(i64 %a) nounwind { ; RV32I-LABEL: mul64_constant: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a2, zero, 5 -; RV32I-NEXT: mv a3, zero -; RV32I-NEXT: call __muldi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a3, a0, 2 +; RV32I-NEXT: add a2, a3, a0 +; RV32I-NEXT: sltu a3, a2, a3 +; RV32I-NEXT: srli a0, a0, 30 +; RV32I-NEXT: slli a4, a1, 2 +; RV32I-NEXT: or a0, a4, a0 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: add a1, a0, a3 +; RV32I-NEXT: mv a0, a2 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: mul64_constant: @@ -197,18 +190,14 @@ define i64 @mul64_constant(i64 %a) nounwind { ; ; RV64I-LABEL: mul64_constant: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 5 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 2 +; RV64I-NEXT: add a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: mul64_constant: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 5 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 2 +; RV64IM-NEXT: add a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i64 %a, 5 ret i64 %1 @@ -305,12 +294,8 @@ define zeroext i32 @mulhu(i32 zeroext %a, i32 zeroext %b) nounwind { define i32 @muli32_p65(i32 %a) nounwind { ; RV32I-LABEL: muli32_p65: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a1, zero, 65 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a1, a0, 6 +; RV32I-NEXT: add a0, a1, a0 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli32_p65: @@ -321,18 +306,14 @@ define i32 @muli32_p65(i32 %a) nounwind { ; ; RV64I-LABEL: muli32_p65: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 65 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: addw a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli32_p65: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 65 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: addw a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i32 %a, 65 ret i32 %1 @@ -341,12 +322,8 @@ define i32 @muli32_p65(i32 %a) nounwind { define i32 @muli32_p63(i32 %a) nounwind { ; RV32I-LABEL: muli32_p63: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a1, zero, 63 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a1, a0, 6 +; RV32I-NEXT: sub a0, a1, a0 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli32_p63: @@ -357,18 +334,14 @@ define i32 @muli32_p63(i32 %a) nounwind { ; ; RV64I-LABEL: muli32_p63: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 63 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: subw a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli32_p63: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 63 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: subw a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i32 %a, 63 ret i32 %1 @@ -377,13 +350,15 @@ define i32 @muli32_p63(i32 %a) nounwind { define i64 @muli64_p65(i64 %a) nounwind { ; RV32I-LABEL: muli64_p65: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a2, zero, 65 -; RV32I-NEXT: mv a3, zero -; RV32I-NEXT: call __muldi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a3, a0, 6 +; RV32I-NEXT: add a2, a3, a0 +; RV32I-NEXT: sltu a3, a2, a3 +; RV32I-NEXT: srli a0, a0, 26 +; RV32I-NEXT: slli a4, a1, 6 +; RV32I-NEXT: or a0, a4, a0 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: add a1, a0, a3 +; RV32I-NEXT: mv a0, a2 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli64_p65: @@ -397,18 +372,14 @@ define i64 @muli64_p65(i64 %a) nounwind { ; ; RV64I-LABEL: muli64_p65: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 65 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: add a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli64_p65: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 65 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: add a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i64 %a, 65 ret i64 %1 @@ -417,13 +388,14 @@ define i64 @muli64_p65(i64 %a) nounwind { define i64 @muli64_p63(i64 %a) nounwind { ; RV32I-LABEL: muli64_p63: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a2, zero, 63 -; RV32I-NEXT: mv a3, zero -; RV32I-NEXT: call __muldi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a2, a0, 6 +; RV32I-NEXT: sltu a3, a2, a0 +; RV32I-NEXT: srli a4, a0, 26 +; RV32I-NEXT: slli a5, a1, 6 +; RV32I-NEXT: or a4, a5, a4 +; RV32I-NEXT: sub a1, a4, a1 +; RV32I-NEXT: sub a1, a1, a3 +; RV32I-NEXT: sub a0, a2, a0 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli64_p63: @@ -437,18 +409,14 @@ define i64 @muli64_p63(i64 %a) nounwind { ; ; RV64I-LABEL: muli64_p63: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, 63 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: sub a0, a1, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli64_p63: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, 63 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: sub a0, a1, a0 ; RV64IM-NEXT: ret %1 = mul i64 %a, 63 ret i64 %1 @@ -457,12 +425,8 @@ define i64 @muli64_p63(i64 %a) nounwind { define i32 @muli32_m63(i32 %a) nounwind { ; RV32I-LABEL: muli32_m63: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a1, zero, -63 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a1, a0, 6 +; RV32I-NEXT: sub a0, a0, a1 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli32_m63: @@ -473,18 +437,14 @@ define i32 @muli32_m63(i32 %a) nounwind { ; ; RV64I-LABEL: muli32_m63: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, -63 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: subw a0, a0, a1 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli32_m63: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, -63 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: subw a0, a0, a1 ; RV64IM-NEXT: ret %1 = mul i32 %a, -63 ret i32 %1 @@ -493,12 +453,9 @@ define i32 @muli32_m63(i32 %a) nounwind { define i32 @muli32_m65(i32 %a) nounwind { ; RV32I-LABEL: muli32_m65: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a1, zero, -65 -; RV32I-NEXT: call __mulsi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a1, a0, 6 +; RV32I-NEXT: add a0, a1, a0 +; RV32I-NEXT: neg a0, a0 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli32_m65: @@ -509,18 +466,16 @@ define i32 @muli32_m65(i32 %a) nounwind { ; ; RV64I-LABEL: muli32_m65: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, -65 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: negw a0, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli32_m65: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, -65 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: add a0, a1, a0 +; RV64IM-NEXT: negw a0, a0 ; RV64IM-NEXT: ret %1 = mul i32 %a, -65 ret i32 %1 @@ -529,13 +484,14 @@ define i32 @muli32_m65(i32 %a) nounwind { define i64 @muli64_m63(i64 %a) nounwind { ; RV32I-LABEL: muli64_m63: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a2, zero, -63 -; RV32I-NEXT: addi a3, zero, -1 -; RV32I-NEXT: call __muldi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a2, a0, 6 +; RV32I-NEXT: sltu a3, a0, a2 +; RV32I-NEXT: srli a4, a0, 26 +; RV32I-NEXT: slli a5, a1, 6 +; RV32I-NEXT: or a4, a5, a4 +; RV32I-NEXT: sub a1, a1, a4 +; RV32I-NEXT: sub a1, a1, a3 +; RV32I-NEXT: sub a0, a0, a2 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli64_m63: @@ -550,18 +506,14 @@ define i64 @muli64_m63(i64 %a) nounwind { ; ; RV64I-LABEL: muli64_m63: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, -63 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: sub a0, a0, a1 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli64_m63: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, -63 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: sub a0, a0, a1 ; RV64IM-NEXT: ret %1 = mul i64 %a, -63 ret i64 %1 @@ -570,13 +522,18 @@ define i64 @muli64_m63(i64 %a) nounwind { define i64 @muli64_m65(i64 %a) nounwind { ; RV32I-LABEL: muli64_m65: ; RV32I: # %bb.0: -; RV32I-NEXT: addi sp, sp, -16 -; RV32I-NEXT: sw ra, 12(sp) -; RV32I-NEXT: addi a2, zero, -65 -; RV32I-NEXT: addi a3, zero, -1 -; RV32I-NEXT: call __muldi3 -; RV32I-NEXT: lw ra, 12(sp) -; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: slli a2, a0, 6 +; RV32I-NEXT: add a3, a2, a0 +; RV32I-NEXT: sltu a2, a3, a2 +; RV32I-NEXT: srli a0, a0, 26 +; RV32I-NEXT: slli a4, a1, 6 +; RV32I-NEXT: or a0, a4, a0 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: add a0, a0, a2 +; RV32I-NEXT: snez a1, a3 +; RV32I-NEXT: add a0, a0, a1 +; RV32I-NEXT: neg a1, a0 +; RV32I-NEXT: neg a0, a3 ; RV32I-NEXT: ret ; ; RV32IM-LABEL: muli64_m65: @@ -591,18 +548,16 @@ define i64 @muli64_m65(i64 %a) nounwind { ; ; RV64I-LABEL: muli64_m65: ; RV64I: # %bb.0: -; RV64I-NEXT: addi sp, sp, -16 -; RV64I-NEXT: sd ra, 8(sp) -; RV64I-NEXT: addi a1, zero, -65 -; RV64I-NEXT: call __muldi3 -; RV64I-NEXT: ld ra, 8(sp) -; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: slli a1, a0, 6 +; RV64I-NEXT: add a0, a1, a0 +; RV64I-NEXT: neg a0, a0 ; RV64I-NEXT: ret ; ; RV64IM-LABEL: muli64_m65: ; RV64IM: # %bb.0: -; RV64IM-NEXT: addi a1, zero, -65 -; RV64IM-NEXT: mul a0, a0, a1 +; RV64IM-NEXT: slli a1, a0, 6 +; RV64IM-NEXT: add a0, a1, a0 +; RV64IM-NEXT: neg a0, a0 ; RV64IM-NEXT: ret %1 = mul i64 %a, -65 ret i64 %1 diff --git a/llvm/test/ExecutionEngine/RuntimeDyld/X86/ELF_x86-64_none.yaml b/llvm/test/ExecutionEngine/RuntimeDyld/X86/ELF_x86-64_none.yaml index ed4b243fae1311..09e14c832a209e 100644 --- a/llvm/test/ExecutionEngine/RuntimeDyld/X86/ELF_x86-64_none.yaml +++ b/llvm/test/ExecutionEngine/RuntimeDyld/X86/ELF_x86-64_none.yaml @@ -22,8 +22,8 @@ Sections: - Offset: 0x0000000000000000 Type: R_X86_64_NONE Symbols: - Global: - - Name: _main - Section: .text - Value: 0 - Size: 4 + - Name: _main + Section: .text + Binding: STB_GLOBAL + Value: 0 + Size: 4 diff --git a/llvm/test/Transforms/SLPVectorizer/AArch64/spillcost-order.ll b/llvm/test/Transforms/SLPVectorizer/AArch64/spillcost-order.ll index 8e0ca4b2938416..9286b7ce9a6902 100644 --- a/llvm/test/Transforms/SLPVectorizer/AArch64/spillcost-order.ll +++ b/llvm/test/Transforms/SLPVectorizer/AArch64/spillcost-order.ll @@ -13,19 +13,22 @@ define void @test(i64* %ptr, i64* noalias %res) { ; CHECK-NEXT: br label [[FOR_BODY:%.*]] ; CHECK: for.body: ; CHECK-NEXT: [[CALL_I_I:%.*]] = call i32* @get_ptr() +; CHECK-NEXT: [[L_0_0:%.*]] = load i32, i32* [[CALL_I_I]], align 2 ; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i32, i32* [[CALL_I_I]], i32 2 +; CHECK-NEXT: [[L_1_0:%.*]] = load i32, i32* [[GEP_1]], align 2 +; CHECK-NEXT: [[EXT_0_0:%.*]] = zext i32 [[L_0_0]] to i64 +; CHECK-NEXT: [[EXT_1_0:%.*]] = zext i32 [[L_1_0]] to i64 +; CHECK-NEXT: [[SUB_1:%.*]] = sub nsw i64 [[EXT_0_0]], [[EXT_1_0]] ; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr i32, i32* [[CALL_I_I]], i32 1 -; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[CALL_I_I]] to <2 x i32>* -; CHECK-NEXT: [[TMP1:%.*]] = load <2 x i32>, <2 x i32>* [[TMP0]], align 2 +; CHECK-NEXT: [[L_0_1:%.*]] = load i32, i32* [[GEP_2]], align 2 ; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr i32, i32* [[CALL_I_I]], i32 3 -; CHECK-NEXT: [[TMP2:%.*]] = bitcast i32* [[GEP_1]] to <2 x i32>* -; CHECK-NEXT: [[TMP3:%.*]] = load <2 x i32>, <2 x i32>* [[TMP2]], align 2 -; CHECK-NEXT: [[TMP4:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64> -; CHECK-NEXT: [[TMP5:%.*]] = zext <2 x i32> [[TMP3]] to <2 x i64> -; CHECK-NEXT: [[TMP6:%.*]] = sub nsw <2 x i64> [[TMP4]], [[TMP5]] -; CHECK-NEXT: [[RES_1:%.*]] = getelementptr i64, i64* [[RES:%.*]], i64 1 -; CHECK-NEXT: [[TMP7:%.*]] = bitcast i64* [[RES]] to <2 x i64>* -; CHECK-NEXT: store <2 x i64> [[TMP6]], <2 x i64>* [[TMP7]], align 8 +; CHECK-NEXT: [[L_1_1:%.*]] = load i32, i32* [[GEP_3]], align 2 +; CHECK-NEXT: [[EXT_0_1:%.*]] = zext i32 [[L_0_1]] to i64 +; CHECK-NEXT: [[EXT_1_1:%.*]] = zext i32 [[L_1_1]] to i64 +; CHECK-NEXT: [[SUB_2:%.*]] = sub nsw i64 [[EXT_0_1]], [[EXT_1_1]] +; CHECK-NEXT: store i64 [[SUB_1]], i64* [[RES:%.*]], align 8 +; CHECK-NEXT: [[RES_1:%.*]] = getelementptr i64, i64* [[RES]], i64 1 +; CHECK-NEXT: store i64 [[SUB_2]], i64* [[RES_1]], align 8 ; CHECK-NEXT: [[C:%.*]] = call i1 @cond() ; CHECK-NEXT: br i1 [[C]], label [[FOR_BODY]], label [[EXIT:%.*]] ; CHECK: exit: diff --git a/llvm/test/tools/llvm-readobj/ELF/verneed-flags.yaml b/llvm/test/tools/llvm-readobj/ELF/verneed-flags.yaml index eedc7fe7ad7a40..685acfbd696a2b 100644 --- a/llvm/test/tools/llvm-readobj/ELF/verneed-flags.yaml +++ b/llvm/test/tools/llvm-readobj/ELF/verneed-flags.yaml @@ -13,37 +13,52 @@ # LLVM-VERDEF-NEXT: Entries [ # LLVM-VERDEF-NEXT: Entry { # LLVM-VERDEF-NEXT: Hash: 0 -# LLVM-VERDEF-NEXT: Flags: Base (0x1) +# LLVM-VERDEF-NEXT: Flags [ (0x1) +# LLVM-VERDEF-NEXT: Base (0x1) +# LLVM-VERDEF-NEXT: ] # LLVM-VERDEF-NEXT: Index: 0 # LLVM-VERDEF-NEXT: Name: base # LLVM-VERDEF-NEXT: } # LLVM-VERDEF-NEXT: Entry { # LLVM-VERDEF-NEXT: Hash: 0 -# LLVM-VERDEF-NEXT: Flags: Weak (0x2) +# LLVM-VERDEF-NEXT: Flags [ (0x2) +# LLVM-VERDEF-NEXT: Weak (0x2) +# LLVM-VERDEF-NEXT: ] # LLVM-VERDEF-NEXT: Index: 0 # LLVM-VERDEF-NEXT: Name: weak # LLVM-VERDEF-NEXT: } # LLVM-VERDEF-NEXT: Entry { # LLVM-VERDEF-NEXT: Hash: 0 -# LLVM-VERDEF-NEXT: Flags: Info (0x4) +# LLVM-VERDEF-NEXT: Flags [ (0x4) +# LLVM-VERDEF-NEXT: Info (0x4) +# LLVM-VERDEF-NEXT: ] # LLVM-VERDEF-NEXT: Index: 0 # LLVM-VERDEF-NEXT: Name: info # LLVM-VERDEF-NEXT: } # LLVM-VERDEF-NEXT: Entry { # LLVM-VERDEF-NEXT: Hash: 0 -# LLVM-VERDEF-NEXT: Flags: 0x7 +# LLVM-VERDEF-NEXT: Flags [ (0x7) +# LLVM-VERDEF-NEXT: Base (0x1) +# LLVM-VERDEF-NEXT: Info (0x4) +# LLVM-VERDEF-NEXT: Weak (0x2) +# LLVM-VERDEF-NEXT: ] # LLVM-VERDEF-NEXT: Index: 0 # LLVM-VERDEF-NEXT: Name: all # LLVM-VERDEF-NEXT: } # LLVM-VERDEF-NEXT: Entry { # LLVM-VERDEF-NEXT: Hash: 0 -# LLVM-VERDEF-NEXT: Flags: 0x8 +# LLVM-VERDEF-NEXT: Flags [ (0x8) +# LLVM-VERDEF-NEXT: ] # LLVM-VERDEF-NEXT: Index: 0 # LLVM-VERDEF-NEXT: Name: unknown # LLVM-VERDEF-NEXT: } # LLVM-VERDEF-NEXT: Entry { # LLVM-VERDEF-NEXT: Hash: 0 -# LLVM-VERDEF-NEXT: Flags: 0xF +# LLVM-VERDEF-NEXT: Flags [ (0xF) +# LLVM-VERDEF-NEXT: Base (0x1) +# LLVM-VERDEF-NEXT: Info (0x4) +# LLVM-VERDEF-NEXT: Weak (0x2) +# LLVM-VERDEF-NEXT: ] # LLVM-VERDEF-NEXT: Index: 0 # LLVM-VERDEF-NEXT: Name: all_and_unknown # LLVM-VERDEF-NEXT: } @@ -52,7 +67,7 @@ # LLVM-VERDEF-NEXT: ] # GNU-VERDEF: Version needs section '.gnu.version_r' contains 1 entries: -# GNU-VERDEF-NEXT: Addr: 0000000000000000 Offset: 0x000200 Link: 6 (.dynstr) +# GNU-VERDEF-NEXT: Addr: 0000000000000000 Offset: 0x000040 Link: 3 (.dynstr) # GNU-VERDEF-NEXT: 0x0000: Version: 1 File: dso.so.0 Cnt: 6 # GNU-VERDEF-NEXT: 0x0010: Name: base Flags: BASE Version: 0 # GNU-VERDEF-NEXT: 0x0020: Name: weak Flags: WEAK Version: 0 diff --git a/llvm/unittests/AsmParser/AsmParserTest.cpp b/llvm/unittests/AsmParser/AsmParserTest.cpp index 198191bf435fd9..9a7d70ad1ed022 100644 --- a/llvm/unittests/AsmParser/AsmParserTest.cpp +++ b/llvm/unittests/AsmParser/AsmParserTest.cpp @@ -230,7 +230,7 @@ TEST(AsmParserTest, TypeWithSlotMappingParsing) { ASSERT_TRUE(Ty->isVectorTy()); // Check the details of the vector. - VectorType *VT = cast(Ty); + auto *VT = cast(Ty); ASSERT_TRUE(VT->getNumElements() == 5); ASSERT_TRUE(VT->getPrimitiveSizeInBits().getFixedSize() == 160); Ty = VT->getElementType(); @@ -362,7 +362,7 @@ TEST(AsmParserTest, TypeAtBeginningWithSlotMappingParsing) { ASSERT_TRUE(Read == 9); // Check the details of the vector. - VectorType *VT = cast(Ty); + auto *VT = cast(Ty); ASSERT_TRUE(VT->getNumElements() == 5); ASSERT_TRUE(VT->getPrimitiveSizeInBits().getFixedSize() == 160); Ty = VT->getElementType(); diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td b/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td index fab1f63f7f30e4..f114c878569d6d 100644 --- a/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td +++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVBase.td @@ -3166,6 +3166,7 @@ def SPV_OC_OpSMod : I32EnumAttrCase<"OpSMod", 139>; def SPV_OC_OpFRem : I32EnumAttrCase<"OpFRem", 140>; def SPV_OC_OpFMod : I32EnumAttrCase<"OpFMod", 141>; def SPV_OC_OpMatrixTimesScalar : I32EnumAttrCase<"OpMatrixTimesScalar", 143>; +def SPV_OC_OpMatrixTimesMatrix : I32EnumAttrCase<"OpMatrixTimesMatrix", 146>; def SPV_OC_OpLogicalEqual : I32EnumAttrCase<"OpLogicalEqual", 164>; def SPV_OC_OpLogicalNotEqual : I32EnumAttrCase<"OpLogicalNotEqual", 165>; def SPV_OC_OpLogicalOr : I32EnumAttrCase<"OpLogicalOr", 166>; @@ -3273,38 +3274,38 @@ def SPV_OpcodeAttr : SPV_OC_OpFNegate, SPV_OC_OpIAdd, SPV_OC_OpFAdd, SPV_OC_OpISub, SPV_OC_OpFSub, SPV_OC_OpIMul, SPV_OC_OpFMul, SPV_OC_OpUDiv, SPV_OC_OpSDiv, SPV_OC_OpFDiv, SPV_OC_OpUMod, SPV_OC_OpSRem, SPV_OC_OpSMod, SPV_OC_OpFRem, SPV_OC_OpFMod, - SPV_OC_OpMatrixTimesScalar, SPV_OC_OpLogicalEqual, SPV_OC_OpLogicalNotEqual, - SPV_OC_OpLogicalOr, SPV_OC_OpLogicalAnd, SPV_OC_OpLogicalNot, SPV_OC_OpSelect, - SPV_OC_OpIEqual, SPV_OC_OpINotEqual, SPV_OC_OpUGreaterThan, - SPV_OC_OpSGreaterThan, SPV_OC_OpUGreaterThanEqual, SPV_OC_OpSGreaterThanEqual, - SPV_OC_OpULessThan, SPV_OC_OpSLessThan, SPV_OC_OpULessThanEqual, - SPV_OC_OpSLessThanEqual, SPV_OC_OpFOrdEqual, SPV_OC_OpFUnordEqual, - SPV_OC_OpFOrdNotEqual, SPV_OC_OpFUnordNotEqual, SPV_OC_OpFOrdLessThan, - SPV_OC_OpFUnordLessThan, SPV_OC_OpFOrdGreaterThan, SPV_OC_OpFUnordGreaterThan, - SPV_OC_OpFOrdLessThanEqual, SPV_OC_OpFUnordLessThanEqual, - SPV_OC_OpFOrdGreaterThanEqual, SPV_OC_OpFUnordGreaterThanEqual, - SPV_OC_OpShiftRightLogical, SPV_OC_OpShiftRightArithmetic, - SPV_OC_OpShiftLeftLogical, SPV_OC_OpBitwiseOr, SPV_OC_OpBitwiseXor, - SPV_OC_OpBitwiseAnd, SPV_OC_OpNot, SPV_OC_OpBitFieldInsert, - SPV_OC_OpBitFieldSExtract, SPV_OC_OpBitFieldUExtract, SPV_OC_OpBitReverse, - SPV_OC_OpBitCount, SPV_OC_OpControlBarrier, SPV_OC_OpMemoryBarrier, - SPV_OC_OpAtomicCompareExchangeWeak, SPV_OC_OpAtomicIIncrement, - SPV_OC_OpAtomicIDecrement, SPV_OC_OpAtomicIAdd, SPV_OC_OpAtomicISub, - SPV_OC_OpAtomicSMin, SPV_OC_OpAtomicUMin, SPV_OC_OpAtomicSMax, - SPV_OC_OpAtomicUMax, SPV_OC_OpAtomicAnd, SPV_OC_OpAtomicOr, SPV_OC_OpAtomicXor, - SPV_OC_OpPhi, SPV_OC_OpLoopMerge, SPV_OC_OpSelectionMerge, SPV_OC_OpLabel, - SPV_OC_OpBranch, SPV_OC_OpBranchConditional, SPV_OC_OpReturn, - SPV_OC_OpReturnValue, SPV_OC_OpUnreachable, SPV_OC_OpNoLine, - SPV_OC_OpModuleProcessed, SPV_OC_OpGroupNonUniformElect, - SPV_OC_OpGroupNonUniformBallot, SPV_OC_OpGroupNonUniformIAdd, - SPV_OC_OpGroupNonUniformFAdd, SPV_OC_OpGroupNonUniformIMul, - SPV_OC_OpGroupNonUniformFMul, SPV_OC_OpGroupNonUniformSMin, - SPV_OC_OpGroupNonUniformUMin, SPV_OC_OpGroupNonUniformFMin, - SPV_OC_OpGroupNonUniformSMax, SPV_OC_OpGroupNonUniformUMax, - SPV_OC_OpGroupNonUniformFMax, SPV_OC_OpSubgroupBallotKHR, - SPV_OC_OpTypeCooperativeMatrixNV, SPV_OC_OpCooperativeMatrixLoadNV, - SPV_OC_OpCooperativeMatrixStoreNV, SPV_OC_OpCooperativeMatrixMulAddNV, - SPV_OC_OpCooperativeMatrixLengthNV + SPV_OC_OpMatrixTimesScalar, SPV_OC_OpMatrixTimesMatrix, SPV_OC_OpLogicalEqual, + SPV_OC_OpLogicalNotEqual, SPV_OC_OpLogicalOr, SPV_OC_OpLogicalAnd, + SPV_OC_OpLogicalNot, SPV_OC_OpSelect, SPV_OC_OpIEqual, SPV_OC_OpINotEqual, + SPV_OC_OpUGreaterThan, SPV_OC_OpSGreaterThan, SPV_OC_OpUGreaterThanEqual, + SPV_OC_OpSGreaterThanEqual, SPV_OC_OpULessThan, SPV_OC_OpSLessThan, + SPV_OC_OpULessThanEqual, SPV_OC_OpSLessThanEqual, SPV_OC_OpFOrdEqual, + SPV_OC_OpFUnordEqual, SPV_OC_OpFOrdNotEqual, SPV_OC_OpFUnordNotEqual, + SPV_OC_OpFOrdLessThan, SPV_OC_OpFUnordLessThan, SPV_OC_OpFOrdGreaterThan, + SPV_OC_OpFUnordGreaterThan, SPV_OC_OpFOrdLessThanEqual, + SPV_OC_OpFUnordLessThanEqual, SPV_OC_OpFOrdGreaterThanEqual, + SPV_OC_OpFUnordGreaterThanEqual, SPV_OC_OpShiftRightLogical, + SPV_OC_OpShiftRightArithmetic, SPV_OC_OpShiftLeftLogical, SPV_OC_OpBitwiseOr, + SPV_OC_OpBitwiseXor, SPV_OC_OpBitwiseAnd, SPV_OC_OpNot, + SPV_OC_OpBitFieldInsert, SPV_OC_OpBitFieldSExtract, SPV_OC_OpBitFieldUExtract, + SPV_OC_OpBitReverse, SPV_OC_OpBitCount, SPV_OC_OpControlBarrier, + SPV_OC_OpMemoryBarrier, SPV_OC_OpAtomicCompareExchangeWeak, + SPV_OC_OpAtomicIIncrement, SPV_OC_OpAtomicIDecrement, SPV_OC_OpAtomicIAdd, + SPV_OC_OpAtomicISub, SPV_OC_OpAtomicSMin, SPV_OC_OpAtomicUMin, + SPV_OC_OpAtomicSMax, SPV_OC_OpAtomicUMax, SPV_OC_OpAtomicAnd, + SPV_OC_OpAtomicOr, SPV_OC_OpAtomicXor, SPV_OC_OpPhi, SPV_OC_OpLoopMerge, + SPV_OC_OpSelectionMerge, SPV_OC_OpLabel, SPV_OC_OpBranch, + SPV_OC_OpBranchConditional, SPV_OC_OpReturn, SPV_OC_OpReturnValue, + SPV_OC_OpUnreachable, SPV_OC_OpNoLine, SPV_OC_OpModuleProcessed, + SPV_OC_OpGroupNonUniformElect, SPV_OC_OpGroupNonUniformBallot, + SPV_OC_OpGroupNonUniformIAdd, SPV_OC_OpGroupNonUniformFAdd, + SPV_OC_OpGroupNonUniformIMul, SPV_OC_OpGroupNonUniformFMul, + SPV_OC_OpGroupNonUniformSMin, SPV_OC_OpGroupNonUniformUMin, + SPV_OC_OpGroupNonUniformFMin, SPV_OC_OpGroupNonUniformSMax, + SPV_OC_OpGroupNonUniformUMax, SPV_OC_OpGroupNonUniformFMax, + SPV_OC_OpSubgroupBallotKHR, SPV_OC_OpTypeCooperativeMatrixNV, + SPV_OC_OpCooperativeMatrixLoadNV, SPV_OC_OpCooperativeMatrixStoreNV, + SPV_OC_OpCooperativeMatrixMulAddNV, SPV_OC_OpCooperativeMatrixLengthNV ]>; // End opcode section. Generated from SPIR-V spec; DO NOT MODIFY! diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td b/mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td index 8545c7ad29e24f..70479e743b0dc8 100644 --- a/mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td +++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVMatrixOps.td @@ -12,10 +12,65 @@ #ifndef SPIRV_MATRIX_OPS #define SPIRV_MATRIX_OPS +include "mlir/Interfaces/SideEffectInterfaces.td" // ----- -def SPV_MatrixTimesScalarOp : SPV_Op<"MatrixTimesScalar", []> { +def SPV_MatrixTimesMatrixOp : SPV_Op<"MatrixTimesMatrix", [NoSideEffect]> { + let summary = "Linear-algebraic multiply of LeftMatrix X RightMatrix."; + + let description = [{ + Result Type must be an OpTypeMatrix whose Column Type is a vector of + floating-point type. + + LeftMatrix must be a matrix whose Column Type is the same as the Column + Type in Result Type. + + RightMatrix must be a matrix with the same Component Type as the + Component Type in Result Type. Its number of columns must equal the + number of columns in Result Type. Its columns must have the same number + of components as the number of columns in LeftMatrix. + + + + ``` + matrix-times-matrix-op ::= ssa-id `=` `spv.MatrixTimesMatrix` ssa-use, + ssa-use `:` matrix-type `,` matrix-type `->` matrix-type + ```mlir + + #### Example: + + ``` + %0 = spv.MatrixTimesMatrix %matrix_1, %matrix_2 : + !spv.matrix<4 x vector<3xf32>>, !spv.matrix<3 x vector<4xf32>> -> + !spv.matrix<4 x vector<4xf32>> + ``` + }]; + + let availability = [ + MinVersion, + MaxVersion, + Extension<[]>, + Capability<[SPV_C_Matrix]> + ]; + + let arguments = (ins + SPV_AnyMatrix:$leftmatrix, + SPV_AnyMatrix:$rightmatrix + ); + + let results = (outs + SPV_AnyMatrix:$result + ); + let assemblyFormat = [{ + operands attr-dict `:` type($leftmatrix) `,` type($rightmatrix) `->` type($result) + }]; + let verifier = [{ return verifyMatrixTimesMatrix(*this); }]; +} + +// ----- + +def SPV_MatrixTimesScalarOp : SPV_Op<"MatrixTimesScalar", [NoSideEffect]> { let summary = "Scale a floating-point matrix."; let description = [{ @@ -79,7 +134,7 @@ def SPV_MatrixTimesScalarOp : SPV_Op<"MatrixTimesScalar", []> { // ----- -def SPV_TransposeOp : SPV_Op<"Transpose", []> { +def SPV_TransposeOp : SPV_Op<"Transpose", [NoSideEffect]> { let summary = "Transpose a matrix."; let description = [{ diff --git a/mlir/include/mlir/Dialect/SPIRV/SPIRVTypes.h b/mlir/include/mlir/Dialect/SPIRV/SPIRVTypes.h index d2dac563bfcf43..91ad96fed7b048 100644 --- a/mlir/include/mlir/Dialect/SPIRV/SPIRVTypes.h +++ b/mlir/include/mlir/Dialect/SPIRV/SPIRVTypes.h @@ -410,13 +410,23 @@ class MatrixType : public Type::TypeBase storage = llvm::None); void getCapabilities(SPIRVType::CapabilityArrayRefVector &capabilities, diff --git a/mlir/include/mlir/IR/Function.h b/mlir/include/mlir/IR/Function.h index f50a1cf8c63a22..60ae8497d8d7b4 100644 --- a/mlir/include/mlir/IR/Function.h +++ b/mlir/include/mlir/IR/Function.h @@ -51,10 +51,8 @@ class FuncOp ArrayRef argAttrs); static void build(OpBuilder &builder, OperationState &result, StringRef name, - FunctionType type, ArrayRef attrs); - static void build(OpBuilder &builder, OperationState &result, StringRef name, - FunctionType type, ArrayRef attrs, - ArrayRef argAttrs); + FunctionType type, ArrayRef attrs = {}, + ArrayRef argAttrs = {}); /// Operation hooks. static ParseResult parse(OpAsmParser &parser, OperationState &result); diff --git a/mlir/include/mlir/Reducer/Tester.h b/mlir/include/mlir/Reducer/Tester.h new file mode 100644 index 00000000000000..8ca2a4a68765c5 --- /dev/null +++ b/mlir/include/mlir/Reducer/Tester.h @@ -0,0 +1,59 @@ +//===- Tester.h -------------------------------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file defines the Tester class used in the MLIR Reduce tool. +// +// A Tester object is passed as an argument to the reduction passes and it is +// used to keep track of the state of the reduction throughout the multiple +// passes. +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_REDUCER_TESTER_H +#define MLIR_REDUCER_TESTER_H + +#include + +#include "mlir/IR/Module.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Program.h" + +namespace mlir { + +/// This class is used to keep track of the state of the reduction. It contains +/// a method to run the interestingness testing script on MLIR test case files +/// and provides functionality to track the most reduced test case. +class Tester { +public: + Tester(StringRef testScript, ArrayRef testScriptArgs); + + /// Runs the interestingness testing script on a MLIR test case file. Returns + /// true if the interesting behavior is present in the test case or false + /// otherwise. + bool isInteresting(StringRef testCase); + + /// Returns the most reduced MLIR test case module. + ModuleOp getMostReduced() const { return mostReduced; } + + /// Updates the most reduced MLIR test case module. If a + /// generated variant is found to be successful and shorter than the + /// mostReduced module, the mostReduced module must be updated with the new + /// variant. + void setMostReduced(ModuleOp t) { mostReduced = t; } + +private: + StringRef testScript; + ArrayRef testScriptArgs; + ModuleOp mostReduced; +}; + +} // end namespace mlir + +#endif \ No newline at end of file diff --git a/mlir/lib/CMakeLists.txt b/mlir/lib/CMakeLists.txt index c1392313faa9e6..be78a448e372c7 100644 --- a/mlir/lib/CMakeLists.txt +++ b/mlir/lib/CMakeLists.txt @@ -10,8 +10,9 @@ add_subdirectory(IR) add_subdirectory(Interfaces) add_subdirectory(Parser) add_subdirectory(Pass) +add_subdirectory(Reducer) add_subdirectory(Support) add_subdirectory(TableGen) add_subdirectory(Target) add_subdirectory(Transforms) -add_subdirectory(Translation) +add_subdirectory(Translation) \ No newline at end of file diff --git a/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp b/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp index d6908680d798df..1ebf48174aafb6 100644 --- a/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp +++ b/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp @@ -124,8 +124,7 @@ LogicalResult ConvertGpuLaunchFuncToVulkanLaunchFunc::declareVulkanLaunchFunc( // Declare vulkan launch function. builder.create( loc, kVulkanLaunch, - FunctionType::get(vulkanLaunchTypes, ArrayRef{}, loc->getContext()), - ArrayRef{}); + FunctionType::get(vulkanLaunchTypes, {}, loc->getContext())); return success(); } diff --git a/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp b/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp index 75b8466ff7fdc3..43f9d88253275d 100644 --- a/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp +++ b/mlir/lib/Conversion/LinalgToStandard/LinalgToStandard.cpp @@ -79,8 +79,7 @@ static FlatSymbolRefAttr getLibraryCallSymbolRef(Operation *op, rewriter.setInsertionPoint(module.getBody(), std::prev(module.getBody()->end())); FuncOp funcOp = - rewriter.create(op->getLoc(), fnNameAttr.getValue(), libFnType, - ArrayRef{}); + rewriter.create(op->getLoc(), fnNameAttr.getValue(), libFnType); // Insert a function attribute that will trigger the emission of the // corresponding `_mlir_ciface_xxx` interface so that external libraries see // a normalized ABI. This interface is added during std to llvm conversion. diff --git a/mlir/lib/Dialect/SPIRV/SPIRVDialect.cpp b/mlir/lib/Dialect/SPIRV/SPIRVDialect.cpp index fbc644d38ae352..47440265239deb 100644 --- a/mlir/lib/Dialect/SPIRV/SPIRVDialect.cpp +++ b/mlir/lib/Dialect/SPIRV/SPIRVDialect.cpp @@ -723,7 +723,7 @@ static void print(CooperativeMatrixNVType type, DialectAsmPrinter &os) { } static void print(MatrixType type, DialectAsmPrinter &os) { - os << "matrix<" << type.getNumElements() << " x " << type.getElementType(); + os << "matrix<" << type.getNumColumns() << " x " << type.getColumnType(); os << ">"; } diff --git a/mlir/lib/Dialect/SPIRV/SPIRVOps.cpp b/mlir/lib/Dialect/SPIRV/SPIRVOps.cpp index 32d13e6afd6156..1f1b6e11c336e3 100644 --- a/mlir/lib/Dialect/SPIRV/SPIRVOps.cpp +++ b/mlir/lib/Dialect/SPIRV/SPIRVOps.cpp @@ -2779,37 +2779,30 @@ static LogicalResult verifyMatrixTimesScalar(spirv::MatrixTimesScalarOp op) { // auto-generated verify method. auto inputMatrix = op.matrix().getType().cast(); - // Check that the scalar type is the same as the matrix components type. - if (auto inputMatrixColumns = - inputMatrix.getElementType().dyn_cast()) { - if (op.scalar().getType() != inputMatrixColumns.getElementType()) - return op.emitError("input matrix components' type and scaling " - "value must have the same type"); - - // Note that the next three checks could be done using the AllTypesMatch - // trait in the Op definition file but it generates a vague error message. - - // Check that the input and result matrices have the same size - auto resultMatrix = op.result().getType().cast(); - if (inputMatrix.getNumElements() != resultMatrix.getNumElements()) - return op.emitError("input and result matrices must have " - "the same number of columns"); - - if (auto resultMatrixColumns = - resultMatrix.getElementType().dyn_cast()) { - // Check that the input and result matrices' columns have the same type - if (inputMatrixColumns.getElementType() != - resultMatrixColumns.getElementType()) - return op.emitError("input and result matrices' columns must " - "have the same component type"); - - // Check that the input and result matrices' columns have the same size - if (inputMatrixColumns.getNumElements() != - resultMatrixColumns.getNumElements()) - return op.emitError("input and result matrices' columns must " - "have the same size"); - } - } + auto resultMatrix = op.result().getType().cast(); + + // Check that the scalar type is the same as the matrix element type. + if (op.scalar().getType() != inputMatrix.getElementType()) + return op.emitError("input matrix components' type and scaling value must " + "have the same type"); + + // Note that the next three checks could be done using the AllTypesMatch + // trait in the Op definition file but it generates a vague error message. + + // Check that the input and result matrices have the same columns' count + if (inputMatrix.getNumColumns() != resultMatrix.getNumColumns()) + return op.emitError("input and result matrices must have the same " + "number of columns"); + + // Check that the input and result matrices' have the same rows count + if (inputMatrix.getNumRows() != resultMatrix.getNumRows()) + return op.emitError("input and result matrices' columns must have " + "the same size"); + + // Check that the input and result matrices' have the same component type + if (inputMatrix.getElementType() != resultMatrix.getElementType()) + return op.emitError("input and result matrices' columns must have " + "the same component type"); return success(); } @@ -2902,24 +2895,56 @@ static LogicalResult verifyTranspose(spirv::TransposeOp op) { auto resultMatrix = op.result().getType().cast(); // Verify that the input and output matrices have correct shapes. - if (auto inputMatrixColumns = - inputMatrix.getElementType().dyn_cast()) { - if (inputMatrixColumns.getNumElements() != resultMatrix.getNumElements()) - return op.emitError("input matrix rows count must be equal to " - "output matrix columns count"); - if (auto resultMatrixColumns = - resultMatrix.getElementType().dyn_cast()) { - if (resultMatrixColumns.getNumElements() != inputMatrix.getNumElements()) - return op.emitError("input matrix columns count must be equal " - "to output matrix rows count"); - - // Verify that the input and output matrices have the same component type - if (inputMatrixColumns.getElementType() != - resultMatrixColumns.getElementType()) - return op.emitError("input and output matrices must have the " - "same component type"); - } - } + if (inputMatrix.getNumRows() != resultMatrix.getNumColumns()) + return op.emitError("input matrix rows count must be equal to " + "output matrix columns count"); + + if (inputMatrix.getNumColumns() != resultMatrix.getNumRows()) + return op.emitError("input matrix columns count must be equal to " + "output matrix rows count"); + + // Verify that the input and output matrices have the same component type + if (inputMatrix.getElementType() != resultMatrix.getElementType()) + return op.emitError("input and output matrices must have the same " + "component type"); + + return success(); +} + +//===----------------------------------------------------------------------===// +// spv.MatrixTimesMatrix +//===----------------------------------------------------------------------===// + +static LogicalResult verifyMatrixTimesMatrix(spirv::MatrixTimesMatrixOp op) { + auto leftMatrix = op.leftmatrix().getType().cast(); + auto rightMatrix = op.rightmatrix().getType().cast(); + auto resultMatrix = op.result().getType().cast(); + + // left matrix columns' count and right matrix rows' count must be equal + if (leftMatrix.getNumColumns() != rightMatrix.getNumRows()) + return op.emitError("left matrix columns' count must be equal to " + "the right matrix rows' count"); + + // right and result matrices columns' count must be the same + if (rightMatrix.getNumColumns() != resultMatrix.getNumColumns()) + return op.emitError( + "right and result matrices must have equal columns' count"); + + // right and result matrices component type must be the same + if (rightMatrix.getElementType() != resultMatrix.getElementType()) + return op.emitError("right and result matrices' component type must" + " be the same"); + + // left and result matrices component type must be the same + if (leftMatrix.getElementType() != resultMatrix.getElementType()) + return op.emitError("left and result matrices' component type" + " must be the same"); + + // left and result matrices rows count must be the same + if (leftMatrix.getNumRows() != resultMatrix.getNumRows()) + return op.emitError("left and result matrices must have equal rows'" + " count"); + return success(); } diff --git a/mlir/lib/Dialect/SPIRV/SPIRVTypes.cpp b/mlir/lib/Dialect/SPIRV/SPIRVTypes.cpp index b0396bfc11638c..07ffe40464837e 100644 --- a/mlir/lib/Dialect/SPIRV/SPIRVTypes.cpp +++ b/mlir/lib/Dialect/SPIRV/SPIRVTypes.cpp @@ -182,7 +182,7 @@ Type CompositeType::getElementType(unsigned index) const { case spirv::TypeKind::CooperativeMatrix: return cast().getElementType(); case spirv::TypeKind::Matrix: - return cast().getElementType(); + return cast().getColumnType(); case spirv::TypeKind::RuntimeArray: return cast().getElementType(); case spirv::TypeKind::Struct: @@ -202,7 +202,7 @@ unsigned CompositeType::getNumElements() const { llvm_unreachable( "invalid to query number of elements of spirv::CooperativeMatrix type"); case spirv::TypeKind::Matrix: - return cast().getNumElements(); + return cast().getNumColumns(); case spirv::TypeKind::RuntimeArray: llvm_unreachable( "invalid to query number of elements of spirv::RuntimeArray type"); @@ -1086,13 +1086,25 @@ bool MatrixType::isValidColumnType(Type columnType) { return false; } -Type MatrixType::getElementType() const { return getImpl()->columnType; } +Type MatrixType::getColumnType() const { return getImpl()->columnType; } -unsigned MatrixType::getNumElements() const { return getImpl()->columnCount; } +Type MatrixType::getElementType() const { + return getImpl()->columnType.cast().getElementType(); +} + +unsigned MatrixType::getNumColumns() const { return getImpl()->columnCount; } + +unsigned MatrixType::getNumRows() const { + return getImpl()->columnType.cast().getShape()[0]; +} + +unsigned MatrixType::getNumElements() const { + return (getImpl()->columnCount) * getNumRows(); +} void MatrixType::getExtensions(SPIRVType::ExtensionArrayRefVector &extensions, Optional storage) { - getElementType().cast().getExtensions(extensions, storage); + getColumnType().cast().getExtensions(extensions, storage); } void MatrixType::getCapabilities( @@ -1104,5 +1116,5 @@ void MatrixType::getCapabilities( capabilities.push_back(ref); } // Add any capabilities associated with the underlying vectors (i.e., columns) - getElementType().cast().getCapabilities(capabilities, storage); + getColumnType().cast().getCapabilities(capabilities, storage); } diff --git a/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp b/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp index 8f6e02de27e757..b015c2391a06f4 100644 --- a/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp +++ b/mlir/lib/Dialect/SPIRV/Serialization/Serializer.cpp @@ -1127,12 +1127,12 @@ Serializer::prepareBasicType(Location loc, Type type, uint32_t resultID, if (auto matrixType = type.dyn_cast()) { uint32_t elementTypeID = 0; - if (failed(processType(loc, matrixType.getElementType(), elementTypeID))) { + if (failed(processType(loc, matrixType.getColumnType(), elementTypeID))) { return failure(); } typeEnum = spirv::Opcode::OpTypeMatrix; operands.push_back(elementTypeID); - operands.push_back(matrixType.getNumElements()); + operands.push_back(matrixType.getNumColumns()); return success(); } diff --git a/mlir/lib/IR/Function.cpp b/mlir/lib/IR/Function.cpp index 305022dd84513f..09c9441bb11010 100644 --- a/mlir/lib/IR/Function.cpp +++ b/mlir/lib/IR/Function.cpp @@ -42,18 +42,16 @@ FuncOp FuncOp::create(Location location, StringRef name, FunctionType type, } void FuncOp::build(OpBuilder &builder, OperationState &result, StringRef name, - FunctionType type, ArrayRef attrs) { + FunctionType type, ArrayRef attrs, + ArrayRef argAttrs) { result.addAttribute(SymbolTable::getSymbolAttrName(), builder.getStringAttr(name)); result.addAttribute(getTypeAttrName(), TypeAttr::get(type)); result.attributes.append(attrs.begin(), attrs.end()); result.addRegion(); -} -void FuncOp::build(OpBuilder &builder, OperationState &result, StringRef name, - FunctionType type, ArrayRef attrs, - ArrayRef argAttrs) { - build(builder, result, name, type, attrs); + if (argAttrs.empty()) + return; assert(type.getNumInputs() == argAttrs.size()); SmallString<8> argAttrName; for (unsigned i = 0, e = type.getNumInputs(); i != e; ++i) diff --git a/mlir/lib/Reducer/CMakeLists.txt b/mlir/lib/Reducer/CMakeLists.txt new file mode 100644 index 00000000000000..dd5fd277ce120b --- /dev/null +++ b/mlir/lib/Reducer/CMakeLists.txt @@ -0,0 +1,7 @@ +add_mlir_library(MLIRReduce + Tester.cpp + DEPENDS + MLIRIR + ) + + mlir_check_all_link_libraries(MLIRReduce) \ No newline at end of file diff --git a/mlir/lib/Reducer/Tester.cpp b/mlir/lib/Reducer/Tester.cpp new file mode 100644 index 00000000000000..dcfce3237cecfa --- /dev/null +++ b/mlir/lib/Reducer/Tester.cpp @@ -0,0 +1,48 @@ +//===- Tester.cpp ---------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file defines the Tester class used in the MLIR Reduce tool. +// +// A Tester object is passed as an argument to the reduction passes and it is +// used to keep track of the state of the reduction throughout the multiple +// passes. +// +//===----------------------------------------------------------------------===// + +#include "mlir/Reducer/Tester.h" + +using namespace mlir; + +Tester::Tester(StringRef scriptName, ArrayRef scriptArgs) + : testScript(scriptName), testScriptArgs(scriptArgs) {} + +/// Runs the interestingness testing script on a MLIR test case file. Returns +/// true if the interesting behavior is present in the test case or false +/// otherwise. +bool Tester::isInteresting(StringRef testCase) { + + std::vector testerArgs; + testerArgs.push_back(testCase); + + for (const std::string &arg : testScriptArgs) + testerArgs.push_back(arg); + + std::string errMsg; + int result = llvm::sys::ExecuteAndWait( + testScript, testerArgs, /*Env=*/None, /*Redirects=*/None, + /*SecondsToWait=*/0, /*MemoryLimit=*/0, &errMsg); + + if (result < 0) + llvm::report_fatal_error("Error running interestingness test: " + errMsg, + false); + + if (!result) + return false; + + return true; +} diff --git a/mlir/test/CMakeLists.txt b/mlir/test/CMakeLists.txt index 52756b6aae7fe6..7c06bd740773ce 100644 --- a/mlir/test/CMakeLists.txt +++ b/mlir/test/CMakeLists.txt @@ -38,6 +38,7 @@ set(MLIR_TEST_DEPENDS mlir-edsc-builder-api-test mlir-linalg-ods-gen mlir-opt + mlir-reduce mlir-sdbm-api-test mlir-tblgen mlir-translate diff --git a/mlir/test/Dialect/SPIRV/Serialization/matrix.mlir b/mlir/test/Dialect/SPIRV/Serialization/matrix.mlir index 6db8a7666768eb..8900ff6137dbb7 100644 --- a/mlir/test/Dialect/SPIRV/Serialization/matrix.mlir +++ b/mlir/test/Dialect/SPIRV/Serialization/matrix.mlir @@ -29,6 +29,20 @@ spv.module Logical GLSL450 requires #spv.vce { %result = spv.Transpose %arg0 : !spv.matrix<3 x vector<2xf32>> -> !spv.matrix<2 x vector<3xf32>> spv.ReturnValue %result : !spv.matrix<2 x vector<3xf32>> } + + // CHECK-LABEL: @matrix_times_matrix_1 + spv.func @matrix_times_matrix_1(%arg0: !spv.matrix<3 x vector<3xf32>>, %arg1: !spv.matrix<3 x vector<3xf32>>) -> !spv.matrix<3 x vector<3xf32>> "None"{ + // CHECK: {{%.*}} = spv.MatrixTimesMatrix {{%.*}}, {{%.*}} : !spv.matrix<3 x vector<3xf32>>, !spv.matrix<3 x vector<3xf32>> -> !spv.matrix<3 x vector<3xf32>> + %result = spv.MatrixTimesMatrix %arg0, %arg1 : !spv.matrix<3 x vector<3xf32>>, !spv.matrix<3 x vector<3xf32>> -> !spv.matrix<3 x vector<3xf32>> + spv.ReturnValue %result : !spv.matrix<3 x vector<3xf32>> + } + + // CHECK-LABEL: @matrix_times_matrix_2 + spv.func @matrix_times_matrix_2(%arg0: !spv.matrix<3 x vector<2xf32>>, %arg1: !spv.matrix<2 x vector<3xf32>>) -> !spv.matrix<2 x vector<2xf32>> "None"{ + // CHECK: {{%.*}} = spv.MatrixTimesMatrix {{%.*}}, {{%.*}} : !spv.matrix<3 x vector<2xf32>>, !spv.matrix<2 x vector<3xf32>> -> !spv.matrix<2 x vector<2xf32>> + %result = spv.MatrixTimesMatrix %arg0, %arg1 : !spv.matrix<3 x vector<2xf32>>, !spv.matrix<2 x vector<3xf32>> -> !spv.matrix<2 x vector<2xf32>> + spv.ReturnValue %result : !spv.matrix<2 x vector<2xf32>> + } } // ----- diff --git a/mlir/test/Dialect/SPIRV/matrix-ops.mlir b/mlir/test/Dialect/SPIRV/matrix-ops.mlir index 09bdf39830051c..4ec78344bc385b 100644 --- a/mlir/test/Dialect/SPIRV/matrix-ops.mlir +++ b/mlir/test/Dialect/SPIRV/matrix-ops.mlir @@ -21,6 +21,20 @@ spv.module Logical GLSL450 requires #spv.vce { %result = spv.Transpose %arg0 : !spv.matrix<3 x vector<3xf32>> -> !spv.matrix<3 x vector<3xf32>> spv.ReturnValue %result : !spv.matrix<3 x vector<3xf32>> } + + // CHECK-LABEL: @matrix_times_matrix_1 + spv.func @matrix_times_matrix_1(%arg0: !spv.matrix<3 x vector<3xf32>>, %arg1: !spv.matrix<3 x vector<3xf32>>) -> !spv.matrix<3 x vector<3xf32>> "None"{ + // CHECK: {{%.*}} = spv.MatrixTimesMatrix {{%.*}}, {{%.*}} : !spv.matrix<3 x vector<3xf32>>, !spv.matrix<3 x vector<3xf32>> -> !spv.matrix<3 x vector<3xf32>> + %result = spv.MatrixTimesMatrix %arg0, %arg1 : !spv.matrix<3 x vector<3xf32>>, !spv.matrix<3 x vector<3xf32>> -> !spv.matrix<3 x vector<3xf32>> + spv.ReturnValue %result : !spv.matrix<3 x vector<3xf32>> + } + + // CHECK-LABEL: @matrix_times_matrix_2 + spv.func @matrix_times_matrix_2(%arg0: !spv.matrix<3 x vector<2xf32>>, %arg1: !spv.matrix<2 x vector<3xf32>>) -> !spv.matrix<2 x vector<2xf32>> "None"{ + // CHECK: {{%.*}} = spv.MatrixTimesMatrix {{%.*}}, {{%.*}} : !spv.matrix<3 x vector<2xf32>>, !spv.matrix<2 x vector<3xf32>> -> !spv.matrix<2 x vector<2xf32>> + %result = spv.MatrixTimesMatrix %arg0, %arg1 : !spv.matrix<3 x vector<2xf32>>, !spv.matrix<2 x vector<3xf32>> -> !spv.matrix<2 x vector<2xf32>> + spv.ReturnValue %result : !spv.matrix<2 x vector<2xf32>> + } } // ----- @@ -74,3 +88,39 @@ func @transpose_op_type_mismatch(%arg0 : !spv.matrix<3 x vector<4xf32>>) -> () { %result = spv.Transpose %arg0 : !spv.matrix<3 x vector<4xf32>> -> !spv.matrix<4 x vector<3xf16>> spv.Return } + +// ----- + +func @matrix_times_matrix_invalid_input_shape_1(%arg0 : !spv.matrix<3 x vector<2xf32>>, %arg1 : !spv.matrix<2 x vector<3xf32>>){ + // expected-error @+1 {{right and result matrices must have equal columns' count}} + %result = spv.MatrixTimesMatrix %arg0, %arg1 : !spv.matrix<3 x vector<2xf32>>, !spv.matrix<2 x vector<3xf32>> -> !spv.matrix<3 x vector<2xf32>> +} + +// ----- + +func @matrix_times_matrix_invalid_input_shape_2(%arg0 : !spv.matrix<3 x vector<2xf32>>, %arg1 : !spv.matrix<2 x vector<3xf32>>){ + // expected-error @+1 {{left and result matrices must have equal rows' count}} + %result = spv.MatrixTimesMatrix %arg0, %arg1 : !spv.matrix<3 x vector<2xf32>>, !spv.matrix<2 x vector<3xf32>> -> !spv.matrix<2 x vector<3xf32>> +} + +// ----- + +func @matrix_times_matrix_inputs_shape_mismatch(%arg0 : !spv.matrix<3 x vector<2xf32>>, %arg1 : !spv.matrix<2 x vector<2xf32>>){ + // expected-error @+1 {{left matrix columns' count must be equal to the right matrix rows' count}} + %result = spv.MatrixTimesMatrix %arg0, %arg1 : !spv.matrix<3 x vector<2xf32>>, !spv.matrix<2 x vector<2xf32>> -> !spv.matrix<2 x vector<2xf32>> +} + +// ----- + +func @matrix_times_matrix_component_type_mismatch_1(%arg0 : !spv.matrix<3 x vector<3xf32>>, %arg1 : !spv.matrix<3x vector<3xf32>>){ + // expected-error @+1 {{right and result matrices' component type must be the same}} + %result = spv.MatrixTimesMatrix %arg0, %arg1 : !spv.matrix<3 x vector<3xf32>>, !spv.matrix<3 x vector<3xf32>> -> !spv.matrix<3 x vector<3xf64>> +} + + +// ----- + +func @matrix_times_matrix_component_type_mismatch_2(%arg0 : !spv.matrix<3 x vector<3xf64>>, %arg1 : !spv.matrix<3x vector<3xf32>>){ + // expected-error @+1 {{left and result matrices' component type must be the same}} + %result = spv.MatrixTimesMatrix %arg0, %arg1 : !spv.matrix<3 x vector<3xf64>>, !spv.matrix<3 x vector<3xf32>> -> !spv.matrix<3 x vector<3xf32>> +} diff --git a/mlir/test/mlir-reduce/test.sh b/mlir/test/mlir-reduce/test.sh new file mode 100755 index 00000000000000..33d02f41a95e55 --- /dev/null +++ b/mlir/test/mlir-reduce/test.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +#Replicate bug + +#Interesting behavior +exit 1 \ No newline at end of file diff --git a/mlir/test/mlir-reduce/testcase-linux.mlir b/mlir/test/mlir-reduce/testcase-linux.mlir new file mode 100644 index 00000000000000..f2bb161bb5a690 --- /dev/null +++ b/mlir/test/mlir-reduce/testcase-linux.mlir @@ -0,0 +1,13 @@ +// UNSUPPORTED: -windows- +// RUN: mlir-reduce %s -test %S/test.sh + +func @simple1(%arg0: i1, %arg1: memref<2xf32>, %arg2: memref<2xf32>) { + cond_br %arg0, ^bb1, ^bb2 +^bb1: + br ^bb3(%arg1 : memref<2xf32>) +^bb2: + %0 = alloc() : memref<2xf32> + br ^bb3(%0 : memref<2xf32>) +^bb3(%1: memref<2xf32>): + return +} \ No newline at end of file diff --git a/mlir/tools/CMakeLists.txt b/mlir/tools/CMakeLists.txt index e8f61633c92b17..23a2fcbc14ebba 100644 --- a/mlir/tools/CMakeLists.txt +++ b/mlir/tools/CMakeLists.txt @@ -2,7 +2,8 @@ add_subdirectory(mlir-cuda-runner) add_subdirectory(mlir-cpu-runner) add_subdirectory(mlir-linalg-ods-gen) add_subdirectory(mlir-opt) +add_subdirectory(mlir-reduce) add_subdirectory(mlir-rocm-runner) -add_subdirectory(mlir-translate) -add_subdirectory(mlir-vulkan-runner) add_subdirectory(mlir-shlib) +add_subdirectory(mlir-translate) +add_subdirectory(mlir-vulkan-runner) \ No newline at end of file diff --git a/mlir/tools/mlir-reduce/CMakeLists.txt b/mlir/tools/mlir-reduce/CMakeLists.txt new file mode 100644 index 00000000000000..642c5d96c2153b --- /dev/null +++ b/mlir/tools/mlir-reduce/CMakeLists.txt @@ -0,0 +1,41 @@ +get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS) +get_property(conversion_libs GLOBAL PROPERTY MLIR_CONVERSION_LIBS) +set(LLVM_LINK_COMPONENTS + AllTargetsAsmParsers + AllTargetsCodeGens + AllTargetsDescs + AllTargetsInfos + AsmParser + Core + IRReader + Support + Target + TransformUtils + ) + +set(LIBS + ${dialect_libs} + ${conversion_libs} + ${test_libs} + MLIRAnalysis + MLIRDialect + MLIREDSC + MLIRIR + MLIRLoopAnalysis + MLIROptLib + MLIRParser + MLIRPass + MLIRReduce + MLIRSupport + MLIRTransforms + MLIRTransformUtils + ) + +add_llvm_tool(mlir-reduce + mlir-reduce.cpp + ) + +target_link_libraries(mlir-reduce PRIVATE ${LIBS}) +llvm_update_compile_flags(mlir-reduce) + +mlir_check_all_link_libraries(mlir-reduce) \ No newline at end of file diff --git a/mlir/tools/mlir-reduce/mlir-reduce.cpp b/mlir/tools/mlir-reduce/mlir-reduce.cpp new file mode 100644 index 00000000000000..3edef61f1d7288 --- /dev/null +++ b/mlir/tools/mlir-reduce/mlir-reduce.cpp @@ -0,0 +1,97 @@ +//===- mlir-reduce.cpp - The MLIR reducer ---------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file implements the general framework of the MLIR reducer tool. It +// parses the command line arguments, parses the initial MLIR test case and sets +// up the testing environment. It outputs the most reduced test case variant +// after executing the reduction passes. +// +//===----------------------------------------------------------------------===// + +#include + +#include "mlir/InitAllDialects.h" +#include "mlir/Parser.h" +#include "mlir/Pass/Pass.h" +#include "mlir/Pass/PassManager.h" +#include "mlir/Reducer/Tester.h" +#include "mlir/Support/FileUtilities.h" +#include "mlir/Support/LogicalResult.h" +#include "mlir/Transforms/Passes.h" +#include "llvm/Support/InitLLVM.h" +#include "llvm/Support/ToolOutputFile.h" + +using namespace mlir; + +static llvm::cl::opt inputFilename(llvm::cl::Positional, + llvm::cl::Required, + llvm::cl::desc("")); + +static llvm::cl::opt + testFilename("test", llvm::cl::Required, llvm::cl::desc("Testing script")); + +static llvm::cl::list + testArguments("test-args", llvm::cl::ZeroOrMore, + llvm::cl::desc("Testing script arguments")); + +static llvm::cl::opt + outputFilename("o", + llvm::cl::desc("Output filename for the reduced test case"), + llvm::cl::init("-")); + +// Parse and verify the input MLIR file. +static LogicalResult loadModule(MLIRContext &context, OwningModuleRef &module, + StringRef inputFilename) { + module = parseSourceFile(inputFilename, &context); + if (!module) + return failure(); + + return success(); +} + +int main(int argc, char **argv) { + + llvm::InitLLVM y(argc, argv); + + registerAllDialects(); + registerMLIRContextCLOptions(); + registerPassManagerCLOptions(); + + llvm::cl::ParseCommandLineOptions(argc, argv, + "MLIR test case reduction tool.\n"); + + std::string errorMessage; + + auto testscript = openInputFile(testFilename, &errorMessage); + if (!testscript) + llvm::report_fatal_error(errorMessage); + + auto output = openOutputFile(outputFilename, &errorMessage); + if (!output) + llvm::report_fatal_error(errorMessage); + + mlir::MLIRContext context; + mlir::OwningModuleRef moduleRef; + context.allowUnregisteredDialects(true); + + if (failed(loadModule(context, moduleRef, inputFilename))) + llvm::report_fatal_error("Input test case can't be parsed"); + + // Initialize test environment. + Tester test(testFilename, testArguments); + test.setMostReduced(moduleRef.get()); + + if (!test.isInteresting(inputFilename)) + llvm::report_fatal_error( + "Input test case does not exhibit interesting behavior"); + + test.getMostReduced().print(output->os()); + output->keep(); + + return 0; +} \ No newline at end of file diff --git a/openmp/runtime/test/ompt/worksharing/for/runtime.c b/openmp/runtime/test/ompt/worksharing/for/runtime.c index 1dc3dd67c26df1..bcf160faeb8981 100644 --- a/openmp/runtime/test/ompt/worksharing/for/runtime.c +++ b/openmp/runtime/test/ompt/worksharing/for/runtime.c @@ -1,7 +1,5 @@ // RUN: %libomp-compile-and-run | %sort-threads | FileCheck %S/base.h // REQUIRES: ompt -// gcc 9/10 use GOMP_parallel_loop_maybe_nonmonotonic_runtime, not implemented -// XFAIL: gcc-9, gcc-10 #define SCHEDULE runtime #include "base.h" diff --git a/openmp/runtime/test/ompt/worksharing/for/runtime_serialized.c b/openmp/runtime/test/ompt/worksharing/for/runtime_serialized.c index 136e9efb182c16..231d67d91aa9eb 100644 --- a/openmp/runtime/test/ompt/worksharing/for/runtime_serialized.c +++ b/openmp/runtime/test/ompt/worksharing/for/runtime_serialized.c @@ -1,7 +1,5 @@ // RUN: %libomp-compile-and-run | %sort-threads | FileCheck %S/base_serialized.h // REQUIRES: ompt -// gcc 9/10 use GOMP_parallel_loop_maybe_nonmonotonic_runtime, not implemented -// XFAIL: gcc-9, gcc-10 #define SCHEDULE runtime #include "base_serialized.h" diff --git a/openmp/runtime/test/ompt/worksharing/for/runtime_split.c b/openmp/runtime/test/ompt/worksharing/for/runtime_split.c index b21bc248d62301..7a677edbfd0e3a 100644 --- a/openmp/runtime/test/ompt/worksharing/for/runtime_split.c +++ b/openmp/runtime/test/ompt/worksharing/for/runtime_split.c @@ -3,8 +3,5 @@ // REQUIRES: ompt // UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7 -// gcc 9/10 use GOMP_parallel_loop_maybe_nonmonotonic_runtime, not implemented -// XFAIL: gcc-9, gcc-10 - #define SCHEDULE runtime #include "base_split.h" diff --git a/openmp/runtime/test/worksharing/for/bug_set_schedule_0.c b/openmp/runtime/test/worksharing/for/bug_set_schedule_0.c index 97ba492da3d280..813b31c20c1eea 100644 --- a/openmp/runtime/test/worksharing/for/bug_set_schedule_0.c +++ b/openmp/runtime/test/worksharing/for/bug_set_schedule_0.c @@ -1,9 +1,5 @@ // RUN: %libomp-compile-and-run -// gcc 9/10 use GOMP_parallel_loop_maybe_nonmonotonic_runtime, not implemented -// Should be removed once the functions are implemented -// XFAIL: gcc-9, gcc-10 - #include #include #include "omp_testsuite.h" diff --git a/openmp/runtime/test/worksharing/for/omp_for_schedule_runtime.c b/openmp/runtime/test/worksharing/for/omp_for_schedule_runtime.c index 0b8cd8900f0865..27a76567fbe2eb 100644 --- a/openmp/runtime/test/worksharing/for/omp_for_schedule_runtime.c +++ b/openmp/runtime/test/worksharing/for/omp_for_schedule_runtime.c @@ -11,10 +11,6 @@ // RUN: env OMP_SCHEDULE=static_steal %libomp-run 102 1 // RUN: env OMP_SCHEDULE=static_steal,14 %libomp-run 102 14 -// gcc 9/10 use GOMP_parallel_loop_maybe_nonmonotonic_runtime, not implemented -// Should be removed once the functions are implemented -// XFAIL: gcc-9, gcc-10 - #include #include #include diff --git a/openmp/runtime/test/worksharing/for/omp_nonmonotonic_dynamic1.c b/openmp/runtime/test/worksharing/for/omp_nonmonotonic_dynamic1.c index 47341484283f72..0691353fe59e57 100644 --- a/openmp/runtime/test/worksharing/for/omp_nonmonotonic_dynamic1.c +++ b/openmp/runtime/test/worksharing/for/omp_nonmonotonic_dynamic1.c @@ -1,10 +1,6 @@ // RUN: %libomp-compile // RUN: env OMP_SCHEDULE=nonmonotonic:dynamic,10 %libomp-run -// gcc 9/10 use GOMP_parallel_loop_maybe_nonmonotonic_runtime, not implemented -// Should be removed once the functions are implemented -// XFAIL: gcc-9, gcc-10 - // The test checks iterations distribution for OMP 5.0 nonmonotonic OMP_SCHEDULE // case #threads > #chunks (fallback to monotonic dynamic)