diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 8731dc73c64879..09445ae21592f8 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -=================================================== -Extra Clang Tools 8.0.0 (In-Progress) Release Notes -=================================================== +===================================== +Extra Clang Tools 8.0.0 Release Notes +===================================== .. contents:: :local: @@ -8,12 +8,6 @@ Extra Clang Tools 8.0.0 (In-Progress) Release Notes Written by the `LLVM Team `_ -.. warning:: - - These are in-progress notes for the upcoming Extra Clang Tools 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -27,11 +21,6 @@ For more information about Clang or LLVM, including information about the latest release, please see the `Clang Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Clang web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. - What's New in Extra Clang Tools 8.0.0? ====================================== diff --git a/clang-tools-extra/docs/index.rst b/clang-tools-extra/docs/index.rst index 8e6beb35a60918..55fd1a6d08be2a 100644 --- a/clang-tools-extra/docs/index.rst +++ b/clang-tools-extra/docs/index.rst @@ -29,24 +29,6 @@ Contents clang-doc -Doxygen Documentation -===================== -The Doxygen documentation describes the **internal** software that makes up the -tools of clang-tools-extra, not the **external** use of these tools. The Doxygen -documentation contains no instructions about how to use the tools, only the APIs -that make up the software. For usage instructions, please see the user's guide -or reference manual for each tool. - -* `Doxygen documentation`_ - -.. _`Doxygen documentation`: doxygen/annotated.html - -.. note:: - This documentation is generated directly from the source code with doxygen. - Since the tools of clang-tools-extra are constantly under active - development, what you're about to read is out of date! - - Indices and tables ================== diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 50bf636a51f437..4c593977e2c320 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -======================================= -Clang 8.0.0 (In-Progress) Release Notes -======================================= +========================= +Clang 8.0.0 Release Notes +========================= .. contents:: :local: @@ -8,12 +8,6 @@ Clang 8.0.0 (In-Progress) Release Notes Written by the `LLVM Team `_ -.. warning:: - - These are in-progress notes for the upcoming Clang 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -30,11 +24,6 @@ For more information about Clang or LLVM, including information about the latest release, please see the `Clang Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Clang web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. - What's New in Clang 8.0.0? ========================== @@ -50,7 +39,38 @@ Major New Features profile data captured for one version of a program to be applied when building another version where symbols have changed (for example, due to renaming a class or namespace). - See the :doc:`UsersManual` for details. + See the :ref:`UsersManual ` for details. + +- Clang has new options to initialize automatic variables with either a pattern or with zeroes. The default is still that automatic variables are uninitialized. This isn't meant to change the semantics of C and C++. Rather, it's meant to be a last resort when programmers inadvertently have some undefined behavior in their code. These options aim to make undefined behavior hurt less, which security-minded people will be very happy about. Notably, this means that there's no inadvertent information leak when: + + * The compiler re-uses stack slots, and a value is used uninitialized. + + * The compiler re-uses a register, and a value is used uninitialized. + + * Stack structs / arrays / unions with padding are copied. + + These options only address stack and register information leaks. + + Caveats: + + * Variables declared in unreachable code and used later aren't initialized. This affects goto statements, Duff's device, and other objectionable uses of switch statements. This should instead be a hard-error in any serious codebase. + + * These options don't affect volatile stack variables. + + * Padding isn't fully handled yet. + + How to use it on the command line: + + * ``-ftrivial-auto-var-init=uninitialized`` (the default) + + * ``-ftrivial-auto-var-init=pattern`` + + * ``-ftrivial-auto-var-init=zero`` ``-enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang`` + + There is also a new attribute to request a variable to not be initialized, mainly to disable initialization of large stack arrays when deemed too expensive: + + * ``int dont_initialize_me __attribute((uninitialized));`` + Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -131,14 +151,24 @@ Non-comprehensive list of changes in this release - Improved support for MIPS N32 ABI and MIPS R6 target triples. +- Clang now includes builtin functions for bitwise rotation of common value + sizes, such as: `__builtin_rotateleft32 + `_ + +- Improved optimization for the corresponding MSVC compatibility builtins such + as ``_rotl()``. + New Compiler Flags ------------------ +- ``-mspeculative-load-hardening`` Clang now has an option to enable + Speculative Load Hardening. + - ``-fprofile-filter-files=[regexes]`` and ``-fprofile-exclude-files=[regexes]``. Clang has now options to filter or exclude some files when instrumenting for gcov-based profiling. - See the :doc:`UsersManual` for details. + See the `UsersManual `_ for details. - When using a custom stack alignment, the ``stackrealign`` attribute is now implicitly set on the main function. @@ -175,7 +205,9 @@ New Pragmas in Clang Attribute Changes in Clang -------------------------- -- ... +* Clang now supports enabling/disabling speculative load hardening on a + per-function basis using the function attribute + ``speculative_load_hardening``/``no_speculative_load_hardening``. Windows Support --------------- diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 7634d24eb5a6ac..38f7615bf95b01 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1799,6 +1799,8 @@ In these cases, you can use the flag ``-fno-profile-instr-generate`` (or Note that these flags should appear after the corresponding profile flags to have an effect. +.. _profile_remapping: + Profile remapping ^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 3de73428829b33..bf4f3babbd3c63 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2577,6 +2577,11 @@ class CallExpr : public Expr { NumArgs = NewNumArgs; } + /// Bluntly set a new number of arguments without doing any checks whatsoever. + /// Only used during construction of a CallExpr in a few places in Sema. + /// FIXME: Find a way to remove it. + void setNumArgsUnsafe(unsigned NewNumArgs) { NumArgs = NewNumArgs; } + typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; typedef llvm::iterator_range arg_range; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index bf1068019b77bd..b792db2852a80f 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -103,13 +103,6 @@ def ObjCInstanceMethod : SubsetSubjectisInstanceMethod()}], "Objective-C instance methods">; -def ObjCInterfaceDeclInitMethod : SubsetSubjectgetMethodFamily() == OMF_init && - (isa(S->getDeclContext()) || - (isa(S->getDeclContext()) && - cast(S->getDeclContext())->IsClassExtension()))}], - "init methods of interface or class extension declarations">; - def Struct : SubsetSubjectisUnion()}], "structs">; @@ -1762,7 +1755,7 @@ def ObjCExplicitProtocolImpl : InheritableAttr { def ObjCDesignatedInitializer : Attr { let Spellings = [Clang<"objc_designated_initializer">]; - let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag>; + let Subjects = SubjectList<[ObjCMethod], ErrorDiag>; let Documentation = [Undocumented]; } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index b71f65d146cab5..7ef57b02fe1c63 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3460,6 +3460,9 @@ def warn_objc_secondary_init_missing_init_call : Warning< def warn_objc_implementation_missing_designated_init_override : Warning< "method override for the designated initializer of the superclass %objcinstance0 not found">, InGroup; +def err_designated_init_attr_non_init : Error< + "'objc_designated_initializer' attribute only applies to init methods " + "of interface or class extension declarations">; // objc_bridge attribute diagnostics. def err_objc_attr_not_id : Error< diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 438ff0e2ed4507..46e4431913e763 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -360,11 +360,6 @@ class Parser : public CodeCompletionHandler { /// just a regular sub-expression. SourceLocation ExprStatementTokLoc; - /// Tests whether an expression value is discarded based on token lookahead. - /// It will return true if the lexer is currently processing the }) - /// terminating a GNU statement expression and false otherwise. - bool isExprValueDiscarded(); - public: Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies); ~Parser() override; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e5b7465820a982..ced5773f0c0737 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1369,7 +1369,6 @@ class Sema { void PopCompoundScope(); sema::CompoundScopeInfo &getCurCompoundScope() const; - bool isCurCompoundStmtAStmtExpr() const; bool hasAnyUnrecoverableErrorsInThisFunction() const; @@ -3690,17 +3689,16 @@ class Sema { return MakeFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation()); } FullExprArg MakeFullExpr(Expr *Arg, SourceLocation CC) { - return FullExprArg( - ActOnFinishFullExpr(Arg, CC, /*DiscardedValue*/ false).get()); + return FullExprArg(ActOnFinishFullExpr(Arg, CC).get()); } FullExprArg MakeFullDiscardedValueExpr(Expr *Arg) { ExprResult FE = - ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), - /*DiscardedValue*/ true); + ActOnFinishFullExpr(Arg, Arg ? Arg->getExprLoc() : SourceLocation(), + /*DiscardedValue*/ true); return FullExprArg(FE.get()); } - StmtResult ActOnExprStmt(ExprResult Arg, bool DiscardedValue = true); + StmtResult ActOnExprStmt(ExprResult Arg); StmtResult ActOnExprStmtError(); StmtResult ActOnNullStmt(SourceLocation SemiLoc, @@ -5346,12 +5344,13 @@ class Sema { CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference); - ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue) { - return ActOnFinishFullExpr( - Expr, Expr ? Expr->getExprLoc() : SourceLocation(), DiscardedValue); + ExprResult ActOnFinishFullExpr(Expr *Expr) { + return ActOnFinishFullExpr(Expr, Expr ? Expr->getExprLoc() + : SourceLocation()); } ExprResult ActOnFinishFullExpr(Expr *Expr, SourceLocation CC, - bool DiscardedValue, bool IsConstexpr = false); + bool DiscardedValue = false, + bool IsConstexpr = false); StmtResult ActOnFinishFullStmt(Stmt *Stmt); // Marks SS invalid if it represents an incomplete type. diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index b98657ffd8006c..790a8df3d7e419 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -1620,8 +1620,9 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { bool capturedByInit = Init && emission.IsEscapingByRef && isCapturedBy(D, Init); - Address Loc = - capturedByInit ? emission.Addr : emission.getObjectAddress(*this); + bool locIsByrefHeader = !capturedByInit; + const Address Loc = + locIsByrefHeader ? emission.getObjectAddress(*this) : emission.Addr; // Note: constexpr already initializes everything correctly. LangOptions::TrivialAutoVarInitKind trivialAutoVarInit = @@ -1637,7 +1638,7 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { return; // Only initialize a __block's storage: we always initialize the header. - if (emission.IsEscapingByRef) + if (emission.IsEscapingByRef && !locIsByrefHeader) Loc = emitBlockByrefAddress(Loc, &D, /*follow=*/false); CharUnits Size = getContext().getTypeSizeInChars(type); @@ -1745,10 +1746,9 @@ void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) { } llvm::Type *BP = CGM.Int8Ty->getPointerTo(Loc.getAddressSpace()); - if (Loc.getType() != BP) - Loc = Builder.CreateBitCast(Loc, BP); - - emitStoresForConstant(CGM, D, Loc, isVolatile, Builder, constant); + emitStoresForConstant( + CGM, D, (Loc.getType() == BP) ? Loc : Builder.CreateBitCast(Loc, BP), + isVolatile, Builder, constant); } /// Emit an expression as an initializer for an object (variable, field, etc.) diff --git a/clang/lib/Frontend/TextDiagnostic.cpp b/clang/lib/Frontend/TextDiagnostic.cpp index 35b99b10f94a40..8b18fcccb4623e 100644 --- a/clang/lib/Frontend/TextDiagnostic.cpp +++ b/clang/lib/Frontend/TextDiagnostic.cpp @@ -838,7 +838,7 @@ void TextDiagnostic::emitDiagnosticLoc(FullSourceLoc Loc, PresumedLoc PLoc, if (LangOpts.MSCompatibilityVersion && !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015)) OS << ' '; - OS << ": "; + OS << ':'; break; } diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index bd55f717939959..c8d7bda3d6e91c 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -2741,7 +2741,7 @@ StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc) { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Res, isExprValueDiscarded()); + return Actions.ActOnExprStmt(Res); } ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index dd2a8aae9f2fb6..17c3fa3cf2aa51 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -314,7 +314,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); ExprResult CombinerResult = Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), - D->getLocation(), /*DiscardedValue*/ false); + D->getLocation(), /*DiscardedValue=*/true); Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && @@ -356,7 +356,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { if (Actions.getLangOpts().CPlusPlus) { InitializerResult = Actions.ActOnFinishFullExpr( ParseAssignmentExpression().get(), D->getLocation(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); } else { ConsumeToken(); ParseOpenMPReductionInitializerForDecl(OmpPrivParm); @@ -364,7 +364,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { } else { InitializerResult = Actions.ActOnFinishFullExpr( ParseAssignmentExpression().get(), D->getLocation(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); } Actions.ActOnOpenMPDeclareReductionInitializerEnd( D, InitializerResult.get(), OmpPrivParm); @@ -1455,7 +1455,7 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, ExprResult LHS(ParseCastExpression( /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); - Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); // Parse ')'. RLoc = Tok.getLocation(); @@ -1711,8 +1711,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, SourceLocation ELoc = Tok.getLocation(); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); - Val = - Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); } // Parse ')'. @@ -1997,8 +1996,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.ColonLoc = Tok.getLocation(); SourceLocation ELoc = ConsumeToken(); ExprResult Tail = ParseAssignmentExpression(); - Tail = - Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); + Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc); if (Tail.isUsable()) Data.TailExpr = Tail.get(); else diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 2974e6a245b0ef..313793c3e8fb83 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -439,7 +439,7 @@ StmtResult Parser::ParseExprStatement() { // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - return Actions.ActOnExprStmt(Expr, isExprValueDiscarded()); + return Actions.ActOnExprStmt(Expr); } /// ParseSEHTryBlockCommon @@ -958,16 +958,6 @@ bool Parser::ConsumeNullStmt(StmtVector &Stmts) { return true; } -bool Parser::isExprValueDiscarded() { - if (Actions.isCurCompoundStmtAStmtExpr()) { - // Look to see if the next two tokens close the statement expression; - // if so, this expression statement is the last statement in a - // statment expression. - return Tok.isNot(tok::r_brace) || NextToken().isNot(tok::r_paren); - } - return true; -} - /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the /// ActOnCompoundStmt action. This expects the '{' to be the current token, and /// consume the '}' at the end of the block. It does not manipulate the scope @@ -1072,7 +1062,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // Eat the semicolon at the end of stmt and convert the expr into a // statement. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); - R = Actions.ActOnExprStmt(Res, isExprValueDiscarded()); + R = Actions.ActOnExprStmt(Res); } } @@ -1708,16 +1698,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { if (!Value.isInvalid()) { if (ForEach) FirstPart = Actions.ActOnForEachLValueExpr(Value.get()); - else { - // We already know this is not an init-statement within a for loop, so - // if we are parsing a C++11 range-based for loop, we should treat this - // expression statement as being a discarded value expression because - // we will err below. This way we do not warn on an unused expression - // that was an error in the first place, like with: for (expr : expr); - bool IsRangeBasedFor = - getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon); - FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor); - } + else + FirstPart = Actions.ActOnExprStmt(Value); } if (Tok.is(tok::semi)) { diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 8dc1fdb76988da..b2c727b5c483b7 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -10622,16 +10622,16 @@ static void AnalyzeCompoundAssignment(Sema &S, BinaryOperator *E) { // The below checks assume source is floating point. if (!ResultBT || !RBT || !RBT->isFloatingPoint()) return; - // If source is floating point but target is not. - if (!ResultBT->isFloatingPoint()) - return DiagnoseFloatingImpCast(S, E, E->getRHS()->getType(), - E->getExprLoc()); - - // If both source and target are floating points. - // Builtin FP kinds are ordered by increasing FP rank. - if (ResultBT->getKind() < RBT->getKind() && - // We don't want to warn for system macro. - !S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) + // If source is floating point but target is an integer. + if (ResultBT->isInteger()) + DiagnoseImpCast(S, E, E->getRHS()->getType(), E->getLHS()->getType(), + E->getExprLoc(), diag::warn_impcast_float_integer); + // If both source and target are floating points. Builtin FP kinds are ordered + // by increasing FP rank. FIXME: except _Float16, we currently emit a bogus + // warning. + else if (ResultBT->isFloatingPoint() && ResultBT->getKind() < RBT->getKind() && + // We don't want to warn for system macro. + !S.SourceMgr.isInSystemMacro(E->getOperatorLoc())) // warn about dropping FP rank. DiagnoseImpCast(S, E->getRHS(), E->getLHS()->getType(), E->getOperatorLoc(), diag::warn_impcast_float_result_precision); diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 181efa6d3dd094..e282bb62f03269 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -646,7 +646,7 @@ bool Sema::ActOnCoroutineBodyStart(Scope *SC, SourceLocation KWLoc, return StmtError(); Suspend = BuildResolvedCoawaitExpr(Loc, Suspend.get(), /*IsImplicit*/ true); - Suspend = ActOnFinishFullExpr(Suspend.get(), /*DiscardedValue*/ false); + Suspend = ActOnFinishFullExpr(Suspend.get()); if (Suspend.isInvalid()) { Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required) << ((Name == "initial_suspend") ? 0 : 1); @@ -867,7 +867,7 @@ StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E, if (PC.isInvalid()) return StmtError(); - Expr *PCE = ActOnFinishFullExpr(PC.get(), /*DiscardedValue*/ false).get(); + Expr *PCE = ActOnFinishFullExpr(PC.get()).get(); Stmt *Res = new (Context) CoreturnStmt(Loc, E, PCE, IsImplicit); return Res; @@ -1236,7 +1236,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { ExprResult NewExpr = S.ActOnCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc); - NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), /*DiscardedValue*/ false); + NewExpr = S.ActOnFinishFullExpr(NewExpr.get()); if (NewExpr.isInvalid()) return false; @@ -1262,8 +1262,7 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() { ExprResult DeleteExpr = S.ActOnCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc); - DeleteExpr = - S.ActOnFinishFullExpr(DeleteExpr.get(), /*DiscardedValue*/ false); + DeleteExpr = S.ActOnFinishFullExpr(DeleteExpr.get()); if (DeleteExpr.isInvalid()) return false; @@ -1348,8 +1347,7 @@ bool CoroutineStmtBuilder::makeOnException() { ExprResult UnhandledException = buildPromiseCall(S, Fn.CoroutinePromise, Loc, "unhandled_exception", None); - UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc, - /*DiscardedValue*/ false); + UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc); if (UnhandledException.isInvalid()) return false; @@ -1402,8 +1400,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { "get_return_object type must no longer be dependent"); if (FnRetType->isVoidType()) { - ExprResult Res = - S.ActOnFinishFullExpr(this->ReturnValue, Loc, /*DiscardedValue*/ false); + ExprResult Res = S.ActOnFinishFullExpr(this->ReturnValue, Loc); if (Res.isInvalid()) return false; @@ -1435,7 +1432,7 @@ bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() { if (Res.isInvalid()) return false; - Res = S.ActOnFinishFullExpr(Res.get(), /*DiscardedValue*/ false); + Res = S.ActOnFinishFullExpr(Res.get()); if (Res.isInvalid()) return false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 23c99d45a78d4d..7ddf2e88b78719 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11200,9 +11200,9 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // struct T { S a, b; } t = { Temp(), Temp() } // // we should destroy the first Temp before constructing the second. - ExprResult Result = - ActOnFinishFullExpr(Init, VDecl->getLocation(), - /*DiscardedValue*/ false, VDecl->isConstexpr()); + ExprResult Result = ActOnFinishFullExpr(Init, VDecl->getLocation(), + false, + VDecl->isConstexpr()); if (Result.isInvalid()) { VDecl->setInvalidDecl(); return; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 8819f0396a270d..c4c3598ee7f3cb 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5116,11 +5116,22 @@ static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D, static void handleObjCDesignatedInitializer(Sema &S, Decl *D, const ParsedAttr &AL) { + DeclContext *Ctx = D->getDeclContext(); + + // This attribute can only be applied to methods in interfaces or class + // extensions. + if (!isa(Ctx) && + !(isa(Ctx) && + cast(Ctx)->IsClassExtension())) { + S.Diag(D->getLocation(), diag::err_designated_init_attr_non_init); + return; + } + ObjCInterfaceDecl *IFace; - if (auto *CatDecl = dyn_cast(D->getDeclContext())) + if (auto *CatDecl = dyn_cast(Ctx)) IFace = CatDecl->getClassInterface(); else - IFace = cast(D->getDeclContext()); + IFace = cast(Ctx); if (!IFace) return; @@ -7067,6 +7078,17 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } } } + + // Do this check after processing D's attributes because the attribute + // objc_method_family can change whether the given method is in the init + // family, and it can be applied after objc_designated_initializer. This is a + // bit of a hack, but we need it to be compatible with versions of clang that + // processed the attribute list in the wrong order. + if (D->hasAttr() && + cast(D)->getMethodFamily() != OMF_init) { + Diag(D->getLocation(), diag::err_designated_init_attr_non_init); + D->dropAttr(); + } } // Helper for delayed processing TransparentUnion attribute. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8b3556f715bfdc..950a63aa451be4 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1205,7 +1205,7 @@ static bool checkTupleLikeDecomposition(Sema &S, E = Seq.Perform(S, Entity, Kind, Init); if (E.isInvalid()) return true; - E = S.ActOnFinishFullExpr(E.get(), Loc, /*DiscardedValue*/ false); + E = S.ActOnFinishFullExpr(E.get(), Loc); if (E.isInvalid()) return true; RefVD->setInit(E.get()); @@ -3686,7 +3686,7 @@ void Sema::ActOnFinishCXXInClassMemberInitializer(Decl *D, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - Init = ActOnFinishFullExpr(Init.get(), InitLoc, /*DiscardedValue*/ false); + Init = ActOnFinishFullExpr(Init.get(), InitLoc); if (Init.isInvalid()) { FD->setInvalidDecl(); return; @@ -4044,8 +4044,7 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin(), - /*DiscardedValue*/ false); + MemberInit = ActOnFinishFullExpr(MemberInit.get(), InitRange.getBegin()); if (MemberInit.isInvalid()) return true; @@ -4100,8 +4099,8 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - DelegationInit = ActOnFinishFullExpr( - DelegationInit.get(), InitRange.getBegin(), /*DiscardedValue*/ false); + DelegationInit = ActOnFinishFullExpr(DelegationInit.get(), + InitRange.getBegin()); if (DelegationInit.isInvalid()) return true; @@ -4230,8 +4229,7 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // C++11 [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. - BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin(), - /*DiscardedValue*/ false); + BaseInit = ActOnFinishFullExpr(BaseInit.get(), InitRange.getBegin()); if (BaseInit.isInvalid()) return true; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2bcd47abe35699..ff9393a56b9cba 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -4723,9 +4723,8 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD, if (Result.isInvalid()) return true; - Result = - ActOnFinishFullExpr(Result.getAs(), Param->getOuterLocStart(), - /*DiscardedValue*/ false); + Result = ActOnFinishFullExpr(Result.getAs(), + Param->getOuterLocStart()); if (Result.isInvalid()) return true; @@ -5677,18 +5676,36 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl, } if (!getLangOpts().CPlusPlus) { + // Forget about the nulled arguments since typo correction + // do not handle them well. + TheCall->shrinkNumArgs(Args.size()); // C cannot always handle TypoExpr nodes in builtin calls and direct // function calls as their argument checking don't necessarily handle // dependent types properly, so make sure any TypoExprs have been // dealt with. ExprResult Result = CorrectDelayedTyposInExpr(TheCall); if (!Result.isUsable()) return ExprError(); + CallExpr *TheOldCall = TheCall; TheCall = dyn_cast(Result.get()); + bool CorrectedTypos = TheCall != TheOldCall; if (!TheCall) return Result; - // TheCall at this point has max(Args.size(), NumParams) arguments, - // with extra arguments nulled. We don't want to introduce nulled - // arguments in Args and so we only take the first Args.size() arguments. - Args = llvm::makeArrayRef(TheCall->getArgs(), Args.size()); + Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs()); + + // A new call expression node was created if some typos were corrected. + // However it may not have been constructed with enough storage. In this + // case, rebuild the node with enough storage. The waste of space is + // immaterial since this only happens when some typos were corrected. + if (CorrectedTypos && Args.size() < NumParams) { + if (Config) + TheCall = CUDAKernelCallExpr::Create( + Context, Fn, cast(Config), Args, ResultTy, VK_RValue, + RParenLoc, NumParams); + else + TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue, + RParenLoc, NumParams, UsesADL); + } + // We can now handle the nulled arguments for the default arguments. + TheCall->setNumArgsUnsafe(std::max(Args.size(), NumParams)); } // Bail out early if calling a builtin with custom type checking. diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 8c89a3cee3dbbb..cce7a216548fff 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7815,8 +7815,6 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC, FullExpr = IgnoredValueConversions(FullExpr.get()); if (FullExpr.isInvalid()) return ExprError(); - - DiagnoseUnusedExprResult(FullExpr.get()); } FullExpr = CorrectDelayedTyposInExpr(FullExpr.get()); diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index af233b96d69b49..4e002a853dc217 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1724,7 +1724,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, /*NRVO=*/false), CurrentLocation, Src); if (!Init.isInvalid()) - Init = ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); + Init = ActOnFinishFullExpr(Init.get()); if (Init.isInvalid()) return ExprError(); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 36048a38b999cb..aedec746af9e79 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5367,7 +5367,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), UB.get()); EUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, UB.get(), CondOp.get()); - EUB = SemaRef.ActOnFinishFullExpr(EUB.get(), /*DiscardedValue*/ false); + EUB = SemaRef.ActOnFinishFullExpr(EUB.get()); // If we have a combined directive that combines 'distribute', 'for' or // 'simd' we need to be able to access the bounds of the schedule of the @@ -5396,8 +5396,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, LastIteration.get(), CombUB.get()); CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), CombCondOp.get()); - CombEUB = - SemaRef.ActOnFinishFullExpr(CombEUB.get(), /*DiscardedValue*/ false); + CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get()); const CapturedDecl *CD = cast(AStmt)->getCapturedDecl(); // We expect to have at least 2 more parameters than the 'parallel' @@ -5431,7 +5430,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, ? LB.get() : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); - Init = SemaRef.ActOnFinishFullExpr(Init.get(), /*DiscardedValue*/ false); + Init = SemaRef.ActOnFinishFullExpr(Init.get()); if (isOpenMPLoopBoundSharingDirective(DKind)) { Expr *CombRHS = @@ -5442,8 +5441,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); CombInit = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); - CombInit = - SemaRef.ActOnFinishFullExpr(CombInit.get(), /*DiscardedValue*/ false); + CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get()); } } @@ -5475,7 +5473,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, if (!Inc.isUsable()) return 0; Inc = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, IV.get(), Inc.get()); - Inc = SemaRef.ActOnFinishFullExpr(Inc.get(), /*DiscardedValue*/ false); + Inc = SemaRef.ActOnFinishFullExpr(Inc.get()); if (!Inc.isUsable()) return 0; @@ -5493,8 +5491,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // LB = LB + ST NextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, LB.get(), NextLB.get()); - NextLB = - SemaRef.ActOnFinishFullExpr(NextLB.get(), /*DiscardedValue*/ false); + NextLB = SemaRef.ActOnFinishFullExpr(NextLB.get()); if (!NextLB.isUsable()) return 0; // UB + ST @@ -5504,8 +5501,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // UB = UB + ST NextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, UB.get(), NextUB.get()); - NextUB = - SemaRef.ActOnFinishFullExpr(NextUB.get(), /*DiscardedValue*/ false); + NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get()); if (!NextUB.isUsable()) return 0; if (isOpenMPLoopBoundSharingDirective(DKind)) { @@ -5516,8 +5512,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // LB = LB + ST CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), CombNextLB.get()); - CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get(), - /*DiscardedValue*/ false); + CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get()); if (!CombNextLB.isUsable()) return 0; // UB + ST @@ -5528,8 +5523,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, // UB = UB + ST CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), CombNextUB.get()); - CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get(), - /*DiscardedValue*/ false); + CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get()); if (!CombNextUB.isUsable()) return 0; } @@ -5550,8 +5544,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, assert(DistInc.isUsable() && "distribute inc expr was not built"); DistInc = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, IV.get(), DistInc.get()); - DistInc = - SemaRef.ActOnFinishFullExpr(DistInc.get(), /*DiscardedValue*/ false); + DistInc = SemaRef.ActOnFinishFullExpr(DistInc.get()); assert(DistInc.isUsable() && "distribute inc expr was not built"); // Build expression: UB = min(UB, prevUB) for #for in composite or combined @@ -5563,8 +5556,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, DistEUBLoc, DistEUBLoc, IsUBGreater.get(), PrevUB.get(), UB.get()); PrevEUB = SemaRef.BuildBinOp(CurScope, DistIncLoc, BO_Assign, UB.get(), CondOp.get()); - PrevEUB = - SemaRef.ActOnFinishFullExpr(PrevEUB.get(), /*DiscardedValue*/ false); + PrevEUB = SemaRef.ActOnFinishFullExpr(PrevEUB.get()); // Build IV <= PrevUB to be used in parallel for is in combination with // a distribute directive with schedule(static, 1) @@ -5680,10 +5672,8 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr, Built.IterationVarRef = IV.get(); Built.LastIteration = LastIteration.get(); Built.NumIterations = NumIterations.get(); - Built.CalcLastIteration = SemaRef - .ActOnFinishFullExpr(CalcLastIteration.get(), - /*DiscardedValue*/ false) - .get(); + Built.CalcLastIteration = + SemaRef.ActOnFinishFullExpr(CalcLastIteration.get()).get(); Built.PreCond = PreCond.get(); Built.PreInits = buildPreInits(C, Captures); Built.Cond = Cond.get(); @@ -10358,8 +10348,8 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef VarList, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = - ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, + /*DiscardedValue=*/true); if (AssignmentOp.isInvalid()) continue; @@ -11357,8 +11347,7 @@ static bool actOnOMPReductionKindClause( BO_Assign, LHSDRE, ConditionalOp); } if (ReductionOp.isUsable()) - ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get(), - /*DiscardedValue*/ false); + ReductionOp = S.ActOnFinishFullExpr(ReductionOp.get()); } if (!ReductionOp.isUsable()) continue; @@ -11688,7 +11677,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause( buildDeclRefExpr(*this, SaveVar, StepExpr->getType(), StepLoc); ExprResult CalcStep = BuildBinOp(CurScope, StepLoc, BO_Assign, SaveRef.get(), StepExpr); - CalcStep = ActOnFinishFullExpr(CalcStep.get(), /*DiscardedValue*/ false); + CalcStep = ActOnFinishFullExpr(CalcStep.get()); // Warn about zero linear step (it would be probably better specified as // making corresponding variables 'const'). @@ -11776,7 +11765,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, else Update = *CurPrivate; Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); // Build final: Var = InitExpr + NumIterations * Step ExprResult Final; @@ -11787,7 +11776,7 @@ static bool FinishOpenMPLinearClause(OMPLinearClause &Clause, DeclRefExpr *IV, else Final = *CurPrivate; Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); if (!Update.isUsable() || !Final.isUsable()) { Updates.push_back(nullptr); @@ -11955,7 +11944,7 @@ OMPClause *Sema::ActOnOpenMPCopyinClause(ArrayRef VarList, if (AssignmentOp.isInvalid()) continue; AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), DE->getExprLoc(), - /*DiscardedValue*/ false); + /*DiscardedValue=*/true); if (AssignmentOp.isInvalid()) continue; @@ -12063,8 +12052,8 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef VarList, DSAStack->getCurScope(), ELoc, BO_Assign, PseudoDstExpr, PseudoSrcExpr); if (AssignmentOp.isInvalid()) continue; - AssignmentOp = - ActOnFinishFullExpr(AssignmentOp.get(), ELoc, /*DiscardedValue*/ false); + AssignmentOp = ActOnFinishFullExpr(AssignmentOp.get(), ELoc, + /*DiscardedValue=*/true); if (AssignmentOp.isInvalid()) continue; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 9e30c9a396c0a1..dacf8d0cf4e7fd 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -42,11 +42,12 @@ using namespace clang; using namespace sema; -StmtResult Sema::ActOnExprStmt(ExprResult FE, bool DiscardedValue) { +StmtResult Sema::ActOnExprStmt(ExprResult FE) { if (FE.isInvalid()) return StmtError(); - FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), DiscardedValue); + FE = ActOnFinishFullExpr(FE.get(), FE.get()->getExprLoc(), + /*DiscardedValue*/ true); if (FE.isInvalid()) return StmtError(); @@ -347,10 +348,6 @@ sema::CompoundScopeInfo &Sema::getCurCompoundScope() const { return getCurFunction()->CompoundScopes.back(); } -bool Sema::isCurCompoundStmtAStmtExpr() const { - return getCurCompoundScope().IsStmtExpr; -} - StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef Elts, bool isStmtExpr) { const unsigned NumElts = Elts.size(); @@ -373,6 +370,14 @@ StmtResult Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, Diag(D->getLocation(), diag::ext_mixed_decls_code); } } + // Warn about unused expressions in statements. + for (unsigned i = 0; i != NumElts; ++i) { + // Ignore statements that are last in a statement expression. + if (isStmtExpr && i == NumElts - 1) + continue; + + DiagnoseUnusedExprResult(Elts[i]); + } // Check for suspicious empty body (null statement) in `for' and `while' // statements. Don't do anything for template instantiations, this just adds @@ -464,12 +469,15 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal, /// ActOnCaseStmtBody - This installs a statement as the body of a case. void Sema::ActOnCaseStmtBody(Stmt *S, Stmt *SubStmt) { + DiagnoseUnusedExprResult(SubStmt); cast(S)->setSubStmt(SubStmt); } StmtResult Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc, Stmt *SubStmt, Scope *CurScope) { + DiagnoseUnusedExprResult(SubStmt); + if (getCurFunction()->SwitchStack.empty()) { Diag(DefaultLoc, diag::err_default_not_in_switch); return SubStmt; @@ -563,6 +571,9 @@ StmtResult Sema::BuildIfStmt(SourceLocation IfLoc, bool IsConstexpr, if (IsConstexpr || isa(Cond.get().second)) setFunctionHasBranchProtectedScope(); + DiagnoseUnusedExprResult(thenStmt); + DiagnoseUnusedExprResult(elseStmt); + return IfStmt::Create(Context, IfLoc, IsConstexpr, InitStmt, Cond.get().first, Cond.get().second, thenStmt, ElseLoc, elseStmt); } @@ -1290,6 +1301,8 @@ StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, ConditionResult Cond, !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc())) CommaVisitor(*this).Visit(CondVal.second); + DiagnoseUnusedExprResult(Body); + if (isa(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); @@ -1309,7 +1322,7 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, return StmtError(); Cond = CondResult.get(); - CondResult = ActOnFinishFullExpr(Cond, DoLoc, /*DiscardedValue*/ false); + CondResult = ActOnFinishFullExpr(Cond, DoLoc); if (CondResult.isInvalid()) return StmtError(); Cond = CondResult.get(); @@ -1319,6 +1332,8 @@ Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc())) CommaVisitor(*this).Visit(Cond); + DiagnoseUnusedExprResult(Body); + return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen); } @@ -1763,6 +1778,11 @@ StmtResult Sema::ActOnForStmt(SourceLocation ForLoc, SourceLocation LParenLoc, CommaVisitor(*this).Visit(Second.get().second); Expr *Third = third.release().getAs(); + + DiagnoseUnusedExprResult(First); + DiagnoseUnusedExprResult(Third); + DiagnoseUnusedExprResult(Body); + if (isa(Body)) getCurCompoundScope().setHasEmptyLoopBodies(); @@ -1782,7 +1802,7 @@ StmtResult Sema::ActOnForEachLValueExpr(Expr *E) { if (result.isInvalid()) return StmtError(); E = result.get(); - ExprResult FullExpr = ActOnFinishFullExpr(E, /*DiscardedValue*/ false); + ExprResult FullExpr = ActOnFinishFullExpr(E); if (FullExpr.isInvalid()) return StmtError(); return StmtResult(static_cast(FullExpr.get())); @@ -1936,8 +1956,7 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, if (CollectionExprResult.isInvalid()) return StmtError(); - CollectionExprResult = - ActOnFinishFullExpr(CollectionExprResult.get(), /*DiscardedValue*/ false); + CollectionExprResult = ActOnFinishFullExpr(CollectionExprResult.get()); if (CollectionExprResult.isInvalid()) return StmtError(); @@ -2574,8 +2593,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, if (!NotEqExpr.isInvalid()) NotEqExpr = CheckBooleanCondition(ColonLoc, NotEqExpr.get()); if (!NotEqExpr.isInvalid()) - NotEqExpr = - ActOnFinishFullExpr(NotEqExpr.get(), /*DiscardedValue*/ false); + NotEqExpr = ActOnFinishFullExpr(NotEqExpr.get()); if (NotEqExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 0 << BeginRangeRef.get()->getType(); @@ -2598,7 +2616,7 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, // co_await during the initial parse. IncrExpr = ActOnCoawaitExpr(S, CoawaitLoc, IncrExpr.get()); if (!IncrExpr.isInvalid()) - IncrExpr = ActOnFinishFullExpr(IncrExpr.get(), /*DiscardedValue*/ false); + IncrExpr = ActOnFinishFullExpr(IncrExpr.get()); if (IncrExpr.isInvalid()) { Diag(RangeLoc, diag::note_for_range_invalid_iterator) << RangeLoc << 2 << BeginRangeRef.get()->getType() ; @@ -2853,7 +2871,7 @@ Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, return StmtError(); } - ExprResult ExprRes = ActOnFinishFullExpr(E, /*DiscardedValue*/ false); + ExprResult ExprRes = ActOnFinishFullExpr(E); if (ExprRes.isInvalid()) return StmtError(); E = ExprRes.get(); @@ -3203,8 +3221,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ExpressionEvaluationContext::DiscardedStatement && (HasDeducedReturnType || CurCap->HasImplicitReturnType)) { if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3331,8 +3348,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3562,8 +3578,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { ExpressionEvaluationContext::DiscardedStatement && FnRetType->getContainedAutoType()) { if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3657,8 +3672,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3737,8 +3751,7 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (RetValExp) { - ExprResult ER = - ActOnFinishFullExpr(RetValExp, ReturnLoc, /*DiscardedValue*/ false); + ExprResult ER = ActOnFinishFullExpr(RetValExp, ReturnLoc); if (ER.isInvalid()) return StmtError(); RetValExp = ER.get(); @@ -3791,7 +3804,7 @@ StmtResult Sema::BuildObjCAtThrowStmt(SourceLocation AtLoc, Expr *Throw) { if (Result.isInvalid()) return StmtError(); - Result = ActOnFinishFullExpr(Result.get(), /*DiscardedValue*/ false); + Result = ActOnFinishFullExpr(Result.get()); if (Result.isInvalid()) return StmtError(); Throw = Result.get(); @@ -3863,7 +3876,7 @@ Sema::ActOnObjCAtSynchronizedOperand(SourceLocation atLoc, Expr *operand) { } // The operand to @synchronized is a full-expression. - return ActOnFinishFullExpr(operand, /*DiscardedValue*/ false); + return ActOnFinishFullExpr(operand); } StmtResult diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index df14768cbe812a..9de4e8d654f96e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -328,7 +328,7 @@ class TreeTransform { /// other mechanism. /// /// \returns the transformed statement. - StmtResult TransformStmt(Stmt *S, bool DiscardedValue = false); + StmtResult TransformStmt(Stmt *S); /// Transform the given statement. /// @@ -3269,8 +3269,8 @@ class TreeTransform { bool DeducibleTSTContext); }; -template -StmtResult TreeTransform::TransformStmt(Stmt *S, bool DiscardedValue) { +template +StmtResult TreeTransform::TransformStmt(Stmt *S) { if (!S) return S; @@ -3294,7 +3294,7 @@ StmtResult TreeTransform::TransformStmt(Stmt *S, bool DiscardedValue) { if (E.isInvalid()) return StmtError(); - return getSema().ActOnExprStmt(E, DiscardedValue); + return getSema().ActOnExprStmt(E); } } @@ -4715,8 +4715,7 @@ TreeTransform::TransformVariableArrayType(TypeLocBuilder &TLB, } if (SizeResult.isInvalid()) return QualType(); - SizeResult = - SemaRef.ActOnFinishFullExpr(SizeResult.get(), /*DiscardedValue*/ false); + SizeResult = SemaRef.ActOnFinishFullExpr(SizeResult.get()); if (SizeResult.isInvalid()) return QualType(); @@ -6521,9 +6520,7 @@ TreeTransform::TransformCompoundStmt(CompoundStmt *S, bool SubStmtChanged = false; SmallVector Statements; for (auto *B : S->body()) { - StmtResult Result = - getDerived().TransformStmt(B, !IsStmtExpr || B != S->body_back()); - + StmtResult Result = getDerived().TransformStmt(B); if (Result.isInvalid()) { // Immediately fail if this was a DeclStmt, since it's very // likely that this will cause problems for future statements. diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index da94b6eb21e9b2..ea695c4736a3e4 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -154,6 +154,32 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) { return E; } +/// Comparing internal representations of symbolic values (via +/// SVal::operator==()) is a valid way to check if the value was updated, +/// unless it's a LazyCompoundVal that may have a different internal +/// representation every time it is loaded from the state. In this function we +/// do an approximate comparison for lazy compound values, checking that they +/// are the immediate snapshots of the tracked region's bindings within the +/// node's respective states but not really checking that these snapshots +/// actually contain the same set of bindings. +bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal, + const ExplodedNode *RightNode, SVal RightVal) { + if (LeftVal == RightVal) + return true; + + const auto LLCV = LeftVal.getAs(); + if (!LLCV) + return false; + + const auto RLCV = RightVal.getAs(); + if (!RLCV) + return false; + + return LLCV->getRegion() == RLCV->getRegion() && + LLCV->getStore() == LeftNode->getState()->getStore() && + RLCV->getStore() == RightNode->getState()->getStore(); +} + //===----------------------------------------------------------------------===// // Definitions for bug reporter visitors. //===----------------------------------------------------------------------===// @@ -1188,7 +1214,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, if (Succ->getState()->getSVal(R) != V) return nullptr; - if (Pred->getState()->getSVal(R) == V) { + if (hasVisibleUpdate(Pred, Pred->getState()->getSVal(R), Succ, V)) { Optional PS = Succ->getLocationAs(); if (!PS || PS->getLocationValue() != R) return nullptr; @@ -1209,6 +1235,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, // UndefinedVal.) if (Optional CE = Succ->getLocationAs()) { if (const auto *VR = dyn_cast(R)) { + const auto *Param = cast(VR->getDecl()); ProgramStateManager &StateMgr = BRC.getStateManager(); diff --git a/clang/test/Analysis/PR40625.cpp b/clang/test/Analysis/PR40625.cpp new file mode 100644 index 00000000000000..6cc27d39b6c089 --- /dev/null +++ b/clang/test/Analysis/PR40625.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,alpha.core.CallAndMessageUnInitRefArg %s -verify + +void f(const int *end); + +void g(const int (&arrr)[10]) { + f(arrr+sizeof(arrr)); // expected-warning{{1st function call argument is a pointer to uninitialized value}} + // FIXME: This is a false positive that should be fixed. Until then this + // tests the crash fix in FindLastStoreBRVisitor (beside + // uninit-vals.m). +} + +void h() { + int arr[10]; + + g(arr); +} diff --git a/clang/test/Analysis/uninit-vals.m b/clang/test/Analysis/uninit-vals.m index f97af1a6633cce..33352122ca5aa0 100644 --- a/clang/test/Analysis/uninit-vals.m +++ b/clang/test/Analysis/uninit-vals.m @@ -394,11 +394,11 @@ void testSmallStructBitfieldsFirstUnnamed() { struct { int : 4; int y : 4; - } a, b, c; + } a, b, c; // expected-note{{'c' initialized here}} a.y = 2; - b = a; // expected-note{{Value assigned to 'c'}} + b = a; clang_analyzer_eval(b.y == 2); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} @@ -411,11 +411,11 @@ void testSmallStructBitfieldsSecondUnnamed() { struct { int x : 4; int : 4; - } a, b, c; + } a, b, c; // expected-note{{'c' initialized here}} a.x = 1; - b = a; // expected-note{{Value assigned to 'c'}} + b = a; clang_analyzer_eval(b.x == 1); // expected-warning{{TRUE}} // expected-note@-1{{TRUE}} diff --git a/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp b/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp index 4804cc559d007f..7a6a408ec955b8 100644 --- a/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp +++ b/clang/test/CXX/stmt.stmt/stmt.select/p3.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -verify %s -// RUN: %clang_cc1 -fsyntax-only -Wno-unused-value -std=c++1z -Wc++14-compat -verify %s -DCPP17 +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17 int f(); @@ -71,6 +71,7 @@ void whileInitStatement() { // last loop above. It would be nice to remove this. void whileInitStatement2() { while (; false) {} // expected-error {{expected expression}} - // expected-error@-1 {{expected ';' after expression}} - // expected-error@-2 {{expected expression}} + // expected-warning@-1 {{expression result unused}} + // expected-error@-2 {{expected ';' after expression}} + // expected-error@-3 {{expected expression}} } diff --git a/clang/test/CodeCompletion/pragma-macro-token-caching.c b/clang/test/CodeCompletion/pragma-macro-token-caching.c index 59b6621b56ad47..432706e85ceb9c 100644 --- a/clang/test/CodeCompletion/pragma-macro-token-caching.c +++ b/clang/test/CodeCompletion/pragma-macro-token-caching.c @@ -12,7 +12,7 @@ void completeParam(int param) { void completeParamPragmaError(int param) { Outer(__extension__({ _Pragma(2) })); // expected-error {{_Pragma takes a parenthesized string literal}} - param; // expected-warning {{expression result unused}} + param; } // RUN: %clang_cc1 -fsyntax-only -verify -code-completion-at=%s:16:1 %s | FileCheck %s diff --git a/clang/test/CodeGenCXX/trivial-auto-var-init.cpp b/clang/test/CodeGenCXX/trivial-auto-var-init.cpp index 37ff770abf57eb..0a9ad86c7e2feb 100644 --- a/clang/test/CodeGenCXX/trivial-auto-var-init.cpp +++ b/clang/test/CodeGenCXX/trivial-auto-var-init.cpp @@ -45,14 +45,35 @@ void test_block() { // PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured, %struct.__block_byref_captured* %captured, i32 0, i32 4 // PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8 // PATTERN: %call = call %struct.XYZ* @create( +using Block = void (^)(); +typedef struct XYZ { + Block block; +} * xyz_t; void test_block_self_init() { - using Block = void (^)(); - typedef struct XYZ { - Block block; - } * xyz_t; extern xyz_t create(Block block); __block xyz_t captured = create(^() { - (void)captured; + used(captured); + }); +} + +// Capturing with escape after initialization is also an edge case. +// +// UNINIT-LABEL: test_block_captures_self_after_init( +// ZERO-LABEL: test_block_captures_self_after_init( +// ZERO: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8 +// ZERO: %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4 +// ZERO-NEXT: store %struct.XYZ* null, %struct.XYZ** %captured1, align 8 +// ZERO: %call = call %struct.XYZ* @create( +// PATTERN-LABEL: test_block_captures_self_after_init( +// PATTERN: %block = alloca <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, i8* }>, align 8 +// PATTERN: %captured1 = getelementptr inbounds %struct.__block_byref_captured.1, %struct.__block_byref_captured.1* %captured, i32 0, i32 4 +// PATTERN-NEXT: store %struct.XYZ* inttoptr (i64 -6148914691236517206 to %struct.XYZ*), %struct.XYZ** %captured1, align 8 +// PATTERN: %call = call %struct.XYZ* @create( +void test_block_captures_self_after_init() { + extern xyz_t create(Block block); + __block xyz_t captured; + captured = create(^() { + used(captured); }); } diff --git a/clang/test/Misc/diag-format.c b/clang/test/Misc/diag-format.c index bc29894ad03e21..b24aeb9356ae31 100644 --- a/clang/test/Misc/diag-format.c +++ b/clang/test/Misc/diag-format.c @@ -1,30 +1,30 @@ -// RUN: %clang -fsyntax-only %s 2>&1 | FileCheck %s -check-prefix=DEFAULT -// RUN: %clang -fsyntax-only -fdiagnostics-format=clang %s 2>&1 | FileCheck %s -check-prefix=DEFAULT -// RUN: %clang -fsyntax-only -fdiagnostics-format=clang -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=DEFAULT +// RUN: %clang -fsyntax-only %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT +// RUN: %clang -fsyntax-only -fdiagnostics-format=clang %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT +// RUN: %clang -fsyntax-only -fdiagnostics-format=clang -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=DEFAULT // -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2013 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2010 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2013 -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s -check-prefix=MSVC2015 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1300 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fms-compatibility-version=13.00 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1800 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013 +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fmsc-version=1900 -target x86_64-pc-win32 -fshow-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015 // -// RUN: %clang -fsyntax-only -fdiagnostics-format=vi %s 2>&1 | FileCheck %s -check-prefix=VI +// RUN: %clang -fsyntax-only -fdiagnostics-format=vi %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=VI // -// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fno-show-column -fmsc-version=1900 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015_ORIG +// RUN: %clang -fsyntax-only -fdiagnostics-format=msvc -fno-show-column -fmsc-version=1900 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015_ORIG // -// RUN: %clang -fsyntax-only -fno-show-column %s 2>&1 | FileCheck %s -check-prefix=NO_COLUMN +// RUN: %clang -fsyntax-only -fno-show-column %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=NO_COLUMN // -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1300 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010-FALLBACK -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s -check-prefix=MSVC2010-FALLBACK -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1800 %s 2>&1 | FileCheck %s -check-prefix=MSVC2013-FALLBACK -// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1900 %s 2>&1 | FileCheck %s -check-prefix=MSVC2015-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1300 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fms-compatibility-version=13.00 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2010-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1800 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2013-FALLBACK +// RUN: not %clang -fsyntax-only -Werror -fdiagnostics-format=msvc-fallback -fmsc-version=1900 %s 2>&1 | FileCheck %s --strict-whitespace -check-prefix=MSVC2015-FALLBACK diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 98935fc21355b9..5ae4a7ca7bbe99 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -94,6 +94,7 @@ // CHECK-NEXT: ObjCBridge (SubjectMatchRule_record, SubjectMatchRule_type_alias) // CHECK-NEXT: ObjCBridgeMutable (SubjectMatchRule_record) // CHECK-NEXT: ObjCBridgeRelated (SubjectMatchRule_record) +// CHECK-NEXT: ObjCDesignatedInitializer (SubjectMatchRule_objc_method) // CHECK-NEXT: ObjCException (SubjectMatchRule_objc_interface) // CHECK-NEXT: ObjCExplicitProtocolImpl (SubjectMatchRule_objc_protocol) // CHECK-NEXT: ObjCExternallyRetained (SubjectMatchRule_variable_not_is_parameter, SubjectMatchRule_function, SubjectMatchRule_block, SubjectMatchRule_objc_method) diff --git a/clang/test/Parser/cxx1z-init-statement.cpp b/clang/test/Parser/cxx1z-init-statement.cpp index ade60dc762d5c8..3d119ef8e709cb 100644 --- a/clang/test/Parser/cxx1z-init-statement.cpp +++ b/clang/test/Parser/cxx1z-init-statement.cpp @@ -13,9 +13,9 @@ int f() { if (T(n) = 0; n) {} // init-statement expressions - if (T{f()}; f()) {} // expected-warning {{expression result unused}} - if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}} - if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}} expected-warning {{expression result unused}} + if (T{f()}; f()) {} + if (T{f()}, g, h; f()) {} // expected-warning 2{{unused}} + if (T(f()), g, h + 1; f()) {} // expected-warning 2{{unused}} // condition declarations if (T(n){g}) {} @@ -35,7 +35,7 @@ int f() { // Likewise for 'switch' switch (int n; n) {} - switch (g; int g = 5) {} // expected-warning {{expression result unused}} + switch (g; int g = 5) {} if (int a, b; int c = a) { // expected-note 6{{previous}} int a; // expected-error {{redefinition}} diff --git a/clang/test/Parser/switch-recovery.cpp b/clang/test/Parser/switch-recovery.cpp index eacd017ab2364e..a3a0178cd10b67 100644 --- a/clang/test/Parser/switch-recovery.cpp +++ b/clang/test/Parser/switch-recovery.cpp @@ -105,7 +105,7 @@ void test9(int x) { // expected-note {{'x' declared here}} expected-error {{expected expression}} 8:: x; // expected-error {{expected ';' after expression}} \ expected-error {{no member named 'x' in the global namespace; did you mean simply 'x'?}} \ - expected-warning {{expression result unused}} + expected-warning 2 {{expression result unused}} 9:: :y; // expected-error {{expected ';' after expression}} \ expected-error {{expected unqualified-id}} \ expected-warning {{expression result unused}} diff --git a/clang/test/Sema/typo-correction.c b/clang/test/Sema/typo-correction.c index e7992ac90bb3d6..73ba265509e4ce 100644 --- a/clang/test/Sema/typo-correction.c +++ b/clang/test/Sema/typo-correction.c @@ -100,3 +100,18 @@ void rdar38642201_caller() { structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}} structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}} } + +void PR40286_g(int x, int y); +void PR40286_h(int x, int y, int z); +void PR40286_1(int the_value) { + PR40286_g(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}} +} +void PR40286_2(int the_value) { + PR40286_h(the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'}} +} +void PR40286_3(int the_value) { + PR40286_h(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}} +} +void PR40286_4(int the_value) { // expected-note {{'the_value' declared here}} + PR40286_h(the_value, the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'; did you mean 'the_value'?}} +} diff --git a/clang/test/SemaCXX/cxx1z-init-statement.cpp b/clang/test/SemaCXX/cxx1z-init-statement.cpp index eea2589ab7c62e..d37acd08ce77d1 100644 --- a/clang/test/SemaCXX/cxx1z-init-statement.cpp +++ b/clang/test/SemaCXX/cxx1z-init-statement.cpp @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -std=c++1z -Wno-unused-value -verify %s -// RUN: %clang_cc1 -std=c++17 -Wno-unused-value -verify %s +// RUN: %clang_cc1 -std=c++1z -verify %s +// RUN: %clang_cc1 -std=c++17 -verify %s void testIf() { int x = 0; @@ -12,7 +12,7 @@ void testIf() { int x = 0; // expected-error {{redefinition of 'x'}} if (x; int a = 0) ++a; - if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} + if (x, +x; int a = 0) // expected-note 2 {{previous definition is here}} expected-warning {{unused}} int a = 0; // expected-error {{redefinition of 'a'}} else int a = 0; // expected-error {{redefinition of 'a'}} @@ -48,7 +48,7 @@ void testSwitch() { ++a; } - switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} + switch (x, +x; int a = 0) { // expected-note {{previous definition is here}} expected-warning {{unused}} case 0: int a = 0; // expected-error {{redefinition of 'a'}} // expected-note {{previous definition is here}} case 1: diff --git a/clang/test/SemaCXX/for-range-examples.cpp b/clang/test/SemaCXX/for-range-examples.cpp index 5424b7a8ee7978..477789b56c1420 100644 --- a/clang/test/SemaCXX/for-range-examples.cpp +++ b/clang/test/SemaCXX/for-range-examples.cpp @@ -244,7 +244,7 @@ void foo () { int b = 1, a[b]; a[0] = 0; - [&] { for (int c : a) 0; } (); // expected-warning {{expression result unused}} + [&] { for (int c : a) 0; } (); } diff --git a/clang/test/SemaCXX/warn-float-conversion.cpp b/clang/test/SemaCXX/warn-float-conversion.cpp index 7dec4844b062e0..fad1ff147e492d 100644 --- a/clang/test/SemaCXX/warn-float-conversion.cpp +++ b/clang/test/SemaCXX/warn-float-conversion.cpp @@ -44,17 +44,17 @@ void Convert(float f, double d, long double ld) { void CompoundAssignment() { int x = 3; - x += 1.234; //expected-warning{{conversion}} - x -= -0.0; //expected-warning{{conversion}} - x *= 1.1f; //expected-warning{{conversion}} - x /= -2.2f; //expected-warning{{conversion}} + x += 1.234; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} + x -= -0.0; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} + x *= 1.1f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} + x /= -2.2f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} - int y = x += 1.4f; //expected-warning{{conversion}} + int y = x += 1.4f; // expected-warning {{implicit conversion turns floating-point number into integer: 'float' to 'int'}} float z = 1.1f; double w = -2.2; - y += z + w; //expected-warning{{conversion}} + y += z + w; // expected-warning {{implicit conversion turns floating-point number into integer: 'double' to 'int'}} } # 1 "foo.h" 3 diff --git a/clang/test/SemaCXX/warn-unused-result.cpp b/clang/test/SemaCXX/warn-unused-result.cpp index f1de4618a741a7..88f5ab1e85c068 100644 --- a/clang/test/SemaCXX/warn-unused-result.cpp +++ b/clang/test/SemaCXX/warn-unused-result.cpp @@ -33,36 +33,6 @@ void test() { const S &s4 = g1(); } -void testSubstmts(int i) { - switch (i) { - case 0: - f(); // expected-warning {{ignoring return value}} - default: - f(); // expected-warning {{ignoring return value}} - } - - if (i) - f(); // expected-warning {{ignoring return value}} - else - f(); // expected-warning {{ignoring return value}} - - while (i) - f(); // expected-warning {{ignoring return value}} - - do - f(); // expected-warning {{ignoring return value}} - while (i); - - for (f(); // expected-warning {{ignoring return value}} - ; - f() // expected-warning {{ignoring return value}} - ) - f(); // expected-warning {{ignoring return value}} - - f(), // expected-warning {{ignoring return value}} - (void)f(); -} - struct X { int foo() __attribute__((warn_unused_result)); }; @@ -236,13 +206,3 @@ void f() { (void)++p; } } // namespace - -namespace PR39837 { -[[clang::warn_unused_result]] int f(int); - -void g() { - int a[2]; - for (int b : a) - f(b); // expected-warning {{ignoring return value}} -} -} // namespace PR39837 diff --git a/clang/test/SemaObjC/attr-designated-init.m b/clang/test/SemaObjC/attr-designated-init.m index 05085884784b01..3558916dbe54a6 100644 --- a/clang/test/SemaObjC/attr-designated-init.m +++ b/clang/test/SemaObjC/attr-designated-init.m @@ -3,7 +3,7 @@ #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) #define NS_UNAVAILABLE __attribute__((unavailable)) -void fnfoo(void) NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to init methods of interface or class extension declarations}} +void fnfoo(void) NS_DESIGNATED_INITIALIZER; // expected-error {{'objc_designated_initializer' attribute only applies to Objective-C methods}} @protocol P1 -(id)init NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to init methods of interface or class extension declarations}} @@ -428,3 +428,16 @@ - (instancetype)init NS_DESIGNATED_INITIALIZER; @interface CategoryForMissingInterface(Cat) // expected-error{{cannot find interface declaration}} - (instancetype)init NS_DESIGNATED_INITIALIZER; // expected-error{{only applies to init methods of interface or class extension declarations}} @end + +@interface TwoAttrs +-(instancetype)foo + __attribute__((objc_designated_initializer)) + __attribute__((objc_method_family(init))); +-(instancetype)bar + __attribute__((objc_method_family(init))) + __attribute__((objc_designated_initializer)); +-(instancetype)baz + __attribute__((objc_designated_initializer, objc_method_family(init))); +-(instancetype)quux + __attribute__((objc_method_family(init), objc_designated_initializer)); +@end diff --git a/clang/test/SemaObjC/conversion.m b/clang/test/SemaObjC/conversion.m index 88a1a44b2177be..743f7440e2e431 100644 --- a/clang/test/SemaObjC/conversion.m +++ b/clang/test/SemaObjC/conversion.m @@ -14,4 +14,11 @@ void radar14415662(RDar14415662 *f, char x, int y) { x = y; // expected-warning {{implicit conversion loses integer precision: 'int' to 'char'}} } +__attribute__((objc_root_class)) @interface DoubleProp +@property double d; +@end +void use_double_prop(DoubleProp *dp) { + double local = 42; + dp.d += local; // no warning +} diff --git a/compiler-rt/test/msan/Linux/name_to_handle_at.cc b/compiler-rt/test/msan/Linux/name_to_handle_at.cc index 0ff8d982f4f77c..a8bc75fa2ae5c9 100644 --- a/compiler-rt/test/msan/Linux/name_to_handle_at.cc +++ b/compiler-rt/test/msan/Linux/name_to_handle_at.cc @@ -14,7 +14,7 @@ int main(void) { handle->handle_bytes = MAX_HANDLE_SZ; int mount_id; - int res = name_to_handle_at(AT_FDCWD, "/bin/cat", handle, &mount_id, 0); + int res = name_to_handle_at(AT_FDCWD, "/dev/null", handle, &mount_id, 0); assert(!res); __msan_check_mem_is_initialized(&mount_id, sizeof(mount_id)); __msan_check_mem_is_initialized(&handle->handle_bytes, diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst index 20be9f627ef86b..c6db1e7683430c 100644 --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -======================================== -Libc++ 8.0.0 (In-Progress) Release Notes -======================================== +========================== +Libc++ 8.0.0 Release Notes +========================== .. contents:: :local: @@ -8,12 +8,6 @@ Libc++ 8.0.0 (In-Progress) Release Notes Written by the `Libc++ Team `_ -.. warning:: - - These are in-progress notes for the upcoming libc++ 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -27,11 +21,6 @@ be downloaded from the `LLVM releases web site `_. For more information about libc++, please see the `Libc++ Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Libc++ web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. - What's New in Libc++ 8.0.0? =========================== diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 2e2036310fb21b..bce9d944a4a64f 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -130,7 +130,7 @@ static std::tuple parseEmulation(StringRef Emul) { .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) .Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) - .Case("elf32ppc", {ELF32BEKind, EM_PPC}) + .Cases("elf32ppc", "elf32ppclinux", {ELF32BEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) .Case("elf64lriscv", {ELF64LEKind, EM_RISCV}) diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index bc203193661b44..439fe341644c81 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -30,7 +30,7 @@ def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">; def build_id: F<"build-id">, HelpText<"Alias for --build-id=fast">; def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">, - MetaVarName<"[fast,md5,sha,uuid,0x]">; + MetaVarName<"[fast,md5,sha1,uuid,0x]">; defm check_sections: B<"check-sections", "Check section addresses for overlaps (default)", diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index 7cce94659c9e9d..7dbe1641622b6f 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -392,10 +392,11 @@ static std::pair parseBfdName(StringRef S) { .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64}) .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) + .Case("elf32-powerpc", {ELF32BEKind, EM_PPC}) .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64}) .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64}) - .Case("elf32-tradbigmips", {ELF32BEKind, EM_MIPS}) + .Cases("elf32-tradbigmips", "elf32-bigmips", {ELF32BEKind, EM_MIPS}) .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS}) .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS}) .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS}) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 0bebfb3fb1cec8..aab52573d925a4 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -5,11 +5,6 @@ lld 8.0.0 Release Notes .. contents:: :local: -.. warning:: - These are in-progress notes for the upcoming LLVM 8.0.0 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -18,7 +13,7 @@ Mach-O (macOS), MinGW and WebAssembly. lld is command-line-compatible with GNU linkers and Microsoft link.exe and is significantly faster than the system default linkers. -nlld 8.0.0 has lots of feature improvements and bug fixes. +lld 8.0.0 has lots of feature improvements and bug fixes. Non-comprehensive list of changes in this release ================================================= diff --git a/lld/test/ELF/emulation-mips.s b/lld/test/ELF/emulation-mips.s index 42d0dd973eb365..6d7a1198b761ff 100644 --- a/lld/test/ELF/emulation-mips.s +++ b/lld/test/ELF/emulation-mips.s @@ -7,6 +7,9 @@ # RUN: echo 'OUTPUT_FORMAT(elf32-tradbigmips)' > %tmips.script # RUN: ld.lld %tmips.script -e _start %tmips -o %t4mips # RUN: llvm-readobj -file-headers %t4mips | FileCheck --check-prefix=MIPS %s +# RUN: echo 'OUTPUT_FORMAT(elf32-bigmips)' > %tmips2.script +# RUN: ld.lld %tmips2.script -e _start %tmips -o %t5mips +# RUN: llvm-readobj -file-headers %t5mips | FileCheck --check-prefix=MIPS %s # MIPS: ElfHeader { # MIPS-NEXT: Ident { # MIPS-NEXT: Magic: (7F 45 4C 46) diff --git a/lld/test/ELF/emulation-ppc.s b/lld/test/ELF/emulation-ppc.s index 843e77604779b1..4c8beb10159e6c 100644 --- a/lld/test/ELF/emulation-ppc.s +++ b/lld/test/ELF/emulation-ppc.s @@ -103,5 +103,42 @@ # PPC64LE-NEXT: StringTableSectionIndex: # PPC64LE-NEXT: } +# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-linux %s -o %tppc32 +# RUN: ld.lld -m elf32ppc %tppc32 -o %t2ppc32 +# RUN: llvm-readobj -file-headers %t2ppc32 | FileCheck --check-prefix=PPC32 %s +# RUN: ld.lld %tppc32 -o %t3ppc32 +# RUN: llvm-readobj -file-headers %t3ppc32 | FileCheck --check-prefix=PPC32 %s +# RUN: echo 'OUTPUT_FORMAT(elf32-powerpc)' > %tppc32.script +# RUN: ld.lld %tppc32.script %tppc32 -o %t4ppc32 +# RUN: llvm-readobj -file-headers %t4ppc32 | FileCheck --check-prefix=PPC32 %s +# RUN: ld.lld -m elf32ppclinux %tppc32 -o %t5ppc32 +# RUN: llvm-readobj -file-headers %t5ppc32 | FileCheck --check-prefix=PPC32 %s + +# PPC32: ElfHeader { +# PPC32-NEXT: Ident { +# PPC32-NEXT: Magic: (7F 45 4C 46) +# PPC32-NEXT: Class: 32-bit (0x1) +# PPC32-NEXT: DataEncoding: BigEndian (0x2) +# PPC32-NEXT: FileVersion: 1 +# PPC32-NEXT: OS/ABI: SystemV (0x0) +# PPC32-NEXT: ABIVersion: 0 +# PPC32-NEXT: Unused: (00 00 00 00 00 00 00) +# PPC32-NEXT: } +# PPC32-NEXT: Type: Executable (0x2) +# PPC32-NEXT: Machine: EM_PPC (0x14) +# PPC32-NEXT: Version: 1 +# PPC32-NEXT: Entry: +# PPC32-NEXT: ProgramHeaderOffset: 0x34 +# PPC32-NEXT: SectionHeaderOffset: +# PPC32-NEXT: Flags [ (0x0) +# PPC32-NEXT: ] +# PPC32-NEXT: HeaderSize: 52 +# PPC32-NEXT: ProgramHeaderEntrySize: 32 +# PPC32-NEXT: ProgramHeaderCount: +# PPC32-NEXT: SectionHeaderEntrySize: 40 +# PPC32-NEXT: SectionHeaderCount: +# PPC32-NEXT: StringTableSectionIndex: +# PPC32-NEXT: } + .globl _start _start: diff --git a/lldb/source/Host/common/MainLoop.cpp b/lldb/source/Host/common/MainLoop.cpp index 39c353e6717ece..337ddd51dd6b9e 100644 --- a/lldb/source/Host/common/MainLoop.cpp +++ b/lldb/source/Host/common/MainLoop.cpp @@ -108,8 +108,14 @@ Status MainLoop::RunImpl::Poll() { num_events = kevent(loop.m_kqueue, in_events.data(), in_events.size(), out_events, llvm::array_lengthof(out_events), nullptr); - if (num_events < 0) - return Status("kevent() failed with error %d\n", num_events); + if (num_events < 0) { + if (errno == EINTR) { + // in case of EINTR, let the main loop run one iteration + // we need to zero num_events to avoid assertions failing + num_events = 0; + } else + return Status(errno, eErrorTypePOSIX); + } return Status(); } diff --git a/lldb/source/Host/openbsd/Host.cpp b/lldb/source/Host/openbsd/Host.cpp index cba1f4ee6b7cb2..8db0498d14b56e 100644 --- a/lldb/source/Host/openbsd/Host.cpp +++ b/lldb/source/Host/openbsd/Host.cpp @@ -68,8 +68,7 @@ GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr, cstr = data.GetCStr(&offset); if (cstr) { - process_info.GetExecutableFile().SetFile(cstr, false, - FileSpec::Style::native); + process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native); if (!(match_info_ptr == NULL || NameMatches( diff --git a/lldb/unittests/Host/MainLoopTest.cpp b/lldb/unittests/Host/MainLoopTest.cpp index 8f2c55c2416df7..6b7a5cf1f55de5 100644 --- a/lldb/unittests/Host/MainLoopTest.cpp +++ b/lldb/unittests/Host/MainLoopTest.cpp @@ -137,4 +137,28 @@ TEST_F(MainLoopTest, Signal) { ASSERT_TRUE(loop.Run().Success()); ASSERT_EQ(1u, callback_count); } + +// Test that a signal which is not monitored by the MainLoop does not +// cause a premature exit. +TEST_F(MainLoopTest, UnmonitoredSignal) { + MainLoop loop; + Status error; + struct sigaction sa; + sa.sa_sigaction = [](int, siginfo_t *, void *) { }; + sa.sa_flags = SA_SIGINFO; // important: no SA_RESTART + sigemptyset(&sa.sa_mask); + ASSERT_EQ(0, sigaction(SIGUSR2, &sa, nullptr)); + + auto handle = loop.RegisterSignal(SIGUSR1, make_callback(), error); + ASSERT_TRUE(error.Success()); + std::thread killer([]() { + sleep(1); + kill(getpid(), SIGUSR2); + sleep(1); + kill(getpid(), SIGUSR1); + }); + ASSERT_TRUE(loop.Run().Success()); + killer.join(); + ASSERT_EQ(1u, callback_count); +} #endif diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 9e2ee95c651944..eafe1f17f76000 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -5,12 +5,6 @@ LLVM 8.0.0 Release Notes .. contents:: :local: -.. warning:: - These are in-progress notes for the upcoming LLVM 8 release. - Release notes for previous releases can be found on - `the Download Page `_. - - Introduction ============ @@ -26,10 +20,24 @@ have questions or comments, the `LLVM Developer's Mailing List `_ is a good place to send them. -Note that if you are reading this file from a Subversion checkout or the main -LLVM web page, this document applies to the *next* release, not the current -one. To see the release notes for a specific release, please see the `releases -page `_. +Minimum Required Compiler Version +================================= +As `discussed on the mailing list +`_, +building LLVM will soon require more recent toolchains as follows: + +============= ==== +Clang 3.5 +Apple Clang 6.0 +GCC 5.1 +Visual Studio 2017 +============= ==== + +A new CMake check when configuring LLVM provides a soft-error if your +toolchain will become unsupported soon. You can opt out of the soft-error by +setting the ``LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN`` CMake variable to +``ON``. + Non-comprehensive list of changes in this release ================================================= @@ -40,27 +48,11 @@ Non-comprehensive list of changes in this release functionality, or simply have a lot to talk about), see the `NOTE` below for adding a new subsection. -* As `discussed on the mailing list - `_, - building LLVM will soon require more recent toolchains as follows: - - ============= ==== - Clang 3.5 - Apple Clang 6.0 - GCC 5.1 - Visual Studio 2017 - ============= ==== - - A new CMake check when configuring LLVM provides a soft-error if your - toolchain will become unsupported soon. You can opt out of the soft-error by - setting the ``LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN`` CMake variable to - ``ON``. - * The **llvm-cov** tool can now export lcov trace files using the `-format=lcov` option of the `export` command. -* The add_llvm_loadable_module CMake macro has been removed. The - add_llvm_library macro with the MODULE argument now provides the same +* The ``add_llvm_loadable_module`` CMake macro has been removed. The + ``add_llvm_library`` macro with the ``MODULE`` argument now provides the same functionality. See `Writing an LLVM Pass `_. @@ -70,6 +62,24 @@ Non-comprehensive list of changes in this release * Added support for labels as offsets in ``.reloc`` directive. +* Support for precise identification of X86 instructions with memory operands, + by using debug information. This supports profile-driven cache prefetching. + It is enabled with the ``-x86-discriminate-memops`` LLVM Flag. + +* Support for profile-driven software cache prefetching on X86. This is part of + a larger system, consisting of: an offline cache prefetches recommender, + AutoFDO tooling, and LLVM. In this system, a binary compiled with + ``-x86-discriminate-memops`` is run under the observation of the recommender. + The recommender identifies certain memory access instructions by their binary + file address, and recommends a prefetch of a specific type (NTA, T0, etc) be + performed at a specified fixed offset from such an instruction's memory + operand. Next, this information needs to be converted to the AutoFDO syntax + and the resulting profile may be passed back to the compiler with the LLVM + flag ``-prefetch-hints-file``, together with the exact same set of + compilation parameters used for the original binary. More information is + available in the `RFC + `_. + .. NOTE If you would like to document a larger change, then you can add a subsection about it right here. You can copy the following boilerplate @@ -83,10 +93,19 @@ Non-comprehensive list of changes in this release Changes to the LLVM IR ---------------------- +* Function attribute ``speculative_load_hardening`` has been introduced to + allow indicating that `Speculative Load Hardening + `_ must be enabled for the function body. + Changes to the AArch64 Target ----------------------------- +* Support for Speculative Load Hardening has been added. + +* Initial support for the Tiny code model, where code and its statically + defined symbols must live within 1MB of each other. + * Added support for the ``.arch_extension`` assembler directive, just like on ARM. @@ -126,7 +145,40 @@ Changes to the MIPS Target Changes to the PowerPC Target ----------------------------- - During this release ... +* Switched to non-PIC default + +* Deprecated Darwin support + +* Enabled Out-of-Order scheduling for P9 + +* Better overload rules for compatible vector type parameter + +* Support constraint ‘wi’, modifier ‘x’ and VSX registers in inline asm + +* More ``__float128`` support + +* Added new builtins like vector int128 ``pack``/``unpack`` and + ``stxvw4x.be``/``stxvd2x.be`` + +* Provided significant improvements to the automatic vectorizer + +* Code-gen improvements (especially for Power9) + +* Fixed some long-standing bugs in the back end + +* Added experimental prologue/epilogue improvements + +* Enabled builtins tests in compiler-rt + +* Add ``___fixunstfti``/``floattitf`` in compiler-rt to support conversion + between IBM double-double and unsigned int128 + +* Disable randomized address space when running the sanitizers on Linux ppc64le + +* Completed support in LLD for ELFv2 + +* Enabled llvm-exegesis latency mode for PPC + Changes to the X86 Target ------------------------- @@ -134,6 +186,18 @@ Changes to the X86 Target * Machine model for AMD bdver2 (Piledriver) CPU was added. It is used to support instruction scheduling and other instruction cost heuristics. +* New AVX512F gather and scatter intrinsics were added that take a mask + instead of a scalar integer. This removes the need for a bitcast in IR. The + new intrinsics are named like the old intrinsics with ``llvm.avx512.`` + replaced with ``llvm.avx512.mask.``. The old intrinsics will be removed in a + future release. + +* Added ``cascadelake`` as a CPU name for -march. This is ``skylake-avx512`` + with the addition of the ``avx512vnni`` instruction set. + +* ADCX instruction will no longer be emitted. This instruction is rarely better + than the legacy ADC instruction and just increased code size. + Changes to the AMDGPU Target ----------------------------- @@ -156,6 +220,10 @@ use for it will be to add support for returning small structs as multiple return values, once the underlying WebAssembly platform itself supports it. Additionally, multithreading support is not yet included in the stable ABI. +Changes to the Nios2 Target +--------------------------- + +* The Nios2 target was removed from this release. Changes to the OCaml bindings ----------------------------- @@ -169,6 +237,14 @@ Changes to the C API Changes to the DAG infrastructure --------------------------------- +Changes to LLDB +=============== +* Printed source code is now syntax highlighted in the terminal (only for C + languages). + +* The expression command now supports tab completing expressions. + + External Open Source Projects Using LLVM 8 ========================================== diff --git a/llvm/docs/index.rst b/llvm/docs/index.rst index 4527fe5105346b..49bd327f47dec2 100644 --- a/llvm/docs/index.rst +++ b/llvm/docs/index.rst @@ -1,11 +1,6 @@ Overview ======== -.. warning:: - - If you are using a released version of LLVM, see `the download page - `_ to find your documentation. - The LLVM compiler infrastructure supports a wide range of projects, from industrial strength compilers to specialized JIT applications to small research projects. diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 5c6ed816c581ea..68a0a07038f9b6 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -161,25 +161,66 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, } if (T.isOSWindows() && !T.isOSCygMing()) { - // Win32 does not support long double + // XXX: The earliest documentation available at the moment is for VS2015/VC19: + // https://docs.microsoft.com/en-us/cpp/c-runtime-library/floating-point-support?view=vs-2015 + // XXX: In order to use an MSVCRT older than VC19, + // the specific library version must be explicit in the target triple, + // e.g., x86_64-pc-windows-msvc18. + bool hasPartialC99 = true; + if (T.isKnownWindowsMSVCEnvironment()) { + unsigned Major, Minor, Micro; + T.getEnvironmentVersion(Major, Minor, Micro); + hasPartialC99 = (Major == 0 || Major >= 19); + } + + // Latest targets support C89 math functions, in part. + bool isARM = (T.getArch() == Triple::aarch64 || + T.getArch() == Triple::arm); + bool hasPartialFloat = (isARM || + T.getArch() == Triple::x86_64); + + // Win32 does not support float C89 math functions, in general. + if (!hasPartialFloat) { + TLI.setUnavailable(LibFunc_acosf); + TLI.setUnavailable(LibFunc_asinf); + TLI.setUnavailable(LibFunc_atan2f); + TLI.setUnavailable(LibFunc_atanf); + TLI.setUnavailable(LibFunc_ceilf); + TLI.setUnavailable(LibFunc_cosf); + TLI.setUnavailable(LibFunc_coshf); + TLI.setUnavailable(LibFunc_expf); + TLI.setUnavailable(LibFunc_floorf); + TLI.setUnavailable(LibFunc_fmodf); + TLI.setUnavailable(LibFunc_log10f); + TLI.setUnavailable(LibFunc_logf); + TLI.setUnavailable(LibFunc_modff); + TLI.setUnavailable(LibFunc_powf); + TLI.setUnavailable(LibFunc_sinf); + TLI.setUnavailable(LibFunc_sinhf); + TLI.setUnavailable(LibFunc_sqrtf); + TLI.setUnavailable(LibFunc_tanf); + TLI.setUnavailable(LibFunc_tanhf); + } + if (!isARM) + TLI.setUnavailable(LibFunc_fabsf); + TLI.setUnavailable(LibFunc_frexpf); + TLI.setUnavailable(LibFunc_ldexpf); + + // Win32 does not support long double C89 math functions. TLI.setUnavailable(LibFunc_acosl); TLI.setUnavailable(LibFunc_asinl); - TLI.setUnavailable(LibFunc_atanl); TLI.setUnavailable(LibFunc_atan2l); + TLI.setUnavailable(LibFunc_atanl); TLI.setUnavailable(LibFunc_ceill); - TLI.setUnavailable(LibFunc_copysignl); TLI.setUnavailable(LibFunc_cosl); TLI.setUnavailable(LibFunc_coshl); TLI.setUnavailable(LibFunc_expl); - TLI.setUnavailable(LibFunc_fabsf); // Win32 and Win64 both lack fabsf TLI.setUnavailable(LibFunc_fabsl); TLI.setUnavailable(LibFunc_floorl); - TLI.setUnavailable(LibFunc_fmaxl); - TLI.setUnavailable(LibFunc_fminl); TLI.setUnavailable(LibFunc_fmodl); TLI.setUnavailable(LibFunc_frexpl); - TLI.setUnavailable(LibFunc_ldexpf); TLI.setUnavailable(LibFunc_ldexpl); + TLI.setUnavailable(LibFunc_log10l); TLI.setUnavailable(LibFunc_logl); TLI.setUnavailable(LibFunc_modfl); TLI.setUnavailable(LibFunc_powl); @@ -189,81 +230,66 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_tanl); TLI.setUnavailable(LibFunc_tanhl); - // Win32 only has C89 math - TLI.setUnavailable(LibFunc_acosh); - TLI.setUnavailable(LibFunc_acoshf); + // Win32 does not fully support C99 math functions. + if (!hasPartialC99) { + TLI.setUnavailable(LibFunc_acosh); + TLI.setUnavailable(LibFunc_acoshf); + TLI.setUnavailable(LibFunc_asinh); + TLI.setUnavailable(LibFunc_asinhf); + TLI.setUnavailable(LibFunc_atanh); + TLI.setUnavailable(LibFunc_atanhf); + TLI.setAvailableWithName(LibFunc_cabs, "_cabs"); + TLI.setUnavailable(LibFunc_cabsf); + TLI.setUnavailable(LibFunc_cbrt); + TLI.setUnavailable(LibFunc_cbrtf); + TLI.setAvailableWithName(LibFunc_copysign, "_copysign"); + TLI.setAvailableWithName(LibFunc_copysignf, "_copysignf"); + TLI.setUnavailable(LibFunc_exp2); + TLI.setUnavailable(LibFunc_exp2f); + TLI.setUnavailable(LibFunc_expm1); + TLI.setUnavailable(LibFunc_expm1f); + TLI.setUnavailable(LibFunc_fmax); + TLI.setUnavailable(LibFunc_fmaxf); + TLI.setUnavailable(LibFunc_fmin); + TLI.setUnavailable(LibFunc_fminf); + TLI.setUnavailable(LibFunc_log1p); + TLI.setUnavailable(LibFunc_log1pf); + TLI.setUnavailable(LibFunc_log2); + TLI.setUnavailable(LibFunc_log2f); + TLI.setAvailableWithName(LibFunc_logb, "_logb"); + if (hasPartialFloat) + TLI.setAvailableWithName(LibFunc_logbf, "_logbf"); + else + TLI.setUnavailable(LibFunc_logbf); + TLI.setUnavailable(LibFunc_rint); + TLI.setUnavailable(LibFunc_rintf); + TLI.setUnavailable(LibFunc_round); + TLI.setUnavailable(LibFunc_roundf); + TLI.setUnavailable(LibFunc_trunc); + TLI.setUnavailable(LibFunc_truncf); + } + + // Win32 does not support long double C99 math functions. TLI.setUnavailable(LibFunc_acoshl); - TLI.setUnavailable(LibFunc_asinh); - TLI.setUnavailable(LibFunc_asinhf); TLI.setUnavailable(LibFunc_asinhl); - TLI.setUnavailable(LibFunc_atanh); - TLI.setUnavailable(LibFunc_atanhf); TLI.setUnavailable(LibFunc_atanhl); - TLI.setUnavailable(LibFunc_cabs); - TLI.setUnavailable(LibFunc_cabsf); TLI.setUnavailable(LibFunc_cabsl); - TLI.setUnavailable(LibFunc_cbrt); - TLI.setUnavailable(LibFunc_cbrtf); TLI.setUnavailable(LibFunc_cbrtl); - TLI.setUnavailable(LibFunc_exp2); - TLI.setUnavailable(LibFunc_exp2f); + TLI.setUnavailable(LibFunc_copysignl); TLI.setUnavailable(LibFunc_exp2l); - TLI.setUnavailable(LibFunc_expm1); - TLI.setUnavailable(LibFunc_expm1f); TLI.setUnavailable(LibFunc_expm1l); - TLI.setUnavailable(LibFunc_log2); - TLI.setUnavailable(LibFunc_log2f); - TLI.setUnavailable(LibFunc_log2l); - TLI.setUnavailable(LibFunc_log1p); - TLI.setUnavailable(LibFunc_log1pf); + TLI.setUnavailable(LibFunc_fmaxl); + TLI.setUnavailable(LibFunc_fminl); TLI.setUnavailable(LibFunc_log1pl); - TLI.setUnavailable(LibFunc_logb); - TLI.setUnavailable(LibFunc_logbf); + TLI.setUnavailable(LibFunc_log2l); TLI.setUnavailable(LibFunc_logbl); - TLI.setUnavailable(LibFunc_nearbyint); - TLI.setUnavailable(LibFunc_nearbyintf); TLI.setUnavailable(LibFunc_nearbyintl); - TLI.setUnavailable(LibFunc_rint); - TLI.setUnavailable(LibFunc_rintf); TLI.setUnavailable(LibFunc_rintl); - TLI.setUnavailable(LibFunc_round); - TLI.setUnavailable(LibFunc_roundf); TLI.setUnavailable(LibFunc_roundl); - TLI.setUnavailable(LibFunc_trunc); - TLI.setUnavailable(LibFunc_truncf); TLI.setUnavailable(LibFunc_truncl); - // Win32 provides some C99 math with mangled names - TLI.setAvailableWithName(LibFunc_copysign, "_copysign"); - - if (T.getArch() == Triple::x86) { - // Win32 on x86 implements single-precision math functions as macros - TLI.setUnavailable(LibFunc_acosf); - TLI.setUnavailable(LibFunc_asinf); - TLI.setUnavailable(LibFunc_atanf); - TLI.setUnavailable(LibFunc_atan2f); - TLI.setUnavailable(LibFunc_ceilf); - TLI.setUnavailable(LibFunc_copysignf); - TLI.setUnavailable(LibFunc_cosf); - TLI.setUnavailable(LibFunc_coshf); - TLI.setUnavailable(LibFunc_expf); - TLI.setUnavailable(LibFunc_floorf); - TLI.setUnavailable(LibFunc_fminf); - TLI.setUnavailable(LibFunc_fmaxf); - TLI.setUnavailable(LibFunc_fmodf); - TLI.setUnavailable(LibFunc_logf); - TLI.setUnavailable(LibFunc_log10f); - TLI.setUnavailable(LibFunc_modff); - TLI.setUnavailable(LibFunc_powf); - TLI.setUnavailable(LibFunc_sinf); - TLI.setUnavailable(LibFunc_sinhf); - TLI.setUnavailable(LibFunc_sqrtf); - TLI.setUnavailable(LibFunc_tanf); - TLI.setUnavailable(LibFunc_tanhf); - } - - // Win32 does *not* provide these functions, but they are - // generally available on POSIX-compliant systems: + // Win32 does not support these functions, but + // they are generally available on POSIX-compliant systems. TLI.setUnavailable(LibFunc_access); TLI.setUnavailable(LibFunc_bcmp); TLI.setUnavailable(LibFunc_bcopy); @@ -318,12 +344,6 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_utime); TLI.setUnavailable(LibFunc_utimes); TLI.setUnavailable(LibFunc_write); - - // Win32 does *not* provide provide these functions, but they are - // specified by C99: - TLI.setUnavailable(LibFunc_atoll); - TLI.setUnavailable(LibFunc_frexpf); - TLI.setUnavailable(LibFunc_llabs); } switch (T.getOS()) { diff --git a/llvm/lib/MC/ELFObjectWriter.cpp b/llvm/lib/MC/ELFObjectWriter.cpp index 89f3b30cddd6f4..ade858113a3009 100644 --- a/llvm/lib/MC/ELFObjectWriter.cpp +++ b/llvm/lib/MC/ELFObjectWriter.cpp @@ -1275,14 +1275,20 @@ void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, if (!Symbol.isUndefined() && !Rest.startswith("@@@")) continue; - // FIXME: produce a better error message. + // FIXME: Get source locations for these errors or diagnose them earlier. if (Symbol.isUndefined() && Rest.startswith("@@") && - !Rest.startswith("@@@")) - report_fatal_error("A @@ version cannot be undefined"); + !Rest.startswith("@@@")) { + Asm.getContext().reportError(SMLoc(), "versioned symbol " + AliasName + + " must be defined"); + continue; + } - if (Renames.count(&Symbol) && Renames[&Symbol] != Alias) - report_fatal_error(llvm::Twine("Multiple symbol versions defined for ") + - Symbol.getName()); + if (Renames.count(&Symbol) && Renames[&Symbol] != Alias) { + Asm.getContext().reportError( + SMLoc(), llvm::Twine("multiple symbol versions defined for ") + + Symbol.getName()); + continue; + } Renames.insert(std::make_pair(&Symbol, Alias)); } diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index f4f37a894620ed..e1a6d22f061655 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -13884,7 +13884,6 @@ static SDValue lowerVectorShuffleAsLanePermuteAndPermute( int NumEltsPerLane = NumElts / NumLanes; SmallVector SrcLaneMask(NumLanes, SM_SentinelUndef); - SmallVector LaneMask(NumElts, SM_SentinelUndef); SmallVector PermMask(NumElts, SM_SentinelUndef); for (int i = 0; i != NumElts; ++i) { @@ -13899,10 +13898,20 @@ static SDValue lowerVectorShuffleAsLanePermuteAndPermute( return SDValue(); SrcLaneMask[DstLane] = SrcLane; - LaneMask[i] = (SrcLane * NumEltsPerLane) + (i % NumEltsPerLane); PermMask[i] = (DstLane * NumEltsPerLane) + (M % NumEltsPerLane); } + // Make sure we set all elements of the lane mask, to avoid undef propagation. + SmallVector LaneMask(NumElts, SM_SentinelUndef); + for (int DstLane = 0; DstLane != NumLanes; ++DstLane) { + int SrcLane = SrcLaneMask[DstLane]; + if (0 <= SrcLane) + for (int j = 0; j != NumEltsPerLane; ++j) { + LaneMask[(DstLane * NumEltsPerLane) + j] = + (SrcLane * NumEltsPerLane) + j; + } + } + // If we're only shuffling a single lowest lane and the rest are identity // then don't bother. // TODO - isShuffleMaskInputInPlace could be extended to something like this. diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index f530ee1246e8c2..fef051aa1b7c35 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -1376,7 +1376,8 @@ Instruction *InstCombiner::foldVectorBinop(BinaryOperator &Inst) { if (match(LHS, m_ShuffleVector(m_Value(L0), m_Value(L1), m_Constant(Mask))) && match(RHS, m_ShuffleVector(m_Value(R0), m_Value(R1), m_Specific(Mask))) && LHS->hasOneUse() && RHS->hasOneUse() && - cast(LHS)->isConcat()) { + cast(LHS)->isConcat() && + cast(RHS)->isConcat()) { // This transform does not have the speculative execution constraint as // below because the shuffle is a concatenation. The new binops are // operating on exactly the same elements as the existing binop. diff --git a/llvm/lib/Transforms/Scalar/MergeICmps.cpp b/llvm/lib/Transforms/Scalar/MergeICmps.cpp index 69fd8b163a070d..a24fee54949d33 100644 --- a/llvm/lib/Transforms/Scalar/MergeICmps.cpp +++ b/llvm/lib/Transforms/Scalar/MergeICmps.cpp @@ -11,21 +11,37 @@ // later typically inlined as a chain of efficient hardware comparisons). This // typically benefits c++ member or nonmember operator==(). // -// The basic idea is to replace a larger chain of integer comparisons loaded -// from contiguous memory locations into a smaller chain of such integer +// The basic idea is to replace a longer chain of integer comparisons loaded +// from contiguous memory locations into a shorter chain of larger integer // comparisons. Benefits are double: // - There are less jumps, and therefore less opportunities for mispredictions // and I-cache misses. // - Code size is smaller, both because jumps are removed and because the // encoding of a 2*n byte compare is smaller than that of two n-byte // compares. - +// +// Example: +// +// struct S { +// int a; +// char b; +// char c; +// uint16_t d; +// bool operator==(const S& o) const { +// return a == o.a && b == o.b && c == o.c && d == o.d; +// } +// }; +// +// Is optimized as : +// +// bool S::operator==(const S& o) const { +// return memcmp(this, &o, 8) == 0; +// } +// +// Which will later be expanded (ExpandMemCmp) as a single 8-bytes icmp. +// //===----------------------------------------------------------------------===// -#include -#include -#include -#include #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Analysis/TargetTransformInfo.h" @@ -34,6 +50,10 @@ #include "llvm/Pass.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BuildLibCalls.h" +#include +#include +#include +#include using namespace llvm; @@ -50,76 +70,95 @@ static bool isSimpleLoadOrStore(const Instruction *I) { return false; } -// A BCE atom. +// A BCE atom "Binary Compare Expression Atom" represents an integer load +// that is a constant offset from a base value, e.g. `a` or `o.c` in the example +// at the top. struct BCEAtom { - BCEAtom() : GEP(nullptr), LoadI(nullptr), Offset() {} - - const Value *Base() const { return GEP ? GEP->getPointerOperand() : nullptr; } - + BCEAtom() = default; + BCEAtom(GetElementPtrInst *GEP, LoadInst *LoadI, int BaseId, APInt Offset) + : GEP(GEP), LoadI(LoadI), BaseId(BaseId), Offset(Offset) {} + + // We want to order BCEAtoms by (Base, Offset). However we cannot use + // the pointer values for Base because these are non-deterministic. + // To make sure that the sort order is stable, we first assign to each atom + // base value an index based on its order of appearance in the chain of + // comparisons. We call this index `BaseOrdering`. For example, for: + // b[3] == c[2] && a[1] == d[1] && b[4] == c[3] + // | block 1 | | block 2 | | block 3 | + // b gets assigned index 0 and a index 1, because b appears as LHS in block 1, + // which is before block 2. + // We then sort by (BaseOrdering[LHS.Base()], LHS.Offset), which is stable. bool operator<(const BCEAtom &O) const { - assert(Base() && "invalid atom"); - assert(O.Base() && "invalid atom"); - // Just ordering by (Base(), Offset) is sufficient. However because this - // means that the ordering will depend on the addresses of the base - // values, which are not reproducible from run to run. To guarantee - // stability, we use the names of the values if they exist; we sort by: - // (Base.getName(), Base(), Offset). - const int NameCmp = Base()->getName().compare(O.Base()->getName()); - if (NameCmp == 0) { - if (Base() == O.Base()) { - return Offset.slt(O.Offset); - } - return Base() < O.Base(); - } - return NameCmp < 0; + return BaseId != O.BaseId ? BaseId < O.BaseId : Offset.slt(O.Offset); } - GetElementPtrInst *GEP; - LoadInst *LoadI; + GetElementPtrInst *GEP = nullptr; + LoadInst *LoadI = nullptr; + unsigned BaseId = 0; APInt Offset; }; +// A class that assigns increasing ids to values in the order in which they are +// seen. See comment in `BCEAtom::operator<()``. +class BaseIdentifier { +public: + // Returns the id for value `Base`, after assigning one if `Base` has not been + // seen before. + int getBaseId(const Value *Base) { + assert(Base && "invalid base"); + const auto Insertion = BaseToIndex.try_emplace(Base, Order); + if (Insertion.second) + ++Order; + return Insertion.first->second; + } + +private: + unsigned Order = 1; + DenseMap BaseToIndex; +}; + // If this value is a load from a constant offset w.r.t. a base address, and // there are no other users of the load or address, returns the base address and // the offset. -BCEAtom visitICmpLoadOperand(Value *const Val) { - BCEAtom Result; - if (auto *const LoadI = dyn_cast(Val)) { - LLVM_DEBUG(dbgs() << "load\n"); - if (LoadI->isUsedOutsideOfBlock(LoadI->getParent())) { - LLVM_DEBUG(dbgs() << "used outside of block\n"); - return {}; - } - // Do not optimize atomic loads to non-atomic memcmp - if (!LoadI->isSimple()) { - LLVM_DEBUG(dbgs() << "volatile or atomic\n"); - return {}; - } - Value *const Addr = LoadI->getOperand(0); - if (auto *const GEP = dyn_cast(Addr)) { - LLVM_DEBUG(dbgs() << "GEP\n"); - if (GEP->isUsedOutsideOfBlock(LoadI->getParent())) { - LLVM_DEBUG(dbgs() << "used outside of block\n"); - return {}; - } - const auto &DL = GEP->getModule()->getDataLayout(); - if (!isDereferenceablePointer(GEP, DL)) { - LLVM_DEBUG(dbgs() << "not dereferenceable\n"); - // We need to make sure that we can do comparison in any order, so we - // require memory to be unconditionnally dereferencable. - return {}; - } - Result.Offset = APInt(DL.getPointerTypeSizeInBits(GEP->getType()), 0); - if (GEP->accumulateConstantOffset(DL, Result.Offset)) { - Result.GEP = GEP; - Result.LoadI = LoadI; - } - } +BCEAtom visitICmpLoadOperand(Value *const Val, BaseIdentifier &BaseId) { + auto *const LoadI = dyn_cast(Val); + if (!LoadI) + return {}; + LLVM_DEBUG(dbgs() << "load\n"); + if (LoadI->isUsedOutsideOfBlock(LoadI->getParent())) { + LLVM_DEBUG(dbgs() << "used outside of block\n"); + return {}; + } + // Do not optimize atomic loads to non-atomic memcmp + if (!LoadI->isSimple()) { + LLVM_DEBUG(dbgs() << "volatile or atomic\n"); + return {}; } - return Result; + Value *const Addr = LoadI->getOperand(0); + auto *const GEP = dyn_cast(Addr); + if (!GEP) + return {}; + LLVM_DEBUG(dbgs() << "GEP\n"); + if (GEP->isUsedOutsideOfBlock(LoadI->getParent())) { + LLVM_DEBUG(dbgs() << "used outside of block\n"); + return {}; + } + const auto &DL = GEP->getModule()->getDataLayout(); + if (!isDereferenceablePointer(GEP, DL)) { + LLVM_DEBUG(dbgs() << "not dereferenceable\n"); + // We need to make sure that we can do comparison in any order, so we + // require memory to be unconditionnally dereferencable. + return {}; + } + APInt Offset = APInt(DL.getPointerTypeSizeInBits(GEP->getType()), 0); + if (!GEP->accumulateConstantOffset(DL, Offset)) + return {}; + return BCEAtom(GEP, LoadI, BaseId.getBaseId(GEP->getPointerOperand()), + Offset); } -// A basic block with a comparison between two BCE atoms. +// A basic block with a comparison between two BCE atoms, e.g. `a == o.a` in the +// example at the top. // The block might do extra work besides the atom comparison, in which case // doesOtherWork() returns true. Under some conditions, the block can be // split into the atom comparison part and the "other work" part @@ -137,9 +176,7 @@ class BCECmpBlock { if (Rhs_ < Lhs_) std::swap(Rhs_, Lhs_); } - bool IsValid() const { - return Lhs_.Base() != nullptr && Rhs_.Base() != nullptr; - } + bool IsValid() const { return Lhs_.BaseId != 0 && Rhs_.BaseId != 0; } // Assert the block is consistent: If valid, it should also have // non-null members besides Lhs_ and Rhs_. @@ -265,7 +302,8 @@ bool BCECmpBlock::doesOtherWork() const { // Visit the given comparison. If this is a comparison between two valid // BCE atoms, returns the comparison. BCECmpBlock visitICmp(const ICmpInst *const CmpI, - const ICmpInst::Predicate ExpectedPredicate) { + const ICmpInst::Predicate ExpectedPredicate, + BaseIdentifier &BaseId) { // The comparison can only be used once: // - For intermediate blocks, as a branch condition. // - For the final block, as an incoming value for the Phi. @@ -275,25 +313,27 @@ BCECmpBlock visitICmp(const ICmpInst *const CmpI, LLVM_DEBUG(dbgs() << "cmp has several uses\n"); return {}; } - if (CmpI->getPredicate() == ExpectedPredicate) { - LLVM_DEBUG(dbgs() << "cmp " - << (ExpectedPredicate == ICmpInst::ICMP_EQ ? "eq" : "ne") - << "\n"); - auto Lhs = visitICmpLoadOperand(CmpI->getOperand(0)); - if (!Lhs.Base()) return {}; - auto Rhs = visitICmpLoadOperand(CmpI->getOperand(1)); - if (!Rhs.Base()) return {}; - const auto &DL = CmpI->getModule()->getDataLayout(); - return BCECmpBlock(std::move(Lhs), std::move(Rhs), - DL.getTypeSizeInBits(CmpI->getOperand(0)->getType())); - } - return {}; + if (CmpI->getPredicate() != ExpectedPredicate) + return {}; + LLVM_DEBUG(dbgs() << "cmp " + << (ExpectedPredicate == ICmpInst::ICMP_EQ ? "eq" : "ne") + << "\n"); + auto Lhs = visitICmpLoadOperand(CmpI->getOperand(0), BaseId); + if (!Lhs.BaseId) + return {}; + auto Rhs = visitICmpLoadOperand(CmpI->getOperand(1), BaseId); + if (!Rhs.BaseId) + return {}; + const auto &DL = CmpI->getModule()->getDataLayout(); + return BCECmpBlock(std::move(Lhs), std::move(Rhs), + DL.getTypeSizeInBits(CmpI->getOperand(0)->getType())); } // Visit the given comparison block. If this is a comparison between two valid // BCE atoms, returns the comparison. BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block, - const BasicBlock *const PhiBlock) { + const BasicBlock *const PhiBlock, + BaseIdentifier &BaseId) { if (Block->empty()) return {}; auto *const BranchI = dyn_cast(Block->getTerminator()); if (!BranchI) return {}; @@ -306,7 +346,7 @@ BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block, auto *const CmpI = dyn_cast(Val); if (!CmpI) return {}; LLVM_DEBUG(dbgs() << "icmp\n"); - auto Result = visitICmp(CmpI, ICmpInst::ICMP_EQ); + auto Result = visitICmp(CmpI, ICmpInst::ICMP_EQ, BaseId); Result.CmpI = CmpI; Result.BranchI = BranchI; return Result; @@ -323,7 +363,8 @@ BCECmpBlock visitCmpBlock(Value *const Val, BasicBlock *const Block, assert(BranchI->getNumSuccessors() == 2 && "expecting a cond branch"); BasicBlock *const FalseBlock = BranchI->getSuccessor(1); auto Result = visitICmp( - CmpI, FalseBlock == PhiBlock ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE); + CmpI, FalseBlock == PhiBlock ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE, + BaseId); Result.CmpI = CmpI; Result.BranchI = BranchI; return Result; @@ -335,9 +376,9 @@ static inline void enqueueBlock(std::vector &Comparisons, BCECmpBlock &Comparison) { LLVM_DEBUG(dbgs() << "Block '" << Comparison.BB->getName() << "': Found cmp of " << Comparison.SizeBits() - << " bits between " << Comparison.Lhs().Base() << " + " + << " bits between " << Comparison.Lhs().BaseId << " + " << Comparison.Lhs().Offset << " and " - << Comparison.Rhs().Base() << " + " + << Comparison.Rhs().BaseId << " + " << Comparison.Rhs().Offset << "\n"); LLVM_DEBUG(dbgs() << "\n"); Comparisons.push_back(Comparison); @@ -360,8 +401,8 @@ class BCECmpChain { private: static bool IsContiguous(const BCECmpBlock &First, const BCECmpBlock &Second) { - return First.Lhs().Base() == Second.Lhs().Base() && - First.Rhs().Base() == Second.Rhs().Base() && + return First.Lhs().BaseId == Second.Lhs().BaseId && + First.Rhs().BaseId == Second.Rhs().BaseId && First.Lhs().Offset + First.SizeBits() / 8 == Second.Lhs().Offset && First.Rhs().Offset + First.SizeBits() / 8 == Second.Rhs().Offset; } @@ -385,11 +426,12 @@ BCECmpChain::BCECmpChain(const std::vector &Blocks, PHINode &Phi, assert(!Blocks.empty() && "a chain should have at least one block"); // Now look inside blocks to check for BCE comparisons. std::vector Comparisons; + BaseIdentifier BaseId; for (size_t BlockIdx = 0; BlockIdx < Blocks.size(); ++BlockIdx) { BasicBlock *const Block = Blocks[BlockIdx]; assert(Block && "invalid block"); BCECmpBlock Comparison = visitCmpBlock(Phi.getIncomingValueForBlock(Block), - Block, Phi.getParent()); + Block, Phi.getParent(), BaseId); Comparison.BB = Block; if (!Comparison.IsValid()) { LLVM_DEBUG(dbgs() << "chain with invalid BCECmpBlock, no merge.\n"); @@ -466,9 +508,10 @@ BCECmpChain::BCECmpChain(const std::vector &Blocks, PHINode &Phi, #endif // MERGEICMPS_DOT_ON // Reorder blocks by LHS. We can do that without changing the // semantics because we are only accessing dereferencable memory. - llvm::sort(Comparisons_, [](const BCECmpBlock &a, const BCECmpBlock &b) { - return a.Lhs() < b.Lhs(); - }); + llvm::sort(Comparisons_, + [](const BCECmpBlock &LhsBlock, const BCECmpBlock &RhsBlock) { + return LhsBlock.Lhs() < RhsBlock.Lhs(); + }); #ifdef MERGEICMPS_DOT_ON errs() << "AFTER REORDERING:\n\n"; dump(); diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir b/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir index af89ac5885ebea..2fc2cfd5d492ea 100644 --- a/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir +++ b/llvm/test/CodeGen/AArch64/machine-outliner-bad-adrp.mir @@ -10,6 +10,7 @@ ... --- name: foo +# CHECK-LABEL: name: foo tracksRegLiveness: true constants: - id: 0 diff --git a/llvm/test/CodeGen/X86/pr40730.ll b/llvm/test/CodeGen/X86/pr40730.ll new file mode 100644 index 00000000000000..12b372dea33bbe --- /dev/null +++ b/llvm/test/CodeGen/X86/pr40730.ll @@ -0,0 +1,36 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s + +define <8 x i32> @shuffle_v8i32_0dcd3f14(<8 x i32> %a, <8 x i32> %b) { +; CHECK-LABEL: shuffle_v8i32_0dcd3f14: +; CHECK: # %bb.0: +; CHECK-NEXT: vextractf128 $1, %ymm0, %xmm2 +; CHECK-NEXT: vblendps {{.*#+}} xmm2 = xmm2[0],xmm0[1,2,3] +; CHECK-NEXT: vpermilps {{.*#+}} xmm2 = xmm2[3,1,1,0] +; CHECK-NEXT: vinsertf128 $1, %xmm2, %ymm0, %ymm0 +; CHECK-NEXT: vperm2f128 {{.*#+}} ymm1 = ymm1[2,3,2,3] +; CHECK-NEXT: vpermilpd {{.*#+}} ymm1 = ymm1[0,0,3,2] +; CHECK-NEXT: vblendps {{.*#+}} ymm0 = ymm0[0],ymm1[1,2,3],ymm0[4],ymm1[5],ymm0[6,7] +; CHECK-NEXT: retq + %shuffle = shufflevector <8 x i32> %a, <8 x i32> %b, <8 x i32> + ret <8 x i32> %shuffle +} + +; CHECK: .LCPI1_0: +; CHECK-NEXT: .quad 60129542157 +; CHECK-NEXT: .quad 60129542157 +; CHECK-NEXT: .quad 68719476736 +; CHECK-NEXT: .quad 60129542157 + +define <8 x i32> @shuffle_v8i32_0dcd3f14_constant(<8 x i32> %a0) { +; CHECK-LABEL: shuffle_v8i32_0dcd3f14_constant: +; CHECK: # %bb.0: +; CHECK-NEXT: vextractf128 $1, %ymm0, %xmm1 +; CHECK-NEXT: vblendps {{.*#+}} xmm1 = xmm1[0],xmm0[1,2,3] +; CHECK-NEXT: vpermilps {{.*#+}} xmm1 = xmm1[3,1,1,0] +; CHECK-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0 +; CHECK-NEXT: vblendps {{.*#+}} ymm0 = ymm0[0],mem[1,2,3],ymm0[4],mem[5],ymm0[6,7] +; CHECK-NEXT: retq + %res = shufflevector <8 x i32> %a0, <8 x i32> , <8 x i32> + ret <8 x i32> %res +} diff --git a/llvm/test/MC/ELF/invalid-symver.s b/llvm/test/MC/ELF/invalid-symver.s index 3c4f8c084b94b6..d9f97b102b579b 100644 --- a/llvm/test/MC/ELF/invalid-symver.s +++ b/llvm/test/MC/ELF/invalid-symver.s @@ -1,7 +1,7 @@ // RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t 2> %t.out // RUN: FileCheck --input-file=%t.out %s -// CHECK: A @@ version cannot be undefined +// CHECK: error: versioned symbol foo@@bar must be defined .symver undefined, foo@@bar .long undefined diff --git a/llvm/test/MC/ELF/multiple-different-symver.s b/llvm/test/MC/ELF/multiple-different-symver.s index d7706f89f41982..c34626c08173c2 100644 --- a/llvm/test/MC/ELF/multiple-different-symver.s +++ b/llvm/test/MC/ELF/multiple-different-symver.s @@ -1,6 +1,6 @@ // RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t 2>&1 | FileCheck %s -// CHECK: Multiple symbol versions defined for foo +// CHECK: error: multiple symbol versions defined for foo .symver foo, foo@1 .symver foo, foo@2 diff --git a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll index c170f2ca74ba6b..e8f7f720b15273 100644 --- a/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll +++ b/llvm/test/Transforms/InstCombine/double-float-shrink-1.ll @@ -1,8 +1,8 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -instcombine -S | FileCheck %s - -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" +; RUN: opt < %s -instcombine -S -mtriple x86_64-unknown-linux-gnu | FileCheck %s --check-prefixes=CHECK,LINUX,ISC99 +; RUN: opt < %s -instcombine -S -mtriple x86_64-pc-win32 | FileCheck %s --check-prefixes=CHECK,ISC99 +; RUN: opt < %s -instcombine -S -mtriple x86_64-pc-windows-msvc16 | FileCheck %s --check-prefixes=CHECK,MS64,ISC89 +; RUN: opt < %s -instcombine -S -mtriple i386-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,ISC99 +; RUN: opt < %s -instcombine -S -mtriple i686-pc-windows-msvc17 | FileCheck %s --check-prefixes=CHECK,MS32,ISC89 ; Check for and against shrinkage when using the ; unsafe-fp-math function attribute on a math lib @@ -12,8 +12,10 @@ target triple = "x86_64-unknown-linux-gnu" define float @acos_test1(float %f) { ; CHECK-LABEL: @acos_test1( -; CHECK-NEXT: [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ACOSF]] +; LINUX-NEXT: [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[ACOSF]] +; MS32: [[ACOSF:%.*]] = call fast double @acos(double [[F:%.*]]) +; MS64-NEXT: [[ACOSF:%.*]] = call fast float @acosf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @acos(double %conv) @@ -34,8 +36,9 @@ define double @acos_test2(float %f) { define float @acosh_test1(float %f) { ; CHECK-LABEL: @acosh_test1( -; CHECK-NEXT: [[ACOSHF:%.*]] = call fast float @acoshf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ACOSHF]] +; ISC99-NEXT: [[ACOSHF:%.*]] = call fast float @acoshf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[ACOSHF]] +; ISC89: [[ACOSHF:%.*]] = call fast double @acosh(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @acosh(double %conv) @@ -56,8 +59,10 @@ define double @acosh_test2(float %f) { define float @asin_test1(float %f) { ; CHECK-LABEL: @asin_test1( -; CHECK-NEXT: [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ASINF]] +; LINUX-NEXT: [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[ASINF]] +; MS32: [[ASINF:%.*]] = call fast double @asin(double [[F:%.*]]) +; MS64-NEXT: [[ASINF:%.*]] = call fast float @asinf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @asin(double %conv) @@ -78,8 +83,9 @@ define double @asin_test2(float %f) { define float @asinh_test1(float %f) { ; CHECK-LABEL: @asinh_test1( -; CHECK-NEXT: [[ASINHF:%.*]] = call fast float @asinhf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ASINHF]] +; ISC99-NEXT: [[ASINHF:%.*]] = call fast float @asinhf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[ASINHF]] +; ISC89: [[ASINHF:%.*]] = call fast double @asinh(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @asinh(double %conv) @@ -100,8 +106,10 @@ define double @asinh_test2(float %f) { define float @atan_test1(float %f) { ; CHECK-LABEL: @atan_test1( -; CHECK-NEXT: [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ATANF]] +; LINUX-NEXT: [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[ATANF]] +; MS32: [[ATANF:%.*]] = call fast double @atan(double [[F:%.*]]) +; MS64-NEXT: [[ATANF:%.*]] = call fast float @atanf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @atan(double %conv) @@ -122,8 +130,9 @@ define double @atan_test2(float %f) { define float @atanh_test1(float %f) { ; CHECK-LABEL: @atanh_test1( -; CHECK-NEXT: [[ATANHF:%.*]] = call fast float @atanhf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[ATANHF]] +; ISC99-NEXT: [[ATANHF:%.*]] = call fast float @atanhf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[ATANHF]] +; ISC89: [[ATANHF:%.*]] = call fast double @atanh(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @atanh(double %conv) @@ -144,8 +153,9 @@ define double @atanh_test2(float %f) { define float @cbrt_test1(float %f) { ; CHECK-LABEL: @cbrt_test1( -; CHECK-NEXT: [[CBRTF:%.*]] = call fast float @cbrtf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[CBRTF]] +; ISC99-NEXT: [[CBRTF:%.*]] = call fast float @cbrtf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[CBRTF]] +; ISC89: [[CBRTF:%.*]] = call fast double @cbrt(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @cbrt(double %conv) @@ -166,8 +176,10 @@ define double @cbrt_test2(float %f) { define float @exp_test1(float %f) { ; CHECK-LABEL: @exp_test1( -; CHECK-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[EXPF]] +; LINUX-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[EXPF]] +; MS32: [[EXPF:%.*]] = call fast double @exp(double [[F:%.*]]) +; MS64-NEXT: [[EXPF:%.*]] = call fast float @expf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @exp(double %conv) @@ -188,8 +200,9 @@ define double @exp_test2(float %f) { define float @expm1_test1(float %f) { ; CHECK-LABEL: @expm1_test1( -; CHECK-NEXT: [[EXPM1F:%.*]] = call fast float @expm1f(float [[F:%.*]]) -; CHECK-NEXT: ret float [[EXPM1F]] +; ISC99-NEXT: [[EXPM1F:%.*]] = call fast float @expm1f(float [[F:%.*]]) +; ISC99-NEXT: ret float [[EXPM1F]] +; ISC89: [[EXPM1F:%.*]] = call fast double @expm1(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @expm1(double %conv) @@ -236,8 +249,10 @@ define double @exp10_test2(float %f) { define float @log_test1(float %f) { ; CHECK-LABEL: @log_test1( -; CHECK-NEXT: [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOGF]] +; LINUX-NEXT: [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[LOGF]] +; MS32: [[LOGF:%.*]] = call fast double @log(double [[F:%.*]]) +; MS64-NEXT: [[LOGF:%.*]] = call fast float @logf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log(double %conv) @@ -258,8 +273,10 @@ define double @log_test2(float %f) { define float @log10_test1(float %f) { ; CHECK-LABEL: @log10_test1( -; CHECK-NEXT: [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOG10F]] +; LINUX-NEXT: [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]]) +; LINUX-NEXT: ret float [[LOG10F]] +; MS32: [[LOG10F:%.*]] = call fast double @log10(double [[F:%.*]]) +; MS64-NEXT: [[LOG10F:%.*]] = call fast float @log10f(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log10(double %conv) @@ -280,8 +297,9 @@ define double @log10_test2(float %f) { define float @log1p_test1(float %f) { ; CHECK-LABEL: @log1p_test1( -; CHECK-NEXT: [[LOG1PF:%.*]] = call fast float @log1pf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOG1PF]] +; ISC99-NEXT: [[LOG1PF:%.*]] = call fast float @log1pf(float [[F:%.*]]) +; ISC99-NEXT: ret float [[LOG1PF]] +; ISC89: [[LOG1PF:%.*]] = call fast double @log1p(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log1p(double %conv) @@ -302,8 +320,9 @@ define double @log1p_test2(float %f) { define float @log2_test1(float %f) { ; CHECK-LABEL: @log2_test1( -; CHECK-NEXT: [[LOG2F:%.*]] = call fast float @log2f(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOG2F]] +; ISC99-NEXT: [[LOG2F:%.*]] = call fast float @log2f(float [[F:%.*]]) +; ISC99-NEXT: ret float [[LOG2F]] +; ISC89: [[LOG2F:%.*]] = call fast double @log2(double [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @log2(double %conv) @@ -324,8 +343,10 @@ define double @log2_test2(float %f) { define float @logb_test1(float %f) { ; CHECK-LABEL: @logb_test1( -; CHECK-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[LOGBF]] +; LINUX-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[LOGBF]] +; MS32: [[POWF:%.*]] = call fast double @logb(double [[F:%.*]]) +; MS64-NEXT: [[LOGBF:%.*]] = call fast float @logbf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @logb(double %conv) @@ -346,8 +367,10 @@ define double @logb_test2(float %f) { define float @pow_test1(float %f, float %g) { ; CHECK-LABEL: @pow_test1( -; CHECK-NEXT: [[POWF:%.*]] = call fast float @powf(float %f, float %g) -; CHECK-NEXT: ret float [[POWF]] +; LINUX-NEXT: [[POWF:%.*]] = call fast float @powf(float %f, float %g) +; LINUX-NEXT: ret float [[POWF]] +; MS32: [[POWF:%.*]] = call fast double @pow(double %df, double %dg) +; MS64-NEXT: [[POWF:%.*]] = call fast float @powf(float %f, float %g) ; %df = fpext float %f to double %dg = fpext float %g to double @@ -369,8 +392,10 @@ define double @pow_test2(float %f, float %g) { define float @sin_test1(float %f) { ; CHECK-LABEL: @sin_test1( -; CHECK-NEXT: [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[SINF]] +; LINUX-NEXT: [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[SINF]] +; MS32: [[SINF:%.*]] = call fast double @sin(double [[F:%.*]]) +; MS64-NEXT: [[SINF:%.*]] = call fast float @sinf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @sin(double %conv) @@ -391,8 +416,10 @@ define double @sin_test2(float %f) { define float @sqrt_test1(float %f) { ; CHECK-LABEL: @sqrt_test1( -; CHECK-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[SQRTF]] +; LINUX-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[SQRTF]] +; MS32: [[SQRTF:%.*]] = call double @sqrt(double [[F:%.*]]) +; MS64-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call double @sqrt(double %conv) @@ -413,8 +440,10 @@ define double @sqrt_test2(float %f) { define float @sqrt_int_test1(float %f) { ; CHECK-LABEL: @sqrt_int_test1( -; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]]) -; CHECK-NEXT: ret float [[TMP1]] +; LINUX-NEXT: [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]]) +; LINUX-NEXT: ret float [[TMP1]] +; MS32: [[TMP1:%.*]] = call double @llvm.sqrt.f64(double [[F:%.*]]) +; MS64-NEXT: [[TMP1:%.*]] = call float @llvm.sqrt.f32(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call double @llvm.sqrt.f64(double %conv) @@ -435,8 +464,10 @@ define double @sqrt_int_test2(float %f) { define float @tan_test1(float %f) { ; CHECK-LABEL: @tan_test1( -; CHECK-NEXT: [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[TANF]] +; LINUX-NEXT: [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[TANF]] +; MS32: [[TANF:%.*]] = call fast double @tan(double [[F:%.*]]) +; MS64-NEXT: [[TANF:%.*]] = call fast float @tanf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @tan(double %conv) @@ -456,8 +487,10 @@ define double @tan_test2(float %f) { } define float @tanh_test1(float %f) { ; CHECK-LABEL: @tanh_test1( -; CHECK-NEXT: [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]]) -; CHECK-NEXT: ret float [[TANHF]] +; LINUX-NEXT: [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]]) +; LINUX-NEXT: ret float [[TANHF]] +; MS32: [[TANHF:%.*]] = call fast double @tanh(double [[F:%.*]]) +; MS64-NEXT: [[TANHF:%.*]] = call fast float @tanhf(float [[F:%.*]]) ; %conv = fpext float %f to double %call = call fast double @tanh(double %conv) @@ -480,8 +513,9 @@ define double @tanh_test2(float %f) { ; flags are propagated for shrunken *binary* double FP calls. define float @max1(float %a, float %b) { ; CHECK-LABEL: @max1( -; CHECK-NEXT: [[FMAXF:%.*]] = call arcp float @fmaxf(float [[A:%.*]], float [[B:%.*]]) -; CHECK-NEXT: ret float [[FMAXF]] +; ISC99-NEXT: [[FMAXF:%.*]] = call arcp float @fmaxf(float [[A:%.*]], float [[B:%.*]]) +; ISC99-NEXT: ret float [[FMAXF]] +; ISC89: [[FMAXF:%.*]] = call arcp double @fmax(double [[A:%.*]], double [[B:%.*]]) ; %c = fpext float %a to double %d = fpext float %b to double diff --git a/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll b/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll index 5bdeaf7d9d7e0f..76e497bd68fc79 100644 --- a/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll +++ b/llvm/test/Transforms/InstCombine/double-float-shrink-2.ll @@ -1,11 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -instcombine -S -mtriple "i386-pc-linux" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "i386-pc-win32" | FileCheck -check-prefix=ALL -check-prefix=DONT-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-win32" | FileCheck -check-prefix=ALL -check-prefix=C89-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "i386-pc-mingw32" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-mingw32" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -instcombine -S -mtriple "sparc-sun-solaris" | FileCheck -check-prefix=ALL -check-prefix=DO-SIMPLIFY %s -; RUN: opt < %s -enable-debugify -instcombine -S -mtriple "x86_64-pc-win32" 2>&1 | FileCheck -check-prefix=DBG-VALID %s +; RUN: opt < %s -instcombine -S -mtriple "i386-pc-linux" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "i386-pc-win32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-win32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "i386-pc-mingw32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-mingw32" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "sparc-sun-solaris" | FileCheck %s +; RUN: opt < %s -instcombine -S -mtriple "x86_64-pc-win32" -enable-debugify 2>&1 | FileCheck --check-prefix=DBG-VALID %s declare double @floor(double) declare double @ceil(double) @@ -36,9 +36,9 @@ declare double @llvm.trunc.f64(double) declare <2 x double> @llvm.trunc.v2f64(<2 x double>) define float @test_shrink_libcall_floor(float %C) { -; ALL-LABEL: @test_shrink_libcall_floor( -; ALL-NEXT: [[F:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_floor( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> floorf @@ -48,9 +48,9 @@ define float @test_shrink_libcall_floor(float %C) { } define float @test_shrink_libcall_ceil(float %C) { -; ALL-LABEL: @test_shrink_libcall_ceil( -; ALL-NEXT: [[F:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_ceil( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> ceilf @@ -60,21 +60,9 @@ define float @test_shrink_libcall_ceil(float %C) { } define float @test_shrink_libcall_round(float %C) { -; DO-SIMPLIFY-LABEL: @test_shrink_libcall_round( -; DO-SIMPLIFY-NEXT: [[F:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) -; DO-SIMPLIFY-NEXT: ret float [[F]] -; -; DONT-SIMPLIFY-LABEL: @test_shrink_libcall_round( -; DONT-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; DONT-SIMPLIFY-NEXT: [[E:%.*]] = call double @round(double [[D]]) -; DONT-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; DONT-SIMPLIFY-NEXT: ret float [[F]] -; -; C89-SIMPLIFY-LABEL: @test_shrink_libcall_round( -; C89-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; C89-SIMPLIFY-NEXT: [[E:%.*]] = call double @round(double [[D]]) -; C89-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; C89-SIMPLIFY-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_round( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> roundf @@ -84,21 +72,9 @@ define float @test_shrink_libcall_round(float %C) { } define float @test_shrink_libcall_nearbyint(float %C) { -; DO-SIMPLIFY-LABEL: @test_shrink_libcall_nearbyint( -; DO-SIMPLIFY-NEXT: [[F:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) -; DO-SIMPLIFY-NEXT: ret float [[F]] -; -; DONT-SIMPLIFY-LABEL: @test_shrink_libcall_nearbyint( -; DONT-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; DONT-SIMPLIFY-NEXT: [[E:%.*]] = call double @nearbyint(double [[D]]) -; DONT-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; DONT-SIMPLIFY-NEXT: ret float [[F]] -; -; C89-SIMPLIFY-LABEL: @test_shrink_libcall_nearbyint( -; C89-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; C89-SIMPLIFY-NEXT: [[E:%.*]] = call double @nearbyint(double [[D]]) -; C89-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; C89-SIMPLIFY-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_nearbyint( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> nearbyintf @@ -108,21 +84,9 @@ define float @test_shrink_libcall_nearbyint(float %C) { } define float @test_shrink_libcall_trunc(float %C) { -; DO-SIMPLIFY-LABEL: @test_shrink_libcall_trunc( -; DO-SIMPLIFY-NEXT: [[F:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) -; DO-SIMPLIFY-NEXT: ret float [[F]] -; -; DONT-SIMPLIFY-LABEL: @test_shrink_libcall_trunc( -; DONT-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; DONT-SIMPLIFY-NEXT: [[E:%.*]] = call double @trunc(double [[D]]) -; DONT-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; DONT-SIMPLIFY-NEXT: ret float [[F]] -; -; C89-SIMPLIFY-LABEL: @test_shrink_libcall_trunc( -; C89-SIMPLIFY-NEXT: [[D:%.*]] = fpext float [[C:%.*]] to double -; C89-SIMPLIFY-NEXT: [[E:%.*]] = call double @trunc(double [[D]]) -; C89-SIMPLIFY-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; C89-SIMPLIFY-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_trunc( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double ; --> truncf @@ -132,11 +96,11 @@ define float @test_shrink_libcall_trunc(float %C) { } ; This is replaced with the intrinsic, which does the right thing on -; all platforms. +; CHECK platforms. define float @test_shrink_libcall_fabs(float %C) { -; ALL-LABEL: @test_shrink_libcall_fabs( -; ALL-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_fabs( +; CHECK-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double %E = call double @fabs(double %D) @@ -146,9 +110,9 @@ define float @test_shrink_libcall_fabs(float %C) { ; Make sure fast math flags are preserved define float @test_shrink_libcall_fabs_fast(float %C) { -; ALL-LABEL: @test_shrink_libcall_fabs_fast( -; ALL-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_libcall_fabs_fast( +; CHECK-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[F]] ; %D = fpext float %C to double %E = call fast double @fabs(double %D) @@ -157,9 +121,9 @@ define float @test_shrink_libcall_fabs_fast(float %C) { } define float @test_shrink_intrin_ceil(float %C) { -; ALL-LABEL: @test_shrink_intrin_ceil( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_ceil( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ceil.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.ceil.f64(double %D) @@ -168,9 +132,9 @@ define float @test_shrink_intrin_ceil(float %C) { } define float @test_shrink_intrin_fabs(float %C) { -; ALL-LABEL: @test_shrink_intrin_fabs( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_fabs( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.fabs.f64(double %D) @@ -179,9 +143,9 @@ define float @test_shrink_intrin_fabs(float %C) { } define float @test_shrink_intrin_floor(float %C) { -; ALL-LABEL: @test_shrink_intrin_floor( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_floor( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.floor.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.floor.f64(double %D) @@ -190,9 +154,9 @@ define float @test_shrink_intrin_floor(float %C) { } define float @test_shrink_intrin_nearbyint(float %C) { -; ALL-LABEL: @test_shrink_intrin_nearbyint( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_nearbyint( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.nearbyint.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.nearbyint.f64(double %D) @@ -201,9 +165,9 @@ define float @test_shrink_intrin_nearbyint(float %C) { } define half @test_shrink_intrin_rint(half %C) { -; ALL-LABEL: @test_shrink_intrin_rint( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.rint.f16(half [[C:%.*]]) -; ALL-NEXT: ret half [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_rint( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.rint.f16(half [[C:%.*]]) +; CHECK-NEXT: ret half [[TMP1]] ; %D = fpext half %C to float %E = call float @llvm.rint.f32(float %D) @@ -212,9 +176,9 @@ define half @test_shrink_intrin_rint(half %C) { } define float @test_shrink_intrin_round(float %C) { -; ALL-LABEL: @test_shrink_intrin_round( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_round( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.round.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.round.f64(double %D) @@ -223,9 +187,9 @@ define float @test_shrink_intrin_round(float %C) { } define float @test_shrink_intrin_trunc(float %C) { -; ALL-LABEL: @test_shrink_intrin_trunc( -; ALL-NEXT: [[TMP1:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_trunc( +; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.trunc.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call double @llvm.trunc.f64(double %D) @@ -237,12 +201,12 @@ declare void @use_v2f64(<2 x double>) declare void @use_v2f32(<2 x float>) define <2 x float> @test_shrink_intrin_ceil_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_ceil_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.ceil.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_ceil_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.ceil.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.ceil.v2f64(<2 x double> %D) @@ -252,11 +216,11 @@ define <2 x float> @test_shrink_intrin_ceil_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_fabs_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_multi_use( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x float> [[TMP1]] to <2 x double> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[E]]) -; ALL-NEXT: ret <2 x float> [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_fabs_multi_use( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x float> [[TMP1]] to <2 x double> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[E]]) +; CHECK-NEXT: ret <2 x float> [[TMP1]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.fabs.v2f64(<2 x double> %D) @@ -266,13 +230,13 @@ define <2 x float> @test_shrink_intrin_fabs_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_floor_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_floor_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.floor.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: call void @use_v2f64(<2 x double> [[E]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_floor_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.floor.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[E]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.floor.v2f64(<2 x double> %D) @@ -283,12 +247,12 @@ define <2 x float> @test_shrink_intrin_floor_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_nearbyint_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_nearbyint_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_nearbyint_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %D) @@ -298,11 +262,11 @@ define <2 x float> @test_shrink_intrin_nearbyint_multi_use(<2 x float> %C) { } define <2 x half> @test_shrink_intrin_rint_multi_use(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_rint_multi_use( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.rint.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x float> -; ALL-NEXT: call void @use_v2f32(<2 x float> [[E]]) -; ALL-NEXT: ret <2 x half> [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_rint_multi_use( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.rint.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x float> +; CHECK-NEXT: call void @use_v2f32(<2 x float> [[E]]) +; CHECK-NEXT: ret <2 x half> [[TMP1]] ; %D = fpext <2 x half> %C to <2 x float> %E = call <2 x float> @llvm.rint.v2f32(<2 x float> %D) @@ -312,13 +276,13 @@ define <2 x half> @test_shrink_intrin_rint_multi_use(<2 x half> %C) { } define <2 x float> @test_shrink_intrin_round_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_round_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.round.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: call void @use_v2f64(<2 x double> [[E]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_round_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.round.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[E]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.round.v2f64(<2 x double> %D) @@ -329,12 +293,12 @@ define <2 x float> @test_shrink_intrin_round_multi_use(<2 x float> %C) { } define <2 x float> @test_shrink_intrin_trunc_multi_use(<2 x float> %C) { -; ALL-LABEL: @test_shrink_intrin_trunc_multi_use( -; ALL-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> -; ALL-NEXT: [[E:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> -; ALL-NEXT: call void @use_v2f64(<2 x double> [[D]]) -; ALL-NEXT: ret <2 x float> [[F]] +; CHECK-LABEL: @test_shrink_intrin_trunc_multi_use( +; CHECK-NEXT: [[D:%.*]] = fpext <2 x float> [[C:%.*]] to <2 x double> +; CHECK-NEXT: [[E:%.*]] = call <2 x double> @llvm.trunc.v2f64(<2 x double> [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc <2 x double> [[E]] to <2 x float> +; CHECK-NEXT: call void @use_v2f64(<2 x double> [[D]]) +; CHECK-NEXT: ret <2 x float> [[F]] ; %D = fpext <2 x float> %C to <2 x double> %E = call <2 x double> @llvm.trunc.v2f64(<2 x double> %D) @@ -345,9 +309,9 @@ define <2 x float> @test_shrink_intrin_trunc_multi_use(<2 x float> %C) { ; Make sure fast math flags are preserved define float @test_shrink_intrin_fabs_fast(float %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_fast( -; ALL-NEXT: [[TMP1:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) -; ALL-NEXT: ret float [[TMP1]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fast( +; CHECK-NEXT: [[TMP1:%.*]] = call fast float @llvm.fabs.f32(float [[C:%.*]]) +; CHECK-NEXT: ret float [[TMP1]] ; %D = fpext float %C to double %E = call fast double @llvm.fabs.f64(double %D) @@ -356,10 +320,10 @@ define float @test_shrink_intrin_fabs_fast(float %C) { } define float @test_no_shrink_intrin_floor(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_floor( -; ALL-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_floor( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.floor.f64(double %D) %F = fptrunc double %E to float @@ -367,10 +331,10 @@ define float @test_no_shrink_intrin_floor(double %D) { } define float @test_no_shrink_intrin_ceil(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_ceil( -; ALL-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_ceil( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.ceil.f64(double %D) %F = fptrunc double %E to float @@ -378,10 +342,10 @@ define float @test_no_shrink_intrin_ceil(double %D) { } define float @test_no_shrink_intrin_round(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_round( -; ALL-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_round( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.round.f64(double %D) %F = fptrunc double %E to float @@ -389,10 +353,10 @@ define float @test_no_shrink_intrin_round(double %D) { } define float @test_no_shrink_intrin_nearbyint(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_nearbyint( -; ALL-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_nearbyint( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.nearbyint.f64(double %D) %F = fptrunc double %E to float @@ -400,10 +364,10 @@ define float @test_no_shrink_intrin_nearbyint(double %D) { } define float @test_no_shrink_intrin_trunc(double %D) { -; ALL-LABEL: @test_no_shrink_intrin_trunc( -; ALL-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_trunc( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.trunc.f64(double %D) %F = fptrunc double %E to float @@ -411,10 +375,10 @@ define float @test_no_shrink_intrin_trunc(double %D) { } define float @test_shrink_intrin_fabs_double_src(double %D) { -; ALL-LABEL: @test_shrink_intrin_fabs_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float -; ALL-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float +; CHECK-NEXT: [[F:%.*]] = call float @llvm.fabs.f32(float [[TMP1]]) +; CHECK-NEXT: ret float [[F]] ; %E = call double @llvm.fabs.f64(double %D) %F = fptrunc double %E to float @@ -423,10 +387,10 @@ define float @test_shrink_intrin_fabs_double_src(double %D) { ; Make sure fast math flags are preserved define float @test_shrink_intrin_fabs_fast_double_src(double %D) { -; ALL-LABEL: @test_shrink_intrin_fabs_fast_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float -; ALL-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[TMP1]]) -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fast_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to float +; CHECK-NEXT: [[F:%.*]] = call fast float @llvm.fabs.f32(float [[TMP1]]) +; CHECK-NEXT: ret float [[F]] ; %E = call fast double @llvm.fabs.f64(double %D) %F = fptrunc double %E to float @@ -434,8 +398,8 @@ define float @test_shrink_intrin_fabs_fast_double_src(double %D) { } define float @test_shrink_float_convertible_constant_intrin_floor() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_floor( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_floor( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.floor.f64(double 2.1) %F = fptrunc double %E to float @@ -443,8 +407,8 @@ define float @test_shrink_float_convertible_constant_intrin_floor() { } define float @test_shrink_float_convertible_constant_intrin_ceil() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_ceil( -; ALL-NEXT: ret float 3.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_ceil( +; CHECK-NEXT: ret float 3.000000e+00 ; %E = call double @llvm.ceil.f64(double 2.1) %F = fptrunc double %E to float @@ -452,8 +416,8 @@ define float @test_shrink_float_convertible_constant_intrin_ceil() { } define float @test_shrink_float_convertible_constant_intrin_round() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_round( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_round( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.round.f64(double 2.1) %F = fptrunc double %E to float @@ -461,8 +425,8 @@ define float @test_shrink_float_convertible_constant_intrin_round() { } define float @test_shrink_float_convertible_constant_intrin_nearbyint() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_nearbyint( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_nearbyint( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.nearbyint.f64(double 2.1) %F = fptrunc double %E to float @@ -470,8 +434,8 @@ define float @test_shrink_float_convertible_constant_intrin_nearbyint() { } define float @test_shrink_float_convertible_constant_intrin_trunc() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_trunc( -; ALL-NEXT: ret float 2.000000e+00 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_trunc( +; CHECK-NEXT: ret float 2.000000e+00 ; %E = call double @llvm.trunc.f64(double 2.1) %F = fptrunc double %E to float @@ -479,8 +443,8 @@ define float @test_shrink_float_convertible_constant_intrin_trunc() { } define float @test_shrink_float_convertible_constant_intrin_fabs() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_fabs( -; ALL-NEXT: ret float 0x4000CCCCC0000000 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_fabs( +; CHECK-NEXT: ret float 0x4000CCCCC0000000 ; %E = call double @llvm.fabs.f64(double 2.1) %F = fptrunc double %E to float @@ -489,8 +453,8 @@ define float @test_shrink_float_convertible_constant_intrin_fabs() { ; Make sure fast math flags are preserved define float @test_shrink_float_convertible_constant_intrin_fabs_fast() { -; ALL-LABEL: @test_shrink_float_convertible_constant_intrin_fabs_fast( -; ALL-NEXT: ret float 0x4000CCCCC0000000 +; CHECK-LABEL: @test_shrink_float_convertible_constant_intrin_fabs_fast( +; CHECK-NEXT: ret float 0x4000CCCCC0000000 ; %E = call fast double @llvm.fabs.f64(double 2.1) %F = fptrunc double %E to float @@ -498,10 +462,10 @@ define float @test_shrink_float_convertible_constant_intrin_fabs_fast() { } define half @test_no_shrink_mismatched_type_intrin_floor(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_floor( -; ALL-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_floor( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.floor.f64(double %D) %F = fptrunc double %E to half @@ -509,10 +473,10 @@ define half @test_no_shrink_mismatched_type_intrin_floor(double %D) { } define half @test_no_shrink_mismatched_type_intrin_ceil(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_ceil( -; ALL-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_ceil( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.ceil.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.ceil.f64(double %D) %F = fptrunc double %E to half @@ -520,10 +484,10 @@ define half @test_no_shrink_mismatched_type_intrin_ceil(double %D) { } define half @test_no_shrink_mismatched_type_intrin_round(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_round( -; ALL-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_round( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.round.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.round.f64(double %D) %F = fptrunc double %E to half @@ -531,10 +495,10 @@ define half @test_no_shrink_mismatched_type_intrin_round(double %D) { } define half @test_no_shrink_mismatched_type_intrin_nearbyint(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_nearbyint( -; ALL-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_nearbyint( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.nearbyint.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.nearbyint.f64(double %D) %F = fptrunc double %E to half @@ -542,10 +506,10 @@ define half @test_no_shrink_mismatched_type_intrin_nearbyint(double %D) { } define half @test_no_shrink_mismatched_type_intrin_trunc(double %D) { -; ALL-LABEL: @test_no_shrink_mismatched_type_intrin_trunc( -; ALL-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to half -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_no_shrink_mismatched_type_intrin_trunc( +; CHECK-NEXT: [[E:%.*]] = call double @llvm.trunc.f64(double [[D:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to half +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.trunc.f64(double %D) %F = fptrunc double %E to half @@ -553,10 +517,10 @@ define half @test_no_shrink_mismatched_type_intrin_trunc(double %D) { } define half @test_shrink_mismatched_type_intrin_fabs_double_src(double %D) { -; ALL-LABEL: @test_shrink_mismatched_type_intrin_fabs_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half -; ALL-NEXT: [[F:%.*]] = call half @llvm.fabs.f16(half [[TMP1]]) -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_shrink_mismatched_type_intrin_fabs_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half +; CHECK-NEXT: [[F:%.*]] = call half @llvm.fabs.f16(half [[TMP1]]) +; CHECK-NEXT: ret half [[F]] ; %E = call double @llvm.fabs.f64(double %D) %F = fptrunc double %E to half @@ -565,10 +529,10 @@ define half @test_shrink_mismatched_type_intrin_fabs_double_src(double %D) { ; Make sure fast math flags are preserved define half @test_mismatched_type_intrin_fabs_fast_double_src(double %D) { -; ALL-LABEL: @test_mismatched_type_intrin_fabs_fast_double_src( -; ALL-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half -; ALL-NEXT: [[F:%.*]] = call fast half @llvm.fabs.f16(half [[TMP1]]) -; ALL-NEXT: ret half [[F]] +; CHECK-LABEL: @test_mismatched_type_intrin_fabs_fast_double_src( +; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[D:%.*]] to half +; CHECK-NEXT: [[F:%.*]] = call fast half @llvm.fabs.f16(half [[TMP1]]) +; CHECK-NEXT: ret half [[F]] ; %E = call fast double @llvm.fabs.f64(double %D) %F = fptrunc double %E to half @@ -576,10 +540,10 @@ define half @test_mismatched_type_intrin_fabs_fast_double_src(double %D) { } define <2 x double> @test_shrink_intrin_floor_fp16_vec(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_floor_fp16_vec( -; ALL-NEXT: [[TMP1:%.*]] = call arcp <2 x half> @llvm.floor.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> -; ALL-NEXT: ret <2 x double> [[E]] +; CHECK-LABEL: @test_shrink_intrin_floor_fp16_vec( +; CHECK-NEXT: [[TMP1:%.*]] = call arcp <2 x half> @llvm.floor.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> +; CHECK-NEXT: ret <2 x double> [[E]] ; %D = fpext <2 x half> %C to <2 x double> %E = call arcp <2 x double> @llvm.floor.v2f64(<2 x double> %D) @@ -587,10 +551,10 @@ define <2 x double> @test_shrink_intrin_floor_fp16_vec(<2 x half> %C) { } define float @test_shrink_intrin_ceil_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_ceil_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.ceil.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_ceil_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.ceil.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call double @llvm.ceil.f64(double %D) @@ -599,10 +563,10 @@ define float @test_shrink_intrin_ceil_fp16_src(half %C) { } define <2 x double> @test_shrink_intrin_round_fp16_vec(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_round_fp16_vec( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.round.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> -; ALL-NEXT: ret <2 x double> [[E]] +; CHECK-LABEL: @test_shrink_intrin_round_fp16_vec( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.round.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> +; CHECK-NEXT: ret <2 x double> [[E]] ; %D = fpext <2 x half> %C to <2 x double> %E = call <2 x double> @llvm.round.v2f64(<2 x double> %D) @@ -610,10 +574,10 @@ define <2 x double> @test_shrink_intrin_round_fp16_vec(<2 x half> %C) { } define float @test_shrink_intrin_nearbyint_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_nearbyint_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.nearbyint.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_nearbyint_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.nearbyint.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call double @llvm.nearbyint.f64(double %D) @@ -622,10 +586,10 @@ define float @test_shrink_intrin_nearbyint_fp16_src(half %C) { } define <2 x double> @test_shrink_intrin_trunc_fp16_src(<2 x half> %C) { -; ALL-LABEL: @test_shrink_intrin_trunc_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.trunc.v2f16(<2 x half> [[C:%.*]]) -; ALL-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> -; ALL-NEXT: ret <2 x double> [[E]] +; CHECK-LABEL: @test_shrink_intrin_trunc_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.trunc.v2f16(<2 x half> [[C:%.*]]) +; CHECK-NEXT: [[E:%.*]] = fpext <2 x half> [[TMP1]] to <2 x double> +; CHECK-NEXT: ret <2 x double> [[E]] ; %D = fpext <2 x half> %C to <2 x double> %E = call <2 x double> @llvm.trunc.v2f64(<2 x double> %D) @@ -633,10 +597,10 @@ define <2 x double> @test_shrink_intrin_trunc_fp16_src(<2 x half> %C) { } define float @test_shrink_intrin_fabs_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call double @llvm.fabs.f64(double %D) @@ -646,10 +610,10 @@ define float @test_shrink_intrin_fabs_fp16_src(half %C) { ; Make sure fast math flags are preserved define float @test_shrink_intrin_fabs_fast_fp16_src(half %C) { -; ALL-LABEL: @test_shrink_intrin_fabs_fast_fp16_src( -; ALL-NEXT: [[TMP1:%.*]] = call fast half @llvm.fabs.f16(half [[C:%.*]]) -; ALL-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_shrink_intrin_fabs_fast_fp16_src( +; CHECK-NEXT: [[TMP1:%.*]] = call fast half @llvm.fabs.f16(half [[C:%.*]]) +; CHECK-NEXT: [[F:%.*]] = fpext half [[TMP1]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double %E = call fast double @llvm.fabs.f64(double %D) @@ -658,12 +622,12 @@ define float @test_shrink_intrin_fabs_fast_fp16_src(half %C) { } define float @test_no_shrink_intrin_floor_multi_use_fpext(half %C) { -; ALL-LABEL: @test_no_shrink_intrin_floor_multi_use_fpext( -; ALL-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double -; ALL-NEXT: store volatile double [[D]], double* undef, align 8 -; ALL-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_floor_multi_use_fpext( +; CHECK-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double +; CHECK-NEXT: store volatile double [[D]], double* undef, align 8 +; CHECK-NEXT: [[E:%.*]] = call double @llvm.floor.f64(double [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double store volatile double %D, double* undef @@ -673,12 +637,12 @@ define float @test_no_shrink_intrin_floor_multi_use_fpext(half %C) { } define float @test_no_shrink_intrin_fabs_multi_use_fpext(half %C) { -; ALL-LABEL: @test_no_shrink_intrin_fabs_multi_use_fpext( -; ALL-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double -; ALL-NEXT: store volatile double [[D]], double* undef, align 8 -; ALL-NEXT: [[E:%.*]] = call double @llvm.fabs.f64(double [[D]]) -; ALL-NEXT: [[F:%.*]] = fptrunc double [[E]] to float -; ALL-NEXT: ret float [[F]] +; CHECK-LABEL: @test_no_shrink_intrin_fabs_multi_use_fpext( +; CHECK-NEXT: [[D:%.*]] = fpext half [[C:%.*]] to double +; CHECK-NEXT: store volatile double [[D]], double* undef, align 8 +; CHECK-NEXT: [[E:%.*]] = call double @llvm.fabs.f64(double [[D]]) +; CHECK-NEXT: [[F:%.*]] = fptrunc double [[E]] to float +; CHECK-NEXT: ret float [[F]] ; %D = fpext half %C to double store volatile double %D, double* undef diff --git a/llvm/test/Transforms/InstCombine/pow-1.ll b/llvm/test/Transforms/InstCombine/pow-1.ll index 672ec70e71ec2a..957e2488b721b4 100644 --- a/llvm/test/Transforms/InstCombine/pow-1.ll +++ b/llvm/test/Transforms/InstCombine/pow-1.ll @@ -1,15 +1,18 @@ ; Test that the pow library call simplifier works correctly. ; -; RUN: opt -instcombine -S < %s | FileCheck %s --check-prefixes=ANY -; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.9 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios7.0 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.8 | FileCheck %s --check-prefixes=ANY,CHECK-NO-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios6.0 | FileCheck %s --check-prefixes=ANY,CHECK-NO-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=x86_64-netbsd | FileCheck %s --check-prefixes=ANY,CHECK-NO-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-tvos9.0 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 -; RUN: opt -instcombine -S < %s -mtriple=arm-apple-watchos2.0 | FileCheck %s --check-prefixes=ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s | FileCheck %s --check-prefixes=CHECK,ANY +; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.9 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios7.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-apple-macosx10.8 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-ios6.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-netbsd | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-tvos9.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=arm-apple-watchos2.0 | FileCheck %s --check-prefixes=CHECK,ANY,CHECK-EXP10 ; rdar://7251832 -; RUN: opt -instcombine -S < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK-WIN +; RUN: opt -instcombine -S < %s -mtriple=i386-pc-windows-msvc18 | FileCheck %s --check-prefixes=CHECK,MSVC,VC32,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=i386-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,MSVC,VC51,VC19,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-pc-windows-msvc18 | FileCheck %s --check-prefixes=CHECK,MSVC,VC64,CHECK-NO-EXP10 +; RUN: opt -instcombine -S < %s -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,MSVC,VC83,VC19,CHECK-NO-EXP10 ; NOTE: The readonly attribute on the pow call should be preserved ; in the cases below where pow is transformed into another function call. @@ -23,32 +26,39 @@ declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>) nounwind readon ; Check pow(1.0, x) -> 1.0. define float @test_simplify1(float %x) { -; ANY-LABEL: @test_simplify1( +; CHECK-LABEL: @test_simplify1( ; ANY-NEXT: ret float 1.000000e+00 +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 1.000000e+00, float [[X:%.*]]) +; VC32-NEXT: ret float [[POW]] +; VC64-NEXT: ret float 1.000000e+00 ; %retval = call float @powf(float 1.0, float %x) ret float %retval } define <2 x float> @test_simplify1v(<2 x float> %x) { -; ANY-LABEL: @test_simplify1v( +; CHECK-LABEL: @test_simplify1v( ; ANY-NEXT: ret <2 x float> +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> %x) ret <2 x float> %retval } define double @test_simplify2(double %x) { -; ANY-LABEL: @test_simplify2( -; ANY-NEXT: ret double 1.000000e+00 +; CHECK-LABEL: @test_simplify2( +; CHECK-NEXT: ret double 1.000000e+00 ; %retval = call double @pow(double 1.0, double %x) ret double %retval } define <2 x double> @test_simplify2v(<2 x double> %x) { -; ANY-LABEL: @test_simplify2v( +; CHECK-LABEL: @test_simplify2v( ; ANY-NEXT: ret <2 x double> +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval @@ -57,104 +67,114 @@ define <2 x double> @test_simplify2v(<2 x double> %x) { ; Check pow(2.0 ** n, x) -> exp2(n * x). define float @test_simplify3(float %x) { -; ANY-LABEL: @test_simplify3( -; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[X:%.*]]) [[NUW_RO:#[0-9]+]] +; CHECK-LABEL: @test_simplify3( +; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[X:%.*]]) ; ANY-NEXT: ret float [[EXP2F]] -; -; CHECK-WIN-LABEL: @test_simplify3( -; CHECK-WIN-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) -; CHECK-WIN-NEXT: ret float [[POW]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[POW:%.*]] = call float @powf(float 2.000000e+00, float [[X:%.*]]) +; VC64-NEXT: ret float [[POW]] +; VC83-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[X:%.*]]) +; VC83-NEXT: ret float [[EXP2F]] ; %retval = call float @powf(float 2.0, float %x) ret float %retval } define double @test_simplify3n(double %x) { -; ANY-LABEL: @test_simplify3n( +; CHECK-LABEL: @test_simplify3n( ; ANY-NEXT: [[MUL:%.*]] = fmul double [[X:%.*]], -2.000000e+00 -; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[MUL]]) [[NUW_RO]] +; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[MUL]]) ; ANY-NEXT: ret double [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify3n( -; CHECK-WIN-NEXT: [[POW:%.*]] = call double @pow(double 2.500000e-01, double [[X:%.*]]) -; CHECK-WIN-NEXT: ret double [[POW]] +; VC19-NEXT: [[MUL:%.*]] = fmul double [[X:%.*]], -2.000000e+00 +; VC19-NEXT: [[EXP2:%.*]] = call double @exp2(double [[MUL]]) +; VC19-NEXT: ret double [[EXP2]] +; VC32-NEXT: [[POW:%.*]] = call double @pow(double 2.500000e-01, double [[X:%.*]]) +; VC32-NEXT: ret double [[POW]] +; VC64-NEXT: [[POW:%.*]] = call double @pow(double 2.500000e-01, double [[X:%.*]]) +; VC64-NEXT: ret double [[POW]] ; %retval = call double @pow(double 0.25, double %x) ret double %retval } define <2 x float> @test_simplify3v(<2 x float> %x) { -; ANY-LABEL: @test_simplify3v( +; CHECK-LABEL: @test_simplify3v( ; ANY-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[X:%.*]]) ; ANY-NEXT: ret <2 x float> [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify3v( -; CHECK-WIN-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) -; CHECK-WIN-NEXT: ret <2 x float> [[POW]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> %x) ret <2 x float> %retval } define <2 x double> @test_simplify3vn(<2 x double> %x) { -; ANY-LABEL: @test_simplify3vn( +; CHECK-LABEL: @test_simplify3vn( ; ANY-NEXT: [[MUL:%.*]] = fmul <2 x double> [[X:%.*]], ; ANY-NEXT: [[EXP2:%.*]] = call <2 x double> @llvm.exp2.v2f64(<2 x double> [[MUL]]) ; ANY-NEXT: ret <2 x double> [[EXP2]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval } define double @test_simplify4(double %x) { -; ANY-LABEL: @test_simplify4( -; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[X:%.*]]) [[NUW_RO]] +; CHECK-LABEL: @test_simplify4( +; ANY-NEXT: [[EXP2:%.*]] = call double @exp2(double [[X:%.*]]) ; ANY-NEXT: ret double [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify4( -; CHECK-WIN-NEXT: [[POW:%.*]] = call double @pow(double 2.000000e+00, double [[X:%.*]]) -; CHECK-WIN-NEXT: ret double [[POW]] +; VC19-NEXT: [[EXP2:%.*]] = call double @exp2(double [[X:%.*]]) +; VC19-NEXT: ret double [[EXP2]] +; VC32-NEXT: [[POW:%.*]] = call double @pow(double 2.000000e+00, double [[X:%.*]]) +; VC32-NEXT: ret double [[POW]] +; VC64-NEXT: [[POW:%.*]] = call double @pow(double 2.000000e+00, double [[X:%.*]]) +; VC64-NEXT: ret double [[POW]] ; %retval = call double @pow(double 2.0, double %x) ret double %retval } define float @test_simplify4n(float %x) { -; ANY-LABEL: @test_simplify4n( +; CHECK-LABEL: @test_simplify4n( ; ANY-NEXT: [[MUL:%.*]] = fmul float [[X:%.*]], 3.000000e+00 -; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[MUL]]) [[NUW_RO]] +; ANY-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[MUL]]) ; ANY-NEXT: ret float [[EXP2F]] -; -; CHECK-WIN-LABEL: @test_simplify4n( -; CHECK-WIN-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) -; CHECK-WIN-NEXT: ret float [[POW]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[POW:%.*]] = call float @powf(float 8.000000e+00, float [[X:%.*]]) +; VC64-NEXT: ret float [[POW]] +; VC83-NEXT: [[MUL:%.*]] = fmul float [[X:%.*]], 3.000000e+00 +; VC83-NEXT: [[EXP2F:%.*]] = call float @exp2f(float [[MUL]]) +; VC83-NEXT: ret float [[EXP2F]] ; %retval = call float @powf(float 8.0, float %x) ret float %retval } define <2 x double> @test_simplify4v(<2 x double> %x) { -; ANY-LABEL: @test_simplify4v( +; CHECK-LABEL: @test_simplify4v( ; ANY-NEXT: [[EXP2:%.*]] = call <2 x double> @llvm.exp2.v2f64(<2 x double> [[X:%.*]]) ; ANY-NEXT: ret <2 x double> [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify4v( -; CHECK-WIN-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) -; CHECK-WIN-NEXT: ret <2 x double> [[POW]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> [[X:%.*]]) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> , <2 x double> %x) ret <2 x double> %retval } define <2 x float> @test_simplify4vn(<2 x float> %x) { -; ANY-LABEL: @test_simplify4vn( +; CHECK-LABEL: @test_simplify4vn( ; ANY-NEXT: [[MUL:%.*]] = fsub <2 x float> , [[X:%.*]] ; ANY-NEXT: [[EXP2:%.*]] = call <2 x float> @llvm.exp2.v2f32(<2 x float> [[MUL]]) ; ANY-NEXT: ret <2 x float> [[EXP2]] -; -; CHECK-WIN-LABEL: @test_simplify4vn( -; CHECK-WIN-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) -; CHECK-WIN-NEXT: ret <2 x float> [[POW]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> [[X:%.*]]) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> , <2 x float> %x) ret <2 x float> %retval @@ -163,32 +183,42 @@ define <2 x float> @test_simplify4vn(<2 x float> %x) { ; Check pow(x, 0.0) -> 1.0. define float @test_simplify5(float %x) { -; ANY-LABEL: @test_simplify5( +; CHECK-LABEL: @test_simplify5( ; ANY-NEXT: ret float 1.000000e+00 +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 0.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 0.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: ret float 1.000000e+00 +; VC83-NEXT: ret float 1.000000e+00 ; %retval = call float @powf(float %x, float 0.0) ret float %retval } define <2 x float> @test_simplify5v(<2 x float> %x) { -; ANY-LABEL: @test_simplify5v( +; CHECK-LABEL: @test_simplify5v( ; ANY-NEXT: ret <2 x float> +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> zeroinitializer) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %retval } define double @test_simplify6(double %x) { -; ANY-LABEL: @test_simplify6( -; ANY-NEXT: ret double 1.000000e+00 +; CHECK-LABEL: @test_simplify6( +; CHECK-NEXT: ret double 1.000000e+00 ; %retval = call double @pow(double %x, double 0.0) ret double %retval } define <2 x double> @test_simplify6v(<2 x double> %x) { -; ANY-LABEL: @test_simplify6v( +; CHECK-LABEL: @test_simplify6v( ; ANY-NEXT: ret <2 x double> +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> zeroinitializer) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %retval @@ -197,24 +227,38 @@ define <2 x double> @test_simplify6v(<2 x double> %x) { ; Check pow(x, 0.5) -> fabs(sqrt(x)), where x != -infinity. define float @test_simplify7(float %x) { -; ANY-LABEL: @test_simplify7( -; ANY-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) [[NUW_RO]] +; CHECK-LABEL: @test_simplify7( +; ANY-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) ; ANY-NEXT: [[ABS:%.*]] = call float @llvm.fabs.f32(float [[SQRTF]]) ; ANY-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X]], 0xFFF0000000000000 ; ANY-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], float 0x7FF0000000000000, float [[ABS]] ; ANY-NEXT: ret float [[TMP1]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 5.000000e-01) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 5.000000e-01) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) +; VC64-NEXT: [[ABS:%.*]] = call float @llvm.fabs.f32(float [[SQRTF]]) +; VC64-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X]], 0xFFF0000000000000 +; VC64-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], float 0x7FF0000000000000, float [[ABS]] +; VC64-NEXT: ret float [[TMP1]] +; VC83-NEXT: [[SQRTF:%.*]] = call float @sqrtf(float [[X:%.*]]) +; VC83-NEXT: [[ABS:%.*]] = call float @llvm.fabs.f32(float [[SQRTF]]) +; VC83-NEXT: [[ISINF:%.*]] = fcmp oeq float [[X]], 0xFFF0000000000000 +; VC83-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], float 0x7FF0000000000000, float [[ABS]] +; VC83-NEXT: ret float [[TMP1]] ; %retval = call float @powf(float %x, float 0.5) ret float %retval } define double @test_simplify8(double %x) { -; ANY-LABEL: @test_simplify8( -; ANY-NEXT: [[SQRT:%.*]] = call double @sqrt(double [[X:%.*]]) [[NUW_RO]] -; ANY-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) -; ANY-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 -; ANY-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] -; ANY-NEXT: ret double [[TMP1]] +; CHECK-LABEL: @test_simplify8( +; CHECK-NEXT: [[SQRT:%.*]] = call double @sqrt(double [[X:%.*]]) +; CHECK-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) +; CHECK-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] +; CHECK-NEXT: ret double [[TMP1]] ; %retval = call double @pow(double %x, double 0.5) ret double %retval @@ -223,16 +267,22 @@ define double @test_simplify8(double %x) { ; Check pow(-infinity, 0.5) -> +infinity. define float @test_simplify9(float %x) { -; ANY-LABEL: @test_simplify9( +; CHECK-LABEL: @test_simplify9( ; ANY-NEXT: ret float 0x7FF0000000000000 +; VC32-NEXT: [[POW:%.*]] = call float @powf(float 0xFFF0000000000000, float 5.000000e-01) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float 0xFFF0000000000000, float 5.000000e-01) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: ret float 0x7FF0000000000000 +; VC83-NEXT: ret float 0x7FF0000000000000 ; %retval = call float @powf(float 0xFFF0000000000000, float 0.5) ret float %retval } define double @test_simplify10(double %x) { -; ANY-LABEL: @test_simplify10( -; ANY-NEXT: ret double 0x7FF0000000000000 +; CHECK-LABEL: @test_simplify10( +; CHECK-NEXT: ret double 0x7FF0000000000000 ; %retval = call double @pow(double 0xFFF0000000000000, double 0.5) ret double %retval @@ -241,32 +291,42 @@ define double @test_simplify10(double %x) { ; Check pow(x, 1.0) -> x. define float @test_simplify11(float %x) { -; ANY-LABEL: @test_simplify11( +; CHECK-LABEL: @test_simplify11( ; ANY-NEXT: ret float [[X:%.*]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 1.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 1.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: ret float [[X:%.*]] +; VC83-NEXT: ret float [[X:%.*]] ; %retval = call float @powf(float %x, float 1.0) ret float %retval } define <2 x float> @test_simplify11v(<2 x float> %x) { -; ANY-LABEL: @test_simplify11v( +; CHECK-LABEL: @test_simplify11v( ; ANY-NEXT: ret <2 x float> [[X:%.*]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %retval = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %retval } define double @test_simplify12(double %x) { -; ANY-LABEL: @test_simplify12( -; ANY-NEXT: ret double [[X:%.*]] +; CHECK-LABEL: @test_simplify12( +; CHECK-NEXT: ret double [[X:%.*]] ; %retval = call double @pow(double %x, double 1.0) ret double %retval } define <2 x double> @test_simplify12v(<2 x double> %x) { -; ANY-LABEL: @test_simplify12v( +; CHECK-LABEL: @test_simplify12v( ; ANY-NEXT: ret <2 x double> [[X:%.*]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %retval = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %retval @@ -275,36 +335,48 @@ define <2 x double> @test_simplify12v(<2 x double> %x) { ; Check pow(x, 2.0) -> x*x. define float @pow2_strict(float %x) { -; ANY-LABEL: @pow2_strict( +; CHECK-LABEL: @pow2_strict( ; ANY-NEXT: [[SQUARE:%.*]] = fmul float [[X:%.*]], [[X]] ; ANY-NEXT: ret float [[SQUARE]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 2.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float 2.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[SQUARE:%.*]] = fmul float [[X:%.*]], [[X]] +; VC64-NEXT: ret float [[SQUARE]] +; VC83-NEXT: [[SQUARE:%.*]] = fmul float [[X:%.*]], [[X]] +; VC83-NEXT: ret float [[SQUARE]] ; %r = call float @powf(float %x, float 2.0) ret float %r } define <2 x float> @pow2_strictv(<2 x float> %x) { -; ANY-LABEL: @pow2_strictv( +; CHECK-LABEL: @pow2_strictv( ; ANY-NEXT: [[SQUARE:%.*]] = fmul <2 x float> [[X:%.*]], [[X]] ; ANY-NEXT: ret <2 x float> [[SQUARE]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %r = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %r } define double @pow2_double_strict(double %x) { -; ANY-LABEL: @pow2_double_strict( -; ANY-NEXT: [[SQUARE:%.*]] = fmul double [[X:%.*]], [[X]] -; ANY-NEXT: ret double [[SQUARE]] +; CHECK-LABEL: @pow2_double_strict( +; CHECK-NEXT: [[SQUARE:%.*]] = fmul double [[X:%.*]], [[X]] +; CHECK-NEXT: ret double [[SQUARE]] ; %r = call double @pow(double %x, double 2.0) ret double %r } define <2 x double> @pow2_double_strictv(<2 x double> %x) { -; ANY-LABEL: @pow2_double_strictv( +; CHECK-LABEL: @pow2_double_strictv( ; ANY-NEXT: [[SQUARE:%.*]] = fmul <2 x double> [[X:%.*]], [[X]] ; ANY-NEXT: ret <2 x double> [[SQUARE]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %r = call <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %r @@ -313,9 +385,17 @@ define <2 x double> @pow2_double_strictv(<2 x double> %x) { ; Don't drop the FMF - PR35601 ( https://bugs.llvm.org/show_bug.cgi?id=35601 ) define float @pow2_fast(float %x) { -; ANY-LABEL: @pow2_fast( +; CHECK-LABEL: @pow2_fast( ; ANY-NEXT: [[SQUARE:%.*]] = fmul fast float [[X:%.*]], [[X]] ; ANY-NEXT: ret float [[SQUARE]] +; VC32-NEXT: [[POW:%.*]] = call fast float @powf(float [[X:%.*]], float 2.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call fast float @powf(float [[X:%.*]], float 2.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[SQUARE:%.*]] = fmul fast float [[X:%.*]], [[X]] +; VC64-NEXT: ret float [[SQUARE]] +; VC83-NEXT: [[SQUARE:%.*]] = fmul fast float [[X:%.*]], [[X]] +; VC83-NEXT: ret float [[SQUARE]] ; %r = call fast float @powf(float %x, float 2.0) ret float %r @@ -324,48 +404,60 @@ define float @pow2_fast(float %x) { ; Check pow(x, -1.0) -> 1.0/x. define float @pow_neg1_strict(float %x) { -; ANY-LABEL: @pow_neg1_strict( +; CHECK-LABEL: @pow_neg1_strict( ; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv float 1.000000e+00, [[X:%.*]] ; ANY-NEXT: ret float [[RECIPROCAL]] +; VC32-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float -1.000000e+00) +; VC32-NEXT: ret float [[POW]] +; VC51-NEXT: [[POW:%.*]] = call float @powf(float [[X:%.*]], float -1.000000e+00) +; VC51-NEXT: ret float [[POW]] +; VC64-NEXT: [[RECIPROCAL:%.*]] = fdiv float 1.000000e+00, [[X:%.*]] +; VC64-NEXT: ret float [[RECIPROCAL]] +; VC83-NEXT: [[RECIPROCAL:%.*]] = fdiv float 1.000000e+00, [[X:%.*]] +; VC83-NEXT: ret float [[RECIPROCAL]] ; %r = call float @powf(float %x, float -1.0) ret float %r } define <2 x float> @pow_neg1_strictv(<2 x float> %x) { -; ANY-LABEL: @pow_neg1_strictv( +; CHECK-LABEL: @pow_neg1_strictv( ; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv <2 x float> , [[X:%.*]] ; ANY-NEXT: ret <2 x float> [[RECIPROCAL]] +; MSVC-NEXT: [[POW:%.*]] = call <2 x float> @llvm.pow.v2f32(<2 x float> [[X:%.*]], <2 x float> ) +; MSVC-NEXT: ret <2 x float> [[POW]] ; %r = call <2 x float> @llvm.pow.v2f32(<2 x float> %x, <2 x float> ) ret <2 x float> %r } define double @pow_neg1_double_fast(double %x) { -; ANY-LABEL: @pow_neg1_double_fast( -; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv fast double 1.000000e+00, [[X:%.*]] -; ANY-NEXT: ret double [[RECIPROCAL]] +; CHECK-LABEL: @pow_neg1_double_fast( +; CHECK-NEXT: [[RECIPROCAL:%.*]] = fdiv fast double 1.000000e+00, [[X:%.*]] +; CHECK-NEXT: ret double [[RECIPROCAL]] ; %r = call fast double @pow(double %x, double -1.0) ret double %r } define <2 x double> @pow_neg1_double_fastv(<2 x double> %x) { -; ANY-LABEL: @pow_neg1_double_fastv( +; CHECK-LABEL: @pow_neg1_double_fastv( ; ANY-NEXT: [[RECIPROCAL:%.*]] = fdiv fast <2 x double> , [[X:%.*]] ; ANY-NEXT: ret <2 x double> [[RECIPROCAL]] +; MSVC-NEXT: [[POW:%.*]] = call fast <2 x double> @llvm.pow.v2f64(<2 x double> [[X:%.*]], <2 x double> ) +; MSVC-NEXT: ret <2 x double> [[POW]] ; %r = call fast <2 x double> @llvm.pow.v2f64(<2 x double> %x, <2 x double> ) ret <2 x double> %r } define double @test_simplify17(double %x) { -; ANY-LABEL: @test_simplify17( -; ANY-NEXT: [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[X:%.*]]) -; ANY-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) -; ANY-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 -; ANY-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] -; ANY-NEXT: ret double [[TMP1]] +; CHECK-LABEL: @test_simplify17( +; CHECK-NEXT: [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[X:%.*]]) +; CHECK-NEXT: [[ABS:%.*]] = call double @llvm.fabs.f64(double [[SQRT]]) +; CHECK-NEXT: [[ISINF:%.*]] = fcmp oeq double [[X]], 0xFFF0000000000000 +; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[ISINF]], double 0x7FF0000000000000, double [[ABS]] +; CHECK-NEXT: ret double [[TMP1]] ; %retval = call double @llvm.pow.f64(double %x, double 0.5) ret double %retval @@ -374,29 +466,23 @@ define double @test_simplify17(double %x) { ; Check pow(10.0, x) -> __exp10(x) on OS X 10.9+ and iOS 7.0+. define float @test_simplify18(float %x) { -; CHECK-EXP10-LABEL: @test_simplify18( -; CHECK-EXP10-NEXT: [[__EXP10F:%.*]] = call float @__exp10f(float [[X:%.*]]) [[NUW_RO]] -; CHECK-EXP10-NEXT: ret float [[__EXP10F]] -; -; CHECK-NO-EXP10-LABEL: @test_simplify18( -; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call float @powf(float 1.000000e+01, float [[X:%.*]]) -; CHECK-NO-EXP10-NEXT: ret float [[RETVAL]] +; CHECK-LABEL: @test_simplify18( +; CHECK-EXP10-NEXT: [[__EXP10F:%.*]] = call float @__exp10f(float [[X:%.*]]) +; CHECK-EXP10-NEXT: ret float [[__EXP10F]] +; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call float @powf(float 1.000000e+01, float [[X:%.*]]) +; CHECK-NO-EXP10-NEXT: ret float [[RETVAL]] ; %retval = call float @powf(float 10.0, float %x) ret float %retval } define double @test_simplify19(double %x) { -; CHECK-EXP10-LABEL: @test_simplify19( -; CHECK-EXP10-NEXT: [[__EXP10:%.*]] = call double @__exp10(double [[X:%.*]]) [[NUW_RO]] -; CHECK-EXP10-NEXT: ret double [[__EXP10]] -; -; CHECK-NO-EXP10-LABEL: @test_simplify19( -; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call double @pow(double 1.000000e+01, double [[X:%.*]]) -; CHECK-NO-EXP10-NEXT: ret double [[RETVAL]] +; CHECK-LABEL: @test_simplify19( +; CHECK-EXP10-NEXT: [[__EXP10:%.*]] = call double @__exp10(double [[X:%.*]]) +; CHECK-EXP10-NEXT: ret double [[__EXP10]] +; CHECK-NO-EXP10-NEXT: [[RETVAL:%.*]] = call double @pow(double 1.000000e+01, double [[X:%.*]]) +; CHECK-NO-EXP10-NEXT: ret double [[RETVAL]] ; %retval = call double @pow(double 10.0, double %x) ret double %retval } - -; CHECK-EXP10: attributes [[NUW_RO]] = { nounwind readonly } diff --git a/llvm/test/Transforms/InstCombine/vec_shuffle.ll b/llvm/test/Transforms/InstCombine/vec_shuffle.ll index b82c8117eebf58..8f6818f4eb79d8 100644 --- a/llvm/test/Transforms/InstCombine/vec_shuffle.ll +++ b/llvm/test/Transforms/InstCombine/vec_shuffle.ll @@ -1114,3 +1114,18 @@ define <2 x float> @frem_splat_constant1(<2 x float> %x) { ret <2 x float> %r } +; Equivalent shuffle masks, but only one is a narrowing op. + +define <2 x i1> @PR40734(<1 x i1> %x, <4 x i1> %y) { +; CHECK-LABEL: @PR40734( +; CHECK-NEXT: [[WIDEN:%.*]] = shufflevector <1 x i1> zeroinitializer, <1 x i1> [[X:%.*]], <2 x i32> +; CHECK-NEXT: [[NARROW:%.*]] = shufflevector <4 x i1> [[Y:%.*]], <4 x i1> undef, <2 x i32> +; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[WIDEN]], [[NARROW]] +; CHECK-NEXT: ret <2 x i1> [[R]] +; + %widen = shufflevector <1 x i1> zeroinitializer, <1 x i1> %x, <2 x i32> + %narrow = shufflevector <4 x i1> %y, <4 x i1> undef, <2 x i32> + %r = and <2 x i1> %widen, %narrow + ret <2 x i1> %r +} + diff --git a/llvm/test/Transforms/InstCombine/win-math.ll b/llvm/test/Transforms/InstCombine/win-math.ll index 36947791393d9a..38ed949e949dce 100644 --- a/llvm/test/Transforms/InstCombine/win-math.ll +++ b/llvm/test/Transforms/InstCombine/win-math.ll @@ -1,17 +1,21 @@ -; RUN: opt -O2 -S -mtriple=i386-pc-win32 < %s | FileCheck %s -check-prefix=WIN32 -; RUN: opt -O2 -S -mtriple=x86_64-pc-win32 < %s | FileCheck %s -check-prefix=WIN64 -; RUN: opt -O2 -S -mtriple=i386-pc-mingw32 < %s | FileCheck %s -check-prefix=MINGW32 -; RUN: opt -O2 -S -mtriple=x86_64-pc-mingw32 < %s | FileCheck %s -check-prefix=MINGW64 +; RUN: opt < %s -O2 -S -mtriple=i386-pc-windows-msvc18 | FileCheck %s --check-prefixes=CHECK,MSVCXX,MSVC32 +; RUN: opt < %s -O2 -S -mtriple=i386-pc-windows-msvc | FileCheck %s --check-prefixes=CHECK,MSVC19,MSVC51 +; RUN: opt < %s -O2 -S -mtriple=x86_64-pc-windows-msvc17 | FileCheck %s --check-prefixes=CHECK,MSVCXX,MSVC64 +; RUN: opt < %s -O2 -S -mtriple=x86_64-pc-win32 | FileCheck %s --check-prefixes=CHECK,MSVC19,MSVC83 +; RUN: opt < %s -O2 -S -mtriple=i386-pc-mingw32 | FileCheck %s --check-prefixes=CHECK,MINGW32 +; RUN: opt < %s -O2 -S -mtriple=x86_64-pc-mingw32 | FileCheck %s --check-prefixes=CHECK,MINGW64 ; x86 win32 msvcrt does not provide entry points for single-precision libm. -; x86-64 win32 msvcrt does (except for fabsf) -; msvcrt does not provide C99 math, but mingw32 does. +; x86-64 win32 msvcrt does, but with exceptions +; msvcrt does not provide all of C99 math, but mingw32 does. declare double @acos(double %x) define float @float_acos(float %x) nounwind readnone { -; WIN32-LABEL: @float_acos( -; WIN32-NOT: float @acosf -; WIN32: double @acos +; CHECK-LABEL: @float_acos( +; MSVCXX-NOT: float @acosf +; MSVCXX: double @acos +; MSVC19-NOT: float @acosf +; MSVC19: double @acos %1 = fpext float %x to double %2 = call double @acos(double %1) %3 = fptrunc double %2 to float @@ -20,9 +24,11 @@ define float @float_acos(float %x) nounwind readnone { declare double @asin(double %x) define float @float_asin(float %x) nounwind readnone { -; WIN32-LABEL: @float_asin( -; WIN32-NOT: float @asinf -; WIN32: double @asin +; CHECK-LABEL: @float_asin( +; MSVCXX-NOT: float @asinf +; MSVCXX: double @asin +; MSVC19-NOT: float @asinf +; MSVC19: double @asin %1 = fpext float %x to double %2 = call double @asin(double %1) %3 = fptrunc double %2 to float @@ -31,9 +37,11 @@ define float @float_asin(float %x) nounwind readnone { declare double @atan(double %x) define float @float_atan(float %x) nounwind readnone { -; WIN32-LABEL: @float_atan( -; WIN32-NOT: float @atanf -; WIN32: double @atan +; CHECK-LABEL: @float_atan( +; MSVCXX-NOT: float @atanf +; MSVCXX: double @atan +; MSVC19-NOT: float @atanf +; MSVC19: double @atan %1 = fpext float %x to double %2 = call double @atan(double %1) %3 = fptrunc double %2 to float @@ -42,9 +50,11 @@ define float @float_atan(float %x) nounwind readnone { declare double @atan2(double %x, double %y) define float @float_atan2(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_atan2( -; WIN32-NOT: float @atan2f -; WIN32: double @atan2 +; CHECK-LABEL: @float_atan2( +; MSVCXX-NOT: float @atan2f +; MSVCXX: double @atan2 +; MSVC19-NOT: float @atan2f +; MSVC19: double @atan2 %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @atan2(double %1, double %2) @@ -54,18 +64,15 @@ define float @float_atan2(float %x, float %y) nounwind readnone { declare double @ceil(double %x) define float @float_ceil(float %x) nounwind readnone { -; WIN32-LABEL: @float_ceil( -; WIN32-NOT: float @ceilf -; WIN32: float @llvm.ceil.f32 -; WIN64-LABEL: @float_ceil( -; WIN64: float @llvm.ceil.f32 -; WIN64-NOT: double @ceil -; MINGW32-LABEL: @float_ceil( -; MINGW32: float @llvm.ceil.f32 +; CHECK-LABEL: @float_ceil( +; MSVCXX-NOT: float @ceilf +; MSVCXX: float @llvm.ceil.f32 +; MSVC19-NOT: double @ceil +; MSVC19: float @llvm.ceil.f32 ; MINGW32-NOT: double @ceil -; MINGW64-LABEL: @float_ceil( -; MINGW64: float @llvm.ceil.f32 +; MINGW32: float @llvm.ceil.f32 ; MINGW64-NOT: double @ceil +; MINGW64: float @llvm.ceil.f32 %1 = fpext float %x to double %2 = call double @ceil(double %1) %3 = fptrunc double %2 to float @@ -74,10 +81,11 @@ define float @float_ceil(float %x) nounwind readnone { declare double @_copysign(double %x) define float @float_copysign(float %x) nounwind readnone { -; WIN32-LABEL: @float_copysign( -; WIN32-NOT: float @copysignf -; WIN32-NOT: float @_copysignf -; WIN32: double @_copysign +; CHECK-LABEL: @float_copysign( +; MSVCXX-NOT: float @_copysignf +; MSVCXX: double @_copysign +; MSVC19-NOT: float @_copysignf +; MSVC19: double @_copysign %1 = fpext float %x to double %2 = call double @_copysign(double %1) %3 = fptrunc double %2 to float @@ -86,9 +94,11 @@ define float @float_copysign(float %x) nounwind readnone { declare double @cos(double %x) define float @float_cos(float %x) nounwind readnone { -; WIN32-LABEL: @float_cos( -; WIN32-NOT: float @cosf -; WIN32: double @cos +; CHECK-LABEL: @float_cos( +; MSVCXX-NOT: float @cosf +; MSVCXX: double @cos +; MSVC19-NOT: float @cosf +; MSVC19: double @cos %1 = fpext float %x to double %2 = call double @cos(double %1) %3 = fptrunc double %2 to float @@ -97,9 +107,11 @@ define float @float_cos(float %x) nounwind readnone { declare double @cosh(double %x) define float @float_cosh(float %x) nounwind readnone { -; WIN32-LABEL: @float_cosh( -; WIN32-NOT: float @coshf -; WIN32: double @cosh +; CHECK-LABEL: @float_cosh( +; MSVCXX-NOT: float @coshf +; MSVCXX: double @cosh +; MSVC19-NOT: float @coshf +; MSVC19: double @cosh %1 = fpext float %x to double %2 = call double @cosh(double %1) %3 = fptrunc double %2 to float @@ -108,9 +120,11 @@ define float @float_cosh(float %x) nounwind readnone { declare double @exp(double %x, double %y) define float @float_exp(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_exp( -; WIN32-NOT: float @expf -; WIN32: double @exp +; CHECK-LABEL: @float_exp( +; MSVCXX-NOT: float @expf +; MSVCXX: double @exp +; MSVC19-NOT: float @expf +; MSVC19: double @exp %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @exp(double %1, double %2) @@ -120,12 +134,11 @@ define float @float_exp(float %x, float %y) nounwind readnone { declare double @fabs(double %x, double %y) define float @float_fabs(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_fabs( -; WIN32-NOT: float @fabsf -; WIN32: double @fabs -; WIN64-LABEL: @float_fabs( -; WIN64-NOT: float @fabsf -; WIN64: double @fabs +; CHECK-LABEL: @float_fabs( +; MSVCXX-NOT: float @fabsf +; MSVCXX: double @fabs +; MSVC19-NOT: float @fabsf +; MSVC19: double @fabs %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @fabs(double %1, double %2) @@ -135,18 +148,15 @@ define float @float_fabs(float %x, float %y) nounwind readnone { declare double @floor(double %x) define float @float_floor(float %x) nounwind readnone { -; WIN32-LABEL: @float_floor( -; WIN32-NOT: float @floorf -; WIN32: float @llvm.floor.f32 -; WIN64-LABEL: @float_floor( -; WIN64: float @llvm.floor.f32 -; WIN64-NOT: double @floor -; MINGW32-LABEL: @float_floor( -; MINGW32: float @llvm.floor.f32 +; CHECK-LABEL: @float_floor( +; MSVCXX-NOT: float @floorf +; MSVCXX: float @llvm.floor.f32 +; MSVC19-NOT: double @floor +; MSVC19: float @llvm.floor.f32 ; MINGW32-NOT: double @floor -; MINGW64-LABEL: @float_floor( -; MINGW64: float @llvm.floor.f32 +; MINGW32: float @llvm.floor.f32 ; MINGW64-NOT: double @floor +; MINGW64: float @llvm.floor.f32 %1 = fpext float %x to double %2 = call double @floor(double %1) %3 = fptrunc double %2 to float @@ -155,9 +165,11 @@ define float @float_floor(float %x) nounwind readnone { declare double @fmod(double %x, double %y) define float @float_fmod(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_fmod( -; WIN32-NOT: float @fmodf -; WIN32: double @fmod +; MSVCXX-LABEL: @float_fmod( +; MSVCXX-NOT: float @fmodf +; MSVCXX: double @fmod +; MSVC19-NOT: float @fmodf +; MSVC19: double @fmod %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @fmod(double %1, double %2) @@ -167,20 +179,37 @@ define float @float_fmod(float %x, float %y) nounwind readnone { declare double @log(double %x) define float @float_log(float %x) nounwind readnone { -; WIN32-LABEL: @float_log( -; WIN32-NOT: float @logf -; WIN32: double @log +; CHECK-LABEL: @float_log( +; MSVCXX-NOT: float @logf +; MSVCXX: double @log +; MSVC19-NOT: float @logf +; MSVC19: double @log %1 = fpext float %x to double %2 = call double @log(double %1) %3 = fptrunc double %2 to float ret float %3 } +declare double @logb(double %x) +define float @float_logb(float %x) nounwind readnone { +; CHECK-LABEL: @float_logb( +; MSVCXX-NOT: float @logbf +; MSVCXX: double @logb +; MSVC19-NOT: float @logbf +; MSVC19: double @logb + %1 = fpext float %x to double + %2 = call double @logb(double %1) + %3 = fptrunc double %2 to float + ret float %3 +} + declare double @pow(double %x, double %y) define float @float_pow(float %x, float %y) nounwind readnone { -; WIN32-LABEL: @float_pow( -; WIN32-NOT: float @powf -; WIN32: double @pow +; CHECK-LABEL: @float_pow( +; MSVCXX-NOT: float @powf +; MSVCXX: double @pow +; MSVC19-NOT: float @powf +; MSVC19: double @pow %1 = fpext float %x to double %2 = fpext float %y to double %3 = call double @pow(double %1, double %2) @@ -190,9 +219,11 @@ define float @float_pow(float %x, float %y) nounwind readnone { declare double @sin(double %x) define float @float_sin(float %x) nounwind readnone { -; WIN32-LABEL: @float_sin( -; WIN32-NOT: float @sinf -; WIN32: double @sin +; CHECK-LABEL: @float_sin( +; MSVCXX-NOT: float @sinf +; MSVCXX: double @sin +; MSVC19-NOT: float @sinf +; MSVC19: double @sin %1 = fpext float %x to double %2 = call double @sin(double %1) %3 = fptrunc double %2 to float @@ -201,9 +232,11 @@ define float @float_sin(float %x) nounwind readnone { declare double @sinh(double %x) define float @float_sinh(float %x) nounwind readnone { -; WIN32-LABEL: @float_sinh( -; WIN32-NOT: float @sinhf -; WIN32: double @sinh +; CHECK-LABEL: @float_sinh( +; MSVCXX-NOT: float @sinhf +; MSVCXX: double @sinh +; MSVC19-NOT: float @sinhf +; MSVC19: double @sinh %1 = fpext float %x to double %2 = call double @sinh(double %1) %3 = fptrunc double %2 to float @@ -212,18 +245,19 @@ define float @float_sinh(float %x) nounwind readnone { declare double @sqrt(double %x) define float @float_sqrt(float %x) nounwind readnone { -; WIN32-LABEL: @float_sqrt( -; WIN32-NOT: float @sqrtf -; WIN32: double @sqrt -; WIN64-LABEL: @float_sqrt( -; WIN64: float @sqrtf -; WIN64-NOT: double @sqrt -; MINGW32-LABEL: @float_sqrt( -; MINGW32: float @sqrtf +; CHECK-LABEL: @float_sqrt( +; MSVC32-NOT: float @sqrtf +; MSVC32: double @sqrt +; MSVC51-NOT: float @sqrtf +; MSVC51: double @sqrt +; MSVC64-NOT: double @sqrt +; MSVC64: float @sqrtf +; MSVC83-NOT: double @sqrt +; MSVC83: float @sqrtf ; MINGW32-NOT: double @sqrt -; MINGW64-LABEL: @float_sqrt( -; MINGW64: float @sqrtf +; MINGW32: float @sqrtf ; MINGW64-NOT: double @sqrt +; MINGW64: float @sqrtf %1 = fpext float %x to double %2 = call double @sqrt(double %1) %3 = fptrunc double %2 to float @@ -232,9 +266,11 @@ define float @float_sqrt(float %x) nounwind readnone { declare double @tan(double %x) define float @float_tan(float %x) nounwind readnone { -; WIN32-LABEL: @float_tan( -; WIN32-NOT: float @tanf -; WIN32: double @tan +; CHECK-LABEL: @float_tan( +; MSVCXX-NOT: float @tanf +; MSVCXX: double @tan +; MSVC19-NOT: float @tanf +; MSVC19: double @tan %1 = fpext float %x to double %2 = call double @tan(double %1) %3 = fptrunc double %2 to float @@ -243,30 +279,29 @@ define float @float_tan(float %x) nounwind readnone { declare double @tanh(double %x) define float @float_tanh(float %x) nounwind readnone { -; WIN32-LABEL: @float_tanh( -; WIN32-NOT: float @tanhf -; WIN32: double @tanh +; CHECK-LABEL: @float_tanh( +; MSVCXX-NOT: float @tanhf +; MSVCXX: double @tanh +; MSVC19-NOT: float @tanhf +; MSVC19: double @tanh %1 = fpext float %x to double %2 = call double @tanh(double %1) %3 = fptrunc double %2 to float ret float %3 } -; win32 does not have round; mingw32 does +; win32 does not have roundf; mingw32 does declare double @round(double %x) define float @float_round(float %x) nounwind readnone { -; WIN32-LABEL: @float_round( -; WIN32-NOT: float @roundf -; WIN32: double @round -; WIN64-LABEL: @float_round( -; WIN64-NOT: float @roundf -; WIN64: double @round -; MINGW32-LABEL: @float_round( -; MINGW32: float @llvm.round.f32 +; CHECK-LABEL: @float_round( +; MSVCXX-NOT: double @roundf +; MSVCXX: double @round +; MSVC19-NOT: double @round +; MSVC19: float @llvm.round.f32 ; MINGW32-NOT: double @round -; MINGW64-LABEL: @float_round( -; MINGW64: float @llvm.round.f32 +; MINGW32: float @llvm.round.f32 ; MINGW64-NOT: double @round +; MINGW64: float @llvm.round.f32 %1 = fpext float %x to double %2 = call double @round(double %1) %3 = fptrunc double %2 to float @@ -275,26 +310,26 @@ define float @float_round(float %x) nounwind readnone { declare float @powf(float, float) -; win32 lacks sqrtf&fabsf, win64 lacks fabsf, but +; win32 lacks sqrtf & fabsf, win64 lacks fabsf, but ; calls to the intrinsics can be emitted instead. define float @float_powsqrt(float %x) nounwind readnone { -; WIN32-LABEL: @float_powsqrt( -; WIN32-NOT: float @sqrtf -; WIN32: float @powf - -; WIN64-LABEL: @float_powsqrt( -; WIN64: float @sqrtf -; WIN64: float @llvm.fabs.f32( -; WIN64-NOT: float @powf - -; MINGW32-LABEL: @float_powsqrt( +; CHECK-LABEL: @float_powsqrt( +; MSVC32-NOT: float @sqrtf +; MSVC32: float @powf +; MSVC51-NOT: float @sqrtf +; MSVC51: float @powf +; MSVC64-NOT: float @powf +; MSVC64: float @sqrtf +; MSVC64: float @llvm.fabs.f32( +; MSVC83-NOT: float @powf +; MSVC83: float @sqrtf +; MSVC83: float @llvm.fabs.f32( +; MINGW32-NOT: float @powf ; MINGW32: float @sqrtf ; MINGW32: float @llvm.fabs.f32 -; MINGW32-NOT: float @powf -; MINGW64-LABEL: @float_powsqrt( +; MINGW64-NOT: float @powf ; MINGW64: float @sqrtf ; MINGW64: float @llvm.fabs.f32( -; MINGW64-NOT: float @powf %1 = call float @powf(float %x, float 0.5) ret float %1 }