diff options
Diffstat (limited to 'clang')
156 files changed, 3027 insertions, 1836 deletions
diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst index 8a44db7..f33950b 100644 --- a/clang/docs/InternalsManual.rst +++ b/clang/docs/InternalsManual.rst @@ -312,7 +312,7 @@ Description: * number: A simple decimal number matches if the argument is the same as the number. Example: ``"%plural{1:mouse|:mice}0"`` * range: A range in square brackets matches if the argument is within the - range. Then range is inclusive on both ends. Example: + range. The range is inclusive on both ends. Example: ``"%plural{0:none|1:one|[2,5]:some|:many}0"`` * modulo: A modulo operator is followed by a number, and equals sign and either a number or a range. The tests are the same as for plain numbers @@ -341,7 +341,7 @@ Example: Class: Integers Description: - This is a formatter which represents the argument number in a human readable + This is a formatter which represents the argument number in a human-readable format: the value ``123`` stays ``123``, ``12345`` becomes ``12.34k``, ``6666666` becomes ``6.67M``, and so on for 'G' and 'T'. @@ -561,7 +561,7 @@ documentation for the ``-verify`` mode can be found at There are many other possible implementations of this interface, and this is why we prefer diagnostics to pass down rich structured information in -arguments. For example, an HTML output might want declaration names be +arguments. For example, an HTML output might want declaration names to be linkified to where they come from in the source. Another example is that a GUI might let you click on typedefs to expand them. This application would want to pass significantly more information about types through to the GUI than a @@ -846,7 +846,7 @@ Option Marshalling Infrastructure The option marshalling infrastructure automates the parsing of the Clang ``-cc1`` frontend command line arguments into ``CompilerInvocation`` and their generation from ``CompilerInvocation``. The system replaces lots of repetitive -C++ code with simple, declarative tablegen annotations and it's being used for +C++ code with simple, declarative tablegen annotations and is being used for the majority of the ``-cc1`` command line interface. This section provides an overview of the system. @@ -986,7 +986,7 @@ line. NegFlag<SetFalse, [], [], "Use the new pass manager in LLVM">, BothFlags<[], [ClangOption, CC1Option]>>; -With most such pair of flags, the ``-cc1`` frontend accepts only the flag that +With most such pairs of flags, the ``-cc1`` frontend accepts only the flag that changes the default key path value. The Clang driver is responsible for accepting both and either forwarding the changing flag or discarding the flag that would just set the key path to its default. @@ -1042,8 +1042,8 @@ and the result is assigned to the key path on success. The key path defaults to the value specified in ``MarshallingInfoEnum`` prefixed by the contents of ``NormalizedValuesScope`` and ``::``. This ensures correct reference to an enum case is formed even if the enum resides in different -namespace or is an enum class. If the value present on command line does not -match any of the comma-separated values from ``Values``, an error diagnostics is +namespace or is an enum class. If the value present on the command line does not +match any of the comma-separated values from ``Values``, an error diagnostic is issued. Otherwise, the corresponding element from ``NormalizedValues`` at the same index is assigned to the key path (also correctly scoped). The number of comma-separated string values and elements of the array within @@ -1111,7 +1111,7 @@ The Token class --------------- The ``Token`` class is used to represent a single lexed token. Tokens are -intended to be used by the lexer/preprocess and parser libraries, but are not +intended to be used by the lexer/preprocessor and parser libraries, but are not intended to live beyond them (for example, they should not live in the ASTs). Tokens most often live on the stack (or some other location that is efficient @@ -1253,7 +1253,7 @@ In order to do this, whenever the parser expects a ``tok::identifier`` or ``tok::coloncolon``, it should call the ``TryAnnotateTypeOrScopeToken`` or ``TryAnnotateCXXScopeToken`` methods to form the annotation token. These methods will maximally form the specified annotation tokens and replace the -current token with them, if applicable. If the current tokens is not valid for +current token with them, if applicable. If the current token is not valid for an annotation token, it will remain an identifier or "``::``" token. .. _Lexer: @@ -1276,7 +1276,7 @@ The lexer has a couple of interesting modal features: This mode is used for lexing within an "``#if 0``" block, for example. * The lexer can capture and return comments as tokens. This is required to support the ``-C`` preprocessor mode, which passes comments through, and is - used by the diagnostic checker to identifier expect-error annotations. + used by the diagnostic checker to identify expect-error annotations. * The lexer can be in ``ParsingFilename`` mode, which happens when preprocessing after reading a ``#include`` directive. This mode changes the parsing of "``<``" to return an "angled string" instead of a bunch of tokens @@ -1308,7 +1308,7 @@ The ``TokenLexer`` class ------------------------ The ``TokenLexer`` class is a token provider that returns tokens from a list of -tokens that came from somewhere else. It typically used for two things: 1) +tokens that came from somewhere else. It is typically used for two things: 1) returning tokens from a macro definition as it is being expanded 2) returning tokens from an arbitrary buffer of tokens. The later use is used by ``_Pragma`` and will most likely be used to handle unbounded look-ahead for the @@ -1509,7 +1509,7 @@ type checker must verify that the operand has a pointer type. It would not be correct to check that with "``isa<PointerType>(SubExpr->getType())``", because this predicate would fail if the subexpression had a typedef type. -The solution to this problem are a set of helper methods on ``Type``, used to +The solution to this problem is a set of helper methods on ``Type``, used to check their properties. In this case, it would be correct to use "``SubExpr->getType()->isPointerType()``" to do the check. This predicate will return true if the *canonical type is a pointer*, which is true any time the @@ -1632,7 +1632,7 @@ the names are inside the ``DeclarationName`` class). ``CXXLiteralOperatorName`` - The name is a C++11 user defined literal operator. User defined + The name is a C++11 user-defined literal operator. User-defined Literal operators are named according to the suffix they define, e.g., "``_foo``" for "``operator "" _foo``". Use ``N.getCXXLiteralIdentifier()`` to retrieve the corresponding @@ -2215,7 +2215,7 @@ Consequently, we must either set the virtual flag for the definition (but then we create a malformed AST which the parser would never create), or we import the whole redeclaration chain of the function. The most recent version of the ``ASTImporter`` uses the latter mechanism. We do import all function -declarations - regardless if they are definitions or prototypes - in the order +declarations - regardless of whether they are definitions or prototypes - in the order as they appear in the "from" context. .. One definition @@ -2338,7 +2338,7 @@ library receive an Error object, which they must check. During import of a specific declaration, it may happen that some AST nodes had already been created before we recognize an error. In this case, we signal back the error to the caller, but the "to" context remains polluted with those nodes -which had been created. Ideally, those nodes should not had been created, but +which had been created. Ideally, those nodes should not have been created, but that time we did not know about the error, the error happened later. Since the AST is immutable (most of the cases we can't remove existing nodes) we choose to mark these nodes as erroneous. @@ -2579,7 +2579,7 @@ that there are global declarations which collide with declarations from other translation units, but they are not referenced outside from their translation unit. These declarations should be in an unnamed namespace ideally. If we treat these collisions liberally then CTU analysis can find more results. Note, the -feature be able to choose between name conflict handling strategies is still an +feature to be able to choose between name conflict handling strategies is still an ongoing work. .. _CFG: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9d9a000..4a2edae 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -134,6 +134,11 @@ Bug Fixes in This Version ------------------------- - Fix a crash when marco name is empty in ``#pragma push_macro("")`` or ``#pragma pop_macro("")``. (#GH149762). +- `-Wunreachable-code`` now diagnoses tautological or contradictory + comparisons such as ``x != 0 || x != 1.0`` and ``x == 0 && x == 1.0`` on + targets that treat ``_Float16``/``__fp16`` as native scalar types. Previously + the warning was silently lost because the operands differed only by an implicit + cast chain. (#GH149967). Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/docs/ShadowCallStack.rst b/clang/docs/ShadowCallStack.rst index fc8bea8..9b104cc 100644 --- a/clang/docs/ShadowCallStack.rst +++ b/clang/docs/ShadowCallStack.rst @@ -61,7 +61,7 @@ The instrumentation makes use of the platform register ``x18`` on AArch64, ``x3`` (``gp``) on RISC-V with software shadow stack and ``ssp`` on RISC-V with hardware shadow stack, which needs `Zicfiss`_ and ``-fcf-protection=return``. Users can choose between the software and hardware based shadow stack -implementation on RISC-V backend by passing ``-fsanitize=shadowcallstack`` +implementation on RISC-V backend by passing ``-fsanitize=shadow-call-stack`` or ``Zicfiss`` with ``-fcf-protection=return``. For simplicity we will refer to this as the ``SCSReg``. On some platforms, ``SCSReg`` is reserved, and on others, it is designated as a scratch register. diff --git a/clang/docs/analyzer/user-docs/CrossTranslationUnit.rst b/clang/docs/analyzer/user-docs/CrossTranslationUnit.rst index 700dac0..a04b9f8 100644 --- a/clang/docs/analyzer/user-docs/CrossTranslationUnit.rst +++ b/clang/docs/analyzer/user-docs/CrossTranslationUnit.rst @@ -132,7 +132,7 @@ Once we have set up the `PATH` environment variable and we activated the python .. code-block:: bash - $ CodeChecker analyze --ctu compile_commands.json -o reports + $ CodeChecker analyze --ctu --ctu-ast-mode load-from-pch compile_commands.json -o reports $ ls -F compile_commands.json foo.cpp foo.cpp.ast main.cpp reports/ $ tree reports @@ -318,7 +318,7 @@ Once we have set up the `PATH` environment variable and we activated the python .. code-block:: bash - $ CodeChecker analyze --ctu --ctu-ast-loading-mode on-demand compile_commands.json -o reports + $ CodeChecker analyze --ctu compile_commands.json -o reports $ ls -F compile_commands.json foo.cpp main.cpp reports/ $ tree reports diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 0273109..3b98274a 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1818,7 +1818,7 @@ public: NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u}); } else { NumNegativeBits = - std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits()); + std::max(NumNegativeBits, InitVal.getSignificantBits()); } MembersRepresentableByInt &= isRepresentableIntegerValue(InitVal, IntTy); diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 708c6e2..6c124aa 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -16,7 +16,6 @@ #include "clang/AST/APNumericStorage.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTVector.h" -#include "clang/AST/Attr.h" #include "clang/AST/ComputeDependence.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclAccessPair.h" @@ -58,6 +57,7 @@ namespace clang { class StringLiteral; class TargetInfo; class ValueDecl; + class WarnUnusedResultAttr; /// A simple array of base specifiers. typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def b/clang/include/clang/Basic/BuiltinsAMDGPU.def index b8ece53..172ac46 100644 --- a/clang/include/clang/Basic/BuiltinsAMDGPU.def +++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def @@ -697,10 +697,15 @@ TARGET_BUILTIN(__builtin_amdgcn_exp2_bf16, "yy", "nc", "bf16-trans-insts") TARGET_BUILTIN(__builtin_amdgcn_sin_bf16, "yy", "nc", "bf16-trans-insts") TARGET_BUILTIN(__builtin_amdgcn_cos_bf16, "yy", "nc", "bf16-trans-insts") +TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_pk_bf16_f32, "V2yffi", "nc", "bf16-cvt-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_f16_fp8, "hiIi", "nc", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_f16_bf8, "hiIi", "nc", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_f16_fp8, "V2hs", "nc", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_f16_bf8, "V2hs", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_fp8_f16, "sV2h", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_bf8_f16, "sV2h", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_fp8_f16, "ihiUiIi", "nc", "gfx1250-insts") +TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_bf8_f16, "ihiUiIi", "nc", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_sat_pk4_i4_i8, "UsUi", "nc", "gfx1250-insts") TARGET_BUILTIN(__builtin_amdgcn_sat_pk4_u4_u8, "UsUi", "nc", "gfx1250-insts") diff --git a/clang/include/clang/Basic/CustomizableOptional.h b/clang/include/clang/Basic/CustomizableOptional.h index 2d6ae6a..8559eaa 100644 --- a/clang/include/clang/Basic/CustomizableOptional.h +++ b/clang/include/clang/Basic/CustomizableOptional.h @@ -70,15 +70,6 @@ public: void reset() { Storage.reset(); } - LLVM_DEPRECATED("Use &*X instead.", "&*X") - constexpr const T *getPointer() const { return &Storage.value(); } - LLVM_DEPRECATED("Use &*X instead.", "&*X") - T *getPointer() { return &Storage.value(); } - LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X") - constexpr const T &value() const & { return Storage.value(); } - LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X") - T &value() & { return Storage.value(); } - constexpr explicit operator bool() const { return has_value(); } constexpr bool has_value() const { return Storage.has_value(); } constexpr const T *operator->() const { return &Storage.value(); } @@ -90,8 +81,6 @@ public: return has_value() ? operator*() : std::forward<U>(alt); } - LLVM_DEPRECATED("std::optional::value is throwing. Use *X instead", "*X") - T &&value() && { return std::move(Storage.value()); } T &&operator*() && { return std::move(Storage.value()); } template <typename U> T value_or(U &&alt) && { diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a8a6e88..27d2152 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1812,10 +1812,7 @@ def note_unsatisfied_trait_reason "%DeletedAssign{has a deleted %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}|" - "%FunctionType{is a function type}|" - "%CVVoidType{is a cv void type}|" - "%IncompleteArrayType{is an incomplete array type}" + "%sub{select_special_member_kind}1}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index b6dd4ee..b26e558 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -447,6 +447,10 @@ public: return create<cir::CmpOp>(loc, getBoolTy(), kind, lhs, rhs); } + mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand) { + return createCompare(loc, cir::CmpOpKind::ne, operand, operand); + } + mlir::Value createShift(mlir::Location loc, mlir::Value lhs, mlir::Value rhs, bool isShiftLeft) { return create<cir::ShiftOp>(loc, lhs.getType(), lhs, rhs, isShiftLeft); diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 8e16bf8..5ef5b60 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2823,6 +2823,53 @@ def CIR_ComplexSubOp : CIR_Op<"complex.sub", [ }]; } +//===----------------------------------------------------------------------===// +// ComplexMulOp +//===----------------------------------------------------------------------===// + +def CIR_ComplexRangeKind : CIR_I32EnumAttr< + "ComplexRangeKind", "complex multiplication and division implementation", [ + I32EnumAttrCase<"Full", 0, "full">, + I32EnumAttrCase<"Improved", 1, "improved">, + I32EnumAttrCase<"Promoted", 2, "promoted">, + I32EnumAttrCase<"Basic", 3, "basic">, +]>; + +def CIR_ComplexMulOp : CIR_Op<"complex.mul", [ + Pure, SameOperandsAndResultType +]> { + let summary = "Complex multiplication"; + let description = [{ + The `cir.complex.mul` operation takes two complex numbers and returns + their product. + + Range is used to select the implementation used when the operation + is lowered to the LLVM dialect. For multiplication, 'improved', + 'promoted', and 'basic' are all handled equivalently, producing the + algebraic formula with no special handling for NaN value. If 'full' is + used, a runtime-library function is called if one of the intermediate + calculations produced a NaN value. + + Example: + + ```mlir + %2 = cir.complex.mul %0, %1 range(basic) : !cir.complex<!cir.float> + %2 = cir.complex.mul %0, %1 range(full) : !cir.complex<!cir.float> + ``` + }]; + + let arguments = (ins + CIR_ComplexType:$lhs, + CIR_ComplexType:$rhs, + CIR_ComplexRangeKind:$range + ); + + let results = (outs CIR_ComplexType:$result); + + let assemblyFormat = [{ + $lhs `,` $rhs `range` `(` $range `)` `:` qualified(type($result)) attr-dict + }]; +} //===----------------------------------------------------------------------===// // Bit Manipulation Operations diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index ad3329d..adc7b5f 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -217,6 +217,7 @@ struct MissingFeatures { static bool intrinsics() { return false; } static bool isMemcpyEquivalentSpecialMember() { return false; } static bool isTrivialCtorOrDtor() { return false; } + static bool lambdaCaptures() { return false; } static bool lambdaFieldToName() { return false; } static bool loopInfoStack() { return false; } static bool lowerAggregateLoadStore() { return false; } diff --git a/clang/include/clang/Driver/CudaInstallationDetector.h b/clang/include/clang/Driver/CudaInstallationDetector.h new file mode 100644 index 0000000..0fecbfe --- /dev/null +++ b/clang/include/clang/Driver/CudaInstallationDetector.h @@ -0,0 +1,76 @@ +//===-- CudaInstallationDetector.h - Cuda Instalation Detector --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DRIVER_CUDAINSTALLATIONDETECTOR_H +#define LLVM_CLANG_DRIVER_CUDAINSTALLATIONDETECTOR_H + +#include "clang/Basic/Cuda.h" +#include "clang/Driver/Driver.h" +#include <bitset> + +namespace clang { +namespace driver { + +/// A class to find a viable CUDA installation +class CudaInstallationDetector { +private: + const Driver &D; + bool IsValid = false; + CudaVersion Version = CudaVersion::UNKNOWN; + std::string InstallPath; + std::string BinPath; + std::string LibDevicePath; + std::string IncludePath; + llvm::StringMap<std::string> LibDeviceMap; + + // CUDA architectures for which we have raised an error in + // CheckCudaVersionSupportsArch. + mutable std::bitset<(int)OffloadArch::LAST> ArchsWithBadVersion; + +public: + CudaInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, + const llvm::opt::ArgList &Args); + + void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; + + /// Emit an error if Version does not support the given Arch. + /// + /// If either Version or Arch is unknown, does not emit an error. Emits at + /// most one error per Arch. + void CheckCudaVersionSupportsArch(OffloadArch Arch) const; + + /// Check whether we detected a valid Cuda install. + bool isValid() const { return IsValid; } + /// Print information about the detected CUDA installation. + void print(raw_ostream &OS) const; + + /// Get the detected Cuda install's version. + CudaVersion version() const { + return Version == CudaVersion::NEW ? CudaVersion::PARTIALLY_SUPPORTED + : Version; + } + /// Get the detected Cuda installation path. + StringRef getInstallPath() const { return InstallPath; } + /// Get the detected path to Cuda's bin directory. + StringRef getBinPath() const { return BinPath; } + /// Get the detected Cuda Include path. + StringRef getIncludePath() const { return IncludePath; } + /// Get the detected Cuda device library path. + StringRef getLibDevicePath() const { return LibDevicePath; } + /// Get libdevice file for given architecture + std::string getLibDeviceFile(StringRef Gpu) const { + return LibDeviceMap.lookup(Gpu); + } + void WarnIfUnsupportedVersion() const; +}; + +} // namespace driver +} // namespace clang + +#endif // LLVM_CLANG_DRIVER_CUDAINSTALLATIONDETECTOR_H diff --git a/clang/lib/Driver/ToolChains/LazyDetector.h b/clang/include/clang/Driver/LazyDetector.h index 813d00a..5bd1d01 100644 --- a/clang/lib/Driver/ToolChains/LazyDetector.h +++ b/clang/include/clang/Driver/LazyDetector.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LAZYDETECTOR_H -#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LAZYDETECTOR_H +#ifndef LLVM_CLANG_DRIVER_LAZYDETECTOR_H +#define LLVM_CLANG_DRIVER_LAZYDETECTOR_H #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" @@ -42,4 +42,4 @@ public: } // end namespace clang -#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LAZYDETECTOR_H +#endif // LLVM_CLANG_DRIVER_LAZYDETECTOR_H diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index eb53821..3c04aeb 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5312,6 +5312,8 @@ def mextended_const : Flag<["-"], "mextended-const">, Group<m_wasm_Features_Grou def mno_extended_const : Flag<["-"], "mno-extended-const">, Group<m_wasm_Features_Group>; def mfp16 : Flag<["-"], "mfp16">, Group<m_wasm_Features_Group>; def mno_fp16 : Flag<["-"], "mno-fp16">, Group<m_wasm_Features_Group>; +def mgc : Flag<["-"], "mgc">, Group<m_wasm_Features_Group>; +def mno_gc : Flag<["-"], "mno-gc">, Group<m_wasm_Features_Group>; def mmultimemory : Flag<["-"], "mmultimemory">, Group<m_wasm_Features_Group>; def mno_multimemory : Flag<["-"], "mno-multimemory">, Group<m_wasm_Features_Group>; def mmultivalue : Flag<["-"], "mmultivalue">, Group<m_wasm_Features_Group>; diff --git a/clang/lib/Driver/ToolChains/ROCm.h b/clang/include/clang/Driver/RocmInstallationDetector.h index ebd5443..3a325a6 100644 --- a/clang/lib/Driver/ToolChains/ROCm.h +++ b/clang/include/clang/Driver/RocmInstallationDetector.h @@ -1,4 +1,4 @@ -//===--- ROCm.h - ROCm installation detector --------------------*- C++ -*-===// +//===-- RocmInstallationDetector.h - ROCm Instalation Detector --*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,21 +6,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H -#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H +#ifndef LLVM_CLANG_DRIVER_ROCMINSTALLATIONDETECTOR_H +#define LLVM_CLANG_DRIVER_ROCMINSTALLATIONDETECTOR_H -#include "clang/Basic/Cuda.h" -#include "clang/Basic/LLVM.h" -#include "clang/Driver/CommonArgs.h" #include "clang/Driver/Driver.h" -#include "clang/Driver/Options.h" -#include "clang/Driver/SanitizerArgs.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/Option/ArgList.h" -#include "llvm/Support/VersionTuple.h" -#include "llvm/TargetParser/TargetParser.h" -#include "llvm/TargetParser/Triple.h" namespace clang { namespace driver { @@ -308,7 +297,7 @@ public: StringRef getHIPVersion() const { return DetectedVersion; } }; -} // end namespace driver -} // end namespace clang +} // namespace driver +} // namespace clang -#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ROCM_H +#endif // LLVM_CLANG_DRIVER_ROCMINSTALLATIONDETECTOR_H diff --git a/clang/include/clang/Driver/SyclInstallationDetector.h b/clang/include/clang/Driver/SyclInstallationDetector.h new file mode 100644 index 0000000..6925ec2 --- /dev/null +++ b/clang/include/clang/Driver/SyclInstallationDetector.h @@ -0,0 +1,29 @@ +//===-- SyclInstallationDetector.h - SYCL Instalation Detector --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DRIVER_SYCLINSTALLATIONDETECTOR_H +#define LLVM_CLANG_DRIVER_SYCLINSTALLATIONDETECTOR_H + +#include "clang/Driver/Driver.h" + +namespace clang { +namespace driver { + +class SYCLInstallationDetector { +public: + SYCLInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, + const llvm::opt::ArgList &Args); + + void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; +}; + +} // namespace driver +} // namespace clang + +#endif // LLVM_CLANG_DRIVER_SYCLINSTALLATIONDETECTOR_H diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 2408367..02dd16c 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -420,6 +420,8 @@ public: /// @{ llvm::vfs::FileSystem &getVirtualFileSystem() const; + llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> + getVirtualFileSystemPtr() const; /// @} /// @name File Manager diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td index 6225977..36196cd 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -233,15 +233,11 @@ def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">, HelpText<"Check for undefined results of binary operators">, Documentation<HasDocumentation>; -def StackAddrEscapeBase : Checker<"StackAddrEscapeBase">, - HelpText<"Generate information about stack address escapes.">, - Documentation<NotDocumented>, - Hidden; - -def StackAddrEscapeChecker : Checker<"StackAddressEscape">, - HelpText<"Check that addresses to stack memory do not escape the function">, - Dependencies<[StackAddrEscapeBase]>, - Documentation<HasDocumentation>; +def StackAddrEscapeChecker + : Checker<"StackAddressEscape">, + HelpText< + "Check that addresses to stack memory do not escape the function">, + Documentation<HasDocumentation>; def DynamicTypePropagation : Checker<"DynamicTypePropagation">, HelpText<"Generate dynamic type information">, @@ -295,10 +291,11 @@ def DynamicTypeChecker Dependencies<[DynamicTypePropagation]>, Documentation<HasDocumentation>; -def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">, - HelpText<"Check that addresses to stack memory do not escape the function">, - Dependencies<[StackAddrEscapeBase]>, - Documentation<HasDocumentation>; +def StackAddrAsyncEscapeChecker + : Checker<"StackAddressAsyncEscape">, + HelpText< + "Check that addresses to stack memory do not escape the function">, + Documentation<HasDocumentation>; def PthreadLockBase : Checker<"PthreadLockBase">, HelpText<"Helper registering multiple checks.">, @@ -1047,11 +1044,6 @@ def RetainCountBase : Checker<"RetainCountBase">, let ParentPackage = OSX in { -def NSOrCFErrorDerefChecker : Checker<"NSOrCFErrorDerefChecker">, - HelpText<"Implementation checker for NSErrorChecker and CFErrorChecker">, - Documentation<NotDocumented>, - Hidden; - def NumberObjectConversionChecker : Checker<"NumberObjectConversion">, HelpText<"Check for erroneous conversions of objects representing numbers " "into numbers">, @@ -1149,9 +1141,8 @@ def ObjCSuperCallChecker : Checker<"MissingSuperCall">, Documentation<NotDocumented>; def NSErrorChecker : Checker<"NSError">, - HelpText<"Check usage of NSError** parameters">, - Dependencies<[NSOrCFErrorDerefChecker]>, - Documentation<HasDocumentation>; + HelpText<"Check usage of NSError** parameters">, + Documentation<HasDocumentation>; def RetainCountChecker : Checker<"RetainCount">, HelpText<"Check for leaks and improper reference count management">, @@ -1253,9 +1244,8 @@ def CFRetainReleaseChecker : Checker<"CFRetainRelease">, Documentation<HasDocumentation>; def CFErrorChecker : Checker<"CFError">, - HelpText<"Check usage of CFErrorRef* parameters">, - Dependencies<[NSOrCFErrorDerefChecker]>, - Documentation<HasDocumentation>; + HelpText<"Check usage of CFErrorRef* parameters">, + Documentation<HasDocumentation>; } // end "osx.coreFoundation" diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index d0ddb2e..8b9e5e0 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -106,25 +106,14 @@ bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const { return true; } -/// Scope managing label targets. -template <class Emitter> class LabelScope { -public: - virtual ~LabelScope() {} - -protected: - LabelScope(Compiler<Emitter> *Ctx) : Ctx(Ctx) {} - /// Compiler instance. - Compiler<Emitter> *Ctx; -}; - /// Sets the context for break/continue statements. -template <class Emitter> class LoopScope final : public LabelScope<Emitter> { +template <class Emitter> class LoopScope final { public: using LabelTy = typename Compiler<Emitter>::LabelTy; using OptLabelTy = typename Compiler<Emitter>::OptLabelTy; LoopScope(Compiler<Emitter> *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel) - : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel), + : Ctx(Ctx), OldBreakLabel(Ctx->BreakLabel), OldContinueLabel(Ctx->ContinueLabel), OldBreakVarScope(Ctx->BreakVarScope), OldContinueVarScope(Ctx->ContinueVarScope) { @@ -142,6 +131,7 @@ public: } private: + Compiler<Emitter> *Ctx; OptLabelTy OldBreakLabel; OptLabelTy OldContinueLabel; VariableScope<Emitter> *OldBreakVarScope; @@ -149,7 +139,7 @@ private: }; // Sets the context for a switch scope, mapping labels. -template <class Emitter> class SwitchScope final : public LabelScope<Emitter> { +template <class Emitter> class SwitchScope final { public: using LabelTy = typename Compiler<Emitter>::LabelTy; using OptLabelTy = typename Compiler<Emitter>::OptLabelTy; @@ -157,7 +147,7 @@ public: SwitchScope(Compiler<Emitter> *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel, OptLabelTy DefaultLabel) - : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel), + : Ctx(Ctx), OldBreakLabel(Ctx->BreakLabel), OldDefaultLabel(this->Ctx->DefaultLabel), OldCaseLabels(std::move(this->Ctx->CaseLabels)), OldLabelVarScope(Ctx->BreakVarScope) { @@ -175,6 +165,7 @@ public: } private: + Compiler<Emitter> *Ctx; OptLabelTy OldBreakLabel; OptLabelTy OldDefaultLabel; CaseMap OldCaseLabels; @@ -457,13 +448,17 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { assert(isPtrType(*FromT)); assert(isPtrType(*ToT)); if (FromT == ToT) { - if (CE->getType()->isVoidPointerType()) + if (CE->getType()->isVoidPointerType() && + !SubExprTy->isFunctionPointerType()) { return this->delegate(SubExpr); + } if (!this->visit(SubExpr)) return false; - if (CE->getType()->isFunctionPointerType()) - return true; + if (CE->getType()->isFunctionPointerType() || + SubExprTy->isFunctionPointerType()) { + return this->emitFnPtrCast(CE); + } if (FromT == PT_Ptr) return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), CE); return true; @@ -1763,6 +1758,9 @@ bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, if (Inits.size() == 1 && E->getType() == Inits[0]->getType()) return this->delegate(Inits[0]); + if (!R) + return false; + auto initPrimitiveField = [=](const Record::Field *FieldToInit, const Expr *Init, PrimType T, bool Activate = false) -> bool { diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h index 3a26342..16f108f 100644 --- a/clang/lib/AST/ByteCode/Compiler.h +++ b/clang/lib/AST/ByteCode/Compiler.h @@ -21,7 +21,6 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Basic/TargetInfo.h" namespace clang { class QualType; diff --git a/clang/lib/AST/ByteCode/Disasm.cpp b/clang/lib/AST/ByteCode/Disasm.cpp index 74399d1..5049a65 100644 --- a/clang/lib/AST/ByteCode/Disasm.cpp +++ b/clang/lib/AST/ByteCode/Disasm.cpp @@ -531,7 +531,7 @@ LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream &OS) const { Desc->dump(OS); OS << ")\n"; unsigned NPointers = 0; - for (const Pointer *P = Pointers; P; P = P->Next) { + for (const Pointer *P = Pointers; P; P = P->asBlockPointer().Next) { ++NPointers; } OS << " EvalID: " << EvalID << '\n'; diff --git a/clang/lib/AST/ByteCode/DynamicAllocator.cpp b/clang/lib/AST/ByteCode/DynamicAllocator.cpp index 4f0f511..169250c 100644 --- a/clang/lib/AST/ByteCode/DynamicAllocator.cpp +++ b/clang/lib/AST/ByteCode/DynamicAllocator.cpp @@ -27,7 +27,7 @@ void DynamicAllocator::cleanup() { B->invokeDtor(); if (B->hasPointers()) { while (B->Pointers) { - Pointer *Next = B->Pointers->Next; + Pointer *Next = B->Pointers->asBlockPointer().Next; B->Pointers->PointeeStorage.BS.Pointee = nullptr; B->Pointers = Next; } diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 2602ed7..9a325ab 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -25,7 +25,6 @@ #include "InterpStack.h" #include "InterpState.h" #include "MemberPointer.h" -#include "Opcode.h" #include "PrimType.h" #include "Program.h" #include "State.h" @@ -1131,8 +1130,9 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) { S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end) << LHS.toDiagnosticString(S.getASTContext()); return false; - } else if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() && - LHS.getOffset() == 0) { + } + if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() && + LHS.getOffset() == 0) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end) << RHS.toDiagnosticString(S.getASTContext()); @@ -1150,8 +1150,9 @@ inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_literal_comparison); return false; - } else if (const auto *CE = dyn_cast<CallExpr>(E); - CE && IsOpaqueConstantCall(CE)) { + } + if (const auto *CE = dyn_cast<CallExpr>(E); + CE && IsOpaqueConstantCall(CE)) { const SourceInfo &Loc = S.Current->getSource(OpPC); S.FFDiag(Loc, diag::note_constexpr_opaque_call_comparison) << P.toDiagnosticString(S.getASTContext()); @@ -2681,6 +2682,14 @@ static inline bool CastFixedPointIntegral(InterpState &S, CodePtr OpPC) { return true; } +static inline bool FnPtrCast(InterpState &S, CodePtr OpPC) { + const SourceInfo &E = S.Current->getSource(OpPC); + S.CCEDiag(E, diag::note_constexpr_invalid_cast) + << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret + << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC); + return true; +} + static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) { const auto &Ptr = S.Stk.peek<Pointer>(); @@ -3266,7 +3275,8 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, S.CCEDiag(Loc, diag::note_constexpr_invalid_cast) << static_cast<unsigned>(Kind) << S.Current->getRange(OpPC); return !Fatal; - } else if (Kind == CastKind::Volatile) { + } + if (Kind == CastKind::Volatile) { if (!S.checkingPotentialConstantExpression()) { const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC)); if (S.getLangOpts().CPlusPlus) @@ -3277,7 +3287,8 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind, } return false; - } else if (Kind == CastKind::Dynamic) { + } + if (Kind == CastKind::Dynamic) { assert(!S.getLangOpts().CPlusPlus20); S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast) << diag::ConstexprInvalidCastKind::Dynamic; diff --git a/clang/lib/AST/ByteCode/InterpBlock.cpp b/clang/lib/AST/ByteCode/InterpBlock.cpp index f603078..963b54e 100644 --- a/clang/lib/AST/ByteCode/InterpBlock.cpp +++ b/clang/lib/AST/ByteCode/InterpBlock.cpp @@ -27,9 +27,9 @@ void Block::addPointer(Pointer *P) { assert(!hasPointer(P)); #endif if (Pointers) - Pointers->Prev = P; - P->Next = Pointers; - P->Prev = nullptr; + Pointers->PointeeStorage.BS.Prev = P; + P->PointeeStorage.BS.Next = Pointers; + P->PointeeStorage.BS.Prev = nullptr; Pointers = P; #ifndef NDEBUG assert(hasPointer(P)); @@ -48,13 +48,15 @@ void Block::removePointer(Pointer *P) { assert(hasPointer(P)); #endif + BlockPointer &BP = P->PointeeStorage.BS; + if (Pointers == P) - Pointers = P->Next; + Pointers = BP.Next; - if (P->Prev) - P->Prev->Next = P->Next; - if (P->Next) - P->Next->Prev = P->Prev; + if (BP.Prev) + BP.Prev->PointeeStorage.BS.Next = BP.Next; + if (BP.Next) + BP.Next->PointeeStorage.BS.Prev = BP.Prev; P->PointeeStorage.BS.Pointee = nullptr; #ifndef NDEBUG assert(!hasPointer(P)); @@ -68,7 +70,9 @@ void Block::cleanup() { void Block::replacePointer(Pointer *Old, Pointer *New) { assert(Old); + assert(Old->isBlockPointer()); assert(New); + assert(New->isBlockPointer()); assert(Old != New); if (IsStatic) { assert(!Pointers); @@ -78,17 +82,20 @@ void Block::replacePointer(Pointer *Old, Pointer *New) { assert(hasPointer(Old)); #endif - if (Old->Prev) - Old->Prev->Next = New; - if (Old->Next) - Old->Next->Prev = New; - New->Prev = Old->Prev; - New->Next = Old->Next; + BlockPointer &OldBP = Old->PointeeStorage.BS; + BlockPointer &NewBP = New->PointeeStorage.BS; + + if (OldBP.Prev) + OldBP.Prev->PointeeStorage.BS.Next = New; + if (OldBP.Next) + OldBP.Next->PointeeStorage.BS.Prev = New; + NewBP.Prev = OldBP.Prev; + NewBP.Next = OldBP.Next; if (Pointers == Old) Pointers = New; - Old->PointeeStorage.BS.Pointee = nullptr; - New->PointeeStorage.BS.Pointee = this; + OldBP.Pointee = nullptr; + NewBP.Pointee = this; #ifndef NDEBUG assert(!hasPointer(Old)); assert(hasPointer(New)); @@ -97,7 +104,7 @@ void Block::replacePointer(Pointer *Old, Pointer *New) { #ifndef NDEBUG bool Block::hasPointer(const Pointer *P) const { - for (const Pointer *C = Pointers; C; C = C->Next) { + for (const Pointer *C = Pointers; C; C = C->asBlockPointer().Next) { if (C == P) return true; } @@ -120,7 +127,7 @@ DeadBlock::DeadBlock(DeadBlock *&Root, Block *Blk) // Transfer pointers. B.Pointers = Blk->Pointers; - for (Pointer *P = Blk->Pointers; P; P = P->Next) + for (Pointer *P = Blk->Pointers; P; P = P->asBlockPointer().Next) P->PointeeStorage.BS.Pointee = &B; Blk->Pointers = nullptr; } diff --git a/clang/lib/AST/ByteCode/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp index 7848f29..3010847 100644 --- a/clang/lib/AST/ByteCode/InterpState.cpp +++ b/clang/lib/AST/ByteCode/InterpState.cpp @@ -52,7 +52,7 @@ void InterpState::cleanup() { // As a last resort, make sure all pointers still pointing to a dead block // don't point to it anymore. for (DeadBlock *DB = DeadBlocks; DB; DB = DB->Next) { - for (Pointer *P = DB->B.Pointers; P; P = P->Next) { + for (Pointer *P = DB->B.Pointers; P; P = P->asBlockPointer().Next) { P->PointeeStorage.BS.Pointee = nullptr; } } diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td index abfed77..95a4433 100644 --- a/clang/lib/AST/ByteCode/Opcodes.td +++ b/clang/lib/AST/ByteCode/Opcodes.td @@ -412,7 +412,7 @@ def CheckDecl : Opcode { def CheckEnumValue : Opcode { let Args = [ArgEnumDecl]; - let Types = [FixedSizeIntegralTypeClass]; + let Types = [IntegralTypeClass]; let HasGroup = 1; } @@ -735,6 +735,8 @@ def PtrPtrCast : Opcode { } +def FnPtrCast : Opcode; + def DecayPtr : Opcode { let Types = [PtrTypeClass, PtrTypeClass]; let HasGroup = 1; diff --git a/clang/lib/AST/ByteCode/Pointer.cpp b/clang/lib/AST/ByteCode/Pointer.cpp index 4753a4e1..dec2088 100644 --- a/clang/lib/AST/ByteCode/Pointer.cpp +++ b/clang/lib/AST/ByteCode/Pointer.cpp @@ -42,7 +42,7 @@ Pointer::Pointer(Block *Pointee, unsigned Base, uint64_t Offset) : Offset(Offset), StorageKind(Storage::Block) { assert((Base == RootPtrMark || Base % alignof(void *) == 0) && "wrong base"); - PointeeStorage.BS = {Pointee, Base}; + PointeeStorage.BS = {Pointee, Base, nullptr, nullptr}; if (Pointee) Pointee->addPointer(this); @@ -89,7 +89,6 @@ Pointer &Pointer::operator=(const Pointer &P) { if (P.isBlockPointer()) { PointeeStorage.BS = P.PointeeStorage.BS; - PointeeStorage.BS.Pointee = P.PointeeStorage.BS.Pointee; if (PointeeStorage.BS.Pointee) PointeeStorage.BS.Pointee->addPointer(this); @@ -127,7 +126,6 @@ Pointer &Pointer::operator=(Pointer &&P) { if (P.isBlockPointer()) { PointeeStorage.BS = P.PointeeStorage.BS; - PointeeStorage.BS.Pointee = P.PointeeStorage.BS.Pointee; if (PointeeStorage.BS.Pointee) PointeeStorage.BS.Pointee->addPointer(this); diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h index 9fe224c..5bafc5b 100644 --- a/clang/lib/AST/ByteCode/Pointer.h +++ b/clang/lib/AST/ByteCode/Pointer.h @@ -39,6 +39,10 @@ struct BlockPointer { Block *Pointee; /// Start of the current subfield. unsigned Base; + /// Previous link in the pointer chain. + Pointer *Prev; + /// Next link in the pointer chain. + Pointer *Next; }; struct IntPointer { @@ -832,15 +836,10 @@ private: /// Offset into the storage. uint64_t Offset = 0; - /// Previous link in the pointer chain. - Pointer *Prev = nullptr; - /// Next link in the pointer chain. - Pointer *Next = nullptr; - Storage StorageKind = Storage::Int; union { - BlockPointer BS; IntPointer Int; + BlockPointer BS; FunctionPointer Fn; TypeidPointer Typeid; } PointeeStorage; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 83fcd87..1588be4 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -5988,11 +5988,10 @@ bool clang::IsArmStreamingFunction(const FunctionDecl *FD, if (FD->hasAttr<ArmLocallyStreamingAttr>()) return true; - if (const Type *Ty = FD->getType().getTypePtrOrNull()) - if (const auto *FPT = Ty->getAs<FunctionProtoType>()) - if (FPT->getAArch64SMEAttributes() & - FunctionType::SME_PStateSMEnabledMask) - return true; + assert(!FD->getType().isNull() && "Expected a valid FunctionDecl"); + if (const auto *FPT = FD->getType()->getAs<FunctionProtoType>()) + if (FPT->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask) + return true; return false; } diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index d85655b..cd9672d 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -4233,8 +4233,15 @@ bool Expr::isSameComparisonOperand(const Expr* E1, const Expr* E2) { // template parameters. const auto *DRE1 = cast<DeclRefExpr>(E1); const auto *DRE2 = cast<DeclRefExpr>(E2); - return DRE1->isPRValue() && DRE2->isPRValue() && - DRE1->getDecl() == DRE2->getDecl(); + + if (DRE1->getDecl() != DRE2->getDecl()) + return false; + + if ((DRE1->isPRValue() && DRE2->isPRValue()) || + (DRE1->isLValue() && DRE2->isLValue())) + return true; + + return false; } case ImplicitCastExprClass: { // Peel off implicit casts. @@ -4244,7 +4251,8 @@ bool Expr::isSameComparisonOperand(const Expr* E1, const Expr* E2) { if (!ICE1 || !ICE2) return false; if (ICE1->getCastKind() != ICE2->getCastKind()) - return false; + return isSameComparisonOperand(ICE1->IgnoreParenImpCasts(), + ICE2->IgnoreParenImpCasts()); E1 = ICE1->getSubExpr()->IgnoreParens(); E2 = ICE2->getSubExpr()->IgnoreParens(); // The final cast must be one of these types. diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 9808298..993b64b 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9741,10 +9741,19 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_AddressSpaceConversion: if (!Visit(SubExpr)) return false; - // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are - // permitted in constant expressions in C++11. Bitcasts from cv void* are - // also static_casts, but we disallow them as a resolution to DR1312. - if (!E->getType()->isVoidPointerType()) { + if (E->getType()->isFunctionPointerType() || + SubExpr->getType()->isFunctionPointerType()) { + // Casting between two function pointer types, or between a function + // pointer and an object pointer, is always a reinterpret_cast. + CCEDiag(E, diag::note_constexpr_invalid_cast) + << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret + << Info.Ctx.getLangOpts().CPlusPlus; + Result.Designator.setInvalid(); + } else if (!E->getType()->isVoidPointerType()) { + // Bitcasts to cv void* are static_casts, not reinterpret_casts, so are + // permitted in constant expressions in C++11. Bitcasts from cv void* are + // also static_casts, but we disallow them as a resolution to DR1312. + // // In some circumstances, we permit casting from void* to cv1 T*, when the // actual pointee object is actually a cv2 T. bool HasValidResult = !Result.InvalidBase && !Result.Designator.Invalid && diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index b2b1488..5b8444a 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -2366,18 +2366,16 @@ size_t SourceManager::getDataStructureSizes() const { SourceManagerForFile::SourceManagerForFile(StringRef FileName, StringRef Content) { - // This is referenced by `FileMgr` and will be released by `FileMgr` when it - // is deleted. - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); InMemoryFileSystem->addFile( FileName, 0, llvm::MemoryBuffer::getMemBuffer(Content, FileName, /*RequiresNullTerminator=*/false)); // This is passed to `SM` as reference, so the pointer has to be referenced // in `Environment` so that `FileMgr` can out-live this function scope. - FileMgr = - std::make_unique<FileManager>(FileSystemOptions(), InMemoryFileSystem); + FileMgr = std::make_unique<FileManager>(FileSystemOptions(), + std::move(InMemoryFileSystem)); DiagOpts = std::make_unique<DiagnosticOptions>(); // This is passed to `SM` as reference, so the pointer has to be referenced // by `Environment` due to the same reason above. diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp index 6527fb5..9e8eaa5 100644 --- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp @@ -520,7 +520,7 @@ void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d, llvm_unreachable("bad evaluation kind"); } -void CIRGenFunction::emitDecl(const Decl &d) { +void CIRGenFunction::emitDecl(const Decl &d, bool evaluateConditionDecl) { switch (d.getKind()) { case Decl::BuiltinTemplate: case Decl::TranslationUnit: @@ -608,11 +608,14 @@ void CIRGenFunction::emitDecl(const Decl &d) { case Decl::UsingDirective: // using namespace X; [C++] assert(!cir::MissingFeatures::generateDebugInfo()); return; - case Decl::Var: { + case Decl::Var: + case Decl::Decomposition: { const VarDecl &vd = cast<VarDecl>(d); assert(vd.isLocalVarDecl() && "Should not see file-scope variables inside a function!"); emitVarDecl(vd); + if (evaluateConditionDecl) + maybeEmitDeferredVarDeclInit(&vd); return; } case Decl::OpenACCDeclare: @@ -632,7 +635,6 @@ void CIRGenFunction::emitDecl(const Decl &d) { case Decl::ImplicitConceptSpecialization: case Decl::TopLevelStmt: case Decl::UsingPack: - case Decl::Decomposition: // This could be moved to join Decl::Var case Decl::OMPDeclareReduction: case Decl::OMPDeclareMapper: cgm.errorNYI(d.getSourceRange(), @@ -797,3 +799,11 @@ void CIRGenFunction::emitAutoVarTypeCleanup( assert(!cir::MissingFeatures::ehCleanupFlags()); ehStack.pushCleanup<DestroyObject>(cleanupKind, addr, type, destroyer); } + +void CIRGenFunction::maybeEmitDeferredVarDeclInit(const VarDecl *vd) { + if (auto *dd = dyn_cast_if_present<DecompositionDecl>(vd)) { + for (auto *b : dd->flat_bindings()) + if (auto *hd = b->getHoldingVar()) + emitVarDecl(*hd); + } +} diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index c18498f..a509ffa 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -584,6 +584,15 @@ LValue CIRGenFunction::emitDeclRefLValue(const DeclRefExpr *e) { return lv; } + if (const auto *bd = dyn_cast<BindingDecl>(nd)) { + if (e->refersToEnclosingVariableOrCapture()) { + assert(!cir::MissingFeatures::lambdaCaptures()); + cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: lambda captures"); + return LValue(); + } + return emitLValue(bd->getBinding()); + } + cgm.errorNYI(e->getSourceRange(), "emitDeclRefLValue: unhandled decl type"); return LValue(); } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index a09d739..ea60a95 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -91,6 +91,14 @@ public: } mlir::Value VisitUnaryDeref(const Expr *e); + + mlir::Value VisitUnaryPlus(const UnaryOperator *e); + + mlir::Value VisitPlusMinus(const UnaryOperator *e, cir::UnaryOpKind kind, + QualType promotionType); + + mlir::Value VisitUnaryMinus(const UnaryOperator *e); + mlir::Value VisitUnaryNot(const UnaryOperator *e); struct BinOpInfo { @@ -110,6 +118,7 @@ public: mlir::Value emitBinAdd(const BinOpInfo &op); mlir::Value emitBinSub(const BinOpInfo &op); + mlir::Value emitBinMul(const BinOpInfo &op); QualType getPromotionType(QualType ty, bool isDivOpCode = false) { if (auto *complexTy = ty->getAs<ComplexType>()) { @@ -142,6 +151,7 @@ public: HANDLEBINOP(Add) HANDLEBINOP(Sub) + HANDLEBINOP(Mul) #undef HANDLEBINOP }; } // namespace @@ -282,6 +292,41 @@ mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op, llvm_unreachable("unknown cast resulting in complex value"); } +mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) { + QualType promotionTy = getPromotionType(e->getSubExpr()->getType()); + mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Plus, promotionTy); + if (!promotionTy.isNull()) { + cgf.cgm.errorNYI("ComplexExprEmitter::VisitUnaryPlus emitUnPromotedValue"); + return {}; + } + return result; +} + +mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e, + cir::UnaryOpKind kind, + QualType promotionType) { + assert(kind == cir::UnaryOpKind::Plus || + kind == cir::UnaryOpKind::Minus && + "Invalid UnaryOp kind for ComplexType Plus or Minus"); + + mlir::Value op; + if (!promotionType.isNull()) + op = cgf.emitPromotedComplexExpr(e->getSubExpr(), promotionType); + else + op = Visit(e->getSubExpr()); + return builder.createUnaryOp(cgf.getLoc(e->getExprLoc()), kind, op); +} + +mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) { + QualType promotionTy = getPromotionType(e->getSubExpr()->getType()); + mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy); + if (!promotionTy.isNull()) { + cgf.cgm.errorNYI("ComplexExprEmitter::VisitUnaryMinus emitUnPromotedValue"); + return {}; + } + return result; +} + mlir::Value ComplexExprEmitter::emitConstant( const CIRGenFunction::ConstantEmission &constant, Expr *e) { assert(constant && "not a constant"); @@ -534,13 +579,22 @@ mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e, return emitBin##OP(emitBinOps(bo, promotionTy)); HANDLE_BINOP(Add) HANDLE_BINOP(Sub) + HANDLE_BINOP(Mul) #undef HANDLE_BINOP default: break; } - } else if (isa<UnaryOperator>(e)) { - cgf.cgm.errorNYI("emitPromoted UnaryOperator"); - return {}; + } else if (const auto *unaryOp = dyn_cast<UnaryOperator>(e)) { + switch (unaryOp->getOpcode()) { + case UO_Minus: + case UO_Plus: { + auto kind = unaryOp->getOpcode() == UO_Plus ? cir::UnaryOpKind::Plus + : cir::UnaryOpKind::Minus; + return VisitPlusMinus(unaryOp, kind, promotionTy); + } + default: + break; + } } mlir::Value result = Visit(const_cast<Expr *>(e)); @@ -585,6 +639,31 @@ mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) { return builder.create<cir::ComplexSubOp>(op.loc, op.lhs, op.rhs); } +static cir::ComplexRangeKind +getComplexRangeAttr(LangOptions::ComplexRangeKind range) { + switch (range) { + case LangOptions::CX_Full: + return cir::ComplexRangeKind::Full; + case LangOptions::CX_Improved: + return cir::ComplexRangeKind::Improved; + case LangOptions::CX_Promoted: + return cir::ComplexRangeKind::Promoted; + case LangOptions::CX_Basic: + return cir::ComplexRangeKind::Basic; + case LangOptions::CX_None: + // The default value for ComplexRangeKind is Full is no option is selected + return cir::ComplexRangeKind::Full; + } +} + +mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) { + assert(!cir::MissingFeatures::fastMathFlags()); + assert(!cir::MissingFeatures::cgFPOptionsRAII()); + cir::ComplexRangeKind rangeKind = + getComplexRangeAttr(op.fpFeatures.getComplexRange()); + return builder.create<cir::ComplexMulOp>(op.loc, op.lhs, op.rhs, rangeKind); +} + LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) { assert(e->getOpcode() == BO_Assign && "Expected assign op"); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index c65d025..3e9de17 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -943,6 +943,7 @@ void CIRGenFunction::emitVariablyModifiedType(QualType type) { case Type::HLSLInlineSpirv: case Type::PredefinedSugar: cgm.errorNYI("CIRGenFunction::emitVariablyModifiedType"); + break; #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 603f750..f9c8636 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -870,6 +870,8 @@ public: void emitAutoVarTypeCleanup(const AutoVarEmission &emission, clang::QualType::DestructionKind dtorKind); + void maybeEmitDeferredVarDeclInit(const VarDecl *vd); + void emitBaseInitializer(mlir::Location loc, const CXXRecordDecl *classDecl, CXXCtorInitializer *baseInit); @@ -1059,7 +1061,7 @@ public: void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s); - void emitDecl(const clang::Decl &d); + void emitDecl(const clang::Decl &d, bool evaluateConditionDecl = false); mlir::LogicalResult emitDeclStmt(const clang::DeclStmt &s); LValue emitDeclRefLValue(const clang::DeclRefExpr *e); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 623b84f..d0f9fc3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -1308,8 +1308,13 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) { break; } - case Decl::Var: { + case Decl::Var: + case Decl::Decomposition: { auto *vd = cast<VarDecl>(decl); + if (isa<DecompositionDecl>(decl)) { + errorNYI(decl->getSourceRange(), "global variable decompositions"); + break; + } emitGlobal(vd); break; } @@ -1331,8 +1336,14 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) { break; // No code generation needed. - case Decl::UsingShadow: + case Decl::ClassTemplate: + case Decl::Concept: + case Decl::CXXDeductionGuide: case Decl::Empty: + case Decl::FunctionTemplate: + case Decl::StaticAssert: + case Decl::TypeAliasTemplate: + case Decl::UsingShadow: break; case Decl::CXXConstructor: diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp index e4ec380..0c8ff4bd 100644 --- a/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp @@ -91,6 +91,9 @@ struct CIRRecordLowering final { return astContext.getTargetInfo().getABI().starts_with("aapcs"); } + /// Helper function to check if the target machine is BigEndian. + bool isBigEndian() const { return astContext.getTargetInfo().isBigEndian(); } + CharUnits bitsToCharUnits(uint64_t bitOffset) { return astContext.toCharUnitsFromBits(bitOffset); } @@ -771,7 +774,104 @@ void CIRRecordLowering::computeVolatileBitfields() { !cirGenTypes.getCGModule().getCodeGenOpts().AAPCSBitfieldWidth) return; - assert(!cir::MissingFeatures::armComputeVolatileBitfields()); + for (auto &[field, info] : bitFields) { + mlir::Type resLTy = cirGenTypes.convertTypeForMem(field->getType()); + + if (astContext.toBits(astRecordLayout.getAlignment()) < + getSizeInBits(resLTy).getQuantity()) + continue; + + // CIRRecordLowering::setBitFieldInfo() pre-adjusts the bit-field offsets + // for big-endian targets, but it assumes a container of width + // info.storageSize. Since AAPCS uses a different container size (width + // of the type), we first undo that calculation here and redo it once + // the bit-field offset within the new container is calculated. + const unsigned oldOffset = + isBigEndian() ? info.storageSize - (info.offset + info.size) + : info.offset; + // Offset to the bit-field from the beginning of the struct. + const unsigned absoluteOffset = + astContext.toBits(info.storageOffset) + oldOffset; + + // Container size is the width of the bit-field type. + const unsigned storageSize = getSizeInBits(resLTy).getQuantity(); + // Nothing to do if the access uses the desired + // container width and is naturally aligned. + if (info.storageSize == storageSize && (oldOffset % storageSize == 0)) + continue; + + // Offset within the container. + unsigned offset = absoluteOffset & (storageSize - 1); + // Bail out if an aligned load of the container cannot cover the entire + // bit-field. This can happen for example, if the bit-field is part of a + // packed struct. AAPCS does not define access rules for such cases, we let + // clang to follow its own rules. + if (offset + info.size > storageSize) + continue; + + // Re-adjust offsets for big-endian targets. + if (isBigEndian()) + offset = storageSize - (offset + info.size); + + const CharUnits storageOffset = + astContext.toCharUnitsFromBits(absoluteOffset & ~(storageSize - 1)); + const CharUnits end = storageOffset + + astContext.toCharUnitsFromBits(storageSize) - + CharUnits::One(); + + const ASTRecordLayout &layout = + astContext.getASTRecordLayout(field->getParent()); + // If we access outside memory outside the record, than bail out. + const CharUnits recordSize = layout.getSize(); + if (end >= recordSize) + continue; + + // Bail out if performing this load would access non-bit-fields members. + bool conflict = false; + for (const auto *f : recordDecl->fields()) { + // Allow sized bit-fields overlaps. + if (f->isBitField() && !f->isZeroLengthBitField()) + continue; + + const CharUnits fOffset = astContext.toCharUnitsFromBits( + layout.getFieldOffset(f->getFieldIndex())); + + // As C11 defines, a zero sized bit-field defines a barrier, so + // fields after and before it should be race condition free. + // The AAPCS acknowledges it and imposes no restritions when the + // natural container overlaps a zero-length bit-field. + if (f->isZeroLengthBitField()) { + if (end > fOffset && storageOffset < fOffset) { + conflict = true; + break; + } + } + + const CharUnits fEnd = + fOffset + + astContext.toCharUnitsFromBits(astContext.toBits( + getSizeInBits(cirGenTypes.convertTypeForMem(f->getType())))) - + CharUnits::One(); + // If no overlap, continue. + if (end < fOffset || fEnd < storageOffset) + continue; + + // The desired load overlaps a non-bit-field member, bail out. + conflict = true; + break; + } + + if (conflict) + continue; + // Write the new bit-field access parameters. + // As the storage offset now is defined as the number of elements from the + // start of the structure, we should divide the Offset by the element size. + info.volatileStorageOffset = + storageOffset / + astContext.toCharUnitsFromBits(storageSize).getQuantity(); + info.volatileStorageSize = storageSize; + info.volatileOffset = offset; + } } void CIRRecordLowering::accumulateBases(const CXXRecordDecl *cxxRecordDecl) { diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 21bee33..75da229e 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -363,8 +363,8 @@ mlir::LogicalResult CIRGenFunction::emitIfStmt(const IfStmt &s) { mlir::LogicalResult CIRGenFunction::emitDeclStmt(const DeclStmt &s) { assert(builder.getInsertionBlock() && "expected valid insertion point"); - for (const Decl *I : s.decls()) - emitDecl(*I); + for (const Decl *i : s.decls()) + emitDecl(*i, /*evaluateConditionDecl=*/true); return mlir::success(); } @@ -875,7 +875,7 @@ mlir::LogicalResult CIRGenFunction::emitSwitchStmt(const clang::SwitchStmt &s) { return mlir::failure(); if (s.getConditionVariable()) - emitDecl(*s.getConditionVariable()); + emitDecl(*s.getConditionVariable(), /*evaluateConditionDecl=*/true); mlir::Value condV = emitScalarExpr(s.getCond()); diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index ce3b30d..66260eb 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -15,7 +15,6 @@ #include "clang/CIR/Dialect/Passes.h" #include "clang/CIR/MissingFeatures.h" -#include <iostream> #include <memory> using namespace mlir; @@ -28,21 +27,47 @@ struct LoweringPreparePass : public LoweringPrepareBase<LoweringPreparePass> { void runOnOp(mlir::Operation *op); void lowerCastOp(cir::CastOp op); + void lowerComplexMulOp(cir::ComplexMulOp op); void lowerUnaryOp(cir::UnaryOp op); void lowerArrayDtor(cir::ArrayDtor op); void lowerArrayCtor(cir::ArrayCtor op); + cir::FuncOp buildRuntimeFunction( + mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc, + cir::FuncType type, + cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage); + /// /// AST related /// ----------- clang::ASTContext *astCtx; + /// Tracks current module. + mlir::ModuleOp mlirModule; + void setASTContext(clang::ASTContext *c) { astCtx = c; } }; } // namespace +cir::FuncOp LoweringPreparePass::buildRuntimeFunction( + mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc, + cir::FuncType type, cir::GlobalLinkageKind linkage) { + cir::FuncOp f = dyn_cast_or_null<FuncOp>(SymbolTable::lookupNearestSymbolFrom( + mlirModule, StringAttr::get(mlirModule->getContext(), name))); + if (!f) { + f = builder.create<cir::FuncOp>(loc, name, type); + f.setLinkageAttr( + cir::GlobalLinkageKindAttr::get(builder.getContext(), linkage)); + mlir::SymbolTable::setSymbolVisibility( + f, mlir::SymbolTable::Visibility::Private); + + assert(!cir::MissingFeatures::opFuncExtraAttrs()); + } + return f; +} + static mlir::Value lowerScalarToComplexCast(mlir::MLIRContext &ctx, cir::CastOp op) { cir::CIRBaseBuilderTy builder(ctx); @@ -128,6 +153,124 @@ void LoweringPreparePass::lowerCastOp(cir::CastOp op) { } } +static mlir::Value buildComplexBinOpLibCall( + LoweringPreparePass &pass, CIRBaseBuilderTy &builder, + llvm::StringRef (*libFuncNameGetter)(llvm::APFloat::Semantics), + mlir::Location loc, cir::ComplexType ty, mlir::Value lhsReal, + mlir::Value lhsImag, mlir::Value rhsReal, mlir::Value rhsImag) { + cir::FPTypeInterface elementTy = + mlir::cast<cir::FPTypeInterface>(ty.getElementType()); + + llvm::StringRef libFuncName = libFuncNameGetter( + llvm::APFloat::SemanticsToEnum(elementTy.getFloatSemantics())); + llvm::SmallVector<mlir::Type, 4> libFuncInputTypes(4, elementTy); + + cir::FuncType libFuncTy = cir::FuncType::get(libFuncInputTypes, ty); + + // Insert a declaration for the runtime function to be used in Complex + // multiplication and division when needed + cir::FuncOp libFunc; + { + mlir::OpBuilder::InsertionGuard ipGuard{builder}; + builder.setInsertionPointToStart(pass.mlirModule.getBody()); + libFunc = pass.buildRuntimeFunction(builder, libFuncName, loc, libFuncTy); + } + + cir::CallOp call = + builder.createCallOp(loc, libFunc, {lhsReal, lhsImag, rhsReal, rhsImag}); + return call.getResult(); +} + +static llvm::StringRef +getComplexMulLibCallName(llvm::APFloat::Semantics semantics) { + switch (semantics) { + case llvm::APFloat::S_IEEEhalf: + return "__mulhc3"; + case llvm::APFloat::S_IEEEsingle: + return "__mulsc3"; + case llvm::APFloat::S_IEEEdouble: + return "__muldc3"; + case llvm::APFloat::S_PPCDoubleDouble: + return "__multc3"; + case llvm::APFloat::S_x87DoubleExtended: + return "__mulxc3"; + case llvm::APFloat::S_IEEEquad: + return "__multc3"; + default: + llvm_unreachable("unsupported floating point type"); + } +} + +static mlir::Value lowerComplexMul(LoweringPreparePass &pass, + CIRBaseBuilderTy &builder, + mlir::Location loc, cir::ComplexMulOp op, + mlir::Value lhsReal, mlir::Value lhsImag, + mlir::Value rhsReal, mlir::Value rhsImag) { + // (a+bi) * (c+di) = (ac-bd) + (ad+bc)i + mlir::Value resultRealLhs = + builder.createBinop(loc, lhsReal, cir::BinOpKind::Mul, rhsReal); + mlir::Value resultRealRhs = + builder.createBinop(loc, lhsImag, cir::BinOpKind::Mul, rhsImag); + mlir::Value resultImagLhs = + builder.createBinop(loc, lhsReal, cir::BinOpKind::Mul, rhsImag); + mlir::Value resultImagRhs = + builder.createBinop(loc, lhsImag, cir::BinOpKind::Mul, rhsReal); + mlir::Value resultReal = builder.createBinop( + loc, resultRealLhs, cir::BinOpKind::Sub, resultRealRhs); + mlir::Value resultImag = builder.createBinop( + loc, resultImagLhs, cir::BinOpKind::Add, resultImagRhs); + mlir::Value algebraicResult = + builder.createComplexCreate(loc, resultReal, resultImag); + + cir::ComplexType complexTy = op.getType(); + cir::ComplexRangeKind rangeKind = op.getRange(); + if (mlir::isa<cir::IntType>(complexTy.getElementType()) || + rangeKind == cir::ComplexRangeKind::Basic || + rangeKind == cir::ComplexRangeKind::Improved || + rangeKind == cir::ComplexRangeKind::Promoted) + return algebraicResult; + + assert(!cir::MissingFeatures::fastMathFlags()); + + // Check whether the real part and the imaginary part of the result are both + // NaN. If so, emit a library call to compute the multiplication instead. + // We check a value against NaN by comparing the value against itself. + mlir::Value resultRealIsNaN = builder.createIsNaN(loc, resultReal); + mlir::Value resultImagIsNaN = builder.createIsNaN(loc, resultImag); + mlir::Value resultRealAndImagAreNaN = + builder.createLogicalAnd(loc, resultRealIsNaN, resultImagIsNaN); + + return builder + .create<cir::TernaryOp>( + loc, resultRealAndImagAreNaN, + [&](mlir::OpBuilder &, mlir::Location) { + mlir::Value libCallResult = buildComplexBinOpLibCall( + pass, builder, &getComplexMulLibCallName, loc, complexTy, + lhsReal, lhsImag, rhsReal, rhsImag); + builder.createYield(loc, libCallResult); + }, + [&](mlir::OpBuilder &, mlir::Location) { + builder.createYield(loc, algebraicResult); + }) + .getResult(); +} + +void LoweringPreparePass::lowerComplexMulOp(cir::ComplexMulOp op) { + cir::CIRBaseBuilderTy builder(getContext()); + builder.setInsertionPointAfter(op); + mlir::Location loc = op.getLoc(); + mlir::TypedValue<cir::ComplexType> lhs = op.getLhs(); + mlir::TypedValue<cir::ComplexType> rhs = op.getRhs(); + mlir::Value lhsReal = builder.createComplexReal(loc, lhs); + mlir::Value lhsImag = builder.createComplexImag(loc, lhs); + mlir::Value rhsReal = builder.createComplexReal(loc, rhs); + mlir::Value rhsImag = builder.createComplexImag(loc, rhs); + mlir::Value loweredResult = lowerComplexMul(*this, builder, loc, op, lhsReal, + lhsImag, rhsReal, rhsImag); + op.replaceAllUsesWith(loweredResult); + op.erase(); +} + void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) { mlir::Type ty = op.getType(); if (!mlir::isa<cir::ComplexType>(ty)) @@ -155,7 +298,8 @@ void LoweringPreparePass::lowerUnaryOp(cir::UnaryOp op) { case cir::UnaryOpKind::Plus: case cir::UnaryOpKind::Minus: - llvm_unreachable("Complex unary Plus/Minus NYI"); + resultReal = builder.createUnaryOp(loc, opKind, operandReal); + resultImag = builder.createUnaryOp(loc, opKind, operandImag); break; case cir::UnaryOpKind::Not: @@ -268,18 +412,22 @@ void LoweringPreparePass::runOnOp(mlir::Operation *op) { lowerArrayDtor(arrayDtor); else if (auto cast = mlir::dyn_cast<cir::CastOp>(op)) lowerCastOp(cast); + else if (auto complexMul = mlir::dyn_cast<cir::ComplexMulOp>(op)) + lowerComplexMulOp(complexMul); else if (auto unary = mlir::dyn_cast<cir::UnaryOp>(op)) lowerUnaryOp(unary); } void LoweringPreparePass::runOnOperation() { mlir::Operation *op = getOperation(); + if (isa<::mlir::ModuleOp>(op)) + mlirModule = cast<::mlir::ModuleOp>(op); llvm::SmallVector<mlir::Operation *> opsToTransform; op->walk([&](mlir::Operation *op) { - if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp, cir::UnaryOp>( - op)) + if (mlir::isa<cir::ArrayCtor, cir::ArrayDtor, cir::CastOp, + cir::ComplexMulOp, cir::UnaryOp>(op)) opsToTransform.push_back(op); }); diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 3f784fc..e1f7ea0 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -1148,7 +1148,8 @@ llvm::Value *CodeGenFunction::emitCountedByPointerSize( assert(E->getCastKind() == CK_LValueToRValue && "must be an LValue to RValue cast"); - const MemberExpr *ME = dyn_cast<MemberExpr>(E->getSubExpr()); + const MemberExpr *ME = + dyn_cast<MemberExpr>(E->getSubExpr()->IgnoreParenNoopCasts(getContext())); if (!ME) return nullptr; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 77fc3a2..7a69b5d 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2641,6 +2641,8 @@ void CGDebugInfo::emitVTableSymbol(llvm::GlobalVariable *VTable, const CXXRecordDecl *RD) { if (!CGM.getTarget().getCXXABI().isItaniumFamily()) return; + if (DebugKind <= llvm::codegenoptions::DebugLineTablesOnly) + return; ASTContext &Context = CGM.getContext(); StringRef SymbolName = "_vtable$"; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 90aed79..5a3d4e4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -93,6 +93,7 @@ static llvm::StringRef GetUBSanTrapForHandler(SanitizerHandler ID) { LIST_SANITIZER_CHECKS #undef SANITIZER_CHECK } + llvm_unreachable("unhandled switch case"); } /// CreateTempAlloca - This creates a alloca and inserts it into the entry diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index 2c0767f..dc54c97 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -978,7 +978,7 @@ CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { CI.getPreprocessor()); std::unique_ptr<BackendConsumer> Result(new BackendConsumer( - CI, BA, &CI.getVirtualFileSystem(), *VMContext, std::move(LinkModules), + CI, BA, CI.getVirtualFileSystemPtr(), *VMContext, std::move(LinkModules), InFile, std::move(OS), CoverageInfo)); BEConsumer = Result.get(); @@ -1156,7 +1156,7 @@ void CodeGenAction::ExecuteAction() { // Set clang diagnostic handler. To do this we need to create a fake // BackendConsumer. - BackendConsumer Result(CI, BA, &CI.getVirtualFileSystem(), *VMContext, + BackendConsumer Result(CI, BA, CI.getVirtualFileSystemPtr(), *VMContext, std::move(LinkModules), "", nullptr, nullptr, TheModule.get()); diff --git a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp index 95971e5..074f2a5 100644 --- a/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp +++ b/clang/lib/CodeGen/ObjectFilePCHContainerWriter.cpp @@ -146,7 +146,7 @@ public: : CI(CI), Diags(CI.getDiagnostics()), MainFileName(MainFileName), OutputFileName(OutputFileName), Ctx(nullptr), MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()), - FS(&CI.getVirtualFileSystem()), + FS(CI.getVirtualFileSystemPtr()), HeaderSearchOpts(CI.getHeaderSearchOpts()), PreprocessorOpts(CI.getPreprocessorOpts()), TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 99de951..586f287 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -3606,7 +3606,7 @@ class OffloadingActionBuilder final { if (!CompileDeviceOnly) { C.getDriver().Diag(diag::err_opt_not_valid_without_opt) << "-fhip-emit-relocatable" - << "--cuda-device-only"; + << "--offload-device-only"; } } } @@ -4774,6 +4774,21 @@ Action *Driver::BuildOffloadingActions(Compilation &C, C.isOffloadingHostKind(Action::OFK_HIP) && !Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc, false); + bool HIPRelocatableObj = + C.isOffloadingHostKind(Action::OFK_HIP) && + Args.hasFlag(options::OPT_fhip_emit_relocatable, + options::OPT_fno_hip_emit_relocatable, false); + + if (!HIPNoRDC && HIPRelocatableObj) + C.getDriver().Diag(diag::err_opt_not_valid_with_opt) + << "-fhip-emit-relocatable" + << "-fgpu-rdc"; + + if (!offloadDeviceOnly() && HIPRelocatableObj) + C.getDriver().Diag(diag::err_opt_not_valid_without_opt) + << "-fhip-emit-relocatable" + << "--offload-device-only"; + // For HIP non-rdc non-device-only compilation, create a linker wrapper // action for each host object to link, bundle and wrap device files in // it. @@ -4894,7 +4909,7 @@ Action *Driver::BuildOffloadingActions(Compilation &C, A->getOffloadingToolChain()->getTriple().isSPIRV(); if ((A->getType() != types::TY_Object && !IsAMDGCNSPIRV && A->getType() != types::TY_LTO_BC) || - !HIPNoRDC || !offloadDeviceOnly()) + HIPRelocatableObj || !HIPNoRDC || !offloadDeviceOnly()) continue; ActionList LinkerInput = {A}; A = C.MakeAction<LinkJobAction>(LinkerInput, types::TY_Image); diff --git a/clang/lib/Driver/ToolChains/AMDGPU.h b/clang/lib/Driver/ToolChains/AMDGPU.h index 513c77d..e5d41e2 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.h +++ b/clang/lib/Driver/ToolChains/AMDGPU.h @@ -10,7 +10,6 @@ #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_AMDGPU_H #include "Gnu.h" -#include "ROCm.h" #include "clang/Basic/TargetID.h" #include "clang/Driver/Options.h" #include "clang/Driver/Tool.h" diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp index 207150e..25a16fe 100644 --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -671,7 +671,8 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { CmdArgs.push_back("--start-group"); AddRunTimeLibs(TC, D, CmdArgs, Args); - CmdArgs.push_back("-lc"); + if (!Args.hasArg(options::OPT_nolibc)) + CmdArgs.push_back("-lc"); if (TC.hasValidGCCInstallation() || detectGCCToolchainAdjacent(D)) CmdArgs.push_back("-lgloss"); CmdArgs.push_back("--end-group"); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index d7c8208..4e1b1d9 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -16,6 +16,7 @@ #include "Arch/SystemZ.h" #include "Hexagon.h" #include "PS4CPU.h" +#include "ToolChains/Cuda.h" #include "clang/Basic/CLWarnings.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/HeaderInclude.h" @@ -225,17 +226,19 @@ static bool ShouldEnableAutolink(const ArgList &Args, const ToolChain &TC, static const char *addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs, const llvm::vfs::FileSystem &VFS) { + std::string DebugCompDir; if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, - options::OPT_fdebug_compilation_dir_EQ)) { - if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ)) - CmdArgs.push_back(Args.MakeArgString(Twine("-fdebug-compilation-dir=") + - A->getValue())); + options::OPT_fdebug_compilation_dir_EQ)) + DebugCompDir = A->getValue(); + + if (DebugCompDir.empty()) { + if (llvm::ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory()) + DebugCompDir = std::move(*CWD); else - A->render(Args, CmdArgs); - } else if (llvm::ErrorOr<std::string> CWD = - VFS.getCurrentWorkingDirectory()) { - CmdArgs.push_back(Args.MakeArgString("-fdebug-compilation-dir=" + *CWD)); + return nullptr; } + CmdArgs.push_back( + Args.MakeArgString("-fdebug-compilation-dir=" + DebugCompDir)); StringRef Path(CmdArgs.back()); return Path.substr(Path.find('=') + 1).data(); } @@ -524,17 +527,17 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, CmdArgs.push_back("-fcoverage-mcdc"); } + StringRef CoverageCompDir; if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, - options::OPT_fcoverage_compilation_dir_EQ)) { - if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ)) - CmdArgs.push_back(Args.MakeArgString( - Twine("-fcoverage-compilation-dir=") + A->getValue())); - else - A->render(Args, CmdArgs); - } else if (llvm::ErrorOr<std::string> CWD = - D.getVFS().getCurrentWorkingDirectory()) { - CmdArgs.push_back(Args.MakeArgString("-fcoverage-compilation-dir=" + *CWD)); - } + options::OPT_fcoverage_compilation_dir_EQ)) + CoverageCompDir = A->getValue(); + if (CoverageCompDir.empty()) { + if (auto CWD = D.getVFS().getCurrentWorkingDirectory()) + CmdArgs.push_back( + Args.MakeArgString(Twine("-fcoverage-compilation-dir=") + *CWD)); + } else + CmdArgs.push_back(Args.MakeArgString(Twine("-fcoverage-compilation-dir=") + + CoverageCompDir)); if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) { auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 3086c14..0771c7c 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -23,6 +23,7 @@ #include "Hexagon.h" #include "MSP430.h" #include "Solaris.h" +#include "ToolChains/Cuda.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" @@ -294,17 +295,22 @@ static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs, Format = A->getValue(); SmallString<128> F; - const Arg *A = Args.getLastArg(options::OPT_foptimization_record_file_EQ); - if (A) + if (const Arg *A = + Args.getLastArg(options::OPT_foptimization_record_file_EQ)) { + F = A->getValue(); + F += "."; + } else if (const Arg *A = Args.getLastArg(options::OPT_dumpdir)) { F = A->getValue(); - else if (Output.isFilename()) + } else if (Output.isFilename()) { F = Output.getFilename(); + F += "."; + } assert(!F.empty() && "Cannot determine remarks output name."); // Append "opt.ld.<format>" to the end of the file name. CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + - "opt-remarks-filename=" + F + - ".opt.ld." + Format)); + "opt-remarks-filename=" + F + "opt.ld." + + Format)); if (const Arg *A = Args.getLastArg(options::OPT_foptimization_record_passes_EQ)) @@ -1074,9 +1080,17 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, } } - if (Args.hasArg(options::OPT_gsplit_dwarf)) - CmdArgs.push_back(Args.MakeArgString( - Twine(PluginOptPrefix) + "dwo_dir=" + Output.getFilename() + "_dwo")); + if (Args.hasArg(options::OPT_gsplit_dwarf)) { + SmallString<128> F; + if (const Arg *A = Args.getLastArg(options::OPT_dumpdir)) { + F = A->getValue(); + } else { + F = Output.getFilename(); + F += "_"; + } + CmdArgs.push_back( + Args.MakeArgString(Twine(PluginOptPrefix) + "dwo_dir=" + F + "dwo")); + } if (IsThinLTO && !IsOSAIX) CmdArgs.push_back(Args.MakeArgString(Twine(PluginOptPrefix) + "thinlto")); diff --git a/clang/lib/Driver/ToolChains/Cuda.h b/clang/lib/Driver/ToolChains/Cuda.h index 259eda6..8aeba53 100644 --- a/clang/lib/Driver/ToolChains/Cuda.h +++ b/clang/lib/Driver/ToolChains/Cuda.h @@ -11,6 +11,7 @@ #include "clang/Basic/Cuda.h" #include "clang/Driver/Action.h" +#include "clang/Driver/CudaInstallationDetector.h" #include "clang/Driver/Multilib.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" @@ -22,61 +23,6 @@ namespace clang { namespace driver { - -/// A class to find a viable CUDA installation -class CudaInstallationDetector { -private: - const Driver &D; - bool IsValid = false; - CudaVersion Version = CudaVersion::UNKNOWN; - std::string InstallPath; - std::string BinPath; - std::string LibDevicePath; - std::string IncludePath; - llvm::StringMap<std::string> LibDeviceMap; - - // CUDA architectures for which we have raised an error in - // CheckCudaVersionSupportsArch. - mutable std::bitset<(int)OffloadArch::LAST> ArchsWithBadVersion; - -public: - CudaInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, - const llvm::opt::ArgList &Args); - - void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; - - /// Emit an error if Version does not support the given Arch. - /// - /// If either Version or Arch is unknown, does not emit an error. Emits at - /// most one error per Arch. - void CheckCudaVersionSupportsArch(OffloadArch Arch) const; - - /// Check whether we detected a valid Cuda install. - bool isValid() const { return IsValid; } - /// Print information about the detected CUDA installation. - void print(raw_ostream &OS) const; - - /// Get the detected Cuda install's version. - CudaVersion version() const { - return Version == CudaVersion::NEW ? CudaVersion::PARTIALLY_SUPPORTED - : Version; - } - /// Get the detected Cuda installation path. - StringRef getInstallPath() const { return InstallPath; } - /// Get the detected path to Cuda's bin directory. - StringRef getBinPath() const { return BinPath; } - /// Get the detected Cuda Include path. - StringRef getIncludePath() const { return IncludePath; } - /// Get the detected Cuda device library path. - StringRef getLibDevicePath() const { return LibDevicePath; } - /// Get libdevice file for given architecture - std::string getLibDeviceFile(StringRef Gpu) const { - return LibDeviceMap.lookup(Gpu); - } - void WarnIfUnsupportedVersion() const; -}; - namespace tools { namespace NVPTX { diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h index b38bfe6..d1cfb6f 100644 --- a/clang/lib/Driver/ToolChains/Darwin.h +++ b/clang/lib/Driver/ToolChains/Darwin.h @@ -9,12 +9,12 @@ #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DARWIN_H -#include "Cuda.h" -#include "LazyDetector.h" -#include "ROCm.h" -#include "SYCL.h" #include "clang/Basic/DarwinSDKInfo.h" #include "clang/Basic/LangOptions.h" +#include "clang/Driver/CudaInstallationDetector.h" +#include "clang/Driver/LazyDetector.h" +#include "clang/Driver/RocmInstallationDetector.h" +#include "clang/Driver/SyclInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "clang/Driver/XRayArgs.h" diff --git a/clang/lib/Driver/ToolChains/Gnu.h b/clang/lib/Driver/ToolChains/Gnu.h index 3b8df71..4c42a5e5 100644 --- a/clang/lib/Driver/ToolChains/Gnu.h +++ b/clang/lib/Driver/ToolChains/Gnu.h @@ -9,10 +9,10 @@ #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_GNU_H -#include "Cuda.h" -#include "LazyDetector.h" -#include "ROCm.h" -#include "SYCL.h" +#include "clang/Driver/CudaInstallationDetector.h" +#include "clang/Driver/LazyDetector.h" +#include "clang/Driver/RocmInstallationDetector.h" +#include "clang/Driver/SyclInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include <set> diff --git a/clang/lib/Driver/ToolChains/HIPAMD.h b/clang/lib/Driver/ToolChains/HIPAMD.h index bcc3ebb..30fc01a 100644 --- a/clang/lib/Driver/ToolChains/HIPAMD.h +++ b/clang/lib/Driver/ToolChains/HIPAMD.h @@ -10,6 +10,7 @@ #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HIPAMD_H #include "AMDGPU.h" +#include "clang/Driver/SyclInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" diff --git a/clang/lib/Driver/ToolChains/MSVC.h b/clang/lib/Driver/ToolChains/MSVC.h index b35390c..5c17edc 100644 --- a/clang/lib/Driver/ToolChains/MSVC.h +++ b/clang/lib/Driver/ToolChains/MSVC.h @@ -9,11 +9,11 @@ #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_MSVC_H -#include "AMDGPU.h" -#include "Cuda.h" -#include "LazyDetector.h" -#include "SYCL.h" #include "clang/Driver/Compilation.h" +#include "clang/Driver/CudaInstallationDetector.h" +#include "clang/Driver/LazyDetector.h" +#include "clang/Driver/RocmInstallationDetector.h" +#include "clang/Driver/SyclInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "llvm/Frontend/Debug/Options.h" diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp index 6abd0c0..1bb9bcf 100644 --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -85,11 +85,18 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, CmdArgs.push_back("-lmoldname"); CmdArgs.push_back("-lmingwex"); - for (auto Lib : Args.getAllArgValues(options::OPT_l)) + for (auto Lib : Args.getAllArgValues(options::OPT_l)) { if (StringRef(Lib).starts_with("msvcr") || StringRef(Lib).starts_with("ucrt") || - StringRef(Lib).starts_with("crtdll")) + StringRef(Lib).starts_with("crtdll")) { + std::string CRTLib = (llvm::Twine("-l") + Lib).str(); + // Respect the user's chosen crt variant, but still provide it + // again as the last linker argument, because some of the libraries + // we added above may depend on it. + CmdArgs.push_back(Args.MakeArgStringRef(CRTLib)); return; + } + } CmdArgs.push_back("-lmsvcrt"); } diff --git a/clang/lib/Driver/ToolChains/MinGW.h b/clang/lib/Driver/ToolChains/MinGW.h index a9963d8..1730da4 100644 --- a/clang/lib/Driver/ToolChains/MinGW.h +++ b/clang/lib/Driver/ToolChains/MinGW.h @@ -11,8 +11,9 @@ #include "Cuda.h" #include "Gnu.h" -#include "LazyDetector.h" -#include "ROCm.h" +#include "clang/Driver/CudaInstallationDetector.h" +#include "clang/Driver/LazyDetector.h" +#include "clang/Driver/RocmInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" #include "llvm/Support/ErrorOr.h" diff --git a/clang/lib/Driver/ToolChains/SYCL.h b/clang/lib/Driver/ToolChains/SYCL.h index 2a8b4ec..be4ba47 100644 --- a/clang/lib/Driver/ToolChains/SYCL.h +++ b/clang/lib/Driver/ToolChains/SYCL.h @@ -9,21 +9,12 @@ #ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SYCL_H #define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_SYCL_H +#include "clang/Driver/SyclInstallationDetector.h" #include "clang/Driver/Tool.h" #include "clang/Driver/ToolChain.h" namespace clang { namespace driver { - -class SYCLInstallationDetector { -public: - SYCLInstallationDetector(const Driver &D, const llvm::Triple &HostTriple, - const llvm::opt::ArgList &Args); - - void addSYCLIncludeArgs(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const; -}; - namespace toolchains { class LLVM_LIBRARY_VISIBILITY SYCLToolChain : public ToolChain { diff --git a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp index 80487fa..7772a56 100644 --- a/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp +++ b/clang/lib/Format/IntegerLiteralSeparatorFixer.cpp @@ -45,15 +45,18 @@ std::pair<tooling::Replacements, unsigned> IntegerLiteralSeparatorFixer::process(const Environment &Env, const FormatStyle &Style) { switch (Style.Language) { - case FormatStyle::LK_Cpp: - case FormatStyle::LK_ObjC: - Separator = '\''; - break; case FormatStyle::LK_CSharp: case FormatStyle::LK_Java: case FormatStyle::LK_JavaScript: Separator = '_'; break; + case FormatStyle::LK_Cpp: + case FormatStyle::LK_ObjC: + if (Style.Standard >= FormatStyle::LS_Cpp14) { + Separator = '\''; + break; + } + [[fallthrough]]; default: return {}; } diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 67ed17b..09caf85 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -1773,7 +1773,7 @@ std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation( if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), PrecompilePreambleAfterNParses, - &AST->FileMgr->getVirtualFileSystem())) + AST->FileMgr->getVirtualFileSystemPtr())) return nullptr; return AST; } @@ -1895,7 +1895,7 @@ bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, if (!VFS) { assert(FileMgr && "FileMgr is null on Reparse call"); - VFS = &FileMgr->getVirtualFileSystem(); + VFS = FileMgr->getVirtualFileSystemPtr(); } clearFileLevelDecls(); @@ -2321,7 +2321,8 @@ void ASTUnit::CodeComplete( std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; if (Preamble && Line > 1 && hasSameUniqueID(File, OriginalSourceFile)) { OverrideMainBuffer = getMainBufferWithPrecompiledPreamble( - PCHContainerOps, Inv, &FileMgr.getVirtualFileSystem(), false, Line - 1); + PCHContainerOps, Inv, FileMgr.getVirtualFileSystemPtr(), false, + Line - 1); } // If the main file has been overridden due to the use of a preamble, @@ -2331,7 +2332,7 @@ void ASTUnit::CodeComplete( "No preamble was built, but OverrideMainBuffer is not null"); IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = - &FileMgr.getVirtualFileSystem(); + FileMgr.getVirtualFileSystemPtr(); Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS, OverrideMainBuffer.get()); // FIXME: there is no way to update VFS if it was changed by diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index c7b82db..40fb070 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -160,6 +160,11 @@ llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const { return getFileManager().getVirtualFileSystem(); } +llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> +CompilerInstance::getVirtualFileSystemPtr() const { + return getFileManager().getVirtualFileSystemPtr(); +} + void CompilerInstance::setFileManager(FileManager *Value) { FileMgr = Value; } @@ -375,7 +380,7 @@ IntrusiveRefCntPtr<DiagnosticsEngine> CompilerInstance::createDiagnostics( FileManager *CompilerInstance::createFileManager( IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { if (!VFS) - VFS = FileMgr ? &FileMgr->getVirtualFileSystem() + VFS = FileMgr ? FileMgr->getVirtualFileSystemPtr() : createVFSFromCompilerInvocation(getInvocation(), getDiagnostics()); assert(VFS && "FileManager has no VFS?"); @@ -1218,7 +1223,7 @@ std::unique_ptr<CompilerInstance> CompilerInstance::cloneForModuleCompileImpl( } else if (FrontendOpts.ModulesShareFileManager) { Instance.setFileManager(&getFileManager()); } else { - Instance.createFileManager(&getVirtualFileSystem()); + Instance.createFileManager(getVirtualFileSystemPtr()); } if (ThreadSafeConfig) { diff --git a/clang/lib/Frontend/PrecompiledPreamble.cpp b/clang/lib/Frontend/PrecompiledPreamble.cpp index 146cf90..486cd95 100644 --- a/clang/lib/Frontend/PrecompiledPreamble.cpp +++ b/clang/lib/Frontend/PrecompiledPreamble.cpp @@ -57,11 +57,9 @@ createVFSOverlayForPreamblePCH(StringRef PCHFilename, IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { // We want only the PCH file from the real filesystem to be available, // so we create an in-memory VFS with just that and overlay it on top. - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> PCHFS( - new llvm::vfs::InMemoryFileSystem()); + auto PCHFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); PCHFS->addFile(PCHFilename, 0, std::move(PCHBuffer)); - IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> Overlay( - new llvm::vfs::OverlayFileSystem(VFS)); + auto Overlay = llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(VFS); Overlay->pushOverlay(PCHFS); return Overlay; } diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h index e8ccccb..c877234 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h @@ -12,7 +12,7 @@ namespace hlsl { namespace __detail { -constexpr vector<uint, 4> d3d_color_to_ubyte4_impl(vector<float, 4> V) { +constexpr int4 d3d_color_to_ubyte4_impl(float4 V) { // Use the same scaling factor used by FXC, and DXC for DXIL // (i.e., 255.001953) // https://github.com/microsoft/DirectXShaderCompiler/blob/070d0d5a2beacef9eeb51037a9b04665716fd6f3/lib/HLSL/HLOperationLower.cpp#L666C1-L697C2 diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index 499a053..d9d87c8 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -418,7 +418,7 @@ const inline float4 lit(float NDotL, float NDotH, float M) { /// This function swizzles and scales components of the \a x parameter. Use this /// function to compensate for the lack of UBYTE4 support in some hardware. -constexpr vector<uint, 4> D3DCOLORtoUBYTE4(vector<float, 4> V) { +constexpr int4 D3DCOLORtoUBYTE4(float4 V) { return __detail::d3d_color_to_ubyte4_impl(V); } diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index 829c81b..35ad0b5 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -503,8 +503,12 @@ static bool areAllValuesNoReturn(const VarDecl *VD, const CFGBlock &VarBlk, TransferFunctions TF(VD); BackwardDataflowWorklist Worklist(*AC.getCFG(), AC); + llvm::DenseSet<const CFGBlock *> Visited; Worklist.enqueueBlock(&VarBlk); while (const CFGBlock *B = Worklist.dequeue()) { + if (Visited.contains(B)) + continue; + Visited.insert(B); // First check the current block. for (CFGBlock::const_reverse_iterator ri = B->rbegin(), re = B->rend(); ri != re; ++ri) { diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index d50eeff..43a7f9e 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -2251,16 +2251,15 @@ void Sema::checkTypeSupport(QualType Ty, SourceLocation Loc, ValueDecl *D) { } // Don't allow SVE types in functions without a SVE target. - if (Ty->isSVESizelessBuiltinType() && FD) { + if (Ty->isSVESizelessBuiltinType() && FD && !FD->getType().isNull()) { llvm::StringMap<bool> CallerFeatureMap; Context.getFunctionFeatureMap(CallerFeatureMap, FD); if (!Builtin::evaluateRequiredTargetFeatures("sve", CallerFeatureMap)) { if (!Builtin::evaluateRequiredTargetFeatures("sme", CallerFeatureMap)) Diag(Loc, diag::err_sve_vector_in_non_sve_target) << Ty; else if (!IsArmStreamingFunction(FD, - /*IncludeLocallyStreaming=*/true)) { + /*IncludeLocallyStreaming=*/true)) Diag(Loc, diag::err_sve_vector_in_non_streaming_function) << Ty; - } } } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index c74b671..bc87611 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -15893,9 +15893,7 @@ ExprResult Sema::BuiltinMatrixTranspose(CallExpr *TheCall, // Get and verify the matrix dimensions. static std::optional<unsigned> getAndVerifyMatrixDimension(Expr *Expr, StringRef Name, Sema &S) { - SourceLocation ErrorPos; - std::optional<llvm::APSInt> Value = - Expr->getIntegerConstantExpr(S.Context, &ErrorPos); + std::optional<llvm::APSInt> Value = Expr->getIntegerConstantExpr(S.Context); if (!Value) { S.Diag(Expr->getBeginLoc(), diag::err_builtin_matrix_scalar_unsigned_arg) << Name; diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index a43ac9e..0de5580 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -4034,6 +4034,14 @@ static void AddOverloadParameterChunks( return; } + // C++23 introduces an explicit object parameter, a.k.a. "deducing this" + // Skip it for autocomplete and treat the next parameter as the first + // parameter + if (Function && FirstParameter && + Function->getParamDecl(P)->isExplicitObjectParameter()) { + continue; + } + if (FirstParameter) FirstParameter = false; else diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 044cf5c..da85959 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1105,10 +1105,6 @@ static bool CheckFunctionConstraintsWithoutInstantiation( } Sema::ContextRAII SavedContext(SemaRef, FD); - std::optional<Sema::CXXThisScopeRAII> ThisScope; - if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) - ThisScope.emplace(SemaRef, /*Record=*/Method->getParent(), - /*ThisQuals=*/Method->getMethodQualifiers()); return SemaRef.CheckConstraintSatisfaction( Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 698d127..21fed2e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4749,8 +4749,6 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS, EnterExpressionEvaluationContext EECtx{ *this, ExpressionEvaluationContext::Unevaluated, CSD}; - ContextRAII CurContext(*this, CSD->getDeclContext(), - /*NewThisContext=*/false); if (!AreArgsDependent && CheckConstraintSatisfaction( NamedConcept, AssociatedConstraint(NamedConcept->getConstraintExpr()), diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1d8687e..c2f0600 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,9 +11,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/DeclCXX.h" -#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" -#include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/TypeTraits.h" @@ -1965,7 +1963,6 @@ static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) { .Case("is_assignable", TypeTrait::BTT_IsAssignable) .Case("is_empty", TypeTrait::UTT_IsEmpty) .Case("is_standard_layout", TypeTrait::UTT_IsStandardLayout) - .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -2002,16 +1999,8 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; - for (const auto &Arg : VD->getTemplateArgs().asArray()) { - if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { - for (const auto &InnerArg : Arg.pack_elements()) - Args.push_back(InnerArg.getAsType()); - } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) { - Args.push_back(Arg.getAsType()); - } else { - llvm_unreachable("Unexpected kind"); - } - } + for (const auto &Arg : VD->getTemplateArgs().asArray()) + Args.push_back(Arg.getAsType()); return {{Trait.value(), std::move(Args)}}; } @@ -2284,60 +2273,6 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } -static void DiagnoseNonConstructibleReason( - Sema &SemaRef, SourceLocation Loc, - const llvm::SmallVector<clang::QualType, 1> &Ts) { - if (Ts.empty()) { - return; - } - - bool ContainsVoid = false; - for (const QualType &ArgTy : Ts) { - ContainsVoid |= ArgTy->isVoidType(); - } - - if (ContainsVoid) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::CVVoidType; - - QualType T = Ts[0]; - if (T->isFunctionType()) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::FunctionType; - - if (T->isIncompleteArrayType()) - SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) - << diag::TraitNotSatisfiedReason::IncompleteArrayType; - - const CXXRecordDecl *D = T->getAsCXXRecordDecl(); - if (!D || D->isInvalidDecl() || !D->hasDefinition()) - return; - - llvm::BumpPtrAllocator OpaqueExprAllocator; - SmallVector<Expr *, 2> ArgExprs; - ArgExprs.reserve(Ts.size() - 1); - for (unsigned I = 1, N = Ts.size(); I != N; ++I) { - QualType ArgTy = Ts[I]; - if (ArgTy->isObjectType() || ArgTy->isFunctionType()) - ArgTy = SemaRef.Context.getRValueReferenceType(ArgTy); - ArgExprs.push_back( - new (OpaqueExprAllocator.Allocate<OpaqueValueExpr>()) - OpaqueValueExpr(Loc, ArgTy.getNonLValueExprType(SemaRef.Context), - Expr::getValueKindForType(ArgTy))); - } - - EnterExpressionEvaluationContext Unevaluated( - SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); - Sema::ContextRAII TUContext(SemaRef, - SemaRef.Context.getTranslationUnitDecl()); - InitializedEntity To(InitializedEntity::InitializeTemporary(T)); - InitializationKind InitKind(InitializationKind::CreateDirect(Loc, Loc, Loc)); - InitializationSequence Init(SemaRef, To, InitKind, ArgExprs); - - Init.Diagnose(SemaRef, To, InitKind, ArgExprs); - SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; -} - static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SourceLocation Loc, QualType T) { SemaRef.Diag(Loc, diag::note_unsatisfied_trait) @@ -2624,9 +2559,6 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) { case UTT_IsStandardLayout: DiagnoseNonStandardLayoutReason(*this, E->getBeginLoc(), Args[0]); break; - case TT_IsConstructible: - DiagnoseNonConstructibleReason(*this, E->getBeginLoc(), Args); - break; default: break; } diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 88feb6a..e682c4e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -99,7 +99,7 @@ class NilArgChecker : public Checker<check::PreObjCMessage, check::PostStmt<ObjCDictionaryLiteral>, check::PostStmt<ObjCArrayLiteral>, EventDispatcher<ImplicitNullDerefEvent>> { - mutable std::unique_ptr<APIMisuse> BT; + const APIMisuse BT{this, "nil argument"}; mutable llvm::SmallDenseMap<Selector, unsigned, 16> StringSelectors; mutable Selector ArrayWithObjectSel; @@ -218,10 +218,7 @@ void NilArgChecker::generateBugReport(ExplodedNode *N, SourceRange Range, const Expr *E, CheckerContext &C) const { - if (!BT) - BT.reset(new APIMisuse(this, "nil argument")); - - auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N); + auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N); R->addRange(Range); bugreporter::trackExpressionValue(N, E, *R); C.emitReport(std::move(R)); @@ -350,7 +347,7 @@ void NilArgChecker::checkPostStmt(const ObjCDictionaryLiteral *DL, namespace { class CFNumberChecker : public Checker< check::PreStmt<CallExpr> > { - mutable std::unique_ptr<APIMisuse> BT; + const APIMisuse BT{this, "Bad use of CFNumber APIs"}; mutable IdentifierInfo *ICreate = nullptr, *IGetValue = nullptr; public: CFNumberChecker() = default; @@ -524,10 +521,7 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE, << " bits of the integer value will be " << (isCreate ? "lost." : "garbage."); - if (!BT) - BT.reset(new APIMisuse(this, "Bad use of CFNumber APIs")); - - auto report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N); + auto report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N); report->addRange(CE->getArg(2)->getSourceRange()); C.emitReport(std::move(report)); } @@ -539,7 +533,7 @@ void CFNumberChecker::checkPreStmt(const CallExpr *CE, namespace { class CFRetainReleaseChecker : public Checker<check::PreCall> { - mutable APIMisuse BT{this, "null passed to CF memory management function"}; + const APIMisuse BT{this, "null passed to CF memory management function"}; const CallDescriptionSet ModelledCalls = { {CDM::CLibrary, {"CFRetain"}, 1}, {CDM::CLibrary, {"CFRelease"}, 1}, @@ -600,7 +594,8 @@ class ClassReleaseChecker : public Checker<check::PreObjCMessage> { mutable Selector retainS; mutable Selector autoreleaseS; mutable Selector drainS; - mutable std::unique_ptr<BugType> BT; + const APIMisuse BT{ + this, "message incorrectly sent to class instead of class instance"}; public: void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const; @@ -609,10 +604,7 @@ public: void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const { - if (!BT) { - BT.reset(new APIMisuse( - this, "message incorrectly sent to class instead of class instance")); - + if (releaseS.isNull()) { ASTContext &Ctx = C.getASTContext(); releaseS = GetNullarySelector("release", Ctx); retainS = GetNullarySelector("retain", Ctx); @@ -639,7 +631,7 @@ void ClassReleaseChecker::checkPreObjCMessage(const ObjCMethodCall &msg, "of class '" << Class->getName() << "' and not the class directly"; - auto report = std::make_unique<PathSensitiveBugReport>(*BT, os.str(), N); + auto report = std::make_unique<PathSensitiveBugReport>(BT, os.str(), N); report->addRange(msg.getSourceRange()); C.emitReport(std::move(report)); } @@ -658,7 +650,8 @@ class VariadicMethodTypeChecker : public Checker<check::PreObjCMessage> { mutable Selector orderedSetWithObjectsS; mutable Selector initWithObjectsS; mutable Selector initWithObjectsAndKeysS; - mutable std::unique_ptr<BugType> BT; + const APIMisuse BT{this, "Arguments passed to variadic method aren't all " + "Objective-C pointer types"}; bool isVariadicMessage(const ObjCMethodCall &msg) const; @@ -717,11 +710,7 @@ VariadicMethodTypeChecker::isVariadicMessage(const ObjCMethodCall &msg) const { void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const { - if (!BT) { - BT.reset(new APIMisuse(this, - "Arguments passed to variadic method aren't all " - "Objective-C pointer types")); - + if (arrayWithObjectsS.isNull()) { ASTContext &Ctx = C.getASTContext(); arrayWithObjectsS = GetUnarySelector("arrayWithObjects", Ctx); dictionaryWithObjectsAndKeysS = @@ -792,8 +781,7 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(const ObjCMethodCall &msg, ArgTy.print(os, C.getLangOpts()); os << "'"; - auto R = - std::make_unique<PathSensitiveBugReport>(*BT, os.str(), *errorNode); + auto R = std::make_unique<PathSensitiveBugReport>(BT, os.str(), *errorNode); R->addRange(msg.getArgSourceRange(I)); C.emitReport(std::move(R)); } diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 31cb150..fd0a398 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -78,35 +78,30 @@ static QualType getCharPtrType(ASTContext &Ctx, CharKind CK) { : Ctx.WideCharTy); } -class CStringChecker : public Checker< eval::Call, - check::PreStmt<DeclStmt>, - check::LiveSymbols, - check::DeadSymbols, - check::RegionChanges - > { - mutable std::unique_ptr<BugType> BT_Null, BT_Bounds, BT_Overlap, - BT_NotCString, BT_AdditionOverflow, BT_UninitRead; - +class CStringChecker + : public CheckerFamily<eval::Call, check::PreStmt<DeclStmt>, + check::LiveSymbols, check::DeadSymbols, + check::RegionChanges> { mutable const char *CurrentFunctionDescription = nullptr; public: - /// The filter is used to filter out the diagnostics which are not enabled by - /// the user. - struct CStringChecksFilter { - bool CheckCStringNullArg = false; - bool CheckCStringOutOfBounds = false; - bool CheckCStringBufferOverlap = false; - bool CheckCStringNotNullTerm = false; - bool CheckCStringUninitializedRead = false; - - CheckerNameRef CheckNameCStringNullArg; - CheckerNameRef CheckNameCStringOutOfBounds; - CheckerNameRef CheckNameCStringBufferOverlap; - CheckerNameRef CheckNameCStringNotNullTerm; - CheckerNameRef CheckNameCStringUninitializedRead; - }; - - CStringChecksFilter Filter; + // FIXME: The bug types emitted by this checker family have confused garbage + // in their Description and Category fields (e.g. `categories::UnixAPI` is + // passed as the description in several cases and `uninitialized` is mistyped + // as `unitialized`). This should be cleaned up. + CheckerFrontendWithBugType NullArg{categories::UnixAPI}; + CheckerFrontendWithBugType OutOfBounds{"Out-of-bound array access"}; + CheckerFrontendWithBugType BufferOverlap{categories::UnixAPI, + "Improper arguments"}; + CheckerFrontendWithBugType NotNullTerm{categories::UnixAPI}; + CheckerFrontendWithBugType UninitializedRead{ + "Accessing unitialized/garbage values"}; + + // FIXME: This bug type should be removed because it is only emitted in a + // situation that is practically impossible. + const BugType AdditionOverflow{&OutOfBounds, "API"}; + + StringRef getDebugTag() const override { return "MallocChecker"; } static void *getTag() { static int tag; return &tag; } @@ -384,7 +379,7 @@ ProgramStateRef CStringChecker::checkNonNull(CheckerContext &C, assumeZero(C, State, l, Arg.Expression->getType()); if (stateNull && !stateNonNull) { - if (Filter.CheckCStringNullArg) { + if (NullArg.isEnabled()) { SmallString<80> buf; llvm::raw_svector_ostream OS(buf); assert(CurrentFunctionDescription); @@ -468,7 +463,7 @@ ProgramStateRef CStringChecker::checkInit(CheckerContext &C, return State; // Ensure that we wouldn't read uninitialized value. - if (Filter.CheckCStringUninitializedRead && + if (UninitializedRead.isEnabled() && State->getSVal(*FirstElementVal).isUndef()) { llvm::SmallString<258> Buf; llvm::raw_svector_ostream OS(Buf); @@ -524,7 +519,7 @@ ProgramStateRef CStringChecker::checkInit(CheckerContext &C, if (!isa<Loc>(LastElementVal)) return State; - if (Filter.CheckCStringUninitializedRead && + if (UninitializedRead.isEnabled() && State->getSVal(LastElementVal.castAs<Loc>()).isUndef()) { const llvm::APSInt *IdxInt = LastIdx.getAsInteger(); // If we can't get emit a sensible last element index, just bail out -- @@ -581,13 +576,9 @@ ProgramStateRef CStringChecker::CheckLocation(CheckerContext &C, auto [StInBound, StOutBound] = state->assumeInBoundDual(*Idx, Size); if (StOutBound && !StInBound) { - // These checks are either enabled by the CString out-of-bounds checker - // explicitly or implicitly by the Malloc checker. - // In the latter case we only do modeling but do not emit warning. - if (!Filter.CheckCStringOutOfBounds) + if (!OutOfBounds.isEnabled()) return nullptr; - // Emit a bug report. ErrorMessage Message = createOutOfBoundErrorMsg(CurrentFunctionDescription, Access); emitOutOfBoundsBug(C, StOutBound, Buffer.Expression, Message); @@ -620,7 +611,7 @@ CStringChecker::CheckBufferAccess(CheckerContext &C, ProgramStateRef State, return nullptr; // If out-of-bounds checking is turned off, skip the rest. - if (!Filter.CheckCStringOutOfBounds) + if (!OutOfBounds.isEnabled()) return State; SVal BufStart = @@ -670,7 +661,7 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C, SizeArgExpr Size, AnyArgExpr First, AnyArgExpr Second, CharKind CK) const { - if (!Filter.CheckCStringBufferOverlap) + if (!BufferOverlap.isEnabled()) return state; // Do a simple check for overlap: if the two arguments are from the same @@ -789,13 +780,9 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state, if (!N) return; - if (!BT_Overlap) - BT_Overlap.reset(new BugType(Filter.CheckNameCStringBufferOverlap, - categories::UnixAPI, "Improper arguments")); - // Generate a report for this bug. auto report = std::make_unique<PathSensitiveBugReport>( - *BT_Overlap, "Arguments must not be overlapping buffers", N); + BufferOverlap, "Arguments must not be overlapping buffers", N); report->addRange(First->getSourceRange()); report->addRange(Second->getSourceRange()); @@ -805,15 +792,8 @@ void CStringChecker::emitOverlapBug(CheckerContext &C, ProgramStateRef state, void CStringChecker::emitNullArgBug(CheckerContext &C, ProgramStateRef State, const Stmt *S, StringRef WarningMsg) const { if (ExplodedNode *N = C.generateErrorNode(State)) { - if (!BT_Null) { - // FIXME: This call uses the string constant 'categories::UnixAPI' as the - // description of the bug; it should be replaced by a real description. - BT_Null.reset( - new BugType(Filter.CheckNameCStringNullArg, categories::UnixAPI)); - } - auto Report = - std::make_unique<PathSensitiveBugReport>(*BT_Null, WarningMsg, N); + std::make_unique<PathSensitiveBugReport>(NullArg, WarningMsg, N); Report->addRange(S->getSourceRange()); if (const auto *Ex = dyn_cast<Expr>(S)) bugreporter::trackExpressionValue(N, Ex, *Report); @@ -826,12 +806,8 @@ void CStringChecker::emitUninitializedReadBug(CheckerContext &C, const Expr *E, const MemRegion *R, StringRef Msg) const { if (ExplodedNode *N = C.generateErrorNode(State)) { - if (!BT_UninitRead) - BT_UninitRead.reset(new BugType(Filter.CheckNameCStringUninitializedRead, - "Accessing unitialized/garbage values")); - auto Report = - std::make_unique<PathSensitiveBugReport>(*BT_UninitRead, Msg, N); + std::make_unique<PathSensitiveBugReport>(UninitializedRead, Msg, N); Report->addNote("Other elements might also be undefined", Report->getLocation()); Report->addRange(E->getSourceRange()); @@ -845,17 +821,11 @@ void CStringChecker::emitOutOfBoundsBug(CheckerContext &C, ProgramStateRef State, const Stmt *S, StringRef WarningMsg) const { if (ExplodedNode *N = C.generateErrorNode(State)) { - if (!BT_Bounds) - BT_Bounds.reset(new BugType(Filter.CheckCStringOutOfBounds - ? Filter.CheckNameCStringOutOfBounds - : Filter.CheckNameCStringNullArg, - "Out-of-bound array access")); - // FIXME: It would be nice to eventually make this diagnostic more clear, // e.g., by referencing the original declaration or by saying *why* this // reference is outside the range. auto Report = - std::make_unique<PathSensitiveBugReport>(*BT_Bounds, WarningMsg, N); + std::make_unique<PathSensitiveBugReport>(OutOfBounds, WarningMsg, N); Report->addRange(S->getSourceRange()); C.emitReport(std::move(Report)); } @@ -865,15 +835,8 @@ void CStringChecker::emitNotCStringBug(CheckerContext &C, ProgramStateRef State, const Stmt *S, StringRef WarningMsg) const { if (ExplodedNode *N = C.generateNonFatalErrorNode(State)) { - if (!BT_NotCString) { - // FIXME: This call uses the string constant 'categories::UnixAPI' as the - // description of the bug; it should be replaced by a real description. - BT_NotCString.reset( - new BugType(Filter.CheckNameCStringNotNullTerm, categories::UnixAPI)); - } - auto Report = - std::make_unique<PathSensitiveBugReport>(*BT_NotCString, WarningMsg, N); + std::make_unique<PathSensitiveBugReport>(NotNullTerm, WarningMsg, N); Report->addRange(S->getSourceRange()); C.emitReport(std::move(Report)); @@ -883,14 +846,6 @@ void CStringChecker::emitNotCStringBug(CheckerContext &C, ProgramStateRef State, void CStringChecker::emitAdditionOverflowBug(CheckerContext &C, ProgramStateRef State) const { if (ExplodedNode *N = C.generateErrorNode(State)) { - if (!BT_AdditionOverflow) { - // FIXME: This call uses the word "API" as the description of the bug; - // it should be replaced by a better error message (if this unlikely - // situation continues to exist as a separate bug type). - BT_AdditionOverflow.reset( - new BugType(Filter.CheckNameCStringOutOfBounds, "API")); - } - // This isn't a great error message, but this should never occur in real // code anyway -- you'd have to create a buffer longer than a size_t can // represent, which is sort of a contradiction. @@ -898,7 +853,7 @@ void CStringChecker::emitAdditionOverflowBug(CheckerContext &C, "This expression will create a string whose length is too big to " "be represented as a size_t"; - auto Report = std::make_unique<PathSensitiveBugReport>(*BT_AdditionOverflow, + auto Report = std::make_unique<PathSensitiveBugReport>(AdditionOverflow, WarningMsg, N); C.emitReport(std::move(Report)); } @@ -909,7 +864,7 @@ ProgramStateRef CStringChecker::checkAdditionOverflow(CheckerContext &C, NonLoc left, NonLoc right) const { // If out-of-bounds checking is turned off, skip the rest. - if (!Filter.CheckCStringOutOfBounds) + if (!OutOfBounds.isEnabled()) return state; // If a previous check has failed, propagate the failure. @@ -1048,7 +1003,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state, // C string. In the context of locations, the only time we can issue such // a warning is for labels. if (std::optional<loc::GotoLabel> Label = Buf.getAs<loc::GotoLabel>()) { - if (Filter.CheckCStringNotNullTerm) { + if (NotNullTerm.isEnabled()) { SmallString<120> buf; llvm::raw_svector_ostream os(buf); assert(CurrentFunctionDescription); @@ -1110,7 +1065,7 @@ SVal CStringChecker::getCStringLength(CheckerContext &C, ProgramStateRef &state, // Other regions (mostly non-data) can't have a reliable C string length. // In this case, an error is emitted and UndefinedVal is returned. // The caller should always be prepared to handle this case. - if (Filter.CheckCStringNotNullTerm) { + if (NotNullTerm.isEnabled()) { SmallString<120> buf; llvm::raw_svector_ostream os(buf); @@ -2873,24 +2828,27 @@ void CStringChecker::checkDeadSymbols(SymbolReaper &SR, } void ento::registerCStringModeling(CheckerManager &Mgr) { - Mgr.registerChecker<CStringChecker>(); + // Other checker relies on the modeling implemented in this checker family, + // so this "modeling checker" can register the 'CStringChecker' backend for + // its callbacks without enabling any of its frontends. + Mgr.getChecker<CStringChecker>(); } -bool ento::shouldRegisterCStringModeling(const CheckerManager &mgr) { +bool ento::shouldRegisterCStringModeling(const CheckerManager &) { return true; } -#define REGISTER_CHECKER(name) \ - void ento::register##name(CheckerManager &mgr) { \ - CStringChecker *checker = mgr.getChecker<CStringChecker>(); \ - checker->Filter.Check##name = true; \ - checker->Filter.CheckName##name = mgr.getCurrentCheckerName(); \ +#define REGISTER_CHECKER(NAME) \ + void ento::registerCString##NAME(CheckerManager &Mgr) { \ + Mgr.getChecker<CStringChecker>()->NAME.enable(Mgr); \ } \ \ - bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; } + bool ento::shouldRegisterCString##NAME(const CheckerManager &) { \ + return true; \ + } -REGISTER_CHECKER(CStringNullArg) -REGISTER_CHECKER(CStringOutOfBounds) -REGISTER_CHECKER(CStringBufferOverlap) -REGISTER_CHECKER(CStringNotNullTerm) -REGISTER_CHECKER(CStringUninitializedRead) +REGISTER_CHECKER(NullArg) +REGISTER_CHECKER(OutOfBounds) +REGISTER_CHECKER(BufferOverlap) +REGISTER_CHECKER(NotNullTerm) +REGISTER_CHECKER(UninitializedRead) diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp index 839c8bc..a227ca0 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CheckPlacementNew.cpp @@ -111,32 +111,12 @@ bool PlacementNewChecker::checkPlaceCapacityIsSufficient( if (!SizeOfPlaceCI) return true; - if ((SizeOfPlaceCI->getValue() < SizeOfTargetCI->getValue()) || - (IsArrayTypeAllocated && - SizeOfPlaceCI->getValue() >= SizeOfTargetCI->getValue())) { + if ((SizeOfPlaceCI->getValue() < SizeOfTargetCI->getValue())) { if (ExplodedNode *N = C.generateErrorNode(C.getState())) { - std::string Msg; - // TODO: use clang constant - if (IsArrayTypeAllocated && - SizeOfPlaceCI->getValue() > SizeOfTargetCI->getValue()) - Msg = std::string(llvm::formatv( - "{0} bytes is possibly not enough for array allocation which " - "requires {1} bytes. Current overhead requires the size of {2} " - "bytes", - SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue(), - *SizeOfPlaceCI->getValue() - SizeOfTargetCI->getValue())); - else if (IsArrayTypeAllocated && - SizeOfPlaceCI->getValue() == SizeOfTargetCI->getValue()) - Msg = std::string(llvm::formatv( - "Storage provided to placement new is only {0} bytes, " - "whereas the allocated array type requires more space for " - "internal needs", - SizeOfPlaceCI->getValue())); - else - Msg = std::string(llvm::formatv( - "Storage provided to placement new is only {0} bytes, " - "whereas the allocated type requires {1} bytes", - SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue())); + std::string Msg = + llvm::formatv("Storage provided to placement new is only {0} bytes, " + "whereas the allocated type requires {1} bytes", + SizeOfPlaceCI->getValue(), SizeOfTargetCI->getValue()); auto R = std::make_unique<PathSensitiveBugReport>(SBT, Msg, N); bugreporter::trackExpressionValue(N, NE->getPlacementArg(0), *R); diff --git a/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp index 15fd9a0..d2760ca 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp @@ -142,34 +142,19 @@ void CFErrorFunctionChecker::checkASTDecl(const FunctionDecl *D, //===----------------------------------------------------------------------===// namespace { +class NSOrCFErrorDerefChecker + : public CheckerFamily<check::Location, + check::Event<ImplicitNullDerefEvent>> { + mutable IdentifierInfo *NSErrorII = nullptr; + mutable IdentifierInfo *CFErrorII = nullptr; -class NSErrorDerefBug : public BugType { -public: - NSErrorDerefBug(const CheckerNameRef Checker) - : BugType(Checker, "NSError** null dereference", - "Coding conventions (Apple)") {} -}; - -class CFErrorDerefBug : public BugType { public: - CFErrorDerefBug(const CheckerNameRef Checker) - : BugType(Checker, "CFErrorRef* null dereference", - "Coding conventions (Apple)") {} -}; - -} + CheckerFrontendWithBugType NSError{"NSError** null dereference", + "Coding conventions (Apple)"}; + CheckerFrontendWithBugType CFError{"CFErrorRef* null dereference", + "Coding conventions (Apple)"}; -namespace { -class NSOrCFErrorDerefChecker - : public Checker< check::Location, - check::Event<ImplicitNullDerefEvent> > { - mutable IdentifierInfo *NSErrorII, *CFErrorII; - mutable std::unique_ptr<NSErrorDerefBug> NSBT; - mutable std::unique_ptr<CFErrorDerefBug> CFBT; -public: - bool ShouldCheckNSError = false, ShouldCheckCFError = false; - CheckerNameRef NSErrorName, CFErrorName; - NSOrCFErrorDerefChecker() : NSErrorII(nullptr), CFErrorII(nullptr) {} + StringRef getDebugTag() const override { return "NSOrCFErrorDerefChecker"; } void checkLocation(SVal loc, bool isLoad, const Stmt *S, CheckerContext &C) const; @@ -236,12 +221,12 @@ void NSOrCFErrorDerefChecker::checkLocation(SVal loc, bool isLoad, if (!CFErrorII) CFErrorII = &Ctx.Idents.get("CFErrorRef"); - if (ShouldCheckNSError && IsNSError(parmT, NSErrorII)) { + if (NSError.isEnabled() && IsNSError(parmT, NSErrorII)) { setFlag<NSErrorOut>(state, state->getSVal(loc.castAs<Loc>()), C); return; } - if (ShouldCheckCFError && IsCFError(parmT, CFErrorII)) { + if (CFError.isEnabled() && IsCFError(parmT, CFErrorII)) { setFlag<CFErrorOut>(state, state->getSVal(loc.castAs<Loc>()), C); return; } @@ -274,19 +259,9 @@ void NSOrCFErrorDerefChecker::checkEvent(ImplicitNullDerefEvent event) const { os << " may be null"; - BugType *bug = nullptr; - if (isNSError) { - if (!NSBT) - NSBT.reset(new NSErrorDerefBug(NSErrorName)); - bug = NSBT.get(); - } - else { - if (!CFBT) - CFBT.reset(new CFErrorDerefBug(CFErrorName)); - bug = CFBT.get(); - } + const BugType &BT = isNSError ? NSError : CFError; BR.emitReport( - std::make_unique<PathSensitiveBugReport>(*bug, os.str(), event.SinkNode)); + std::make_unique<PathSensitiveBugReport>(BT, os.str(), event.SinkNode)); } static bool IsNSError(QualType T, IdentifierInfo *II) { @@ -320,32 +295,21 @@ static bool IsCFError(QualType T, IdentifierInfo *II) { return TT->getDecl()->getIdentifier() == II; } -void ento::registerNSOrCFErrorDerefChecker(CheckerManager &mgr) { - mgr.registerChecker<NSOrCFErrorDerefChecker>(); -} - -bool ento::shouldRegisterNSOrCFErrorDerefChecker(const CheckerManager &mgr) { - return true; -} - -void ento::registerNSErrorChecker(CheckerManager &mgr) { - mgr.registerChecker<NSErrorMethodChecker>(); - NSOrCFErrorDerefChecker *checker = mgr.getChecker<NSOrCFErrorDerefChecker>(); - checker->ShouldCheckNSError = true; - checker->NSErrorName = mgr.getCurrentCheckerName(); -} - -bool ento::shouldRegisterNSErrorChecker(const CheckerManager &mgr) { - return true; -} - -void ento::registerCFErrorChecker(CheckerManager &mgr) { - mgr.registerChecker<CFErrorFunctionChecker>(); - NSOrCFErrorDerefChecker *checker = mgr.getChecker<NSOrCFErrorDerefChecker>(); - checker->ShouldCheckCFError = true; - checker->CFErrorName = mgr.getCurrentCheckerName(); -} +// This source file implements two user-facing checkers ("osx.cocoa.NSError" +// and "osx.coreFoundation.CFError") which are both implemented as the +// combination of two `CheckerFrontend`s that are registered under the same +// name (but otherwise act independently). Among these 2+2 `CheckerFrontend`s +// two are coming from the checker family `NSOrCFErrorDerefChecker` while the +// other two (the `ADDITIONAL_PART`s) are small standalone checkers. +#define REGISTER_CHECKER(NAME, ADDITIONAL_PART) \ + void ento::register##NAME##Checker(CheckerManager &Mgr) { \ + Mgr.getChecker<NSOrCFErrorDerefChecker>()->NAME.enable(Mgr); \ + Mgr.registerChecker<ADDITIONAL_PART>(); \ + } \ + \ + bool ento::shouldRegister##NAME##Checker(const CheckerManager &) { \ + return true; \ + } -bool ento::shouldRegisterCFErrorChecker(const CheckerManager &mgr) { - return true; -} +REGISTER_CHECKER(NSError, NSErrorMethodChecker) +REGISTER_CHECKER(CFError, CFErrorFunctionChecker) diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index a63497c..019e81f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -28,23 +28,22 @@ using namespace ento; namespace { class StackAddrEscapeChecker - : public Checker<check::PreCall, check::PreStmt<ReturnStmt>, - check::EndFunction> { + : public CheckerFamily<check::PreCall, check::PreStmt<ReturnStmt>, + check::EndFunction> { mutable IdentifierInfo *dispatch_semaphore_tII = nullptr; - mutable std::unique_ptr<BugType> BT_stackleak; - mutable std::unique_ptr<BugType> BT_returnstack; - mutable std::unique_ptr<BugType> BT_capturedstackasync; - mutable std::unique_ptr<BugType> BT_capturedstackret; public: - enum CheckKind { - CK_StackAddrEscapeChecker, - CK_StackAddrAsyncEscapeChecker, - CK_NumCheckKinds - }; + StringRef getDebugTag() const override { return "StackAddrEscapeChecker"; } + + CheckerFrontend StackAddrEscape; + CheckerFrontend StackAddrAsyncEscape; - bool ChecksEnabled[CK_NumCheckKinds] = {false}; - CheckerNameRef CheckNames[CK_NumCheckKinds]; + const BugType StackLeak{&StackAddrEscape, + "Stack address leaks outside of stack frame"}; + const BugType ReturnStack{&StackAddrEscape, + "Return of address to stack-allocated memory"}; + const BugType CapturedStackAsync{ + &StackAddrAsyncEscape, "Address of stack-allocated memory is captured"}; void checkPreCall(const CallEvent &Call, CheckerContext &C) const; void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const; @@ -170,10 +169,6 @@ void StackAddrEscapeChecker::EmitReturnLeakError(CheckerContext &C, ExplodedNode *N = C.generateNonFatalErrorNode(); if (!N) return; - if (!BT_returnstack) - BT_returnstack = std::make_unique<BugType>( - CheckNames[CK_StackAddrEscapeChecker], - "Return of address to stack-allocated memory"); // Generate a report for this bug. SmallString<128> buf; @@ -184,7 +179,7 @@ void StackAddrEscapeChecker::EmitReturnLeakError(CheckerContext &C, EmitReturnedAsPartOfError(os, C.getSVal(RetE), R); auto report = - std::make_unique<PathSensitiveBugReport>(*BT_returnstack, os.str(), N); + std::make_unique<PathSensitiveBugReport>(ReturnStack, os.str(), N); report->addRange(RetE->getSourceRange()); if (range.isValid()) report->addRange(range); @@ -215,16 +210,12 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures( ExplodedNode *N = C.generateNonFatalErrorNode(); if (!N) continue; - if (!BT_capturedstackasync) - BT_capturedstackasync = std::make_unique<BugType>( - CheckNames[CK_StackAddrAsyncEscapeChecker], - "Address of stack-allocated memory is captured"); SmallString<128> Buf; llvm::raw_svector_ostream Out(Buf); SourceRange Range = genName(Out, Region, C.getASTContext()); Out << " is captured by an asynchronously-executed block"; - auto Report = std::make_unique<PathSensitiveBugReport>( - *BT_capturedstackasync, Out.str(), N); + auto Report = std::make_unique<PathSensitiveBugReport>(CapturedStackAsync, + Out.str(), N); if (Range.isValid()) Report->addRange(Range); C.emitReport(std::move(Report)); @@ -233,7 +224,7 @@ void StackAddrEscapeChecker::checkAsyncExecutedBlockCaptures( void StackAddrEscapeChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const { - if (!ChecksEnabled[CK_StackAddrAsyncEscapeChecker]) + if (!StackAddrAsyncEscape.isEnabled()) return; if (!Call.isGlobalCFunction("dispatch_after") && !Call.isGlobalCFunction("dispatch_async")) @@ -357,7 +348,7 @@ FindEscapingStackRegions(CheckerContext &C, const Expr *RetE, SVal RetVal) { void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const { - if (!ChecksEnabled[CK_StackAddrEscapeChecker]) + if (!StackAddrEscape.isEnabled()) return; const Expr *RetE = RS->getRetValue(); @@ -456,7 +447,7 @@ static bool isInvalidatedSymbolRegion(const MemRegion *Region) { void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const { - if (!ChecksEnabled[CK_StackAddrEscapeChecker]) + if (!StackAddrEscape.isEnabled()) return; ExplodedNode *Node = Ctx.getPredecessor(); @@ -581,11 +572,6 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS, if (!N) return; - if (!BT_stackleak) - BT_stackleak = - std::make_unique<BugType>(CheckNames[CK_StackAddrEscapeChecker], - "Stack address leaks outside of stack frame"); - for (const auto &P : Cb.V) { const MemRegion *Referrer = P.first->getBaseRegion(); const MemRegion *Referred = P.second; @@ -604,7 +590,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS, Out << " is still referred to by a temporary object on the stack" << CommonSuffix; auto Report = - std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str(), N); + std::make_unique<PathSensitiveBugReport>(StackLeak, Out.str(), N); if (Range.isValid()) Report->addRange(Range); Ctx.emitReport(std::move(Report)); @@ -618,7 +604,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS, Out << " is still referred to by the " << *ReferrerVariable << CommonSuffix; auto Report = - std::make_unique<PathSensitiveBugReport>(*BT_stackleak, Out.str(), N); + std::make_unique<PathSensitiveBugReport>(StackLeak, Out.str(), N); if (Range.isValid()) Report->addRange(Range); @@ -626,23 +612,14 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS, } } -void ento::registerStackAddrEscapeBase(CheckerManager &mgr) { - mgr.registerChecker<StackAddrEscapeChecker>(); -} - -bool ento::shouldRegisterStackAddrEscapeBase(const CheckerManager &mgr) { - return true; -} - -#define REGISTER_CHECKER(name) \ - void ento::register##name(CheckerManager &Mgr) { \ - StackAddrEscapeChecker *Chk = Mgr.getChecker<StackAddrEscapeChecker>(); \ - Chk->ChecksEnabled[StackAddrEscapeChecker::CK_##name] = true; \ - Chk->CheckNames[StackAddrEscapeChecker::CK_##name] = \ - Mgr.getCurrentCheckerName(); \ +#define REGISTER_CHECKER(NAME) \ + void ento::register##NAME##Checker(CheckerManager &Mgr) { \ + Mgr.getChecker<StackAddrEscapeChecker>()->NAME.enable(Mgr); \ } \ \ - bool ento::shouldRegister##name(const CheckerManager &mgr) { return true; } + bool ento::shouldRegister##NAME##Checker(const CheckerManager &) { \ + return true; \ + } -REGISTER_CHECKER(StackAddrEscapeChecker) -REGISTER_CHECKER(StackAddrAsyncEscapeChecker) +REGISTER_CHECKER(StackAddrEscape) +REGISTER_CHECKER(StackAddrAsyncEscape) diff --git a/clang/lib/Tooling/Core/Replacement.cpp b/clang/lib/Tooling/Core/Replacement.cpp index 1506218..a3214de 100644 --- a/clang/lib/Tooling/Core/Replacement.cpp +++ b/clang/lib/Tooling/Core/Replacement.cpp @@ -581,8 +581,8 @@ llvm::Expected<std::string> applyAllReplacements(StringRef Code, if (Replaces.empty()) return Code.str(); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); FileManager Files(FileSystemOptions(), InMemoryFileSystem); DiagnosticOptions DiagOpts; DiagnosticsEngine Diagnostics( diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index 8ce2706..b2b61de7 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -605,8 +605,8 @@ DependencyScanningWorker::DependencyScanningWorker( switch (Service.getMode()) { case ScanningMode::DependencyDirectivesScan: - DepFS = - new DependencyScanningWorkerFilesystem(Service.getSharedCache(), FS); + DepFS = llvm::makeIntrusiveRefCnt<DependencyScanningWorkerFilesystem>( + Service.getSharedCache(), FS); BaseFS = DepFS; break; case ScanningMode::CanonicalPreprocessing: diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp index 5333956..ecafe26 100644 --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -227,10 +227,11 @@ bool runToolOnCodeWithArgs( const Twine &ToolName, std::shared_ptr<PCHContainerOperations> PCHContainerOps, const FileContentMappings &VirtualMappedFiles) { - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem()); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); SmallString<1024> CodeStorage; @@ -403,7 +404,7 @@ bool ToolInvocation::run() { } const std::unique_ptr<driver::Driver> Driver( - newDriver(&*Diagnostics, BinaryName, &Files->getVirtualFileSystem())); + newDriver(&*Diagnostics, BinaryName, Files->getVirtualFileSystemPtr())); // The "input file not found" diagnostics from the driver are useful. // The driver is only aware of the VFS working directory, but some clients // change this at the FileManager level instead. @@ -473,8 +474,10 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations, IntrusiveRefCntPtr<FileManager> Files) : Compilations(Compilations), SourcePaths(SourcePaths), PCHContainerOps(std::move(PCHContainerOps)), - OverlayFileSystem(new llvm::vfs::OverlayFileSystem(std::move(BaseFS))), - InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), + OverlayFileSystem(llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + std::move(BaseFS))), + InMemoryFileSystem( + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()), Files(Files ? Files : new FileManager(FileSystemOptions(), OverlayFileSystem)) { OverlayFileSystem->pushOverlay(InMemoryFileSystem); @@ -692,10 +695,11 @@ std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs( IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) { std::vector<std::unique_ptr<ASTUnit>> ASTs; ASTBuilderAction Action(ASTs); - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(std::move(BaseFS))); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + std::move(BaseFS)); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); llvm::IntrusiveRefCntPtr<FileManager> Files( new FileManager(FileSystemOptions(), OverlayFileSystem)); diff --git a/clang/test/AST/ByteCode/codegen.cpp b/clang/test/AST/ByteCode/codegen.cpp index 6f9e75e..1bc756c 100644 --- a/clang/test/AST/ByteCode/codegen.cpp +++ b/clang/test/AST/ByteCode/codegen.cpp @@ -23,6 +23,10 @@ S s; // CHECK: @sp = constant ptr getelementptr (i8, ptr @s, i64 16), align 8 float &sp = s.c[3]; +namespace NearlyZeroInit { + // CHECK: @_ZN14NearlyZeroInit1bE ={{.*}} global{{.*}} { i32, <{ i32, [2147483647 x i32] }> } { i32 1, <{ i32, [2147483647 x i32] }> <{ i32 2, [2147483647 x i32] zeroinitializer }> }{{.*}} + struct B { int n; int arr[1024 * 1024 * 1024 * 2u]; } b = {1, {2}}; +} namespace BaseClassOffsets { struct A { int a; }; diff --git a/clang/test/AST/ByteCode/functions.cpp b/clang/test/AST/ByteCode/functions.cpp index b5e6f5b..363b6a5 100644 --- a/clang/test/AST/ByteCode/functions.cpp +++ b/clang/test/AST/ByteCode/functions.cpp @@ -5,6 +5,8 @@ // RUN: %clang_cc1 -pedantic -std=c++14 -verify=ref,both %s // RUN: %clang_cc1 -pedantic -std=c++20 -verify=ref,both %s +#define fold(x) (__builtin_constant_p(0) ? (x) : (x)) + constexpr void doNothing() {} constexpr int gimme5() { doNothing(); @@ -654,14 +656,26 @@ namespace { } namespace FunctionCast { - // When folding, we allow functions to be cast to different types. Such - // cast functions cannot be called, even if they're constexpr. + // When folding, we allow functions to be cast to different types. We only + // allow calls if the dynamic type of the pointer matches the type of the + // call. constexpr int f() { return 1; } + constexpr void* f2() { return nullptr; } + constexpr int f3(int a) { return a; } typedef double (*DoubleFn)(); typedef int (*IntFn)(); - int a[(int)DoubleFn(f)()]; // both-error {{variable length array}} \ - // both-warning {{are a Clang extension}} - int b[(int)IntFn(f)()]; // ok + typedef int* (*IntPtrFn)(); + constexpr int test1 = (int)DoubleFn(f)(); // both-error {{constant expression}} both-note {{reinterpret_cast}} + // FIXME: We should print a note explaining the error. + constexpr int test2 = (int)fold(DoubleFn(f))(); // both-error {{constant expression}} + constexpr int test3 = (int)IntFn(f)(); // no-op cast + constexpr int test4 = fold(IntFn(DoubleFn(f)))(); + constexpr int test5 = IntFn(fold(DoubleFn(f)))(); // both-error {{constant expression}} \ + // both-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} + // FIXME: Interpreter is less strict here. + constexpr int test6 = fold(IntPtrFn(f2))() == nullptr; // ref-error {{constant expression}} + // FIXME: The following crashes interpreter + // constexpr int test6 = fold(IntFn(f3)()); } #if __cplusplus >= 202002L diff --git a/clang/test/AST/ByteCode/intap.cpp b/clang/test/AST/ByteCode/intap.cpp index 6888387..05ab319b 100644 --- a/clang/test/AST/ByteCode/intap.cpp +++ b/clang/test/AST/ByteCode/intap.cpp @@ -292,7 +292,19 @@ constexpr int shifts() { // both-error {{never produces a constant expression}} (void)(2 << b); // ref-warning {{shift count is negative}} return 1; } -#endif +namespace UnderlyingInt128 { + enum F { + a = (__int128)-1 + }; + + constexpr int foo() { // both-error {{never produces a constant expression}} + F f = (F)(__int128)10; // both-note 2{{integer value 10 is outside the valid range of values [-1, 0] for the enumeration type 'F'}} + return (int)f; + } + static_assert(foo() == 0, ""); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} +} +#endif #endif diff --git a/clang/test/Analysis/analyzer-enabled-checkers.c b/clang/test/Analysis/analyzer-enabled-checkers.c index a632b70..32afcf3 100644 --- a/clang/test/Analysis/analyzer-enabled-checkers.c +++ b/clang/test/Analysis/analyzer-enabled-checkers.c @@ -20,7 +20,6 @@ // CHECK-NEXT: core.NonNullParamChecker // CHECK-NEXT: core.NonnilStringConstants // CHECK-NEXT: core.NullDereference -// CHECK-NEXT: core.StackAddrEscapeBase // CHECK-NEXT: core.StackAddressEscape // CHECK-NEXT: core.UndefinedBinaryOperatorResult // CHECK-NEXT: core.VLASize diff --git a/clang/test/Analysis/placement-new.cpp b/clang/test/Analysis/placement-new.cpp index 766b11c..50bbde2 100644 --- a/clang/test/Analysis/placement-new.cpp +++ b/clang/test/Analysis/placement-new.cpp @@ -166,10 +166,29 @@ void f1() { short a; }; - // bad (not enough space). + // On some systems, (notably before MSVC 16.7), a non-allocating placement + // array new could allocate more memory than the nominal size of the array. + + // Since CWG 2382 (implemented in MSVC 16.7), overhead was disallowed for non-allocating placement new. + // See: + // https://learn.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=msvc-170 + // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1969r0.html#2382 + + // However, as of 17.1, there is a regression when the type comes from a template + // parameter where MSVC reintroduces overhead. + // See: + // https://developercommunity.visualstudio.com/t/10777485 + // https://godbolt.org/z/E1z1Tsfvj + + // The checker doesn't warn here because this behavior only affects older + // MSVC versions (<16.7) or certain specific versions (17.1). + // Suppressing warnings avoids false positives on standard-compliant compilers + // and modern MSVC versions, but users of affected MSVC versions should be + // aware of potential buffer size issues. + const unsigned N = 32; - alignas(S) unsigned char buffer1[sizeof(S) * N]; // expected-note {{'buffer1' initialized here}} - ::new (buffer1) S[N]; // expected-warning{{Storage provided to placement new is only 64 bytes, whereas the allocated array type requires more space for internal needs}} expected-note 1 {{}} + alignas(S) unsigned char buffer1[sizeof(S) * N]; + ::new (buffer1) S[N]; // no-warning: See comments above } void f2() { @@ -177,10 +196,11 @@ void f2() { short a; }; - // maybe ok but we need to warn. + // On some systems, placement array new could allocate more memory than the nominal size of the array. + // See the comment at f1() above for more details. const unsigned N = 32; - alignas(S) unsigned char buffer2[sizeof(S) * N + sizeof(int)]; // expected-note {{'buffer2' initialized here}} - ::new (buffer2) S[N]; // expected-warning{{68 bytes is possibly not enough for array allocation which requires 64 bytes. Current overhead requires the size of 4 bytes}} expected-note 1 {{}} + alignas(S) unsigned char buffer2[sizeof(S) * N + sizeof(int)]; + ::new (buffer2) S[N]; // no-warning: See comments above } } // namespace testArrayTypesAllocation diff --git a/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c b/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c index b388c31..77fa037 100644 --- a/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c +++ b/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c @@ -28,7 +28,6 @@ // CHECK-NEXT: core.NonNullParamChecker // CHECK-NEXT: core.NonnilStringConstants // CHECK-NEXT: core.NullDereference -// CHECK-NEXT: core.StackAddrEscapeBase // CHECK-NEXT: core.StackAddressEscape // CHECK-NEXT: core.UndefinedBinaryOperatorResult // CHECK-NEXT: core.VLASize diff --git a/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c b/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c new file mode 100644 index 0000000..3643cf2 --- /dev/null +++ b/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -fclangir -emit-cir -fdump-record-layouts %s -o %t.cir 1> %t.cirlayout +// RUN: FileCheck --input-file=%t.cirlayout %s --check-prefix=CIR-LAYOUT + +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -emit-llvm -fdump-record-layouts %s -o %t.ll 1> %t.ogcglayout +// RUN: FileCheck --input-file=%t.ogcglayout %s --check-prefix=OGCG-LAYOUT + +typedef struct { + unsigned int a : 9; + volatile unsigned int b : 1; + unsigned int c : 1; +} st1; + +// CIR-LAYOUT: BitFields:[ +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:a offset:0 size:9 isSigned:0 storageSize:16 storageOffset:0 volatileOffset:0 volatileStorageSize:32 volatileStorageOffset:0> +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:b offset:9 size:1 isSigned:0 storageSize:16 storageOffset:0 volatileOffset:9 volatileStorageSize:32 volatileStorageOffset:0> +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:c offset:10 size:1 isSigned:0 storageSize:16 storageOffset:0 volatileOffset:10 volatileStorageSize:32 volatileStorageOffset:0> + +// OGCG-LAYOUT: BitFields:[ +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:9 IsSigned:0 StorageSize:16 StorageOffset:0 VolatileOffset:0 VolatileStorageSize:32 VolatileStorageOffset:0> +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:9 Size:1 IsSigned:0 StorageSize:16 StorageOffset:0 VolatileOffset:9 VolatileStorageSize:32 VolatileStorageOffset:0> +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:10 Size:1 IsSigned:0 StorageSize:16 StorageOffset:0 VolatileOffset:10 VolatileStorageSize:32 VolatileStorageOffset:0> + +// different base types +typedef struct{ + volatile short a : 3; + volatile int b: 13; + volatile long c : 5; +} st2; + +// CIR-LAYOUT: BitFields:[ +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:a offset:0 size:3 isSigned:1 storageSize:32 storageOffset:0 volatileOffset:0 volatileStorageSize:16 volatileStorageOffset:0> +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:b offset:3 size:13 isSigned:1 storageSize:32 storageOffset:0 volatileOffset:3 volatileStorageSize:32 volatileStorageOffset:0> +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:c offset:16 size:5 isSigned:1 storageSize:32 storageOffset:0 volatileOffset:16 volatileStorageSize:64 volatileStorageOffset:0> + +// OGCG-LAYOUT: BitFields:[ +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:3 IsSigned:1 StorageSize:32 StorageOffset:0 VolatileOffset:0 VolatileStorageSize:16 VolatileStorageOffset:0> +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:3 Size:13 IsSigned:1 StorageSize:32 StorageOffset:0 VolatileOffset:3 VolatileStorageSize:32 VolatileStorageOffset:0> +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:16 Size:5 IsSigned:1 StorageSize:32 StorageOffset:0 VolatileOffset:16 VolatileStorageSize:64 VolatileStorageOffset:0> + +typedef struct{ + volatile unsigned int a : 3; + unsigned int : 0; // zero-length bit-field force next field to aligned int boundary + volatile unsigned int b : 5; +} st3; + +// CIR-LAYOUT: BitFields:[ +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:a offset:0 size:3 isSigned:0 storageSize:8 storageOffset:0 volatileOffset:0 volatileStorageSize:32 volatileStorageOffset:0> +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:b offset:0 size:5 isSigned:0 storageSize:8 storageOffset:4 volatileOffset:0 volatileStorageSize:0 volatileStorageOffset:0> + +// OGCG-LAYOUT: BitFields:[ +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:3 IsSigned:0 StorageSize:8 StorageOffset:0 VolatileOffset:0 VolatileStorageSize:32 VolatileStorageOffset:0> +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:5 IsSigned:0 StorageSize:8 StorageOffset:4 VolatileOffset:0 VolatileStorageSize:0 VolatileStorageOffset:0> + +typedef struct{ + volatile unsigned int a : 3; + unsigned int z: 2; + volatile unsigned int b : 5; +} st4; + +// CIR-LAYOUT: BitFields:[ +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:a offset:0 size:3 isSigned:0 storageSize:16 storageOffset:0 volatileOffset:0 volatileStorageSize:32 volatileStorageOffset:0> +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:z offset:3 size:2 isSigned:0 storageSize:16 storageOffset:0 volatileOffset:3 volatileStorageSize:32 volatileStorageOffset:0> +// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:b offset:5 size:5 isSigned:0 storageSize:16 storageOffset:0 volatileOffset:5 volatileStorageSize:32 volatileStorageOffset:0> + +// OGCG-LAYOUT: BitFields:[ +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:3 IsSigned:0 StorageSize:16 StorageOffset:0 VolatileOffset:0 VolatileStorageSize:32 VolatileStorageOffset:0> +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:3 Size:2 IsSigned:0 StorageSize:16 StorageOffset:0 VolatileOffset:3 VolatileStorageSize:32 VolatileStorageOffset:0> +// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:5 Size:5 IsSigned:0 StorageSize:16 StorageOffset:0 VolatileOffset:5 VolatileStorageSize:32 VolatileStorageOffset:0> + +st1 s1; +st2 s2; +st3 s3; +st4 s4; diff --git a/clang/test/CIR/CodeGen/complex-mul-div.cpp b/clang/test/CIR/CodeGen/complex-mul-div.cpp new file mode 100644 index 0000000..9d71ef7 --- /dev/null +++ b/clang/test/CIR/CodeGen/complex-mul-div.cpp @@ -0,0 +1,280 @@ +// complex-range basic +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -complex-range=basic -Wno-unused-value -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE-BASIC %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=basic -Wno-unused-value -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefixes=CIR-AFTER-INT,CIR-AFTER-MUL-COMBINED +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=basic -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefixes=LLVM-INT,LLVM-MUL-COMBINED +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=basic -Wno-unused-value -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s --check-prefixes=OGCG-INT,OGCG-MUL-COMBINED + +// complex-range improved +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -complex-range=improved -Wno-unused-value -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE-IMPROVED %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=improved -Wno-unused-value -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefixes=CIR-AFTER-INT,CIR-AFTER-MUL-COMBINED +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=improved -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefixes=LLVM-INT,LLVM-MUL-COMBINED +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=improved -Wno-unused-value -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s --check-prefixes=OGCG-INT,OGCG-MUL-COMBINED + +// complex-range promoted +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -complex-range=promoted -Wno-unused-value -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE-PROMOTED %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=promoted -Wno-unused-value -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefixes=CIR-AFTER-INT,CIR-AFTER-MUL-COMBINED +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=promoted -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefixes=LLVM-INT,LLVM-MUL-COMBINED +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=promoted -Wno-unused-value -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s --check-prefixes=OGCG-INT,OGCG-MUL-COMBINED + +// complex-range full +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -complex-range=full -Wno-unused-value -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-canonicalize -o %t.cir %s 2>&1 | FileCheck --check-prefix=CIR-BEFORE-FULL %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=full -Wno-unused-value -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefixes=CIR-AFTER-FULL,CIR-AFTER-INT +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=full -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefixes=LLVM-FULL,LLVM-INT +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -complex-range=full -Wno-unused-value -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s --check-prefixes=OGCG-FULL,OGCG-INT + +void foo() { + float _Complex a; + float _Complex b; + float _Complex c = a * b; +} + +// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(basic) : !cir.complex<!cir.float> + +// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(improved) : !cir.complex<!cir.float> + +// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(promoted) : !cir.complex<!cir.float> + +// CIR-AFTER-MUL-COMBINED: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"] +// CIR-AFTER-MUL-COMBINED: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b"] +// CIR-AFTER-MUL-COMBINED: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["c", init] +// CIR-AFTER-MUL-COMBINED: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR-AFTER-MUL-COMBINED: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR-AFTER-MUL-COMBINED: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER-MUL-COMBINED: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER-MUL-COMBINED: %[[B_REAL:.*]] = cir.complex.real %[[TMP_B]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER-MUL-COMBINED: %[[B_IMAG:.*]] = cir.complex.imag %[[TMP_B]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER-MUL-COMBINED: %[[MUL_AR_BR:.*]] = cir.binop(mul, %[[A_REAL]], %[[B_REAL]]) : !cir.float +// CIR-AFTER-MUL-COMBINED: %[[MUL_AI_BI:.*]] = cir.binop(mul, %[[A_IMAG]], %[[B_IMAG]]) : !cir.float +// CIR-AFTER-MUL-COMBINED: %[[MUL_AR_BI:.*]] = cir.binop(mul, %[[A_REAL]], %[[B_IMAG]]) : !cir.float +// CIR-AFTER-MUL-COMBINED: %[[MUL_AI_BR:.*]] = cir.binop(mul, %[[A_IMAG]], %[[B_REAL]]) : !cir.float +// CIR-AFTER-MUL-COMBINED: %[[C_REAL:.*]] = cir.binop(sub, %[[MUL_AR_BR]], %[[MUL_AI_BI]]) : !cir.float +// CIR-AFTER-MUL-COMBINED: %[[C_IMAG:.*]] = cir.binop(add, %[[MUL_AR_BI]], %[[MUL_AI_BR]]) : !cir.float +// CIR-AFTER-MUL-COMBINED: %[[RESULT:.*]] = cir.complex.create %[[C_REAL]], %[[C_IMAG]] : !cir.float -> !cir.complex<!cir.float> +// CIR-AFTER-MUL-COMBINED: cir.store{{.*}} %[[RESULT]], %[[C_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> + +// LLVM-MUL-COMBINED: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM-MUL-COMBINED: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM-MUL-COMBINED: %[[C_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM-MUL-COMBINED: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4 +// LLVM-MUL-COMBINED: %[[TMP_B:.*]] = load { float, float }, ptr %[[B_ADDR]], align 4 +// LLVM-MUL-COMBINED: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0 +// LLVM-MUL-COMBINED: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1 +// LLVM-MUL-COMBINED: %[[B_REAL:.*]] = extractvalue { float, float } %[[TMP_B]], 0 +// LLVM-MUL-COMBINED: %[[B_IMAG:.*]] = extractvalue { float, float } %[[TMP_B]], 1 +// LLVM-MUL-COMBINED: %[[MUL_AR_BR:.*]] = fmul float %[[A_REAL]], %[[B_REAL]] +// LLVM-MUL-COMBINED: %[[MUL_AI_BI:.*]] = fmul float %[[A_IMAG]], %[[B_IMAG]] +// LLVM-MUL-COMBINED: %[[MUL_AR_BI:.*]] = fmul float %[[A_REAL]], %[[B_IMAG]] +// LLVM-MUL-COMBINED: %[[MUL_AI_BR:.*]] = fmul float %[[A_IMAG]], %[[B_REAL]] +// LLVM-MUL-COMBINED: %[[C_REAL:.*]] = fsub float %[[MUL_AR_BR]], %[[MUL_AI_BI]] +// LLVM-MUL-COMBINED: %[[C_IMAG:.*]] = fadd float %[[MUL_AR_BI]], %[[MUL_AI_BR]] +// LLVM-MUL-COMBINED: %[[MUL_A_B:.*]] = insertvalue { float, float } {{.*}}, float %[[C_REAL]], 0 +// LLVM-MUL-COMBINED: %[[RESULT:.*]] = insertvalue { float, float } %[[MUL_A_B]], float %[[C_IMAG]], 1 +// LLVM-MUL-COMBINED: store { float, float } %[[RESULT]], ptr %[[C_ADDR]], align 4 + +// OGCG-MUL-COMBINED: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG-MUL-COMBINED: %[[B_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG-MUL-COMBINED: %[[C_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG-MUL-COMBINED: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG-MUL-COMBINED: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG-MUL-COMBINED: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG-MUL-COMBINED: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG-MUL-COMBINED: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG-MUL-COMBINED: %[[B_REAL:.*]] = load float, ptr %[[B_REAL_PTR]], align 4 +// OGCG-MUL-COMBINED: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG-MUL-COMBINED: %[[B_IMAG:.*]] = load float, ptr %[[B_IMAG_PTR]], align 4 +// OGCG-MUL-COMBINED: %[[MUL_AR_BR:.*]] = fmul float %[[A_REAL]], %[[B_REAL]] +// OGCG-MUL-COMBINED: %[[MUL_AI_BI:.*]] = fmul float %[[A_IMAG]], %[[B_IMAG]] +// OGCG-MUL-COMBINED: %[[MUL_AR_BI:.*]] = fmul float %[[A_REAL]], %[[B_IMAG]] +// OGCG-MUL-COMBINED: %[[MUL_AI_BR:.*]] = fmul float %[[A_IMAG]], %[[B_REAL]] +// OGCG-MUL-COMBINED: %[[C_REAL:.*]] = fsub float %[[MUL_AR_BR]], %[[MUL_AI_BI]] +// OGCG-MUL-COMBINED: %[[C_IMAG:.*]] = fadd float %[[MUL_AR_BI]], %[[MUL_AI_BR]] +// OGCG-MUL-COMBINED: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[C_ADDR]], i32 0, i32 0 +// OGCG-MUL-COMBINED: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[C_ADDR]], i32 0, i32 1 +// OGCG-MUL-COMBINED: store float %[[C_REAL]], ptr %[[C_REAL_PTR]], align 4 +// OGCG-MUL-COMBINED: store float %[[C_IMAG]], ptr %[[C_IMAG_PTR]], align 4 + +// CIR-BEFORE-FULL: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(full) : !cir.complex<!cir.float> + +// CIR-AFTER-FULL: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"] +// CIR-AFTER-FULL: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b"] +// CIR-AFTER-FULL: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["c", init] +// CIR-AFTER-FULL: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR-AFTER-FULL: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR-AFTER-FULL: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER-FULL: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER-FULL: %[[B_REAL:.*]] = cir.complex.real %[[TMP_B]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER-FULL: %[[B_IMAG:.*]] = cir.complex.imag %[[TMP_B]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER-FULL: %[[MUL_AR_BR:.*]] = cir.binop(mul, %[[A_REAL]], %[[B_REAL]]) : !cir.float +// CIR-AFTER-FULL: %[[MUL_AI_BI:.*]] = cir.binop(mul, %[[A_IMAG]], %[[B_IMAG]]) : !cir.float +// CIR-AFTER-FULL: %[[MUL_AR_BI:.*]] = cir.binop(mul, %[[A_REAL]], %[[B_IMAG]]) : !cir.float +// CIR-AFTER-FULL: %[[MUL_AI_BR:.*]] = cir.binop(mul, %[[A_IMAG]], %[[B_REAL]]) : !cir.float +// CIR-AFTER-FULL: %[[C_REAL:.*]] = cir.binop(sub, %[[MUL_AR_BR]], %[[MUL_AI_BI]]) : !cir.float +// CIR-AFTER-FULL: %[[C_IMAG:.*]] = cir.binop(add, %[[MUL_AR_BI]], %[[MUL_AI_BR]]) : !cir.float +// CIR-AFTER-FULL: %[[COMPLEX:.*]] = cir.complex.create %[[C_REAL]], %[[C_IMAG]] : !cir.float -> !cir.complex<!cir.float> +// CIR-AFTER-FULL: %[[IS_C_REAL_NAN:.*]] = cir.cmp(ne, %[[C_REAL]], %[[C_REAL]]) : !cir.float, !cir.bool +// CIR-AFTER-FULL: %[[IS_C_IMAG_NAN:.*]] = cir.cmp(ne, %[[C_IMAG]], %[[C_IMAG]]) : !cir.float, !cir.bool +// CIR-AFTER-FULL: %[[CONST_FALSE:.*]] = cir.const #false +// CIR-AFTER-FULL: %[[SELECT_CONDITION:.*]] = cir.select if %[[IS_C_REAL_NAN]] then %[[IS_C_IMAG_NAN]] else %[[CONST_FALSE]] : (!cir.bool, !cir.bool, !cir.bool) -> !cir.bool +// CIR-AFTER-FULL: %[[RESULT:.*]] = cir.ternary(%[[SELECT_CONDITION]], true { +// CIR-AFTER-FULL: %[[LIBC_COMPLEX:.*]] = cir.call @__mulsc3(%[[A_REAL]], %[[A_IMAG]], %[[B_REAL]], %[[B_IMAG]]) : (!cir.float, !cir.float, !cir.float, !cir.float) -> !cir.complex<!cir.float> +// CIR-AFTER-FULL: cir.yield %[[LIBC_COMPLEX]] : !cir.complex<!cir.float> +// CIR-AFTER-FULL: }, false { +// CIR-AFTER-FULL: cir.yield %[[COMPLEX]] : !cir.complex<!cir.float> +// CIR-AFTER-FULL: }) : (!cir.bool) -> !cir.complex<!cir.float> +// CIR-AFTER-FULL: cir.store{{.*}} %[[RESULT]], %[[C_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> + +// LLVM-FULL: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM-FULL: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM-FULL: %[[C_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM-FULL: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4 +// LLVM-FULL: %[[TMP_B:.*]] = load { float, float }, ptr %[[B_ADDR]], align 4 +// LLVM-FULL: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 0 +// LLVM-FULL: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 1 +// LLVM-FULL: %[[B_REAL:.*]] = extractvalue { float, float } %[[TMP_B]], 0 +// LLVM-FULL: %[[B_IMAG:.*]] = extractvalue { float, float } %[[TMP_B]], 1 +// LLVM-FULL: %[[MUL_AR_BR:.*]] = fmul float %[[A_REAL]], %[[B_REAL]] +// LLVM-FULL: %[[MUL_AI_BI:.*]] = fmul float %[[A_IMAG]], %[[B_IMAG]] +// LLVM-FULL: %[[MUL_AR_BI:.*]] = fmul float %[[A_REAL]], %[[B_IMAG]] +// LLVM-FULL: %[[MUL_AI_BR:.*]] = fmul float %[[A_IMAG]], %[[B_REAL]] +// LLVM-FULL: %[[C_REAL:.*]] = fsub float %[[MUL_AR_BR]], %[[MUL_AI_BI]] +// LLVM-FULL: %[[C_IMAG:.*]] = fadd float %[[MUL_AR_BI]], %[[MUL_AI_BR]] +// LLVM-FULL: %[[MUL_A_B:.*]] = insertvalue { float, float } {{.*}}, float %[[C_REAL]], 0 +// LLVM-FULL: %[[COMPLEX:.*]] = insertvalue { float, float } %[[MUL_A_B]], float %[[C_IMAG]], 1 +// LLVM-FULL: %[[IS_C_REAL_NAN:.*]] = fcmp une float %[[C_REAL]], %[[C_REAL]] +// LLVM-FULL: %[[IS_C_IMAG_NAN:.*]] = fcmp une float %[[C_IMAG]], %[[C_IMAG]] +// LLVM-FULL: %[[SELECT_CONDITION:.*]] = and i1 %[[IS_C_REAL_NAN]], %[[IS_C_IMAG_NAN]] +// LLVM-FULL: br i1 %[[SELECT_CONDITION]], label %[[THEN_LABEL:.*]], label %[[ELSE_LABEL:.*]] +// LLVM-FULL: [[THEN_LABEL]]: +// LLVM-FULL: %[[LIBC_COMPLEX:.*]] = call { float, float } @__mulsc3(float %[[A_REAL]], float %[[A_IMAG]], float %[[B_REAL]], float %[[B_IMAG]]) +// LLVM-FULL: br label %[[PHI_BRANCH:.*]] +// LLVM-FULL: [[ELSE_LABEL]]: +// LLVM-FULL: br label %[[PHI_BRANCH:]] +// LLVM-FULL: [[PHI_BRANCH:]]: +// LLVM-FULL: %[[RESULT:.*]] = phi { float, float } [ %[[COMPLEX]], %[[ELSE_LABEL]] ], [ %[[LIBC_COMPLEX]], %[[THEN_LABEL]] ] +// LLVM-FULL: br label %[[END_LABEL:.*]] +// LLVM-FULL: [[END_LABEL]]: +// LLVM-FULL: store { float, float } %[[RESULT]], ptr %[[C_ADDR]], align 4 + +// OGCG-FULL: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG-FULL: %[[B_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG-FULL: %[[C_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG-FULL: %[[COMPLEX_CALL_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG-FULL: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG-FULL: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG-FULL: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG-FULL: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG-FULL: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG-FULL: %[[B_REAL:.*]] = load float, ptr %[[B_REAL_PTR]], align 4 +// OGCG-FULL: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG-FULL: %[[B_IMAG:.*]] = load float, ptr %[[B_IMAG_PTR]], align 4 +// OGCG-FULL: %[[MUL_AR_BR:.*]] = fmul float %[[A_REAL]], %[[B_REAL]] +// OGCG-FULL: %[[MUL_AI_BI:.*]] = fmul float %[[A_IMAG]], %[[B_IMAG]] +// OGCG-FULL: %[[MUL_AR_BI:.*]] = fmul float %[[A_REAL]], %[[B_IMAG]] +// OGCG-FULL: %[[MUL_AI_BR:.*]] = fmul float %[[A_IMAG]], %[[B_REAL]] +// OGCG-FULL: %[[C_REAL:.*]] = fsub float %[[MUL_AR_BR]], %[[MUL_AI_BI]] +// OGCG-FULL: %[[C_IMAG:.*]] = fadd float %[[MUL_AR_BI]], %[[MUL_AI_BR]] +// OGCG-FULL: %[[IS_C_REAL_NAN:.*]] = fcmp uno float %[[C_REAL]], %[[C_REAL]] +// OGCG-FULL: br i1 %[[IS_C_REAL_NAN]], label %[[COMPLEX_IS_IMAG_NAN:.*]], label %[[END_LABEL:.*]], !prof !2 +// OGCG-FULL: [[COMPLEX_IS_IMAG_NAN]]: +// OGCG-FULL: %[[IS_C_IMAG_NAN:.*]] = fcmp uno float %[[C_IMAG]], %[[C_IMAG]] +// OGCG-FULL: br i1 %[[IS_C_IMAG_NAN]], label %[[COMPLEX_LIB_CALL:.*]], label %[[END_LABEL]], !prof !2 +// OGCG-FULL: [[COMPLEX_LIB_CALL]]: +// OGCG-FULL: %[[CALL_RESULT:.*]] = call noundef <2 x float> @__mulsc3(float noundef %[[A_REAL]], float noundef %[[A_IMAG]], float noundef %[[B_REAL]], float noundef %[[B_IMAG]]) +// OGCG-FULL: store <2 x float> %[[CALL_RESULT]], ptr %[[COMPLEX_CALL_ADDR]], align 4 +// OGCG-FULL: %[[COMPLEX_CALL_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX_CALL_ADDR]], i32 0, i32 0 +// OGCG-FULL: %[[COMPLEX_CALL_REAL:.*]] = load float, ptr %[[COMPLEX_CALL_REAL_PTR]], align 4 +// OGCG-FULL: %[[COMPLEX_CALL_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[COMPLEX_CALL_ADDR]], i32 0, i32 1 +// OGCG-FULL: %[[COMPLEX_CALL_IMAG:.*]] = load float, ptr %[[COMPLEX_CALL_IMAG_PTR]], align 4 +// OGCG-FULL: br label %[[END_LABEL]] +// OGCG-FULL: [[END_LABEL]]: +// OGCG-FULL: %[[FINAL_REAL:.*]] = phi float [ %[[C_REAL]], %[[ENTRY:.*]] ], [ %[[C_REAL]], %[[COMPLEX_IS_IMAG_NAN]] ], [ %[[COMPLEX_CALL_REAL]], %[[COMPLEX_LIB_CALL]] ] +// OGCG-FULL: %[[FINAL_IMAG:.*]] = phi float [ %[[C_IMAG]], %[[ENTRY]] ], [ %[[C_IMAG]], %[[COMPLEX_IS_IMAG_NAN]] ], [ %[[COMPLEX_CALL_IMAG]], %[[COMPLEX_LIB_CALL]] ] +// OGCG-FULL: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[C_ADDR]], i32 0, i32 0 +// OGCG-FULL: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[C_ADDR]], i32 0, i32 1 +// OGCG-FULL: store float %[[FINAL_REAL]], ptr %[[C_REAL_PTR]], align 4 +// OGCG-FULL: store float %[[FINAL_IMAG]], ptr %[[C_IMAG_PTR]], align 4 + +void foo1() { + int _Complex a; + int _Complex b; + int _Complex c = a * b; +} + +// CIR-BEFORE-BASIC: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(basic) : !cir.complex<!s32i> + +// CIR-BEFORE-IMPROVED: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(improved) : !cir.complex<!s32i> + +// CIR-BEFORE-PROMOTED: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(promoted) : !cir.complex<!s32i> + +// CIR-BEFORE-FULL: %{{.*}} = cir.complex.mul {{.*}}, {{.*}} range(full) : !cir.complex<!s32i> + +// CIR-AFTER-INT: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"] +// CIR-AFTER-INT: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b"] +// CIR-AFTER-INT: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init] +// CIR-AFTER-INT: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> +// CIR-AFTER-INT: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> +// CIR-AFTER-INT: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!s32i> -> !s32i +// CIR-AFTER-INT: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!s32i> -> !s32i +// CIR-AFTER-INT: %[[B_REAL:.*]] = cir.complex.real %[[TMP_B]] : !cir.complex<!s32i> -> !s32i +// CIR-AFTER-INT: %[[B_IMAG:.*]] = cir.complex.imag %[[TMP_B]] : !cir.complex<!s32i> -> !s32i +// CIR-AFTER-INT: %[[MUL_AR_BR:.*]] = cir.binop(mul, %[[A_REAL]], %[[B_REAL]]) : !s32i +// CIR-AFTER-INT: %[[MUL_AI_BI:.*]] = cir.binop(mul, %[[A_IMAG]], %[[B_IMAG]]) : !s32i +// CIR-AFTER-INT: %[[MUL_AR_BI:.*]] = cir.binop(mul, %[[A_REAL]], %[[B_IMAG]]) : !s32i +// CIR-AFTER-INT: %[[MUL_AI_BR:.*]] = cir.binop(mul, %[[A_IMAG]], %[[B_REAL]]) : !s32i +// CIR-AFTER-INT: %[[C_REAL:.*]] = cir.binop(sub, %[[MUL_AR_BR]], %[[MUL_AI_BI]]) : !s32i +// CIR-AFTER-INT: %[[C_IMAG:.*]] = cir.binop(add, %[[MUL_AR_BI]], %[[MUL_AI_BR]]) : !s32i +// CIR-AFTER-INT: %[[RESULT:.*]] = cir.complex.create %[[C_REAL]], %[[C_IMAG]] : !s32i -> !cir.complex<!s32i> +// CIR-AFTER-INT: cir.store{{.*}} %[[RESULT]], %[[C_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>> + +// LLVM-INT: %[[A_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM-INT: %[[B_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM-INT: %[[C_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM-INT: %[[TMP_A:.*]] = load { i32, i32 }, ptr %[[A_ADDR]], align 4 +// LLVM-INT: %[[TMP_B:.*]] = load { i32, i32 }, ptr %[[B_ADDR]], align 4 +// LLVM-INT: %[[A_REAL:.*]] = extractvalue { i32, i32 } %[[TMP_A]], 0 +// LLVM-INT: %[[A_IMAG:.*]] = extractvalue { i32, i32 } %[[TMP_A]], 1 +// LLVM-INT: %[[B_REAL:.*]] = extractvalue { i32, i32 } %[[TMP_B]], 0 +// LLVM-INT: %[[B_IMAG:.*]] = extractvalue { i32, i32 } %[[TMP_B]], 1 +// LLVM-INT: %[[MUL_AR_BR:.*]] = mul i32 %[[A_REAL]], %[[B_REAL]] +// LLVM-INT: %[[MUL_AI_BI:.*]] = mul i32 %[[A_IMAG]], %[[B_IMAG]] +// LLVM-INT: %[[MUL_AR_BI:.*]] = mul i32 %[[A_REAL]], %[[B_IMAG]] +// LLVM-INT: %[[MUL_AI_BR:.*]] = mul i32 %[[A_IMAG]], %[[B_REAL]] +// LLVM-INT: %[[C_REAL:.*]] = sub i32 %[[MUL_AR_BR]], %[[MUL_AI_BI]] +// LLVM-INT: %[[C_IMAG:.*]] = add i32 %[[MUL_AR_BI]], %[[MUL_AI_BR]] +// LLVM-INT: %[[MUL_A_B:.*]] = insertvalue { i32, i32 } {{.*}}, i32 %[[C_REAL]], 0 +// LLVM-INT: %[[RESULT:.*]] = insertvalue { i32, i32 } %[[MUL_A_B]], i32 %[[C_IMAG]], 1 +// LLVM-INT: store { i32, i32 } %[[RESULT]], ptr %[[C_ADDR]], align 4 + +// OGCG-INT: %[[A_ADDR:.*]] = alloca { i32, i32 }, align 4 +// OGCG-INT: %[[B_ADDR:.*]] = alloca { i32, i32 }, align 4 +// OGCG-INT: %[[C_ADDR:.*]] = alloca { i32, i32 }, align 4 +// OGCG-INT: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG-INT: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4 +// OGCG-INT: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG-INT: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4 +// OGCG-INT: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG-INT: %[[B_REAL:.*]] = load i32, ptr %[[B_REAL_PTR]], align 4 +// OGCG-INT: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG-INT: %[[B_IMAG:.*]] = load i32, ptr %[[B_IMAG_PTR]], align 4 +// OGCG-INT: %[[MUL_AR_BR:.*]] = mul i32 %[[A_REAL]], %[[B_REAL]] +// OGCG-INT: %[[MUL_AI_BI:.*]] = mul i32 %[[A_IMAG]], %[[B_IMAG]] +// OGCG-INT: %[[C_REAL:.*]] = sub i32 %[[MUL_AR_BR]], %[[MUL_AI_BI]] +// OGCG-INT: %[[MUL_AI_BR:.*]] = mul i32 %[[A_IMAG]], %[[B_REAL]] +// OGCG-INT: %[[MUL_AR_BI:.*]] = mul i32 %[[A_REAL]], %[[B_IMAG]] +// OGCG-INT: %[[C_IMAG:.*]] = add i32 %[[MUL_AI_BR]], %[[MUL_AR_BI]] +// OGCG-INT: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 0 +// OGCG-INT: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 1 +// OGCG-INT: store i32 %[[C_REAL]], ptr %[[C_REAL_PTR]], align 4 +// OGCG-INT: store i32 %[[C_IMAG]], ptr %[[C_IMAG_PTR]], align 4 diff --git a/clang/test/CIR/CodeGen/complex-unary.cpp b/clang/test/CIR/CodeGen/complex-unary.cpp index 676b554..4cd81eb 100644 --- a/clang/test/CIR/CodeGen/complex-unary.cpp +++ b/clang/test/CIR/CodeGen/complex-unary.cpp @@ -284,3 +284,89 @@ void foo6() { // OGCG: %[[RESULT_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 // OGCG: store float %[[A_REAL_DEC]], ptr %[[RESULT_REAL_PTR]], align 4 // OGCG: store float %[[A_IMAG]], ptr %[[RESULT_IMAG_PTR]], align 4 + +void foo7() { + float _Complex a; + float _Complex b = +a; +} + +// CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"] +// CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init] +// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR-BEFORE: %[[COMPLEX_PLUS:.*]] = cir.unary(plus, %[[TMP]]) : !cir.complex<!cir.float>, !cir.complex<!cir.float> +// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_PLUS]], %[[B_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> + +// CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"] +// CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init] +// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER: %[[REAL_PLUS:.*]] = cir.unary(plus, %[[REAL]]) : !cir.float, !cir.float +// CIR-AFTER: %[[IMAG_PLUS:.*]] = cir.unary(plus, %[[IMAG]]) : !cir.float, !cir.float +// CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_PLUS]], %[[IMAG_PLUS]] : !cir.float -> !cir.complex<!cir.float> +// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[B_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4 +// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0 +// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1 +// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL]], 0 +// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG]], 1 +// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[B_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4 + +void foo8() { + float _Complex a; + float _Complex b = -a; +} + +// CIR-BEFORE: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"] +// CIR-BEFORE: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init] +// CIR-BEFORE: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR-BEFORE: %[[COMPLEX_MINUS:.*]] = cir.unary(minus, %[[TMP]]) : !cir.complex<!cir.float>, !cir.complex<!cir.float> +// CIR-BEFORE: cir.store{{.*}} %[[COMPLEX_MINUS]], %[[B_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> + +// CIR-AFTER: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"] +// CIR-AFTER: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b", init] +// CIR-AFTER: %[[TMP:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float> +// CIR-AFTER: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER: %[[IMAG:.*]] = cir.complex.imag %[[TMP]] : !cir.complex<!cir.float> -> !cir.float +// CIR-AFTER: %[[REAL_MINUS:.*]] = cir.unary(minus, %[[REAL]]) : !cir.float, !cir.float +// CIR-AFTER: %[[IMAG_MINUS:.*]] = cir.unary(minus, %[[IMAG]]) : !cir.float, !cir.float +// CIR-AFTER: %[[NEW_COMPLEX:.*]] = cir.complex.create %[[REAL_MINUS]], %[[IMAG_MINUS]] : !cir.float -> !cir.complex<!cir.float> +// CIR-AFTER: cir.store{{.*}} %[[NEW_COMPLEX]], %[[B_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> + +// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 4 +// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4 +// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0 +// LLVM: %[[IMAG:.*]] = extractvalue { float, float } %[[TMP]], 1 +// LLVM: %[[REAL_MINUS:.*]] = fneg float %[[REAL]] +// LLVM: %[[IMAG_MINUS:.*]] = fneg float %[[IMAG]] +// LLVM: %[[RESULT_TMP:.*]] = insertvalue { float, float } {{.*}}, float %[[REAL_MINUS]], 0 +// LLVM: %[[RESULT_VAL:.*]] = insertvalue { float, float } %[[RESULT_TMP]], float %[[IMAG_MINUS]], 1 +// LLVM: store { float, float } %[[RESULT_VAL]], ptr %[[B_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 4 +// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0 +// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4 +// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1 +// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4 +// OGCG: %[[A_REAL_MINUS:.*]] = fneg float %[[A_REAL]] +// OGCG: %[[A_IMAG_MINUS:.*]] = fneg float %[[A_IMAG]] +// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store float %[[A_REAL_MINUS]], ptr %[[B_REAL_PTR]], align 4 +// OGCG: store float %[[A_IMAG_MINUS]], ptr %[[B_IMAG_PTR]], align 4 diff --git a/clang/test/CIR/CodeGen/empty.cpp b/clang/test/CIR/CodeGen/empty.cpp new file mode 100644 index 0000000..378ae21 --- /dev/null +++ b/clang/test/CIR/CodeGen/empty.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR + +// These declarations shouldn't emit any code. Therefore the module is expected to be empty. + +template<typename T> +concept some_concept = true; + +template<some_concept T> +class class_template {}; + +; // Empty declaration + +template<typename T> +void function_template(); + +static_assert(true, "top level static assert"); + +template<typename T> +using type_alias = T; + +namespace N { + using ::class_template; // UsingShadow +} + +template<typename T> +struct deduction_guide {}; + +deduction_guide() -> deduction_guide<int>; + +// CIR: module {{.*}} { +// CIR-NEXT: } diff --git a/clang/test/CIR/CodeGen/variable-decomposition.cpp b/clang/test/CIR/CodeGen/variable-decomposition.cpp new file mode 100644 index 0000000..022d06a --- /dev/null +++ b/clang/test/CIR/CodeGen/variable-decomposition.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -std=c++17 -triple x86_64-pc-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-pc-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-pc-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s + +struct some_struct { + int a; + float b; +}; + +float function() { + auto[a, b] = some_struct{1, 2.f}; + + return a + b; +} + +// CIR-LABEL: cir.func dso_local @_Z8functionv() -> !cir.float +// CIR: %[[RETVAL:.+]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["__retval"] +// CIR: %[[STRUCT:.+]] = cir.alloca !rec_some_struct, !cir.ptr<!rec_some_struct>, [""] +// CIR: %[[MEMBER_A:.+]] = cir.get_member %[[STRUCT]][0] {name = "a"} : !cir.ptr<!rec_some_struct> -> !cir.ptr<!s32i> +// CIR: %[[LOAD_A:.+]] = cir.load align(4) %[[MEMBER_A]] : !cir.ptr<!s32i>, !s32i +// CIR: %[[CAST_A:.+]] = cir.cast(int_to_float, %[[LOAD_A]] : !s32i), !cir.float +// CIR: %[[MEMBER_B:.+]] = cir.get_member %[[STRUCT]][1] {name = "b"} : !cir.ptr<!rec_some_struct> -> !cir.ptr<!cir.float> +// CIR: %[[LOAD_B:.+]] = cir.load align(4) %[[MEMBER_B]] : !cir.ptr<!cir.float>, !cir.float +// CIR: %[[ADD:.+]] = cir.binop(add, %[[CAST_A]], %[[LOAD_B]]) : !cir.float +// CIR: cir.store %[[ADD]], %[[RETVAL]] : !cir.float, !cir.ptr<!cir.float> +// CIR: %[[RET:.+]] = cir.load %[[RETVAL]] : !cir.ptr<!cir.float>, !cir.float +// CIR: cir.return %[[RET]] : !cir.float + +// LLVM-LABEL: define dso_local float @_Z8functionv() +// LLVM: %[[RETVAL:.+]] = alloca float, i64 1 +// LLVM: %[[STRUCT:.+]] = alloca %struct.some_struct, i64 1 +// LLVM: %[[GEP_A:.+]] = getelementptr %struct.some_struct, ptr %[[STRUCT]], i32 0, i32 0 +// LLVM: %[[LOAD_A:.+]] = load i32, ptr %[[GEP_A]] +// LLVM: %[[CAST_A:.+]] = sitofp i32 %[[LOAD_A]] to float +// LLVM: %[[GEP_B:.+]] = getelementptr %struct.some_struct, ptr %[[STRUCT]], i32 0, i32 1 +// LLVM: %[[LOAD_B:.+]] = load float, ptr %[[GEP_B]] +// LLVM: %[[ADD:.+]] = fadd float %[[CAST_A]], %[[LOAD_B]] +// LLVM: store float %[[ADD]], ptr %[[RETVAL]] +// LLVM: %[[RET:.+]] = load float, ptr %[[RETVAL]] +// LLVM: ret float %[[RET]] + +// OGCG: @__const._Z8functionv.{{.*}} = private unnamed_addr constant %struct.some_struct { i32 1, float 2.000000e+00 } +// OGCG-LABEL: define dso_local noundef float @_Z8functionv() +// OGCG: %[[STRUCT:.+]] = alloca %struct.some_struct +// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[STRUCT]], ptr align 4 @__const._Z8functionv.{{.*}}, i64 8, i1 false) +// OGCG: %[[GEP_A:.+]] = getelementptr inbounds nuw %struct.some_struct, ptr %[[STRUCT]], i32 0, i32 0 +// OGCG: %[[LOAD_A:.+]] = load i32, ptr %[[GEP_A]] +// OGCG: %[[CAST_A:.+]] = sitofp i32 %[[LOAD_A]] to float +// OGCG: %[[GEP_B:.+]] = getelementptr inbounds nuw %struct.some_struct, ptr %[[STRUCT]], i32 0, i32 1 +// OGCG: %[[LOAD_B:.+]] = load float, ptr %[[GEP_B]] +// OGCG: %[[ADD:.+]] = fadd float %[[CAST_A]], %[[LOAD_B]] +// OGCG: ret float %[[ADD]] diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp index 9948075..5b4551b 100644 --- a/clang/test/CXX/drs/cwg18xx.cpp +++ b/clang/test/CXX/drs/cwg18xx.cpp @@ -564,12 +564,11 @@ struct A { namespace ex2 { #if __cplusplus >= 201103L struct Bar { - struct Baz { // #cwg1890-Baz + struct Baz { int a = 0; }; static_assert(__is_constructible(Baz), ""); // since-cxx11-error@-1 {{static assertion failed due to requirement '__is_constructible(cwg1890::ex2::Bar::Baz)'}} - // since-cxx11-note@#cwg1890-Baz {{'Baz' defined here}} }; #endif } // namespace ex2 diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp index 910c863..8401d30 100644 --- a/clang/test/CXX/expr/expr.const/p2-0x.cpp +++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp @@ -438,6 +438,11 @@ namespace ReinterpretCast { struct U { int m : (long)(S*)6; // expected-warning {{constant expression}} expected-note {{reinterpret_cast}} }; + void f(); + constexpr void* fp1 = (void*)f; // expected-error {{constant expression}} expected-note {{reinterpret_cast}} + constexpr int* fp2 = (int*)f; // expected-error {{constant expression}} expected-note {{reinterpret_cast}} + constexpr int (*fp3)() = (int(*)())f; // expected-error {{constant expression}} expected-note {{reinterpret_cast}} + constexpr int (&fp4)() = (int(&)())f; // expected-error {{constant expression}} expected-note {{reinterpret_cast}} } // - a pseudo-destructor call (5.2.4); diff --git a/clang/test/CodeCompletion/skip-explicit-object-parameter.cpp b/clang/test/CodeCompletion/skip-explicit-object-parameter.cpp index 55c16bb..587d6cb 100644 --- a/clang/test/CodeCompletion/skip-explicit-object-parameter.cpp +++ b/clang/test/CodeCompletion/skip-explicit-object-parameter.cpp @@ -1,14 +1,48 @@ struct A { - void foo(this A self, int arg); + void foo(this auto&& self, int arg); + void bar(this A self, int arg); }; -int main() { +int func1() { A a {}; a. } -// RUN: %clang_cc1 -cc1 -fsyntax-only -code-completion-at=%s:%(line-2):5 -std=c++23 %s | FileCheck %s -// CHECK: COMPLETION: A : A:: -// CHECK-NEXT: COMPLETION: foo : [#void#]foo(<#int arg#>) -// CHECK-NEXT: COMPLETION: operator= : [#A &#]operator=(<#const A &#>) -// CHECK-NEXT: COMPLETION: operator= : [#A &#]operator=(<#A &&#>) -// CHECK-NEXT: COMPLETION: ~A : [#void#]~A() +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-2):5 -std=c++23 %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: COMPLETION: A : A:: +// CHECK-NEXT-CC1: COMPLETION: bar : [#void#]bar(<#int arg#>) +// CHECK-NEXT-CC1: COMPLETION: foo : [#void#]foo(<#int arg#>) +// CHECK-NEXT-CC1: COMPLETION: operator= : [#A &#]operator=(<#const A &#>) +// CHECK-NEXT-CC1: COMPLETION: operator= : [#A &#]operator=(<#A &&#>) +// CHECK-NEXT-CC1: COMPLETION: ~A : [#void#]~A() + +struct B { + template <typename T> + void foo(this T&& self, int arg); +}; + +int func2() { + B b {}; + b.foo(); +} +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-2):9 -std=c++23 %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: OVERLOAD: [#void#]foo(int arg) + +// TODO: llvm/llvm-project/146649 +// This is incorrect behavior. Correct Result should be a variant of, +// CC3: should be something like [#void#]foo(<#A self#>, <#int arg#>) +// CC4: should be something like [#void#]bar(<#A self#>, <#int arg#>) +int func3() { + (&A::foo) + (&A::bar) +} +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-3):10 -std=c++23 %s | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: COMPLETION: foo : [#void#]foo<<#class self:auto#>>(<#int arg#>) +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-4):10 -std=c++23 %s | FileCheck -check-prefix=CHECK-CC4 %s +// CHECK-CC4: COMPLETION: bar : [#void#]bar(<#int arg#>) + +int func4() { + // TODO (&A::foo)( + (&A::bar)( +} +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-2):13 -std=c++23 %s | FileCheck -check-prefix=CHECK-CC5 %s +// CHECK-CC5: OVERLOAD: [#void#](<#A#>, int) diff --git a/clang/test/CodeGen/AArch64/neon-scalar-copy.c b/clang/test/CodeGen/AArch64/neon-scalar-copy.c index 4ad1ce5..bd80068 100644 --- a/clang/test/CodeGen/AArch64/neon-scalar-copy.c +++ b/clang/test/CodeGen/AArch64/neon-scalar-copy.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \ +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -flax-vector-conversions=none\ // RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -passes=mem2reg | FileCheck %s // REQUIRES: aarch64-registered-target || arm-registered-target diff --git a/clang/test/CodeGen/AArch64/neon-vget.c b/clang/test/CodeGen/AArch64/neon-vget.c index b17a7ab..ebc8c2f 100644 --- a/clang/test/CodeGen/AArch64/neon-vget.c +++ b/clang/test/CodeGen/AArch64/neon-vget.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple arm64-apple-darwin -target-feature +neon \ +// RUN: %clang_cc1 -triple arm64-apple-darwin -target-feature +neon -flax-vector-conversions=none \ // RUN: -disable-O0-optnone -emit-llvm -o - %s \ // RUN: | opt -S -passes=mem2reg | FileCheck %s diff --git a/clang/test/CodeGen/AArch64/poly64.c b/clang/test/CodeGen/AArch64/poly64.c index 578dd20..00838b6 100644 --- a/clang/test/CodeGen/AArch64/poly64.c +++ b/clang/test/CodeGen/AArch64/poly64.c @@ -1,5 +1,5 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 -// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon \ +// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -flax-vector-conversions=none\ // RUN: -ffp-contract=fast -disable-O0-optnone -emit-llvm -o - %s | opt -S -passes=mem2reg,sroa \ // RUN: | FileCheck %s diff --git a/clang/test/CodeGen/attr-counted-by-for-pointers.c b/clang/test/CodeGen/attr-counted-by-for-pointers.c index 2407654..e939e49 100644 --- a/clang/test/CodeGen/attr-counted-by-for-pointers.c +++ b/clang/test/CodeGen/attr-counted-by-for-pointers.c @@ -471,3 +471,80 @@ size_t test9(struct annotated_sized_ptr *p, int index) { size_t test10(struct annotated_sized_ptr *p, int index) { return __bdos(&((unsigned int *) p->buf)[index]); } + +struct pr151236_struct { + int *a __counted_by(a_count); + short a_count; +}; + +// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -262144, 262137) i64 @test11( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i16, ptr [[COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp sgt i16 [[COUNTED_BY_LOAD]], -1 +// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i16 [[COUNTED_BY_LOAD]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = shl nsw i64 [[COUNT]], 3 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i64 [[ARRAY_SIZE]], i64 0 +// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP1]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -262144, 262137) i64 @test11( +// NO-SANITIZE-WITH-ATTR-SAME: ptr noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i16, ptr [[COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i16 [[COUNTED_BY_LOAD]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = shl nsw i64 [[COUNT]], 3 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp sgt i16 [[COUNTED_BY_LOAD]], -1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i64 [[ARRAY_SIZE]], i64 0 +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP1]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local range(i64 0, -1) i64 @test11( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -2 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local range(i64 0, -1) i64 @test11( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -2 +// +size_t test11(struct pr151236_struct *p) { + return __bdos(p->a) + __bdos((p->a)); +} + +// SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -262144, 262137) i64 @test12( +// SANITIZE-WITH-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITH-ATTR-NEXT: entry: +// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 +// SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i16, ptr [[COUNTED_BY_GEP]], align 4 +// SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp sgt i16 [[COUNTED_BY_LOAD]], -1 +// SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i16 [[COUNTED_BY_LOAD]] to i64 +// SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = shl nsw i64 [[COUNT]], 3 +// SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i64 [[ARRAY_SIZE]], i64 0 +// SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP1]] +// +// NO-SANITIZE-WITH-ATTR-LABEL: define dso_local range(i64 -262144, 262137) i64 @test12( +// NO-SANITIZE-WITH-ATTR-SAME: ptr noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITH-ATTR-NEXT: entry: +// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 8 +// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNTED_BY_LOAD:%.*]] = load i16, ptr [[COUNTED_BY_GEP]], align 4 +// NO-SANITIZE-WITH-ATTR-NEXT: [[COUNT:%.*]] = sext i16 [[COUNTED_BY_LOAD]] to i64 +// NO-SANITIZE-WITH-ATTR-NEXT: [[ARRAY_SIZE:%.*]] = shl nsw i64 [[COUNT]], 3 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP0:%.*]] = icmp sgt i16 [[COUNTED_BY_LOAD]], -1 +// NO-SANITIZE-WITH-ATTR-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i64 [[ARRAY_SIZE]], i64 0 +// NO-SANITIZE-WITH-ATTR-NEXT: ret i64 [[TMP1]] +// +// SANITIZE-WITHOUT-ATTR-LABEL: define dso_local range(i64 0, -1) i64 @test12( +// SANITIZE-WITHOUT-ATTR-SAME: ptr noundef [[P:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SANITIZE-WITHOUT-ATTR-NEXT: entry: +// SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -2 +// +// NO-SANITIZE-WITHOUT-ATTR-LABEL: define dso_local range(i64 0, -1) i64 @test12( +// NO-SANITIZE-WITHOUT-ATTR-SAME: ptr noundef readonly captures(none) [[P:%.*]]) local_unnamed_addr #[[ATTR1]] { +// NO-SANITIZE-WITHOUT-ATTR-NEXT: entry: +// NO-SANITIZE-WITHOUT-ATTR-NEXT: ret i64 -2 +// +size_t test12(struct pr151236_struct *p) { + return __bdos(p->a) + __bdos(((int *)p->a)); +} diff --git a/clang/test/CodeGenCXX/debug-info-gline-tables-only.cpp b/clang/test/CodeGenCXX/debug-info-gline-tables-only.cpp index 9b86a49..192169b 100644 --- a/clang/test/CodeGenCXX/debug-info-gline-tables-only.cpp +++ b/clang/test/CodeGenCXX/debug-info-gline-tables-only.cpp @@ -14,9 +14,11 @@ class E : public C { // CHECK-NOT: DW_TAG_reference type void x(const D& d); }; +// CHECK-NOT: DW_TAG_structure_type struct F { enum X { }; void func(X); + // CHECK-NOT: DW_TAG_member virtual ~F(); }; F::~F() { diff --git a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl index 990f0aa..3c9e35a 100644 --- a/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl +++ b/clang/test/CodeGenHLSL/builtins/D3DCOLORtoUBYTE4.hlsl @@ -5,8 +5,16 @@ // CHECK-LABEL: D3DCOLORtoUBYTE4 int4 test_D3DCOLORtoUBYTE4(float4 p1) { // CHECK: %[[SCALED:.*]] = fmul [[FMFLAGS:.*]][[FLOAT_TYPE:<4 x float>]] %{{.*}}, splat (float 0x406FE01000000000) - // CHECK: %[[CONVERTED:.*]] = fptoui [[FLOAT_TYPE]] %[[SCALED]] to [[INT_TYPE:<4 x i32>]] + // CHECK: %[[CONVERTED:.*]] = fptosi [[FLOAT_TYPE]] %[[SCALED]] to [[INT_TYPE:<4 x i32>]] // CHECK: %[[SHUFFLED:.*]] = shufflevector [[INT_TYPE]] %[[CONVERTED]], [[INT_TYPE]] poison, <4 x i32> <i32 2, i32 1, i32 0, i32 3> // CHECK: ret [[INT_TYPE]] %[[SHUFFLED]] return D3DCOLORtoUBYTE4(p1); } + +// Note this test confirms issue 150673 is fixed +// by confirming the negative does not become a poison +// CHECK-LABEL: test_constant_inputs +int4 test_constant_inputs() { + // CHECK: ret <4 x i32> <i32 -12877, i32 2833, i32 0, i32 25500> + return D3DCOLORtoUBYTE4(float4(0, 11.11, -50.5, 100)); +} diff --git a/clang/test/CodeGenObjC/exceptions.m b/clang/test/CodeGenObjC/exceptions.m index 1546ed2..832d3a45 100644 --- a/clang/test/CodeGenObjC/exceptions.m +++ b/clang/test/CodeGenObjC/exceptions.m @@ -144,18 +144,17 @@ void f4(void) { // CHECK-NEXT: br label // -> rethrow - // finally.call-exit: Predecessors are the @try and @catch fallthroughs - // as well as the no-match case in the catch mechanism. The i1 is whether - // to rethrow and should be true only in the last case. - // CHECK: phi ptr - // CHECK-NEXT: phi i1 - // CHECK-NEXT: call void @objc_exception_try_exit(ptr nonnull [[EXNDATA]]) + // finally.call-exit: Predecessor is the no-match case in the catch mechanism + // which rethrows. + // CHECK: call void @objc_exception_try_exit(ptr nonnull [[EXNDATA]]) // CHECK-NEXT: call void @f4_help(i32 noundef 2) - // CHECK-NEXT: br i1 - // -> ret, rethrow + // CHECK-NEXT: br label + // -> rethrow - // ret: - // CHECK: ret void + // finally.end.critedge: Predecessors are the @try and @catch fallthroughs. + // CHECK: call void @objc_exception_try_exit(ptr nonnull [[EXNDATA]]) + // CHECK-NEXT: call void @f4_help(i32 noundef 2) + // CHECK-NEXT: ret void // Catch mechanism: // CHECK: call ptr @objc_exception_extract(ptr nonnull [[EXNDATA]]) diff --git a/clang/test/CodeGenOpenCL/amdgpu-features.cl b/clang/test/CodeGenOpenCL/amdgpu-features.cl index e96dd66..efd70a9 100644 --- a/clang/test/CodeGenOpenCL/amdgpu-features.cl +++ b/clang/test/CodeGenOpenCL/amdgpu-features.cl @@ -108,7 +108,7 @@ // GFX1153: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot12-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" // GFX1200: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot11-insts,+dot12-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" // GFX1201: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot11-insts,+dot12-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32" -// GFX1250: "target-features"="+16-bit-insts,+ashr-pk-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+bf16-trans-insts,+bitop3-insts,+ci-insts,+dl-insts,+dot7-insts,+dot8-insts,+dpp,+fp8-conversion-insts,+fp8e5m3-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx1250-insts,+gfx8-insts,+gfx9-insts,+permlane16-swap,+prng-inst,+setprio-inc-wg-inst,+tanh-insts,+transpose-load-f4f6-insts,+vmem-pref-insts,+wavefrontsize32 +// GFX1250: "target-features"="+16-bit-insts,+ashr-pk-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-buffer-pk-add-bf16-inst,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+bf16-cvt-insts,+bf16-trans-insts,+bitop3-insts,+ci-insts,+dl-insts,+dot7-insts,+dot8-insts,+dpp,+fp8-conversion-insts,+fp8e5m3-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx1250-insts,+gfx8-insts,+gfx9-insts,+permlane16-swap,+prng-inst,+setprio-inc-wg-inst,+tanh-insts,+transpose-load-f4f6-insts,+vmem-pref-insts,+wavefrontsize32 // GFX1103-W64: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot12-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize64" diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl index 81f39f9..1c67fc3 100644 --- a/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl +++ b/clang/test/CodeGenOpenCL/builtins-amdgcn-gfx1250.cl @@ -7,6 +7,7 @@ typedef unsigned int uint; typedef unsigned short int ushort; typedef unsigned int __attribute__((ext_vector_type(2))) uint2; +typedef __bf16 __attribute__((ext_vector_type(2))) bfloat2; typedef half __attribute__((ext_vector_type(2))) half2; // CHECK-LABEL: @test_setprio_inc_wg( @@ -254,6 +255,33 @@ void test_cos_bf16(global __bf16* out, __bf16 a) *out = __builtin_amdgcn_cos_bf16(a); } +// CHECK-LABEL: @test_cvt_sr_pk_bf16_f32( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca float, align 4, addrspace(5) +// CHECK-NEXT: [[SR_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[B_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[B_ADDR]] to ptr +// CHECK-NEXT: [[SR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[SR_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store float [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: store float [[B:%.*]], ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[SR:%.*]], ptr [[SR_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load float, ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, ptr [[B_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[SR_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = call <2 x bfloat> @llvm.amdgcn.cvt.sr.pk.bf16.f32(float [[TMP0]], float [[TMP1]], i32 [[TMP2]]) +// CHECK-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store <2 x bfloat> [[TMP3]], ptr addrspace(1) [[TMP4]], align 4 +// CHECK-NEXT: ret void +// +void test_cvt_sr_pk_bf16_f32(global bfloat2* out, float a, float b, uint sr) +{ + *out = __builtin_amdgcn_cvt_sr_pk_bf16_f32(a, b, sr); +} + // CHECK-LABEL: @test_cvt_f16_fp8( // CHECK-NEXT: entry: // CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) @@ -370,6 +398,144 @@ void test_cvt_pk_f16_bf8(global half2* out, short a) out[0] = __builtin_amdgcn_cvt_pk_f16_bf8(a); } +// CHECK-LABEL: @test_cvt_pk_bf8_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x half>, align 4, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store <2 x half> [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.amdgcn.cvt.pk.bf8.f16(<2 x half> [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i16 [[TMP1]], ptr addrspace(1) [[TMP2]], align 2 +// CHECK-NEXT: ret void +// +void test_cvt_pk_bf8_f16(global short* out, half2 a) +{ + *out = __builtin_amdgcn_cvt_pk_bf8_f16(a); +} + +// CHECK-LABEL: @test_cvt_pk_fp8_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca <2 x half>, align 4, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store <2 x half> [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[A_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.amdgcn.cvt.pk.fp8.f16(<2 x half> [[TMP0]]) +// CHECK-NEXT: [[TMP2:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i16 [[TMP1]], ptr addrspace(1) [[TMP2]], align 2 +// CHECK-NEXT: ret void +// +void test_cvt_pk_fp8_f16(global short* out, half2 a) +{ + *out = __builtin_amdgcn_cvt_pk_fp8_f16(a); +} + +// CHECK-LABEL: @test_cvt_sr_bf8_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca half, align 2, addrspace(5) +// CHECK-NEXT: [[SR_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[OLD_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[SR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[SR_ADDR]] to ptr +// CHECK-NEXT: [[OLD_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OLD_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store half [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: store i32 [[SR:%.*]], ptr [[SR_ADDR_ASCAST]], align 4 +// CHECK-NEXT: store i32 [[OLD:%.*]], ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[SR_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.amdgcn.cvt.sr.bf8.f16(half [[TMP0]], i32 [[TMP1]], i32 [[TMP2]], i32 0) +// CHECK-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[TMP3]], ptr addrspace(1) [[TMP4]], align 4 +// CHECK-NEXT: [[TMP5:%.*]] = load half, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP6:%.*]] = load i32, ptr [[SR_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.cvt.sr.bf8.f16(half [[TMP5]], i32 [[TMP6]], i32 [[TMP7]], i32 1) +// CHECK-NEXT: [[TMP9:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[TMP8]], ptr addrspace(1) [[TMP9]], align 4 +// CHECK-NEXT: [[TMP10:%.*]] = load half, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[SR_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP13:%.*]] = call i32 @llvm.amdgcn.cvt.sr.bf8.f16(half [[TMP10]], i32 [[TMP11]], i32 [[TMP12]], i32 2) +// CHECK-NEXT: [[TMP14:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[TMP13]], ptr addrspace(1) [[TMP14]], align 4 +// CHECK-NEXT: [[TMP15:%.*]] = load half, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP16:%.*]] = load i32, ptr [[SR_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP18:%.*]] = call i32 @llvm.amdgcn.cvt.sr.bf8.f16(half [[TMP15]], i32 [[TMP16]], i32 [[TMP17]], i32 3) +// CHECK-NEXT: [[TMP19:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[TMP18]], ptr addrspace(1) [[TMP19]], align 4 +// CHECK-NEXT: ret void +// +void test_cvt_sr_bf8_f16(global int* out, half a, uint sr, int old) +{ + *out = __builtin_amdgcn_cvt_sr_bf8_f16(a, sr, old, 0); + *out = __builtin_amdgcn_cvt_sr_bf8_f16(a, sr, old, 1); + *out = __builtin_amdgcn_cvt_sr_bf8_f16(a, sr, old, 2); + *out = __builtin_amdgcn_cvt_sr_bf8_f16(a, sr, old, 3); +} + +// CHECK-LABEL: @test_cvt_sr_fp8_f16( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr addrspace(1), align 8, addrspace(5) +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca half, align 2, addrspace(5) +// CHECK-NEXT: [[SR_ADDR:%.*]] = alloca i16, align 2, addrspace(5) +// CHECK-NEXT: [[OLD_ADDR:%.*]] = alloca i32, align 4, addrspace(5) +// CHECK-NEXT: [[OUT_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OUT_ADDR]] to ptr +// CHECK-NEXT: [[A_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[A_ADDR]] to ptr +// CHECK-NEXT: [[SR_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[SR_ADDR]] to ptr +// CHECK-NEXT: [[OLD_ADDR_ASCAST:%.*]] = addrspacecast ptr addrspace(5) [[OLD_ADDR]] to ptr +// CHECK-NEXT: store ptr addrspace(1) [[OUT:%.*]], ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store half [[A:%.*]], ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: store i16 [[SR:%.*]], ptr [[SR_ADDR_ASCAST]], align 2 +// CHECK-NEXT: store i32 [[OLD:%.*]], ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[SR_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[CONV:%.*]] = sext i16 [[TMP1]] to i32 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP3:%.*]] = call i32 @llvm.amdgcn.cvt.sr.fp8.f16(half [[TMP0]], i32 [[CONV]], i32 [[TMP2]], i32 0) +// CHECK-NEXT: [[TMP4:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[TMP3]], ptr addrspace(1) [[TMP4]], align 4 +// CHECK-NEXT: [[TMP5:%.*]] = load half, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP6:%.*]] = load i16, ptr [[SR_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[TMP6]] to i32 +// CHECK-NEXT: [[TMP7:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP8:%.*]] = call i32 @llvm.amdgcn.cvt.sr.fp8.f16(half [[TMP5]], i32 [[CONV1]], i32 [[TMP7]], i32 1) +// CHECK-NEXT: [[TMP9:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[TMP8]], ptr addrspace(1) [[TMP9]], align 4 +// CHECK-NEXT: [[TMP10:%.*]] = load half, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP11:%.*]] = load i16, ptr [[SR_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[CONV2:%.*]] = sext i16 [[TMP11]] to i32 +// CHECK-NEXT: [[TMP12:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP13:%.*]] = call i32 @llvm.amdgcn.cvt.sr.fp8.f16(half [[TMP10]], i32 [[CONV2]], i32 [[TMP12]], i32 2) +// CHECK-NEXT: [[TMP14:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[TMP13]], ptr addrspace(1) [[TMP14]], align 4 +// CHECK-NEXT: [[TMP15:%.*]] = load half, ptr [[A_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[TMP16:%.*]] = load i16, ptr [[SR_ADDR_ASCAST]], align 2 +// CHECK-NEXT: [[CONV3:%.*]] = sext i16 [[TMP16]] to i32 +// CHECK-NEXT: [[TMP17:%.*]] = load i32, ptr [[OLD_ADDR_ASCAST]], align 4 +// CHECK-NEXT: [[TMP18:%.*]] = call i32 @llvm.amdgcn.cvt.sr.fp8.f16(half [[TMP15]], i32 [[CONV3]], i32 [[TMP17]], i32 3) +// CHECK-NEXT: [[TMP19:%.*]] = load ptr addrspace(1), ptr [[OUT_ADDR_ASCAST]], align 8 +// CHECK-NEXT: store i32 [[TMP18]], ptr addrspace(1) [[TMP19]], align 4 +// CHECK-NEXT: ret void +// +void test_cvt_sr_fp8_f16(global int* out, half a, short sr, int old) +{ + *out = __builtin_amdgcn_cvt_sr_fp8_f16(a, sr, old, 0); + *out = __builtin_amdgcn_cvt_sr_fp8_f16(a, sr, old, 1); + *out = __builtin_amdgcn_cvt_sr_fp8_f16(a, sr, old, 2); + *out = __builtin_amdgcn_cvt_sr_fp8_f16(a, sr, old, 3); +} + // CHECK-LABEL: @test_sat_pk4_i4_i8( // CHECK-NEXT: entry: // CHECK-NEXT: [[OUT_ADDR:%.*]] = alloca ptr, align 8, addrspace(5) diff --git a/clang/test/Driver/baremetal.cpp b/clang/test/Driver/baremetal.cpp index 8b5ab43..26f030d 100644 --- a/clang/test/Driver/baremetal.cpp +++ b/clang/test/Driver/baremetal.cpp @@ -163,6 +163,16 @@ // RUN: | FileCheck %s --check-prefix=CHECK-RTLIB-GCC // CHECK-RTLIB-GCC: -lgcc +// RUN: %clang -### --target=arm-none-eabi -nolibc -rtlib=compiler-rt %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NOLIBC +// CHECK-NOLIBC-NOT: "-lc" +// CHECK-NOLIBC: "{{[^"]*}}libclang_rt.builtins.a" + +// RUN: %clang -### --target=arm-none-eabi -nostdlib -rtlib=compiler-rt %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-NOSTDLIB +// CHECK-NOSTDLIB-NOT: "-lc" +// CHECK-NOSTDLIB-NOT: "{{[^"]*}}libclang_rt.builtins.a" + // RUN: %clang -### --target=arm-none-eabi -v %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-SYSROOT-INC // CHECK-SYSROOT-INC-NOT: "-internal-isystem" "include" diff --git a/clang/test/Driver/compilation-dir.c b/clang/test/Driver/compilation-dir.c index dbe801c..70a117b 100644 --- a/clang/test/Driver/compilation-dir.c +++ b/clang/test/Driver/compilation-dir.c @@ -8,3 +8,8 @@ // RUN: %clang -### -integrated-as -ffile-compilation-dir=. -x assembler %s 2>&1 | FileCheck -check-prefixes=CHECK-DEBUG-COMPILATION-DIR %s // CHECK-DEBUG-COMPILATION-DIR: "-fdebug-compilation-dir=." // CHECK-DEBUG-COMPILATION-DIR-NOT: "-ffile-compilation-dir=." + +// RUN: %clang -### -S %s -working-directory %S 2>&1 | FileCheck -check-prefix=CHECK-CWD %s +// RUN: cd %S +// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-CWD %s +// CHECK-CWD: -fdebug-compilation-dir={{.*}}Driver diff --git a/clang/test/Driver/hip-dependent-options.hip b/clang/test/Driver/hip-dependent-options.hip index b0dc7f2..e65fec2 100644 --- a/clang/test/Driver/hip-dependent-options.hip +++ b/clang/test/Driver/hip-dependent-options.hip @@ -4,6 +4,12 @@ // RUN: %S/Inputs/hip_multiple_inputs/a.cu \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip --gpu-bundle-output \ // RUN: 2>&1 | FileCheck -check-prefixes=RELOCRDC %s +// RUN: not %clang -### --target=x86_64-linux-gnu --offload-new-driver \ +// RUN: -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \ +// RUN: -c -fhip-emit-relocatable -nogpuinc -nogpulib --cuda-device-only -fgpu-rdc \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: %S/Inputs/hip_multiple_inputs/b.hip --gpu-bundle-output \ +// RUN: 2>&1 | FileCheck -check-prefixes=RELOCRDC %s // RELOCRDC: error: option '-fhip-emit-relocatable' cannot be specified with '-fgpu-rdc' @@ -13,5 +19,11 @@ // RUN: %S/Inputs/hip_multiple_inputs/a.cu \ // RUN: %S/Inputs/hip_multiple_inputs/b.hip --gpu-bundle-output \ // RUN: 2>&1 | FileCheck -check-prefixes=RELOCHOST %s +// RUN: not %clang -### --target=x86_64-linux-gnu --offload-new-driver \ +// RUN: -x hip --cuda-gpu-arch=gfx803 --cuda-gpu-arch=gfx900 \ +// RUN: -c -fhip-emit-relocatable -nogpuinc -nogpulib \ +// RUN: %S/Inputs/hip_multiple_inputs/a.cu \ +// RUN: %S/Inputs/hip_multiple_inputs/b.hip --gpu-bundle-output \ +// RUN: 2>&1 | FileCheck -check-prefixes=RELOCHOST %s -// RELOCHOST: error: option '-fhip-emit-relocatable' cannot be specified without '--cuda-device-only' +// RELOCHOST: error: option '-fhip-emit-relocatable' cannot be specified without '--offload-device-only' diff --git a/clang/test/Driver/hip-phases.hip b/clang/test/Driver/hip-phases.hip index 0ad5d76..6bac97a 100644 --- a/clang/test/Driver/hip-phases.hip +++ b/clang/test/Driver/hip-phases.hip @@ -275,10 +275,16 @@ // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --no-offload-new-driver \ // RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only -fhip-emit-relocatable 2>&1 \ // RUN: | FileCheck -check-prefixes=RELOC %s +// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --offload-new-driver \ +// RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only -fhip-emit-relocatable 2>&1 \ +// RUN: | FileCheck -check-prefixes=RELOC %s // // RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --no-offload-new-driver \ // RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only -fhip-emit-relocatable -Wl,--disable-new-dtags \ // RUN: 2>&1 | FileCheck -check-prefixes=RELOC %s +// RUN: %clang -x hip --target=x86_64-unknown-linux-gnu -ccc-print-phases --offload-new-driver \ +// RUN: --cuda-gpu-arch=gfx803 %s --cuda-device-only -fhip-emit-relocatable -Wl,--disable-new-dtags \ +// RUN: 2>&1 | FileCheck -check-prefixes=RELOC %s // // RELOC-DAG: [[P0:[0-9]+]]: input, "{{.*}}hip-phases.hip", [[T:hip]], (device-[[T]], [[ARCH:gfx803]]) // RELOC-DAG: [[P1:[0-9]+]]: preprocessor, {[[P0]]}, [[T]]-cpp-output, (device-[[T]], [[ARCH]]) @@ -286,7 +292,7 @@ // RELOC-DAG: [[P3:[0-9]+]]: backend, {[[P2]]}, assembler, (device-[[T]], [[ARCH]]) // RELOC-DAG: [[P4:[0-9]+]]: assembler, {[[P3]]}, object, (device-[[T]], [[ARCH]]) // RELOC-NOT: linker -// RELOC-DAG: [[P5:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:[[ARCH]])" {[[P4]]}, object +// RELOC-DAG: [[P5:[0-9]+]]: offload, "device-[[T]] (amdgcn-amd-amdhsa:[[ARCH]])" {[[P4]]} // RELOC-NOT: host // diff --git a/clang/test/Driver/linker-wrapper-libs.c b/clang/test/Driver/linker-wrapper-libs.c index cb5c7c1..1404fe3 100644 --- a/clang/test/Driver/linker-wrapper-libs.c +++ b/clang/test/Driver/linker-wrapper-libs.c @@ -48,8 +48,8 @@ int bar() { return weak; } // RUN: --linker-path=/usr/bin/ld %t.a %t.o -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=LIBRARY-RESOLVES -// LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o -// LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o +// LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o +// LIBRARY-RESOLVES: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o // // Check that we extract a static library that defines a global visibile to the @@ -72,8 +72,8 @@ int bar() { return weak; } // RUN: --linker-path=/usr/bin/ld %t.a %t.o -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL -// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o -// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o +// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o +// LIBRARY-GLOBAL: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o // // Check that we do not extract a global symbol if the source file was not @@ -95,8 +95,8 @@ int bar() { return weak; } // RUN: --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL-NONE -// LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o -// LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o +// LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o +// LIBRARY-GLOBAL-NONE-NOT: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o // // Check that we do not extract an external weak symbol. @@ -116,9 +116,9 @@ int bar() { return weak; } // RUN: --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=LIBRARY-WEAK -// LIBRARY-WEAK: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 +// LIBRARY-WEAK: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=nvptx64-nvidia-cuda -march=sm_70 // LIBRARY-WEAK-NOT: {{.*}}.o {{.*}}.o -// LIBRARY-WEAK: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 +// LIBRARY-WEAK: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=amdgcn-amd-amdhsa -mcpu=gfx1030 // // Check that we do not extract an unneeded hidden symbol. @@ -138,9 +138,9 @@ int bar() { return weak; } // RUN: --linker-path=/usr/bin/ld %t.o %t.a -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=LIBRARY-HIDDEN -// LIBRARY-HIDDEN: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 +// LIBRARY-HIDDEN: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=nvptx64-nvidia-cuda -march=sm_70 // LIBRARY-HIDDEN-NOT: {{.*}}.o {{.*}}.o -// LIBRARY-HIDDEN: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 +// LIBRARY-HIDDEN: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=amdgcn-amd-amdhsa -mcpu=gfx1030 // // Check that we do not extract a static library that defines a global visibile @@ -161,9 +161,9 @@ int bar() { return weak; } // RUN: --linker-path=/usr/bin/ld %t.o %t.a %t.a -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=LIBRARY-GLOBAL-DEFINED -// LIBRARY-GLOBAL-DEFINED: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o +// LIBRARY-GLOBAL-DEFINED: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o // LIBRARY-GLOBAL-DEFINED-NOT: {{.*}}gfx1030{{.*}}.o -// LIBRARY-GLOBAL-DEFINED: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o +// LIBRARY-GLOBAL-DEFINED: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o // // Check that we can use --[no-]whole-archive to control extraction. @@ -185,7 +185,7 @@ int bar() { return weak; } // RUN: --linker-path=/usr/bin/ld %t.o --whole-archive %t.a -o a.out 2>&1 \ // RUN: | FileCheck %s --check-prefix=LIBRARY-WHOLE-ARCHIVE -// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o -// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o -// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_52 {{.*}}.o -// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a {{.*}}.o +// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o +// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=amdgcn-amd-amdhsa -mcpu=gfx1030 {{.*}}.o {{.*}}.o +// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=nvptx64-nvidia-cuda -march=sm_52 {{.*}}.o +// LIBRARY-WHOLE-ARCHIVE: clang{{.*}} -o {{.*}}.img -dumpdir {{.*}}.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a {{.*}}.o diff --git a/clang/test/Driver/linker-wrapper.c b/clang/test/Driver/linker-wrapper.c index 80b1a57..e73fa5c 100644 --- a/clang/test/Driver/linker-wrapper.c +++ b/clang/test/Driver/linker-wrapper.c @@ -22,7 +22,7 @@ __attribute__((visibility("protected"), used)) int x; // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \ // RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=NVPTX-LINK -// NVPTX-LINK: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o +// NVPTX-LINK: clang{{.*}} -o {{.*}}.img -dumpdir a.out.nvptx64.sm_70.img. --target=nvptx64-nvidia-cuda -march=sm_70 {{.*}}.o {{.*}}.o // RUN: clang-offload-packager -o %t.out \ // RUN: --image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70 \ @@ -40,7 +40,7 @@ __attribute__((visibility("protected"), used)) int x; // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \ // RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=AMDGPU-LINK -// AMDGPU-LINK: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o +// AMDGPU-LINK: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx908.img. --target=amdgcn-amd-amdhsa -mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o // RUN: clang-offload-packager -o %t.out \ // RUN: --image=file=%t.amdgpu.bc,kind=openmp,triple=amdgcn-amd-amdhsa,arch=gfx1030 \ @@ -57,7 +57,7 @@ __attribute__((visibility("protected"), used)) int x; // RUN: not clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \ // RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=SPIRV-LINK -// SPIRV-LINK: clang{{.*}} -o {{.*}}.img --target=spirv64-unknown-unknown {{.*}}.o --sycl-link -Xlinker -triple=spirv64-unknown-unknown -Xlinker -arch= +// SPIRV-LINK: clang{{.*}} -o {{.*}}.img -dumpdir a.out.spirv64..img. --target=spirv64-unknown-unknown {{.*}}.o --sycl-link -Xlinker -triple=spirv64-unknown-unknown -Xlinker -arch= // RUN: clang-offload-packager -o %t.out \ // RUN: --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \ @@ -68,7 +68,7 @@ __attribute__((visibility("protected"), used)) int x; // RUN: --linker-path=/usr/bin/ld.lld --whole-archive %t.a --no-whole-archive \ // RUN: %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CPU-LINK -// CPU-LINK: clang{{.*}} -o {{.*}}.img --target=x86_64-unknown-linux-gnu -Wl,--no-undefined {{.*}}.o {{.*}}.o -Wl,-Bsymbolic -shared -Wl,--whole-archive {{.*}}.a -Wl,--no-whole-archive +// CPU-LINK: clang{{.*}} -o {{.*}}.img -dumpdir a.out.x86_64..img. --target=x86_64-unknown-linux-gnu -Wl,--no-undefined {{.*}}.o {{.*}}.o -Wl,-Bsymbolic -shared -Wl,--whole-archive {{.*}}.a -Wl,--no-whole-archive // RUN: %clang -cc1 %s -triple x86_64-unknown-linux-gnu -emit-obj -o %t.o // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu -mllvm -openmp-opt-disable \ @@ -100,8 +100,8 @@ __attribute__((visibility("protected"), used)) int x; // RUN: clang-linker-wrapper --dry-run --host-triple=x86_64-unknown-linux-gnu \ // RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CUDA -// CUDA: clang{{.*}} -o [[IMG_SM70:.+]] --target=nvptx64-nvidia-cuda -march=sm_70 -// CUDA: clang{{.*}} -o [[IMG_SM52:.+]] --target=nvptx64-nvidia-cuda -march=sm_52 +// CUDA: clang{{.*}} -o [[IMG_SM70:.+]] -dumpdir a.out.nvptx64.sm_70.img. --target=nvptx64-nvidia-cuda -march=sm_70 +// CUDA: clang{{.*}} -o [[IMG_SM52:.+]] -dumpdir a.out.nvptx64.sm_52.img. --target=nvptx64-nvidia-cuda -march=sm_52 // CUDA: fatbinary{{.*}}-64 --create {{.*}}.fatbin --image=profile=sm_70,file=[[IMG_SM70]] --image=profile=sm_52,file=[[IMG_SM52]] // CUDA: usr/bin/ld{{.*}} {{.*}}.openmp.image.{{.*}}.o {{.*}}.cuda.image.{{.*}}.o @@ -127,8 +127,8 @@ __attribute__((visibility("protected"), used)) int x; // RUN: --compress --compression-level=6 \ // RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=HIP -// HIP: clang{{.*}} -o [[IMG_GFX90A:.+]] --target=amdgcn-amd-amdhsa -mcpu=gfx90a -// HIP: clang{{.*}} -o [[IMG_GFX908:.+]] --target=amdgcn-amd-amdhsa -mcpu=gfx908 +// HIP: clang{{.*}} -o [[IMG_GFX90A:.+]] -dumpdir a.out.amdgcn.gfx90a.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a +// HIP: clang{{.*}} -o [[IMG_GFX908:.+]] -dumpdir a.out.amdgcn.gfx908.img. --target=amdgcn-amd-amdhsa -mcpu=gfx908 // HIP: clang-offload-bundler{{.*}}-type=o -bundle-align=4096 -compress -compression-level=6 -targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa--gfx90a,hip-amdgcn-amd-amdhsa--gfx908 -input={{/dev/null|NUL}} -input=[[IMG_GFX90A]] -input=[[IMG_GFX908]] -output={{.*}}.hipfb // RUN: clang-offload-packager -o %t.out \ @@ -157,7 +157,7 @@ __attribute__((visibility("protected"), used)) int x; // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run --clang-backend \ // RUN: --linker-path=/usr/bin/ld %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=CLANG-BACKEND -// CLANG-BACKEND: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o +// CLANG-BACKEND: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx908.img. --target=amdgcn-amd-amdhsa -mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o // RUN: clang-offload-packager -o %t.out \ // RUN: --image=file=%t.elf.o,kind=openmp,triple=nvptx64-nvidia-cuda,arch=sm_70 @@ -180,8 +180,8 @@ __attribute__((visibility("protected"), used)) int x; // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \ // RUN: --linker-path=/usr/bin/ld %t-on.o %t-off.o %t.a -o a.out 2>&1 | FileCheck %s --check-prefix=AMD-TARGET-ID -// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack+ -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o -// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack- -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o +// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx90a:xnack+.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack+ -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o +// AMD-TARGET-ID: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx90a:xnack-.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a:xnack- -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o // RUN: clang-offload-packager -o %t-lib.out \ // RUN: --image=file=%t.elf.o,kind=openmp,triple=amdgcn-amd-amdhsa,arch=generic @@ -196,8 +196,8 @@ __attribute__((visibility("protected"), used)) int x; // RUN: clang-linker-wrapper --host-triple=x86_64-unknown-linux-gnu --dry-run \ // RUN: --linker-path=/usr/bin/ld %t1.o %t2.o %t.a -o a.out 2>&1 | FileCheck %s --check-prefix=ARCH-ALL -// ARCH-ALL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx90a -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o -// ARCH-ALL: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa -mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o +// ARCH-ALL: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx90a.img. --target=amdgcn-amd-amdhsa -mcpu=gfx90a -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o +// ARCH-ALL: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx908.img. --target=amdgcn-amd-amdhsa -mcpu=gfx908 -flto -Wl,--no-undefined {{.*}}.o {{.*}}.o // RUN: clang-offload-packager -o %t.out \ // RUN: --image=file=%t.elf.o,kind=openmp,triple=x86_64-unknown-linux-gnu \ @@ -207,7 +207,7 @@ __attribute__((visibility("protected"), used)) int x; // RUN: --linker-path=/usr/bin/ld.lld -r %t.o \ // RUN: %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK -// RELOCATABLE-LINK: clang{{.*}} -o {{.*}}.img --target=x86_64-unknown-linux-gnu +// RELOCATABLE-LINK: clang{{.*}} -o {{.*}}.img -dumpdir a.out.x86_64..img. --target=x86_64-unknown-linux-gnu // RELOCATABLE-LINK: /usr/bin/ld.lld{{.*}}-r // RELOCATABLE-LINK: llvm-objcopy{{.*}}a.out --remove-section .llvm.offloading @@ -219,7 +219,7 @@ __attribute__((visibility("protected"), used)) int x; // RUN: --linker-path=/usr/bin/ld.lld -r %t.o \ // RUN: %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK-HIP -// RELOCATABLE-LINK-HIP: clang{{.*}} -o {{.*}}.img --target=amdgcn-amd-amdhsa +// RELOCATABLE-LINK-HIP: clang{{.*}} -o {{.*}}.img -dumpdir a.out.amdgcn.gfx90a.img. --target=amdgcn-amd-amdhsa // RELOCATABLE-LINK-HIP: clang-offload-bundler{{.*}} -type=o -bundle-align=4096 -targets=host-x86_64-unknown-linux-gnu,hip-amdgcn-amd-amdhsa--gfx90a -input={{/dev/null|NUL}} -input={{.*}} -output={{.*}} // RELOCATABLE-LINK-HIP: /usr/bin/ld.lld{{.*}}-r // RELOCATABLE-LINK-HIP: llvm-objcopy{{.*}}a.out --remove-section .llvm.offloading @@ -233,7 +233,7 @@ __attribute__((visibility("protected"), used)) int x; // RUN: --linker-path=/usr/bin/ld.lld -r %t.o \ // RUN: %t.o -o a.out 2>&1 | FileCheck %s --check-prefix=RELOCATABLE-LINK-CUDA -// RELOCATABLE-LINK-CUDA: clang{{.*}} -o {{.*}}.img --target=nvptx64-nvidia-cuda +// RELOCATABLE-LINK-CUDA: clang{{.*}} -o {{.*}}.img -dumpdir a.out.nvptx64.sm_89.img. --target=nvptx64-nvidia-cuda // RELOCATABLE-LINK-CUDA: fatbinary{{.*}} -64 --create {{.*}}.fatbin --image=profile=sm_89,file={{.*}}.img // RELOCATABLE-LINK-CUDA: /usr/bin/ld.lld{{.*}}-r // RELOCATABLE-LINK-CUDA: llvm-objcopy{{.*}}a.out --remove-section .llvm.offloading diff --git a/clang/test/Driver/lto-dwo.c b/clang/test/Driver/lto-dwo.c index 206d4cb..5072765 100644 --- a/clang/test/Driver/lto-dwo.c +++ b/clang/test/Driver/lto-dwo.c @@ -1,9 +1,25 @@ // Confirm that -gsplit-dwarf=DIR is passed to linker -// RUN: %clang --target=x86_64-unknown-linux -### %s -flto=thin -gsplit-dwarf -o a.out 2> %t +// DEFINE: %{RUN-ELF} = %clang --target=x86_64-unknown-linux -### %s \ +// DEFINE: -flto=thin -gsplit-dwarf + +// RUN: %{RUN-ELF} -o a.out 2> %t // RUN: FileCheck -check-prefix=CHECK-LINK-ELF-DWO-DIR-DEFAULT < %t %s // RUN: %clang_cl --target=x86_64-unknown-windows-msvc -### -fuse-ld=lld -flto -gsplit-dwarf -o a.out -- %s 2> %t // RUN: FileCheck -check-prefix=CHECK-LINK-COFF-DWO-DIR-DEFAULT < %t %s // -// CHECK-LINK-ELF-DWO-DIR-DEFAULT: "-plugin-opt=dwo_dir=a.out_dwo" +// CHECK-LINK-ELF-DWO-DIR-DEFAULT: "-plugin-opt=dwo_dir=a.out-dwo" // CHECK-LINK-COFF-DWO-DIR-DEFAULT: "/dwodir:a.out_dwo" + +// Check -dumpdir effect on -gsplit-dwarf. +// +// DEFINE: %{RUN-DUMPDIR} = %{RUN-ELF} -dumpdir /dir/file.ext +// +// RUN: %{RUN-ELF} 2>&1 | FileCheck %s -check-prefix=CHECK-NO-O +// RUN: %{RUN-ELF} -o FOO 2>&1 | FileCheck %s -check-prefix=CHECK-O +// RUN: %{RUN-DUMPDIR} 2>&1 | FileCheck %s -check-prefix=CHECK-DUMPDIR +// RUN: %{RUN-DUMPDIR} -o FOO 2>&1 | FileCheck %s -check-prefix=CHECK-DUMPDIR +// +// CHECK-NO-O: "-plugin-opt=dwo_dir=a-dwo" +// CHECK-O: "-plugin-opt=dwo_dir=FOO-dwo" +// CHECK-DUMPDIR: "-plugin-opt=dwo_dir=/dir/file.extdwo" diff --git a/clang/test/Driver/mingw-msvcrt.c b/clang/test/Driver/mingw-msvcrt.c index 340ce1f..e164863 100644 --- a/clang/test/Driver/mingw-msvcrt.c +++ b/clang/test/Driver/mingw-msvcrt.c @@ -7,10 +7,10 @@ // CHECK_DEFAULT: "-lmingwex" "-lmsvcrt" "-ladvapi32" // CHECK_DEFAULT-SAME: "-lmsvcrt" "-lkernel32" "{{.*}}crtend.o" // CHECK_MSVCR120: "-lmsvcr120" -// CHECK_MSVCR120-SAME: "-lmingwex" "-ladvapi32" +// CHECK_MSVCR120-SAME: "-lmingwex" "-lmsvcr120" "-ladvapi32" // CHECK_UCRTBASE: "-lucrtbase" -// CHECK_UCRTBASE-SAME: "-lmingwex" "-ladvapi32" +// CHECK_UCRTBASE-SAME: "-lmingwex" "-lucrtbase" "-ladvapi32" // CHECK_UCRT: "-lucrt" -// CHECK_UCRT-SAME: "-lmingwex" "-ladvapi32" +// CHECK_UCRT-SAME: "-lmingwex" "-lucrt" "-ladvapi32" // CHECK_CRTDLL: "-lcrtdll" -// CHECK_CRTDLL-SAME: "-lmingwex" "-ladvapi32" +// CHECK_CRTDLL-SAME: "-lmingwex" "-lcrtdll" "-ladvapi32" diff --git a/clang/test/Driver/opt-record.c b/clang/test/Driver/opt-record.c index 220f5db..86d00d5 100644 --- a/clang/test/Driver/opt-record.c +++ b/clang/test/Driver/opt-record.c @@ -58,12 +58,12 @@ // CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-format=yaml" // CHECK-NOPASS-NOT: "-plugin-opt=opt-remarks-hotness-threshold=100" -// CHECK-PASS-A: "-plugin-opt=opt-remarks-filename=a.out.opt.ld.yaml" +// CHECK-PASS-A: "-plugin-opt=opt-remarks-filename=a-opt.ld.yaml" // CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-passes=inline" // CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-format=yaml" // CHECK-PASS-A-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" -// CHECK-PASS: "-plugin-opt=opt-remarks-filename=FOO.opt.ld.yaml" +// CHECK-PASS: "-plugin-opt=opt-remarks-filename=FOO-opt.ld.yaml" // CHECK-PASS-SAME: "-plugin-opt=opt-remarks-passes=inline" // CHECK-PASS-SAME: "-plugin-opt=opt-remarks-format=yaml" // CHECK-PASS-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" @@ -78,3 +78,17 @@ // CHECK-PASS-RPASS-SAME: "-plugin-opt=opt-remarks-hotness-threshold=100" // CHECK-PASS-AUTO: "-plugin-opt=opt-remarks-hotness-threshold=auto" + +// Check -dumpdir effect on -foptimization-record-file. +// +// DEFINE: %{RUN-DUMPDIR} = \ +// DEFINE: %clang --target=x86_64-linux -### -fuse-ld=lld -B%S/Inputs/lld \ +// DEFINE: -flto -fsave-optimization-record -dumpdir /dir/file.ext %s +// +// RUN: %{RUN-DUMPDIR} 2>&1 | FileCheck %s -check-prefix=CHECK-DUMPDIR +// RUN: %{RUN-DUMPDIR} -o FOO 2>&1 | FileCheck %s -check-prefix=CHECK-DUMPDIR +// RUN: %{RUN-DUMPDIR} -foptimization-record-file=user-file.ext 2>&1 | \ +// RUN: FileCheck %s -check-prefix=CHECK-DUMPDIR-IGNORE +// +// CHECK-DUMPDIR: "-plugin-opt=opt-remarks-filename=/dir/file.extopt.ld.yaml" +// CHECK-DUMPDIR-IGNORE: "-plugin-opt=opt-remarks-filename=user-file.ext.opt.ld.yaml" diff --git a/clang/test/Frontend/dump-minimization-hints.cpp b/clang/test/Frontend/dump-minimization-hints.cpp index 4843786..273fd7f 100644 --- a/clang/test/Frontend/dump-minimization-hints.cpp +++ b/clang/test/Frontend/dump-minimization-hints.cpp @@ -39,6 +39,26 @@ // RANGE-NEXT: "line": 15, // RANGE-NEXT: "column": 2 // RANGE-NEXT: } +// RANGE-NEXT: }, +// RANGE-NEXT: { +// RANGE-NEXT: "from": { +// RANGE-NEXT: "line": 19, +// RANGE-NEXT: "column": 1 +// RANGE-NEXT: }, +// RANGE-NEXT: "to": { +// RANGE-NEXT: "line": 19, +// RANGE-NEXT: "column": 41 +// RANGE-NEXT: } +// RANGE-NEXT: }, +// RANGE-NEXT: { +// RANGE-NEXT: "from": { +// RANGE-NEXT: "line": 20, +// RANGE-NEXT: "column": 1 +// RANGE-NEXT: }, +// RANGE-NEXT: "to": { +// RANGE-NEXT: "line": 23, +// RANGE-NEXT: "column": 2 +// RANGE-NEXT: } // RANGE-NEXT: } // RANGE-NEXT: ] // RANGE-NEXT: } @@ -68,6 +88,16 @@ int multiply(int a, int b) { return a * b; } +inline int unused_by_foo() {} // line 17 + +inline void recursively_used_by_foo() {} // line 19 +inline int used_by_foo() { // line 20 + recursively_used_by_foo(); + return 1; +} + +struct UnusedByFoo {}; + //--- foo.cpp #include "foo.h" int global_value = 5; @@ -76,4 +106,6 @@ int main() { int current_value = data.getValue(); int doubled_value = multiply(current_value, 2); int final_result = doubled_value + global_value; + + return used_by_foo(); } diff --git a/clang/test/Headers/__clang_hip_math.hip b/clang/test/Headers/__clang_hip_math.hip index d31ca84..81c5f43 100644 --- a/clang/test/Headers/__clang_hip_math.hip +++ b/clang/test/Headers/__clang_hip_math.hip @@ -49,30 +49,27 @@ typedef unsigned long long uint64_t; // CHECK-LABEL: @test___make_mantissa_base8( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND_I:%.*]] -// CHECK: while.cond.i: -// CHECK-NEXT: [[__TAGP_ADDR_0_I:%.*]] = phi ptr [ [[P:%.*]], [[ENTRY:%.*]] ], [ [[__TAGP_ADDR_1_I:%.*]], [[CLEANUP_I:%.*]] ] -// CHECK-NEXT: [[__R_0_I:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[__R_1_I:%.*]], [[CLEANUP_I]] ] -// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I]], align 1, !tbaa [[TBAA4:![0-9]+]] -// CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0 -// CHECK-NEXT: br i1 [[CMP_NOT_I]], label [[_ZL21__MAKE_MANTISSA_BASE8PKC_EXIT:%.*]], label [[WHILE_BODY_I:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[P:%.*]], align 1, !tbaa [[TBAA4:![0-9]+]] +// CHECK-NEXT: [[CMP_NOT_I1:%.*]] = icmp eq i8 [[TMP0]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I1]], label [[_ZL21__MAKE_MANTISSA_BASE8PKC_EXIT:%.*]], label [[WHILE_BODY_I:%.*]] // CHECK: while.body.i: -// CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], -8 -// CHECK-NEXT: [[OR_COND_I:%.*]] = icmp eq i8 [[TMP1]], 48 -// CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I:%.*]], label [[CLEANUP_I]] +// CHECK-NEXT: [[TMP1:%.*]] = phi i8 [ [[TMP3:%.*]], [[IF_THEN_I:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] +// CHECK-NEXT: [[__R_0_I3:%.*]] = phi i64 [ [[SUB_I:%.*]], [[IF_THEN_I]] ], [ 0, [[ENTRY]] ] +// CHECK-NEXT: [[__TAGP_ADDR_0_I2:%.*]] = phi ptr [ [[INCDEC_PTR_I:%.*]], [[IF_THEN_I]] ], [ [[P]], [[ENTRY]] ] +// CHECK-NEXT: [[TMP2:%.*]] = and i8 [[TMP1]], -8 +// CHECK-NEXT: [[OR_COND_I:%.*]] = icmp eq i8 [[TMP2]], 48 +// CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I]], label [[_ZL21__MAKE_MANTISSA_BASE8PKC_EXIT]] // CHECK: if.then.i: -// CHECK-NEXT: [[MUL_I:%.*]] = shl i64 [[__R_0_I]], 3 -// CHECK-NEXT: [[CONV5_I:%.*]] = zext nneg i8 [[TMP0]] to i64 +// CHECK-NEXT: [[MUL_I:%.*]] = shl i64 [[__R_0_I3]], 3 +// CHECK-NEXT: [[CONV5_I:%.*]] = zext nneg i8 [[TMP1]] to i64 // CHECK-NEXT: [[ADD_I:%.*]] = add i64 [[MUL_I]], -48 -// CHECK-NEXT: [[SUB_I:%.*]] = add i64 [[ADD_I]], [[CONV5_I]] -// CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I]], i64 1 -// CHECK-NEXT: br label [[CLEANUP_I]] -// CHECK: cleanup.i: -// CHECK-NEXT: [[__TAGP_ADDR_1_I]] = phi ptr [ [[INCDEC_PTR_I]], [[IF_THEN_I]] ], [ [[__TAGP_ADDR_0_I]], [[WHILE_BODY_I]] ] -// CHECK-NEXT: [[__R_1_I]] = phi i64 [ [[SUB_I]], [[IF_THEN_I]] ], [ [[__R_0_I]], [[WHILE_BODY_I]] ] -// CHECK-NEXT: br i1 [[OR_COND_I]], label [[WHILE_COND_I]], label [[_ZL21__MAKE_MANTISSA_BASE8PKC_EXIT]], !llvm.loop [[LOOP7:![0-9]+]] +// CHECK-NEXT: [[SUB_I]] = add i64 [[ADD_I]], [[CONV5_I]] +// CHECK-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I2]], i64 1 +// CHECK-NEXT: [[TMP3]] = load i8, ptr [[INCDEC_PTR_I]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[TMP3]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I]], label [[_ZL21__MAKE_MANTISSA_BASE8PKC_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP7:![0-9]+]] // CHECK: _ZL21__make_mantissa_base8PKc.exit: -// CHECK-NEXT: [[RETVAL_2_I:%.*]] = phi i64 [ 0, [[CLEANUP_I]] ], [ [[__R_0_I]], [[WHILE_COND_I]] ] +// CHECK-NEXT: [[RETVAL_2_I:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ 0, [[WHILE_BODY_I]] ], [ [[SUB_I]], [[IF_THEN_I]] ] // CHECK-NEXT: ret i64 [[RETVAL_2_I]] // // AMDGCNSPIRV-LABEL: @test___make_mantissa_base8( @@ -105,30 +102,27 @@ extern "C" __device__ uint64_t test___make_mantissa_base8(const char *p) { // CHECK-LABEL: @test___make_mantissa_base10( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND_I:%.*]] -// CHECK: while.cond.i: -// CHECK-NEXT: [[__TAGP_ADDR_0_I:%.*]] = phi ptr [ [[P:%.*]], [[ENTRY:%.*]] ], [ [[__TAGP_ADDR_1_I:%.*]], [[CLEANUP_I:%.*]] ] -// CHECK-NEXT: [[__R_0_I:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[__R_1_I:%.*]], [[CLEANUP_I]] ] -// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I]], align 1, !tbaa [[TBAA4]] -// CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0 -// CHECK-NEXT: br i1 [[CMP_NOT_I]], label [[_ZL22__MAKE_MANTISSA_BASE10PKC_EXIT:%.*]], label [[WHILE_BODY_I:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[P:%.*]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I1:%.*]] = icmp eq i8 [[TMP0]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I1]], label [[_ZL22__MAKE_MANTISSA_BASE10PKC_EXIT:%.*]], label [[WHILE_BODY_I:%.*]] // CHECK: while.body.i: -// CHECK-NEXT: [[TMP1:%.*]] = add i8 [[TMP0]], -48 -// CHECK-NEXT: [[OR_COND_I:%.*]] = icmp ult i8 [[TMP1]], 10 -// CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I:%.*]], label [[CLEANUP_I]] +// CHECK-NEXT: [[TMP1:%.*]] = phi i8 [ [[TMP3:%.*]], [[IF_THEN_I:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] +// CHECK-NEXT: [[__R_0_I3:%.*]] = phi i64 [ [[SUB_I:%.*]], [[IF_THEN_I]] ], [ 0, [[ENTRY]] ] +// CHECK-NEXT: [[__TAGP_ADDR_0_I2:%.*]] = phi ptr [ [[INCDEC_PTR_I:%.*]], [[IF_THEN_I]] ], [ [[P]], [[ENTRY]] ] +// CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], -48 +// CHECK-NEXT: [[OR_COND_I:%.*]] = icmp ult i8 [[TMP2]], 10 +// CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_THEN_I]], label [[_ZL22__MAKE_MANTISSA_BASE10PKC_EXIT]] // CHECK: if.then.i: -// CHECK-NEXT: [[MUL_I:%.*]] = mul i64 [[__R_0_I]], 10 -// CHECK-NEXT: [[CONV5_I:%.*]] = zext nneg i8 [[TMP0]] to i64 +// CHECK-NEXT: [[MUL_I:%.*]] = mul i64 [[__R_0_I3]], 10 +// CHECK-NEXT: [[CONV5_I:%.*]] = zext nneg i8 [[TMP1]] to i64 // CHECK-NEXT: [[ADD_I:%.*]] = add i64 [[MUL_I]], -48 -// CHECK-NEXT: [[SUB_I:%.*]] = add i64 [[ADD_I]], [[CONV5_I]] -// CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I]], i64 1 -// CHECK-NEXT: br label [[CLEANUP_I]] -// CHECK: cleanup.i: -// CHECK-NEXT: [[__TAGP_ADDR_1_I]] = phi ptr [ [[INCDEC_PTR_I]], [[IF_THEN_I]] ], [ [[__TAGP_ADDR_0_I]], [[WHILE_BODY_I]] ] -// CHECK-NEXT: [[__R_1_I]] = phi i64 [ [[SUB_I]], [[IF_THEN_I]] ], [ [[__R_0_I]], [[WHILE_BODY_I]] ] -// CHECK-NEXT: br i1 [[OR_COND_I]], label [[WHILE_COND_I]], label [[_ZL22__MAKE_MANTISSA_BASE10PKC_EXIT]], !llvm.loop [[LOOP10:![0-9]+]] +// CHECK-NEXT: [[SUB_I]] = add i64 [[ADD_I]], [[CONV5_I]] +// CHECK-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I2]], i64 1 +// CHECK-NEXT: [[TMP3]] = load i8, ptr [[INCDEC_PTR_I]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[TMP3]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I]], label [[_ZL22__MAKE_MANTISSA_BASE10PKC_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP10:![0-9]+]] // CHECK: _ZL22__make_mantissa_base10PKc.exit: -// CHECK-NEXT: [[RETVAL_2_I:%.*]] = phi i64 [ 0, [[CLEANUP_I]] ], [ [[__R_0_I]], [[WHILE_COND_I]] ] +// CHECK-NEXT: [[RETVAL_2_I:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ 0, [[WHILE_BODY_I]] ], [ [[SUB_I]], [[IF_THEN_I]] ] // CHECK-NEXT: ret i64 [[RETVAL_2_I]] // // AMDGCNSPIRV-LABEL: @test___make_mantissa_base10( @@ -161,78 +155,70 @@ extern "C" __device__ uint64_t test___make_mantissa_base10(const char *p) { // CHECK-LABEL: @test___make_mantissa_base16( // CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND_I:%.*]] -// CHECK: while.cond.i: -// CHECK-NEXT: [[__TAGP_ADDR_0_I:%.*]] = phi ptr [ [[P:%.*]], [[ENTRY:%.*]] ], [ [[__TAGP_ADDR_1_I:%.*]], [[CLEANUP_I:%.*]] ] -// CHECK-NEXT: [[__R_0_I:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[__R_2_I:%.*]], [[CLEANUP_I]] ] -// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I]], align 1, !tbaa [[TBAA4]] -// CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0 -// CHECK-NEXT: br i1 [[CMP_NOT_I]], label [[_ZL22__MAKE_MANTISSA_BASE16PKC_EXIT:%.*]], label [[WHILE_BODY_I:%.*]] +// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[P:%.*]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I1:%.*]] = icmp eq i8 [[TMP0]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I1]], label [[_ZL22__MAKE_MANTISSA_BASE16PKC_EXIT:%.*]], label [[WHILE_BODY_I:%.*]] // CHECK: while.body.i: -// CHECK-NEXT: [[TMP1:%.*]] = add i8 [[TMP0]], -48 -// CHECK-NEXT: [[OR_COND_I:%.*]] = icmp ult i8 [[TMP1]], 10 -// CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_END31_I:%.*]], label [[IF_ELSE_I:%.*]] +// CHECK-NEXT: [[TMP1:%.*]] = phi i8 [ [[TMP5:%.*]], [[IF_END31_I:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] +// CHECK-NEXT: [[__R_0_I3:%.*]] = phi i64 [ [[ADD28_I:%.*]], [[IF_END31_I]] ], [ 0, [[ENTRY]] ] +// CHECK-NEXT: [[__TAGP_ADDR_0_I2:%.*]] = phi ptr [ [[INCDEC_PTR_I:%.*]], [[IF_END31_I]] ], [ [[P]], [[ENTRY]] ] +// CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], -48 +// CHECK-NEXT: [[OR_COND_I:%.*]] = icmp ult i8 [[TMP2]], 10 +// CHECK-NEXT: br i1 [[OR_COND_I]], label [[IF_END31_I]], label [[IF_ELSE_I:%.*]] // CHECK: if.else.i: -// CHECK-NEXT: [[TMP2:%.*]] = add i8 [[TMP0]], -97 -// CHECK-NEXT: [[OR_COND33_I:%.*]] = icmp ult i8 [[TMP2]], 6 +// CHECK-NEXT: [[TMP3:%.*]] = add i8 [[TMP1]], -97 +// CHECK-NEXT: [[OR_COND33_I:%.*]] = icmp ult i8 [[TMP3]], 6 // CHECK-NEXT: br i1 [[OR_COND33_I]], label [[IF_END31_I]], label [[IF_ELSE17_I:%.*]] // CHECK: if.else17.i: -// CHECK-NEXT: [[TMP3:%.*]] = add i8 [[TMP0]], -65 -// CHECK-NEXT: [[OR_COND34_I:%.*]] = icmp ult i8 [[TMP3]], 6 -// CHECK-NEXT: br i1 [[OR_COND34_I]], label [[IF_END31_I]], label [[CLEANUP_I]] +// CHECK-NEXT: [[TMP4:%.*]] = add i8 [[TMP1]], -65 +// CHECK-NEXT: [[OR_COND34_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// CHECK-NEXT: br i1 [[OR_COND34_I]], label [[IF_END31_I]], label [[_ZL22__MAKE_MANTISSA_BASE16PKC_EXIT]] // CHECK: if.end31.i: // CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I]] ], [ -87, [[IF_ELSE_I]] ], [ -55, [[IF_ELSE17_I]] ] -// CHECK-NEXT: [[MUL24_I:%.*]] = shl i64 [[__R_0_I]], 4 -// CHECK-NEXT: [[CONV25_I:%.*]] = zext nneg i8 [[TMP0]] to i64 +// CHECK-NEXT: [[MUL24_I:%.*]] = shl i64 [[__R_0_I3]], 4 +// CHECK-NEXT: [[CONV25_I:%.*]] = zext nneg i8 [[TMP1]] to i64 // CHECK-NEXT: [[ADD26_I:%.*]] = add i64 [[MUL24_I]], [[DOTSINK]] -// CHECK-NEXT: [[ADD28_I:%.*]] = add i64 [[ADD26_I]], [[CONV25_I]] -// CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I]], i64 1 -// CHECK-NEXT: br label [[CLEANUP_I]] -// CHECK: cleanup.i: -// CHECK-NEXT: [[__TAGP_ADDR_1_I]] = phi ptr [ [[INCDEC_PTR_I]], [[IF_END31_I]] ], [ [[__TAGP_ADDR_0_I]], [[IF_ELSE17_I]] ] -// CHECK-NEXT: [[__R_2_I]] = phi i64 [ [[ADD28_I]], [[IF_END31_I]] ], [ [[__R_0_I]], [[IF_ELSE17_I]] ] -// CHECK-NEXT: [[COND_I:%.*]] = phi i1 [ true, [[IF_END31_I]] ], [ false, [[IF_ELSE17_I]] ] -// CHECK-NEXT: br i1 [[COND_I]], label [[WHILE_COND_I]], label [[_ZL22__MAKE_MANTISSA_BASE16PKC_EXIT]], !llvm.loop [[LOOP11:![0-9]+]] +// CHECK-NEXT: [[ADD28_I]] = add i64 [[ADD26_I]], [[CONV25_I]] +// CHECK-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I2]], i64 1 +// CHECK-NEXT: [[TMP5]] = load i8, ptr [[INCDEC_PTR_I]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[TMP5]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I]], label [[_ZL22__MAKE_MANTISSA_BASE16PKC_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP11:![0-9]+]] // CHECK: _ZL22__make_mantissa_base16PKc.exit: -// CHECK-NEXT: [[RETVAL_2_I:%.*]] = phi i64 [ 0, [[CLEANUP_I]] ], [ [[__R_0_I]], [[WHILE_COND_I]] ] +// CHECK-NEXT: [[RETVAL_2_I:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ 0, [[IF_ELSE17_I]] ], [ [[ADD28_I]], [[IF_END31_I]] ] // CHECK-NEXT: ret i64 [[RETVAL_2_I]] // // AMDGCNSPIRV-LABEL: @test___make_mantissa_base16( // AMDGCNSPIRV-NEXT: entry: -// AMDGCNSPIRV-NEXT: br label [[WHILE_COND_I:%.*]] -// AMDGCNSPIRV: while.cond.i: -// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I:%.*]] = phi ptr addrspace(4) [ [[P:%.*]], [[ENTRY:%.*]] ], [ [[__TAGP_ADDR_1_I:%.*]], [[CLEANUP_I:%.*]] ] -// AMDGCNSPIRV-NEXT: [[__R_0_I:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ [[__R_2_I:%.*]], [[CLEANUP_I]] ] -// AMDGCNSPIRV-NEXT: [[TMP0:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I]], align 1, !tbaa [[TBAA5]] -// AMDGCNSPIRV-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[TMP0]], 0 -// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I]], label [[_ZL22__MAKE_MANTISSA_BASE16PKC_EXIT:%.*]], label [[WHILE_BODY_I:%.*]] +// AMDGCNSPIRV-NEXT: [[TMP0:%.*]] = load i8, ptr addrspace(4) [[P:%.*]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I1:%.*]] = icmp eq i8 [[TMP0]], 0 +// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I1]], label [[_ZL22__MAKE_MANTISSA_BASE16PKC_EXIT:%.*]], label [[WHILE_BODY_I:%.*]] // AMDGCNSPIRV: while.body.i: -// AMDGCNSPIRV-NEXT: [[TMP1:%.*]] = add i8 [[TMP0]], -48 -// AMDGCNSPIRV-NEXT: [[OR_COND_I:%.*]] = icmp ult i8 [[TMP1]], 10 -// AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I]], label [[IF_END31_I:%.*]], label [[IF_ELSE_I:%.*]] +// AMDGCNSPIRV-NEXT: [[TMP1:%.*]] = phi i8 [ [[TMP5:%.*]], [[IF_END31_I:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] +// AMDGCNSPIRV-NEXT: [[__R_0_I3:%.*]] = phi i64 [ [[ADD28_I:%.*]], [[IF_END31_I]] ], [ 0, [[ENTRY]] ] +// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I2:%.*]] = phi ptr addrspace(4) [ [[INCDEC_PTR_I:%.*]], [[IF_END31_I]] ], [ [[P]], [[ENTRY]] ] +// AMDGCNSPIRV-NEXT: [[TMP2:%.*]] = add i8 [[TMP1]], -48 +// AMDGCNSPIRV-NEXT: [[OR_COND_I:%.*]] = icmp ult i8 [[TMP2]], 10 +// AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I]], label [[IF_END31_I]], label [[IF_ELSE_I:%.*]] // AMDGCNSPIRV: if.else.i: -// AMDGCNSPIRV-NEXT: [[TMP2:%.*]] = add i8 [[TMP0]], -97 -// AMDGCNSPIRV-NEXT: [[OR_COND33_I:%.*]] = icmp ult i8 [[TMP2]], 6 +// AMDGCNSPIRV-NEXT: [[TMP3:%.*]] = add i8 [[TMP1]], -97 +// AMDGCNSPIRV-NEXT: [[OR_COND33_I:%.*]] = icmp ult i8 [[TMP3]], 6 // AMDGCNSPIRV-NEXT: br i1 [[OR_COND33_I]], label [[IF_END31_I]], label [[IF_ELSE17_I:%.*]] // AMDGCNSPIRV: if.else17.i: -// AMDGCNSPIRV-NEXT: [[TMP3:%.*]] = add i8 [[TMP0]], -65 -// AMDGCNSPIRV-NEXT: [[OR_COND34_I:%.*]] = icmp ult i8 [[TMP3]], 6 -// AMDGCNSPIRV-NEXT: br i1 [[OR_COND34_I]], label [[IF_END31_I]], label [[CLEANUP_I]] +// AMDGCNSPIRV-NEXT: [[TMP4:%.*]] = add i8 [[TMP1]], -65 +// AMDGCNSPIRV-NEXT: [[OR_COND34_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// AMDGCNSPIRV-NEXT: br i1 [[OR_COND34_I]], label [[IF_END31_I]], label [[_ZL22__MAKE_MANTISSA_BASE16PKC_EXIT]] // AMDGCNSPIRV: if.end31.i: // AMDGCNSPIRV-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I]] ], [ -87, [[IF_ELSE_I]] ], [ -55, [[IF_ELSE17_I]] ] -// AMDGCNSPIRV-NEXT: [[MUL24_I:%.*]] = shl i64 [[__R_0_I]], 4 -// AMDGCNSPIRV-NEXT: [[CONV25_I:%.*]] = zext nneg i8 [[TMP0]] to i64 +// AMDGCNSPIRV-NEXT: [[MUL24_I:%.*]] = shl i64 [[__R_0_I3]], 4 +// AMDGCNSPIRV-NEXT: [[CONV25_I:%.*]] = zext nneg i8 [[TMP1]] to i64 // AMDGCNSPIRV-NEXT: [[ADD26_I:%.*]] = add i64 [[MUL24_I]], [[DOTSINK]] -// AMDGCNSPIRV-NEXT: [[ADD28_I:%.*]] = add i64 [[ADD26_I]], [[CONV25_I]] -// AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[__TAGP_ADDR_0_I]], i64 1 -// AMDGCNSPIRV-NEXT: br label [[CLEANUP_I]] -// AMDGCNSPIRV: cleanup.i: -// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_1_I]] = phi ptr addrspace(4) [ [[INCDEC_PTR_I]], [[IF_END31_I]] ], [ [[__TAGP_ADDR_0_I]], [[IF_ELSE17_I]] ] -// AMDGCNSPIRV-NEXT: [[__R_2_I]] = phi i64 [ [[ADD28_I]], [[IF_END31_I]] ], [ [[__R_0_I]], [[IF_ELSE17_I]] ] -// AMDGCNSPIRV-NEXT: [[COND_I:%.*]] = phi i1 [ true, [[IF_END31_I]] ], [ false, [[IF_ELSE17_I]] ] -// AMDGCNSPIRV-NEXT: br i1 [[COND_I]], label [[WHILE_COND_I]], label [[_ZL22__MAKE_MANTISSA_BASE16PKC_EXIT]], !llvm.loop [[LOOP12:![0-9]+]] +// AMDGCNSPIRV-NEXT: [[ADD28_I]] = add i64 [[ADD26_I]], [[CONV25_I]] +// AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[__TAGP_ADDR_0_I2]], i64 1 +// AMDGCNSPIRV-NEXT: [[TMP5]] = load i8, ptr addrspace(4) [[INCDEC_PTR_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I:%.*]] = icmp eq i8 [[TMP5]], 0 +// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I]], label [[_ZL22__MAKE_MANTISSA_BASE16PKC_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP12:![0-9]+]] // AMDGCNSPIRV: _ZL22__make_mantissa_base16PKc.exit: -// AMDGCNSPIRV-NEXT: [[RETVAL_2_I:%.*]] = phi i64 [ 0, [[CLEANUP_I]] ], [ [[__R_0_I]], [[WHILE_COND_I]] ] +// AMDGCNSPIRV-NEXT: [[RETVAL_2_I:%.*]] = phi i64 [ 0, [[ENTRY]] ], [ 0, [[IF_ELSE17_I]] ], [ [[ADD28_I]], [[IF_END31_I]] ] // AMDGCNSPIRV-NEXT: ret i64 [[RETVAL_2_I]] // extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) { @@ -243,91 +229,85 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) { // CHECK-NEXT: entry: // CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[P:%.*]], align 1, !tbaa [[TBAA4]] // CHECK-NEXT: [[CMP_I:%.*]] = icmp eq i8 [[TMP0]], 48 -// CHECK-NEXT: br i1 [[CMP_I]], label [[IF_THEN_I:%.*]], label [[WHILE_COND_I14_I:%.*]] +// CHECK-NEXT: br i1 [[CMP_I]], label [[IF_THEN_I:%.*]], label [[WHILE_COND_I14_I_PREHEADER:%.*]] +// CHECK: while.cond.i14.i.preheader: +// CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[P]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I17_I5:%.*]] = icmp eq i8 [[TMP1]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I17_I5]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT:%.*]], label [[WHILE_BODY_I18_I:%.*]] // CHECK: if.then.i: // CHECK-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[P]], i64 1 -// CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[INCDEC_PTR_I]], align 1, !tbaa [[TBAA4]] -// CHECK-NEXT: switch i8 [[TMP1]], label [[WHILE_COND_I_I:%.*]] [ -// CHECK-NEXT: i8 120, label [[WHILE_COND_I30_I_PREHEADER:%.*]] -// CHECK-NEXT: i8 88, label [[WHILE_COND_I30_I_PREHEADER]] +// CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[INCDEC_PTR_I]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: switch i8 [[TMP2]], label [[WHILE_COND_I_I_PREHEADER:%.*]] [ +// CHECK-NEXT: i8 120, label [[IF_THEN5_I:%.*]] +// CHECK-NEXT: i8 88, label [[IF_THEN5_I]] // CHECK-NEXT: ] -// CHECK: while.cond.i30.i.preheader: -// CHECK-NEXT: br label [[WHILE_COND_I30_I:%.*]] -// CHECK: while.cond.i30.i: -// CHECK-NEXT: [[__TAGP_ADDR_0_I31_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I37_I:%.*]], [[CLEANUP_I36_I:%.*]] ], [ [[INCDEC_PTR_I]], [[WHILE_COND_I30_I_PREHEADER]] ] -// CHECK-NEXT: [[__R_0_I32_I:%.*]] = phi i64 [ [[__R_2_I_I:%.*]], [[CLEANUP_I36_I]] ], [ 0, [[WHILE_COND_I30_I_PREHEADER]] ] -// CHECK-NEXT: [[TMP2:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I31_I]], align 1, !tbaa [[TBAA4]] -// CHECK-NEXT: [[CMP_NOT_I33_I:%.*]] = icmp eq i8 [[TMP2]], 0 -// CHECK-NEXT: br i1 [[CMP_NOT_I33_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT:%.*]], label [[WHILE_BODY_I34_I:%.*]] -// CHECK: while.body.i34.i: -// CHECK-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], -48 -// CHECK-NEXT: [[OR_COND_I35_I:%.*]] = icmp ult i8 [[TMP3]], 10 -// CHECK-NEXT: br i1 [[OR_COND_I35_I]], label [[IF_END31_I_I:%.*]], label [[IF_ELSE_I_I:%.*]] +// CHECK: while.cond.i.i.preheader: +// CHECK-NEXT: [[TMP3:%.*]] = load i8, ptr [[INCDEC_PTR_I]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I_I14:%.*]] = icmp eq i8 [[TMP3]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I_I14]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], label [[WHILE_BODY_I_I:%.*]] +// CHECK: if.then5.i: +// CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[INCDEC_PTR_I]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I30_I9:%.*]] = icmp eq i8 [[TMP4]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I30_I9]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], label [[WHILE_BODY_I31_I:%.*]] +// CHECK: while.body.i31.i: +// CHECK-NEXT: [[TMP5:%.*]] = phi i8 [ [[TMP9:%.*]], [[IF_END31_I_I:%.*]] ], [ [[TMP4]], [[IF_THEN5_I]] ] +// CHECK-NEXT: [[__R_0_I29_I11:%.*]] = phi i64 [ [[ADD28_I_I:%.*]], [[IF_END31_I_I]] ], [ 0, [[IF_THEN5_I]] ] +// CHECK-NEXT: [[__TAGP_ADDR_0_I28_I10:%.*]] = phi ptr [ [[INCDEC_PTR_I34_I:%.*]], [[IF_END31_I_I]] ], [ [[INCDEC_PTR_I]], [[IF_THEN5_I]] ] +// CHECK-NEXT: [[TMP6:%.*]] = add i8 [[TMP5]], -48 +// CHECK-NEXT: [[OR_COND_I32_I:%.*]] = icmp ult i8 [[TMP6]], 10 +// CHECK-NEXT: br i1 [[OR_COND_I32_I]], label [[IF_END31_I_I]], label [[IF_ELSE_I_I:%.*]] // CHECK: if.else.i.i: -// CHECK-NEXT: [[TMP4:%.*]] = add i8 [[TMP2]], -97 -// CHECK-NEXT: [[OR_COND33_I_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// CHECK-NEXT: [[TMP7:%.*]] = add i8 [[TMP5]], -97 +// CHECK-NEXT: [[OR_COND33_I_I:%.*]] = icmp ult i8 [[TMP7]], 6 // CHECK-NEXT: br i1 [[OR_COND33_I_I]], label [[IF_END31_I_I]], label [[IF_ELSE17_I_I:%.*]] // CHECK: if.else17.i.i: -// CHECK-NEXT: [[TMP5:%.*]] = add i8 [[TMP2]], -65 -// CHECK-NEXT: [[OR_COND34_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 -// CHECK-NEXT: br i1 [[OR_COND34_I_I]], label [[IF_END31_I_I]], label [[CLEANUP_I36_I]] +// CHECK-NEXT: [[TMP8:%.*]] = add i8 [[TMP5]], -65 +// CHECK-NEXT: [[OR_COND34_I_I:%.*]] = icmp ult i8 [[TMP8]], 6 +// CHECK-NEXT: br i1 [[OR_COND34_I_I]], label [[IF_END31_I_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]] // CHECK: if.end31.i.i: -// CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I]] ], [ -87, [[IF_ELSE_I_I]] ], [ -55, [[IF_ELSE17_I_I]] ] -// CHECK-NEXT: [[MUL24_I_I:%.*]] = shl i64 [[__R_0_I32_I]], 4 -// CHECK-NEXT: [[CONV25_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 +// CHECK-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I31_I]] ], [ -87, [[IF_ELSE_I_I]] ], [ -55, [[IF_ELSE17_I_I]] ] +// CHECK-NEXT: [[MUL24_I_I:%.*]] = shl i64 [[__R_0_I29_I11]], 4 +// CHECK-NEXT: [[CONV25_I_I:%.*]] = zext nneg i8 [[TMP5]] to i64 // CHECK-NEXT: [[ADD26_I_I:%.*]] = add i64 [[MUL24_I_I]], [[DOTSINK]] -// CHECK-NEXT: [[ADD28_I_I:%.*]] = add i64 [[ADD26_I_I]], [[CONV25_I_I]] -// CHECK-NEXT: [[INCDEC_PTR_I40_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I31_I]], i64 1 -// CHECK-NEXT: br label [[CLEANUP_I36_I]] -// CHECK: cleanup.i36.i: -// CHECK-NEXT: [[__TAGP_ADDR_1_I37_I]] = phi ptr [ [[INCDEC_PTR_I40_I]], [[IF_END31_I_I]] ], [ [[__TAGP_ADDR_0_I31_I]], [[IF_ELSE17_I_I]] ] -// CHECK-NEXT: [[__R_2_I_I]] = phi i64 [ [[ADD28_I_I]], [[IF_END31_I_I]] ], [ [[__R_0_I32_I]], [[IF_ELSE17_I_I]] ] -// CHECK-NEXT: [[COND_I_I:%.*]] = phi i1 [ true, [[IF_END31_I_I]] ], [ false, [[IF_ELSE17_I_I]] ] -// CHECK-NEXT: br i1 [[COND_I_I]], label [[WHILE_COND_I30_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], !llvm.loop [[LOOP11]] -// CHECK: while.cond.i.i: -// CHECK-NEXT: [[__TAGP_ADDR_0_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I_I:%.*]], [[CLEANUP_I_I:%.*]] ], [ [[INCDEC_PTR_I]], [[IF_THEN_I]] ] -// CHECK-NEXT: [[__R_0_I_I:%.*]] = phi i64 [ [[__R_1_I_I:%.*]], [[CLEANUP_I_I]] ], [ 0, [[IF_THEN_I]] ] -// CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I_I]], align 1, !tbaa [[TBAA4]] -// CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq i8 [[TMP6]], 0 -// CHECK-NEXT: br i1 [[CMP_NOT_I_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], label [[WHILE_BODY_I_I:%.*]] +// CHECK-NEXT: [[ADD28_I_I]] = add i64 [[ADD26_I_I]], [[CONV25_I_I]] +// CHECK-NEXT: [[INCDEC_PTR_I34_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I28_I10]], i64 1 +// CHECK-NEXT: [[TMP9]] = load i8, ptr [[INCDEC_PTR_I34_I]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I30_I:%.*]] = icmp eq i8 [[TMP9]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I30_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], label [[WHILE_BODY_I31_I]], !llvm.loop [[LOOP11]] // CHECK: while.body.i.i: -// CHECK-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -8 -// CHECK-NEXT: [[OR_COND_I_I:%.*]] = icmp eq i8 [[TMP7]], 48 -// CHECK-NEXT: br i1 [[OR_COND_I_I]], label [[IF_THEN_I_I:%.*]], label [[CLEANUP_I_I]] +// CHECK-NEXT: [[TMP10:%.*]] = phi i8 [ [[TMP12:%.*]], [[IF_THEN_I_I:%.*]] ], [ [[TMP3]], [[WHILE_COND_I_I_PREHEADER]] ] +// CHECK-NEXT: [[__R_0_I_I16:%.*]] = phi i64 [ [[SUB_I_I:%.*]], [[IF_THEN_I_I]] ], [ 0, [[WHILE_COND_I_I_PREHEADER]] ] +// CHECK-NEXT: [[__TAGP_ADDR_0_I_I15:%.*]] = phi ptr [ [[INCDEC_PTR_I_I:%.*]], [[IF_THEN_I_I]] ], [ [[INCDEC_PTR_I]], [[WHILE_COND_I_I_PREHEADER]] ] +// CHECK-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], -8 +// CHECK-NEXT: [[OR_COND_I_I:%.*]] = icmp eq i8 [[TMP11]], 48 +// CHECK-NEXT: br i1 [[OR_COND_I_I]], label [[IF_THEN_I_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]] // CHECK: if.then.i.i: -// CHECK-NEXT: [[MUL_I_I:%.*]] = shl i64 [[__R_0_I_I]], 3 -// CHECK-NEXT: [[CONV5_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 +// CHECK-NEXT: [[MUL_I_I:%.*]] = shl i64 [[__R_0_I_I16]], 3 +// CHECK-NEXT: [[CONV5_I_I:%.*]] = zext nneg i8 [[TMP10]] to i64 // CHECK-NEXT: [[ADD_I_I:%.*]] = add i64 [[MUL_I_I]], -48 -// CHECK-NEXT: [[SUB_I_I:%.*]] = add i64 [[ADD_I_I]], [[CONV5_I_I]] -// CHECK-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I]], i64 1 -// CHECK-NEXT: br label [[CLEANUP_I_I]] -// CHECK: cleanup.i.i: -// CHECK-NEXT: [[__TAGP_ADDR_1_I_I]] = phi ptr [ [[INCDEC_PTR_I_I]], [[IF_THEN_I_I]] ], [ [[__TAGP_ADDR_0_I_I]], [[WHILE_BODY_I_I]] ] -// CHECK-NEXT: [[__R_1_I_I]] = phi i64 [ [[SUB_I_I]], [[IF_THEN_I_I]] ], [ [[__R_0_I_I]], [[WHILE_BODY_I_I]] ] -// CHECK-NEXT: br i1 [[OR_COND_I_I]], label [[WHILE_COND_I_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], !llvm.loop [[LOOP7]] -// CHECK: while.cond.i14.i: -// CHECK-NEXT: [[__TAGP_ADDR_0_I15_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I21_I:%.*]], [[CLEANUP_I20_I:%.*]] ], [ [[P]], [[ENTRY:%.*]] ] -// CHECK-NEXT: [[__R_0_I16_I:%.*]] = phi i64 [ [[__R_1_I22_I:%.*]], [[CLEANUP_I20_I]] ], [ 0, [[ENTRY]] ] -// CHECK-NEXT: [[TMP8:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I15_I]], align 1, !tbaa [[TBAA4]] -// CHECK-NEXT: [[CMP_NOT_I17_I:%.*]] = icmp eq i8 [[TMP8]], 0 -// CHECK-NEXT: br i1 [[CMP_NOT_I17_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], label [[WHILE_BODY_I18_I:%.*]] +// CHECK-NEXT: [[SUB_I_I]] = add i64 [[ADD_I_I]], [[CONV5_I_I]] +// CHECK-NEXT: [[INCDEC_PTR_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I15]], i64 1 +// CHECK-NEXT: [[TMP12]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq i8 [[TMP12]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], label [[WHILE_BODY_I_I]], !llvm.loop [[LOOP7]] // CHECK: while.body.i18.i: -// CHECK-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], -48 -// CHECK-NEXT: [[OR_COND_I19_I:%.*]] = icmp ult i8 [[TMP9]], 10 -// CHECK-NEXT: br i1 [[OR_COND_I19_I]], label [[IF_THEN_I24_I:%.*]], label [[CLEANUP_I20_I]] -// CHECK: if.then.i24.i: -// CHECK-NEXT: [[MUL_I25_I:%.*]] = mul i64 [[__R_0_I16_I]], 10 -// CHECK-NEXT: [[CONV5_I26_I:%.*]] = zext nneg i8 [[TMP8]] to i64 -// CHECK-NEXT: [[ADD_I27_I:%.*]] = add i64 [[MUL_I25_I]], -48 -// CHECK-NEXT: [[SUB_I28_I:%.*]] = add i64 [[ADD_I27_I]], [[CONV5_I26_I]] -// CHECK-NEXT: [[INCDEC_PTR_I29_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I]], i64 1 -// CHECK-NEXT: br label [[CLEANUP_I20_I]] -// CHECK: cleanup.i20.i: -// CHECK-NEXT: [[__TAGP_ADDR_1_I21_I]] = phi ptr [ [[INCDEC_PTR_I29_I]], [[IF_THEN_I24_I]] ], [ [[__TAGP_ADDR_0_I15_I]], [[WHILE_BODY_I18_I]] ] -// CHECK-NEXT: [[__R_1_I22_I]] = phi i64 [ [[SUB_I28_I]], [[IF_THEN_I24_I]] ], [ [[__R_0_I16_I]], [[WHILE_BODY_I18_I]] ] -// CHECK-NEXT: br i1 [[OR_COND_I19_I]], label [[WHILE_COND_I14_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], !llvm.loop [[LOOP10]] +// CHECK-NEXT: [[TMP13:%.*]] = phi i8 [ [[TMP15:%.*]], [[IF_THEN_I21_I:%.*]] ], [ [[TMP1]], [[WHILE_COND_I14_I_PREHEADER]] ] +// CHECK-NEXT: [[__R_0_I16_I7:%.*]] = phi i64 [ [[SUB_I25_I:%.*]], [[IF_THEN_I21_I]] ], [ 0, [[WHILE_COND_I14_I_PREHEADER]] ] +// CHECK-NEXT: [[__TAGP_ADDR_0_I15_I6:%.*]] = phi ptr [ [[INCDEC_PTR_I26_I:%.*]], [[IF_THEN_I21_I]] ], [ [[P]], [[WHILE_COND_I14_I_PREHEADER]] ] +// CHECK-NEXT: [[TMP14:%.*]] = add i8 [[TMP13]], -48 +// CHECK-NEXT: [[OR_COND_I19_I:%.*]] = icmp ult i8 [[TMP14]], 10 +// CHECK-NEXT: br i1 [[OR_COND_I19_I]], label [[IF_THEN_I21_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]] +// CHECK: if.then.i21.i: +// CHECK-NEXT: [[MUL_I22_I:%.*]] = mul i64 [[__R_0_I16_I7]], 10 +// CHECK-NEXT: [[CONV5_I23_I:%.*]] = zext nneg i8 [[TMP13]] to i64 +// CHECK-NEXT: [[ADD_I24_I:%.*]] = add i64 [[MUL_I22_I]], -48 +// CHECK-NEXT: [[SUB_I25_I]] = add i64 [[ADD_I24_I]], [[CONV5_I23_I]] +// CHECK-NEXT: [[INCDEC_PTR_I26_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I6]], i64 1 +// CHECK-NEXT: [[TMP15]] = load i8, ptr [[INCDEC_PTR_I26_I]], align 1, !tbaa [[TBAA4]] +// CHECK-NEXT: [[CMP_NOT_I17_I:%.*]] = icmp eq i8 [[TMP15]], 0 +// CHECK-NEXT: br i1 [[CMP_NOT_I17_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], label [[WHILE_BODY_I18_I]], !llvm.loop [[LOOP10]] // CHECK: _ZL15__make_mantissaPKc.exit: -// CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i64 [ 0, [[CLEANUP_I_I]] ], [ [[__R_0_I_I]], [[WHILE_COND_I_I]] ], [ 0, [[CLEANUP_I36_I]] ], [ [[__R_0_I32_I]], [[WHILE_COND_I30_I]] ], [ 0, [[CLEANUP_I20_I]] ], [ [[__R_0_I16_I]], [[WHILE_COND_I14_I]] ] +// CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi i64 [ 0, [[WHILE_COND_I_I_PREHEADER]] ], [ 0, [[IF_THEN5_I]] ], [ 0, [[WHILE_COND_I14_I_PREHEADER]] ], [ [[SUB_I_I]], [[IF_THEN_I_I]] ], [ 0, [[WHILE_BODY_I_I]] ], [ [[ADD28_I_I]], [[IF_END31_I_I]] ], [ 0, [[IF_ELSE17_I_I]] ], [ [[SUB_I25_I]], [[IF_THEN_I21_I]] ], [ 0, [[WHILE_BODY_I18_I]] ] // CHECK-NEXT: ret i64 [[RETVAL_0_I]] // // AMDGCNSPIRV-LABEL: @test___make_mantissa( @@ -339,53 +319,49 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) { // AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[P]], i64 1 // AMDGCNSPIRV-NEXT: [[TMP1:%.*]] = load i8, ptr addrspace(4) [[INCDEC_PTR_I]], align 1, !tbaa [[TBAA5]] // AMDGCNSPIRV-NEXT: switch i8 [[TMP1]], label [[WHILE_COND_I_I:%.*]] [ -// AMDGCNSPIRV-NEXT: i8 120, label [[WHILE_COND_I28_I_PREHEADER:%.*]] -// AMDGCNSPIRV-NEXT: i8 88, label [[WHILE_COND_I28_I_PREHEADER]] +// AMDGCNSPIRV-NEXT: i8 120, label [[IF_THEN5_I:%.*]] +// AMDGCNSPIRV-NEXT: i8 88, label [[IF_THEN5_I]] // AMDGCNSPIRV-NEXT: ] -// AMDGCNSPIRV: while.cond.i28.i.preheader: -// AMDGCNSPIRV-NEXT: br label [[WHILE_COND_I28_I:%.*]] -// AMDGCNSPIRV: while.cond.i28.i: -// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I29_I:%.*]] = phi ptr addrspace(4) [ [[__TAGP_ADDR_1_I34_I:%.*]], [[CLEANUP_I_I:%.*]] ], [ [[INCDEC_PTR_I]], [[WHILE_COND_I28_I_PREHEADER]] ] -// AMDGCNSPIRV-NEXT: [[__R_0_I30_I:%.*]] = phi i64 [ [[__R_2_I_I:%.*]], [[CLEANUP_I_I]] ], [ 0, [[WHILE_COND_I28_I_PREHEADER]] ] -// AMDGCNSPIRV-NEXT: [[TMP2:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I29_I]], align 1, !tbaa [[TBAA5]] -// AMDGCNSPIRV-NEXT: [[CMP_NOT_I31_I:%.*]] = icmp eq i8 [[TMP2]], 0 -// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I31_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT:%.*]], label [[WHILE_BODY_I32_I:%.*]] +// AMDGCNSPIRV: if.then5.i: +// AMDGCNSPIRV-NEXT: [[TMP2:%.*]] = load i8, ptr addrspace(4) [[INCDEC_PTR_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I31_I5:%.*]] = icmp eq i8 [[TMP2]], 0 +// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I31_I5]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT:%.*]], label [[WHILE_BODY_I32_I:%.*]] // AMDGCNSPIRV: while.body.i32.i: -// AMDGCNSPIRV-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], -48 -// AMDGCNSPIRV-NEXT: [[OR_COND_I33_I:%.*]] = icmp ult i8 [[TMP3]], 10 -// AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I33_I]], label [[IF_END31_I_I:%.*]], label [[IF_ELSE_I_I:%.*]] +// AMDGCNSPIRV-NEXT: [[TMP3:%.*]] = phi i8 [ [[TMP7:%.*]], [[IF_END31_I_I:%.*]] ], [ [[TMP2]], [[IF_THEN5_I]] ] +// AMDGCNSPIRV-NEXT: [[__R_0_I30_I7:%.*]] = phi i64 [ [[ADD28_I_I:%.*]], [[IF_END31_I_I]] ], [ 0, [[IF_THEN5_I]] ] +// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I29_I6:%.*]] = phi ptr addrspace(4) [ [[INCDEC_PTR_I36_I:%.*]], [[IF_END31_I_I]] ], [ [[INCDEC_PTR_I]], [[IF_THEN5_I]] ] +// AMDGCNSPIRV-NEXT: [[TMP4:%.*]] = add i8 [[TMP3]], -48 +// AMDGCNSPIRV-NEXT: [[OR_COND_I33_I:%.*]] = icmp ult i8 [[TMP4]], 10 +// AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I33_I]], label [[IF_END31_I_I]], label [[IF_ELSE_I_I:%.*]] // AMDGCNSPIRV: if.else.i.i: -// AMDGCNSPIRV-NEXT: [[TMP4:%.*]] = add i8 [[TMP2]], -97 -// AMDGCNSPIRV-NEXT: [[OR_COND33_I_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// AMDGCNSPIRV-NEXT: [[TMP5:%.*]] = add i8 [[TMP3]], -97 +// AMDGCNSPIRV-NEXT: [[OR_COND33_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 // AMDGCNSPIRV-NEXT: br i1 [[OR_COND33_I_I]], label [[IF_END31_I_I]], label [[IF_ELSE17_I_I:%.*]] // AMDGCNSPIRV: if.else17.i.i: -// AMDGCNSPIRV-NEXT: [[TMP5:%.*]] = add i8 [[TMP2]], -65 -// AMDGCNSPIRV-NEXT: [[OR_COND34_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 -// AMDGCNSPIRV-NEXT: br i1 [[OR_COND34_I_I]], label [[IF_END31_I_I]], label [[CLEANUP_I_I]] +// AMDGCNSPIRV-NEXT: [[TMP6:%.*]] = add i8 [[TMP3]], -65 +// AMDGCNSPIRV-NEXT: [[OR_COND34_I_I:%.*]] = icmp ult i8 [[TMP6]], 6 +// AMDGCNSPIRV-NEXT: br i1 [[OR_COND34_I_I]], label [[IF_END31_I_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]] // AMDGCNSPIRV: if.end31.i.i: // AMDGCNSPIRV-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I32_I]] ], [ -87, [[IF_ELSE_I_I]] ], [ -55, [[IF_ELSE17_I_I]] ] -// AMDGCNSPIRV-NEXT: [[MUL24_I_I:%.*]] = shl i64 [[__R_0_I30_I]], 4 -// AMDGCNSPIRV-NEXT: [[CONV25_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 +// AMDGCNSPIRV-NEXT: [[MUL24_I_I:%.*]] = shl i64 [[__R_0_I30_I7]], 4 +// AMDGCNSPIRV-NEXT: [[CONV25_I_I:%.*]] = zext nneg i8 [[TMP3]] to i64 // AMDGCNSPIRV-NEXT: [[ADD26_I_I:%.*]] = add i64 [[MUL24_I_I]], [[DOTSINK]] -// AMDGCNSPIRV-NEXT: [[ADD28_I_I:%.*]] = add i64 [[ADD26_I_I]], [[CONV25_I_I]] -// AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I37_I:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[__TAGP_ADDR_0_I29_I]], i64 1 -// AMDGCNSPIRV-NEXT: br label [[CLEANUP_I_I]] -// AMDGCNSPIRV: cleanup.i.i: -// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_1_I34_I]] = phi ptr addrspace(4) [ [[INCDEC_PTR_I37_I]], [[IF_END31_I_I]] ], [ [[__TAGP_ADDR_0_I29_I]], [[IF_ELSE17_I_I]] ] -// AMDGCNSPIRV-NEXT: [[__R_2_I_I]] = phi i64 [ [[ADD28_I_I]], [[IF_END31_I_I]] ], [ [[__R_0_I30_I]], [[IF_ELSE17_I_I]] ] -// AMDGCNSPIRV-NEXT: [[COND_I_I:%.*]] = phi i1 [ true, [[IF_END31_I_I]] ], [ false, [[IF_ELSE17_I_I]] ] -// AMDGCNSPIRV-NEXT: br i1 [[COND_I_I]], label [[WHILE_COND_I28_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], !llvm.loop [[LOOP12]] +// AMDGCNSPIRV-NEXT: [[ADD28_I_I]] = add i64 [[ADD26_I_I]], [[CONV25_I_I]] +// AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I36_I]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[__TAGP_ADDR_0_I29_I6]], i64 1 +// AMDGCNSPIRV-NEXT: [[TMP7]] = load i8, ptr addrspace(4) [[INCDEC_PTR_I36_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I31_I:%.*]] = icmp eq i8 [[TMP7]], 0 +// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I31_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], label [[WHILE_BODY_I32_I]], !llvm.loop [[LOOP12]] // AMDGCNSPIRV: while.cond.i.i: // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I_I:%.*]] = phi ptr addrspace(4) [ [[__TAGP_ADDR_1_I_I:%.*]], [[WHILE_BODY_I_I:%.*]] ], [ [[INCDEC_PTR_I]], [[IF_THEN_I]] ] // AMDGCNSPIRV-NEXT: [[__R_0_I_I:%.*]] = phi i64 [ [[__R_1_I_I:%.*]], [[WHILE_BODY_I_I]] ], [ 0, [[IF_THEN_I]] ] -// AMDGCNSPIRV-NEXT: [[TMP6:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I_I]], align 1, !tbaa [[TBAA5]] -// AMDGCNSPIRV-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq i8 [[TMP6]], 0 +// AMDGCNSPIRV-NEXT: [[TMP8:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 // AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], label [[WHILE_BODY_I_I]] // AMDGCNSPIRV: while.body.i.i: -// AMDGCNSPIRV-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -8 -// AMDGCNSPIRV-NEXT: [[OR_COND_I_I:%.*]] = icmp eq i8 [[TMP7]], 48 +// AMDGCNSPIRV-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], -8 +// AMDGCNSPIRV-NEXT: [[OR_COND_I_I:%.*]] = icmp eq i8 [[TMP9]], 48 // AMDGCNSPIRV-NEXT: [[MUL_I_I:%.*]] = shl i64 [[__R_0_I_I]], 3 -// AMDGCNSPIRV-NEXT: [[CONV5_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 +// AMDGCNSPIRV-NEXT: [[CONV5_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 // AMDGCNSPIRV-NEXT: [[ADD_I_I:%.*]] = add i64 [[MUL_I_I]], -48 // AMDGCNSPIRV-NEXT: [[SUB_I_I:%.*]] = add i64 [[ADD_I_I]], [[CONV5_I_I]] // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_1_I_I_IDX:%.*]] = zext i1 [[OR_COND_I_I]] to i64 @@ -395,14 +371,14 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) { // AMDGCNSPIRV: while.cond.i14.i: // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I15_I:%.*]] = phi ptr addrspace(4) [ [[__TAGP_ADDR_1_I25_I:%.*]], [[WHILE_BODY_I18_I:%.*]] ], [ [[P]], [[ENTRY:%.*]] ] // AMDGCNSPIRV-NEXT: [[__R_0_I16_I:%.*]] = phi i64 [ [[__R_1_I26_I:%.*]], [[WHILE_BODY_I18_I]] ], [ 0, [[ENTRY]] ] -// AMDGCNSPIRV-NEXT: [[TMP8:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I15_I]], align 1, !tbaa [[TBAA5]] -// AMDGCNSPIRV-NEXT: [[CMP_NOT_I17_I:%.*]] = icmp eq i8 [[TMP8]], 0 +// AMDGCNSPIRV-NEXT: [[TMP10:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I15_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I17_I:%.*]] = icmp eq i8 [[TMP10]], 0 // AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I17_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], label [[WHILE_BODY_I18_I]] // AMDGCNSPIRV: while.body.i18.i: -// AMDGCNSPIRV-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], -48 -// AMDGCNSPIRV-NEXT: [[OR_COND_I19_I:%.*]] = icmp ult i8 [[TMP9]], 10 +// AMDGCNSPIRV-NEXT: [[TMP11:%.*]] = add i8 [[TMP10]], -48 +// AMDGCNSPIRV-NEXT: [[OR_COND_I19_I:%.*]] = icmp ult i8 [[TMP11]], 10 // AMDGCNSPIRV-NEXT: [[MUL_I20_I:%.*]] = mul i64 [[__R_0_I16_I]], 10 -// AMDGCNSPIRV-NEXT: [[CONV5_I21_I:%.*]] = zext nneg i8 [[TMP8]] to i64 +// AMDGCNSPIRV-NEXT: [[CONV5_I21_I:%.*]] = zext nneg i8 [[TMP10]] to i64 // AMDGCNSPIRV-NEXT: [[ADD_I22_I:%.*]] = add i64 [[MUL_I20_I]], -48 // AMDGCNSPIRV-NEXT: [[SUB_I23_I:%.*]] = add i64 [[ADD_I22_I]], [[CONV5_I21_I]] // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_1_I25_I_IDX:%.*]] = zext i1 [[OR_COND_I19_I]] to i64 @@ -410,7 +386,7 @@ extern "C" __device__ uint64_t test___make_mantissa_base16(const char *p) { // AMDGCNSPIRV-NEXT: [[__R_1_I26_I]] = select i1 [[OR_COND_I19_I]], i64 [[SUB_I23_I]], i64 [[__R_0_I16_I]] // AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I19_I]], label [[WHILE_COND_I14_I]], label [[_ZL15__MAKE_MANTISSAPKC_EXIT]], !llvm.loop [[LOOP11]] // AMDGCNSPIRV: _ZL15__make_mantissaPKc.exit: -// AMDGCNSPIRV-NEXT: [[RETVAL_0_I:%.*]] = phi i64 [ 0, [[WHILE_BODY_I_I]] ], [ [[__R_0_I_I]], [[WHILE_COND_I_I]] ], [ 0, [[CLEANUP_I_I]] ], [ [[__R_0_I30_I]], [[WHILE_COND_I28_I]] ], [ 0, [[WHILE_BODY_I18_I]] ], [ [[__R_0_I16_I]], [[WHILE_COND_I14_I]] ] +// AMDGCNSPIRV-NEXT: [[RETVAL_0_I:%.*]] = phi i64 [ 0, [[IF_THEN5_I]] ], [ 0, [[WHILE_BODY_I_I]] ], [ [[__R_0_I_I]], [[WHILE_COND_I_I]] ], [ [[ADD28_I_I]], [[IF_END31_I_I]] ], [ 0, [[IF_ELSE17_I_I]] ], [ 0, [[WHILE_BODY_I18_I]] ], [ [[__R_0_I16_I]], [[WHILE_COND_I14_I]] ] // AMDGCNSPIRV-NEXT: ret i64 [[RETVAL_0_I]] // extern "C" __device__ uint64_t test___make_mantissa(const char *p) { @@ -3771,96 +3747,90 @@ extern "C" __device__ double test_modf(double x, double* y) { // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[TMP0:%.*]] = load i8, ptr [[TAG:%.*]], align 1, !tbaa [[TBAA4]] // DEFAULT-NEXT: [[CMP_I_I:%.*]] = icmp eq i8 [[TMP0]], 48 -// DEFAULT-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I:%.*]] +// DEFAULT-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I_PREHEADER:%.*]] +// DEFAULT: while.cond.i14.i.i.preheader: +// DEFAULT-NEXT: [[TMP1:%.*]] = load i8, ptr [[TAG]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I17_I_I5:%.*]] = icmp eq i8 [[TMP1]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I17_I_I5]], label [[_ZL4NANFPKC_EXIT:%.*]], label [[WHILE_BODY_I18_I_I:%.*]] // DEFAULT: if.then.i.i: // DEFAULT-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[TAG]], i64 1 -// DEFAULT-NEXT: [[TMP1:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] -// DEFAULT-NEXT: switch i8 [[TMP1]], label [[WHILE_COND_I_I_I:%.*]] [ -// DEFAULT-NEXT: i8 120, label [[WHILE_COND_I30_I_I_PREHEADER:%.*]] -// DEFAULT-NEXT: i8 88, label [[WHILE_COND_I30_I_I_PREHEADER]] +// DEFAULT-NEXT: [[TMP2:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: switch i8 [[TMP2]], label [[WHILE_COND_I_I_I_PREHEADER:%.*]] [ +// DEFAULT-NEXT: i8 120, label [[IF_THEN5_I_I:%.*]] +// DEFAULT-NEXT: i8 88, label [[IF_THEN5_I_I]] // DEFAULT-NEXT: ] -// DEFAULT: while.cond.i30.i.i.preheader: -// DEFAULT-NEXT: br label [[WHILE_COND_I30_I_I:%.*]] -// DEFAULT: while.cond.i30.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_0_I31_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I37_I_I:%.*]], [[CLEANUP_I36_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I30_I_I_PREHEADER]] ] -// DEFAULT-NEXT: [[__R_0_I32_I_I:%.*]] = phi i64 [ [[__R_2_I_I_I:%.*]], [[CLEANUP_I36_I_I]] ], [ 0, [[WHILE_COND_I30_I_I_PREHEADER]] ] -// DEFAULT-NEXT: [[TMP2:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I31_I_I]], align 1, !tbaa [[TBAA4]] -// DEFAULT-NEXT: [[CMP_NOT_I33_I_I:%.*]] = icmp eq i8 [[TMP2]], 0 -// DEFAULT-NEXT: br i1 [[CMP_NOT_I33_I_I]], label [[_ZL4NANFPKC_EXIT:%.*]], label [[WHILE_BODY_I34_I_I:%.*]] -// DEFAULT: while.body.i34.i.i: -// DEFAULT-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], -48 -// DEFAULT-NEXT: [[OR_COND_I35_I_I:%.*]] = icmp ult i8 [[TMP3]], 10 -// DEFAULT-NEXT: br i1 [[OR_COND_I35_I_I]], label [[IF_END31_I_I_I:%.*]], label [[IF_ELSE_I_I_I:%.*]] +// DEFAULT: while.cond.i.i.i.preheader: +// DEFAULT-NEXT: [[TMP3:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I_I_I14:%.*]] = icmp eq i8 [[TMP3]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I_I_I14]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// DEFAULT: if.then5.i.i: +// DEFAULT-NEXT: [[TMP4:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I30_I_I9:%.*]] = icmp eq i8 [[TMP4]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I30_I_I9]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I31_I_I:%.*]] +// DEFAULT: while.body.i31.i.i: +// DEFAULT-NEXT: [[TMP5:%.*]] = phi i8 [ [[TMP9:%.*]], [[IF_END31_I_I_I:%.*]] ], [ [[TMP4]], [[IF_THEN5_I_I]] ] +// DEFAULT-NEXT: [[__R_0_I29_I_I11:%.*]] = phi i64 [ [[ADD28_I_I_I:%.*]], [[IF_END31_I_I_I]] ], [ 0, [[IF_THEN5_I_I]] ] +// DEFAULT-NEXT: [[__TAGP_ADDR_0_I28_I_I10:%.*]] = phi ptr [ [[INCDEC_PTR_I34_I_I:%.*]], [[IF_END31_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN5_I_I]] ] +// DEFAULT-NEXT: [[TMP6:%.*]] = add i8 [[TMP5]], -48 +// DEFAULT-NEXT: [[OR_COND_I32_I_I:%.*]] = icmp ult i8 [[TMP6]], 10 +// DEFAULT-NEXT: br i1 [[OR_COND_I32_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE_I_I_I:%.*]] // DEFAULT: if.else.i.i.i: -// DEFAULT-NEXT: [[TMP4:%.*]] = add i8 [[TMP2]], -97 -// DEFAULT-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// DEFAULT-NEXT: [[TMP7:%.*]] = add i8 [[TMP5]], -97 +// DEFAULT-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP7]], 6 // DEFAULT-NEXT: br i1 [[OR_COND33_I_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE17_I_I_I:%.*]] // DEFAULT: if.else17.i.i.i: -// DEFAULT-NEXT: [[TMP5:%.*]] = add i8 [[TMP2]], -65 -// DEFAULT-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 -// DEFAULT-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[CLEANUP_I36_I_I]] +// DEFAULT-NEXT: [[TMP8:%.*]] = add i8 [[TMP5]], -65 +// DEFAULT-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP8]], 6 +// DEFAULT-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[_ZL4NANFPKC_EXIT]] // DEFAULT: if.end31.i.i.i: -// DEFAULT-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] -// DEFAULT-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4 -// DEFAULT-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 +// DEFAULT-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I31_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] +// DEFAULT-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I29_I_I11]], 4 +// DEFAULT-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP5]] to i64 // DEFAULT-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]] -// DEFAULT-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] -// DEFAULT-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1 -// DEFAULT-NEXT: br label [[CLEANUP_I36_I_I]] -// DEFAULT: cleanup.i36.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_1_I37_I_I]] = phi ptr [ [[INCDEC_PTR_I40_I_I]], [[IF_END31_I_I_I]] ], [ [[__TAGP_ADDR_0_I31_I_I]], [[IF_ELSE17_I_I_I]] ] -// DEFAULT-NEXT: [[__R_2_I_I_I]] = phi i64 [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ [[__R_0_I32_I_I]], [[IF_ELSE17_I_I_I]] ] -// DEFAULT-NEXT: [[COND_I_I_I:%.*]] = phi i1 [ true, [[IF_END31_I_I_I]] ], [ false, [[IF_ELSE17_I_I_I]] ] -// DEFAULT-NEXT: br i1 [[COND_I_I_I]], label [[WHILE_COND_I30_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP11]] -// DEFAULT: while.cond.i.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_0_I_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I_I_I:%.*]], [[CLEANUP_I_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN_I_I]] ] -// DEFAULT-NEXT: [[__R_0_I_I_I:%.*]] = phi i64 [ [[__R_1_I_I_I:%.*]], [[CLEANUP_I_I_I]] ], [ 0, [[IF_THEN_I_I]] ] -// DEFAULT-NEXT: [[TMP6:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I_I_I]], align 1, !tbaa [[TBAA4]] -// DEFAULT-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP6]], 0 -// DEFAULT-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// DEFAULT-NEXT: [[ADD28_I_I_I]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] +// DEFAULT-NEXT: [[INCDEC_PTR_I34_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I28_I_I10]], i64 1 +// DEFAULT-NEXT: [[TMP9]] = load i8, ptr [[INCDEC_PTR_I34_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I30_I_I:%.*]] = icmp eq i8 [[TMP9]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I30_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I31_I_I]], !llvm.loop [[LOOP11]] // DEFAULT: while.body.i.i.i: -// DEFAULT-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -8 -// DEFAULT-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP7]], 48 -// DEFAULT-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]] +// DEFAULT-NEXT: [[TMP10:%.*]] = phi i8 [ [[TMP12:%.*]], [[IF_THEN_I_I_I:%.*]] ], [ [[TMP3]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[__R_0_I_I_I16:%.*]] = phi i64 [ [[SUB_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[__TAGP_ADDR_0_I_I_I15:%.*]] = phi ptr [ [[INCDEC_PTR_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], -8 +// DEFAULT-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP11]], 48 +// DEFAULT-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I]], label [[_ZL4NANFPKC_EXIT]] // DEFAULT: if.then.i.i.i: -// DEFAULT-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3 -// DEFAULT-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 +// DEFAULT-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I16]], 3 +// DEFAULT-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP10]] to i64 // DEFAULT-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48 -// DEFAULT-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] -// DEFAULT-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1 -// DEFAULT-NEXT: br label [[CLEANUP_I_I_I]] -// DEFAULT: cleanup.i.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_1_I_I_I]] = phi ptr [ [[INCDEC_PTR_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__TAGP_ADDR_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// DEFAULT-NEXT: [[__R_1_I_I_I]] = phi i64 [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// DEFAULT-NEXT: br i1 [[OR_COND_I_I_I]], label [[WHILE_COND_I_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP7]] -// DEFAULT: while.cond.i14.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_0_I15_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I21_I_I:%.*]], [[CLEANUP_I20_I_I:%.*]] ], [ [[TAG]], [[ENTRY:%.*]] ] -// DEFAULT-NEXT: [[__R_0_I16_I_I:%.*]] = phi i64 [ [[__R_1_I22_I_I:%.*]], [[CLEANUP_I20_I_I]] ], [ 0, [[ENTRY]] ] -// DEFAULT-NEXT: [[TMP8:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I15_I_I]], align 1, !tbaa [[TBAA4]] -// DEFAULT-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 -// DEFAULT-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I18_I_I:%.*]] +// DEFAULT-NEXT: [[SUB_I_I_I]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] +// DEFAULT-NEXT: [[INCDEC_PTR_I_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I15]], i64 1 +// DEFAULT-NEXT: [[TMP12]] = load i8, ptr [[INCDEC_PTR_I_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP12]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I_I_I]], !llvm.loop [[LOOP7]] // DEFAULT: while.body.i18.i.i: -// DEFAULT-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], -48 -// DEFAULT-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP9]], 10 -// DEFAULT-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]] -// DEFAULT: if.then.i24.i.i: -// DEFAULT-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10 -// DEFAULT-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 -// DEFAULT-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48 -// DEFAULT-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]] -// DEFAULT-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1 -// DEFAULT-NEXT: br label [[CLEANUP_I20_I_I]] -// DEFAULT: cleanup.i20.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_1_I21_I_I]] = phi ptr [ [[INCDEC_PTR_I29_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__TAGP_ADDR_0_I15_I_I]], [[WHILE_BODY_I18_I_I]] ] -// DEFAULT-NEXT: [[__R_1_I22_I_I]] = phi i64 [ [[SUB_I28_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_BODY_I18_I_I]] ] -// DEFAULT-NEXT: br i1 [[OR_COND_I19_I_I]], label [[WHILE_COND_I14_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP10]] +// DEFAULT-NEXT: [[TMP13:%.*]] = phi i8 [ [[TMP15:%.*]], [[IF_THEN_I21_I_I:%.*]] ], [ [[TMP1]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[__R_0_I16_I_I7:%.*]] = phi i64 [ [[SUB_I25_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[__TAGP_ADDR_0_I15_I_I6:%.*]] = phi ptr [ [[INCDEC_PTR_I26_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ [[TAG]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[TMP14:%.*]] = add i8 [[TMP13]], -48 +// DEFAULT-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP14]], 10 +// DEFAULT-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I21_I_I]], label [[_ZL4NANFPKC_EXIT]] +// DEFAULT: if.then.i21.i.i: +// DEFAULT-NEXT: [[MUL_I22_I_I:%.*]] = mul i64 [[__R_0_I16_I_I7]], 10 +// DEFAULT-NEXT: [[CONV5_I23_I_I:%.*]] = zext nneg i8 [[TMP13]] to i64 +// DEFAULT-NEXT: [[ADD_I24_I_I:%.*]] = add i64 [[MUL_I22_I_I]], -48 +// DEFAULT-NEXT: [[SUB_I25_I_I]] = add i64 [[ADD_I24_I_I]], [[CONV5_I23_I_I]] +// DEFAULT-NEXT: [[INCDEC_PTR_I26_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I6]], i64 1 +// DEFAULT-NEXT: [[TMP15]] = load i8, ptr [[INCDEC_PTR_I26_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP15]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I18_I_I]], !llvm.loop [[LOOP10]] // DEFAULT: _ZL4nanfPKc.exit: -// DEFAULT-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[CLEANUP_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_COND_I_I_I]] ], [ 0, [[CLEANUP_I36_I_I]] ], [ [[__R_0_I32_I_I]], [[WHILE_COND_I30_I_I]] ], [ 0, [[CLEANUP_I20_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_COND_I14_I_I]] ] +// DEFAULT-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ], [ 0, [[IF_THEN5_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ], [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_BODY_I_I_I]] ], [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ 0, [[IF_ELSE17_I_I_I]] ], [ [[SUB_I25_I_I]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_BODY_I18_I_I]] ] // DEFAULT-NEXT: [[CONV_I:%.*]] = trunc i64 [[RETVAL_0_I_I]] to i32 // DEFAULT-NEXT: [[BF_VALUE_I:%.*]] = and i32 [[CONV_I]], 4194303 // DEFAULT-NEXT: [[BF_SET9_I:%.*]] = or disjoint i32 [[BF_VALUE_I]], 2143289344 -// DEFAULT-NEXT: [[TMP10:%.*]] = bitcast i32 [[BF_SET9_I]] to float -// DEFAULT-NEXT: ret float [[TMP10]] +// DEFAULT-NEXT: [[TMP16:%.*]] = bitcast i32 [[BF_SET9_I]] to float +// DEFAULT-NEXT: ret float [[TMP16]] // // FINITEONLY-LABEL: @test_nanf( // FINITEONLY-NEXT: entry: @@ -3870,191 +3840,179 @@ extern "C" __device__ double test_modf(double x, double* y) { // APPROX-NEXT: entry: // APPROX-NEXT: [[TMP0:%.*]] = load i8, ptr [[TAG:%.*]], align 1, !tbaa [[TBAA4]] // APPROX-NEXT: [[CMP_I_I:%.*]] = icmp eq i8 [[TMP0]], 48 -// APPROX-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I:%.*]] +// APPROX-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I_PREHEADER:%.*]] +// APPROX: while.cond.i14.i.i.preheader: +// APPROX-NEXT: [[TMP1:%.*]] = load i8, ptr [[TAG]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I17_I_I5:%.*]] = icmp eq i8 [[TMP1]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I17_I_I5]], label [[_ZL4NANFPKC_EXIT:%.*]], label [[WHILE_BODY_I18_I_I:%.*]] // APPROX: if.then.i.i: // APPROX-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[TAG]], i64 1 -// APPROX-NEXT: [[TMP1:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] -// APPROX-NEXT: switch i8 [[TMP1]], label [[WHILE_COND_I_I_I:%.*]] [ -// APPROX-NEXT: i8 120, label [[WHILE_COND_I30_I_I_PREHEADER:%.*]] -// APPROX-NEXT: i8 88, label [[WHILE_COND_I30_I_I_PREHEADER]] +// APPROX-NEXT: [[TMP2:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: switch i8 [[TMP2]], label [[WHILE_COND_I_I_I_PREHEADER:%.*]] [ +// APPROX-NEXT: i8 120, label [[IF_THEN5_I_I:%.*]] +// APPROX-NEXT: i8 88, label [[IF_THEN5_I_I]] // APPROX-NEXT: ] -// APPROX: while.cond.i30.i.i.preheader: -// APPROX-NEXT: br label [[WHILE_COND_I30_I_I:%.*]] -// APPROX: while.cond.i30.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_0_I31_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I37_I_I:%.*]], [[CLEANUP_I36_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I30_I_I_PREHEADER]] ] -// APPROX-NEXT: [[__R_0_I32_I_I:%.*]] = phi i64 [ [[__R_2_I_I_I:%.*]], [[CLEANUP_I36_I_I]] ], [ 0, [[WHILE_COND_I30_I_I_PREHEADER]] ] -// APPROX-NEXT: [[TMP2:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I31_I_I]], align 1, !tbaa [[TBAA4]] -// APPROX-NEXT: [[CMP_NOT_I33_I_I:%.*]] = icmp eq i8 [[TMP2]], 0 -// APPROX-NEXT: br i1 [[CMP_NOT_I33_I_I]], label [[_ZL4NANFPKC_EXIT:%.*]], label [[WHILE_BODY_I34_I_I:%.*]] -// APPROX: while.body.i34.i.i: -// APPROX-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], -48 -// APPROX-NEXT: [[OR_COND_I35_I_I:%.*]] = icmp ult i8 [[TMP3]], 10 -// APPROX-NEXT: br i1 [[OR_COND_I35_I_I]], label [[IF_END31_I_I_I:%.*]], label [[IF_ELSE_I_I_I:%.*]] +// APPROX: while.cond.i.i.i.preheader: +// APPROX-NEXT: [[TMP3:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I_I_I14:%.*]] = icmp eq i8 [[TMP3]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I_I_I14]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// APPROX: if.then5.i.i: +// APPROX-NEXT: [[TMP4:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I30_I_I9:%.*]] = icmp eq i8 [[TMP4]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I30_I_I9]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I31_I_I:%.*]] +// APPROX: while.body.i31.i.i: +// APPROX-NEXT: [[TMP5:%.*]] = phi i8 [ [[TMP9:%.*]], [[IF_END31_I_I_I:%.*]] ], [ [[TMP4]], [[IF_THEN5_I_I]] ] +// APPROX-NEXT: [[__R_0_I29_I_I11:%.*]] = phi i64 [ [[ADD28_I_I_I:%.*]], [[IF_END31_I_I_I]] ], [ 0, [[IF_THEN5_I_I]] ] +// APPROX-NEXT: [[__TAGP_ADDR_0_I28_I_I10:%.*]] = phi ptr [ [[INCDEC_PTR_I34_I_I:%.*]], [[IF_END31_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN5_I_I]] ] +// APPROX-NEXT: [[TMP6:%.*]] = add i8 [[TMP5]], -48 +// APPROX-NEXT: [[OR_COND_I32_I_I:%.*]] = icmp ult i8 [[TMP6]], 10 +// APPROX-NEXT: br i1 [[OR_COND_I32_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE_I_I_I:%.*]] // APPROX: if.else.i.i.i: -// APPROX-NEXT: [[TMP4:%.*]] = add i8 [[TMP2]], -97 -// APPROX-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// APPROX-NEXT: [[TMP7:%.*]] = add i8 [[TMP5]], -97 +// APPROX-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP7]], 6 // APPROX-NEXT: br i1 [[OR_COND33_I_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE17_I_I_I:%.*]] // APPROX: if.else17.i.i.i: -// APPROX-NEXT: [[TMP5:%.*]] = add i8 [[TMP2]], -65 -// APPROX-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 -// APPROX-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[CLEANUP_I36_I_I]] +// APPROX-NEXT: [[TMP8:%.*]] = add i8 [[TMP5]], -65 +// APPROX-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP8]], 6 +// APPROX-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[_ZL4NANFPKC_EXIT]] // APPROX: if.end31.i.i.i: -// APPROX-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] -// APPROX-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4 -// APPROX-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 +// APPROX-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I31_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] +// APPROX-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I29_I_I11]], 4 +// APPROX-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP5]] to i64 // APPROX-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]] -// APPROX-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] -// APPROX-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1 -// APPROX-NEXT: br label [[CLEANUP_I36_I_I]] -// APPROX: cleanup.i36.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_1_I37_I_I]] = phi ptr [ [[INCDEC_PTR_I40_I_I]], [[IF_END31_I_I_I]] ], [ [[__TAGP_ADDR_0_I31_I_I]], [[IF_ELSE17_I_I_I]] ] -// APPROX-NEXT: [[__R_2_I_I_I]] = phi i64 [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ [[__R_0_I32_I_I]], [[IF_ELSE17_I_I_I]] ] -// APPROX-NEXT: [[COND_I_I_I:%.*]] = phi i1 [ true, [[IF_END31_I_I_I]] ], [ false, [[IF_ELSE17_I_I_I]] ] -// APPROX-NEXT: br i1 [[COND_I_I_I]], label [[WHILE_COND_I30_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP11]] -// APPROX: while.cond.i.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_0_I_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I_I_I:%.*]], [[CLEANUP_I_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN_I_I]] ] -// APPROX-NEXT: [[__R_0_I_I_I:%.*]] = phi i64 [ [[__R_1_I_I_I:%.*]], [[CLEANUP_I_I_I]] ], [ 0, [[IF_THEN_I_I]] ] -// APPROX-NEXT: [[TMP6:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I_I_I]], align 1, !tbaa [[TBAA4]] -// APPROX-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP6]], 0 -// APPROX-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// APPROX-NEXT: [[ADD28_I_I_I]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] +// APPROX-NEXT: [[INCDEC_PTR_I34_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I28_I_I10]], i64 1 +// APPROX-NEXT: [[TMP9]] = load i8, ptr [[INCDEC_PTR_I34_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I30_I_I:%.*]] = icmp eq i8 [[TMP9]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I30_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I31_I_I]], !llvm.loop [[LOOP11]] // APPROX: while.body.i.i.i: -// APPROX-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -8 -// APPROX-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP7]], 48 -// APPROX-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]] +// APPROX-NEXT: [[TMP10:%.*]] = phi i8 [ [[TMP12:%.*]], [[IF_THEN_I_I_I:%.*]] ], [ [[TMP3]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// APPROX-NEXT: [[__R_0_I_I_I16:%.*]] = phi i64 [ [[SUB_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ] +// APPROX-NEXT: [[__TAGP_ADDR_0_I_I_I15:%.*]] = phi ptr [ [[INCDEC_PTR_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// APPROX-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], -8 +// APPROX-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP11]], 48 +// APPROX-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I]], label [[_ZL4NANFPKC_EXIT]] // APPROX: if.then.i.i.i: -// APPROX-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3 -// APPROX-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 +// APPROX-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I16]], 3 +// APPROX-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP10]] to i64 // APPROX-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48 -// APPROX-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] -// APPROX-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1 -// APPROX-NEXT: br label [[CLEANUP_I_I_I]] -// APPROX: cleanup.i.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_1_I_I_I]] = phi ptr [ [[INCDEC_PTR_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__TAGP_ADDR_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// APPROX-NEXT: [[__R_1_I_I_I]] = phi i64 [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// APPROX-NEXT: br i1 [[OR_COND_I_I_I]], label [[WHILE_COND_I_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP7]] -// APPROX: while.cond.i14.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_0_I15_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I21_I_I:%.*]], [[CLEANUP_I20_I_I:%.*]] ], [ [[TAG]], [[ENTRY:%.*]] ] -// APPROX-NEXT: [[__R_0_I16_I_I:%.*]] = phi i64 [ [[__R_1_I22_I_I:%.*]], [[CLEANUP_I20_I_I]] ], [ 0, [[ENTRY]] ] -// APPROX-NEXT: [[TMP8:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I15_I_I]], align 1, !tbaa [[TBAA4]] -// APPROX-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 -// APPROX-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I18_I_I:%.*]] +// APPROX-NEXT: [[SUB_I_I_I]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] +// APPROX-NEXT: [[INCDEC_PTR_I_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I15]], i64 1 +// APPROX-NEXT: [[TMP12]] = load i8, ptr [[INCDEC_PTR_I_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP12]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I_I_I]], !llvm.loop [[LOOP7]] // APPROX: while.body.i18.i.i: -// APPROX-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], -48 -// APPROX-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP9]], 10 -// APPROX-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]] -// APPROX: if.then.i24.i.i: -// APPROX-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10 -// APPROX-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 -// APPROX-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48 -// APPROX-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]] -// APPROX-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1 -// APPROX-NEXT: br label [[CLEANUP_I20_I_I]] -// APPROX: cleanup.i20.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_1_I21_I_I]] = phi ptr [ [[INCDEC_PTR_I29_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__TAGP_ADDR_0_I15_I_I]], [[WHILE_BODY_I18_I_I]] ] -// APPROX-NEXT: [[__R_1_I22_I_I]] = phi i64 [ [[SUB_I28_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_BODY_I18_I_I]] ] -// APPROX-NEXT: br i1 [[OR_COND_I19_I_I]], label [[WHILE_COND_I14_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP10]] +// APPROX-NEXT: [[TMP13:%.*]] = phi i8 [ [[TMP15:%.*]], [[IF_THEN_I21_I_I:%.*]] ], [ [[TMP1]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// APPROX-NEXT: [[__R_0_I16_I_I7:%.*]] = phi i64 [ [[SUB_I25_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ] +// APPROX-NEXT: [[__TAGP_ADDR_0_I15_I_I6:%.*]] = phi ptr [ [[INCDEC_PTR_I26_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ [[TAG]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// APPROX-NEXT: [[TMP14:%.*]] = add i8 [[TMP13]], -48 +// APPROX-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP14]], 10 +// APPROX-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I21_I_I]], label [[_ZL4NANFPKC_EXIT]] +// APPROX: if.then.i21.i.i: +// APPROX-NEXT: [[MUL_I22_I_I:%.*]] = mul i64 [[__R_0_I16_I_I7]], 10 +// APPROX-NEXT: [[CONV5_I23_I_I:%.*]] = zext nneg i8 [[TMP13]] to i64 +// APPROX-NEXT: [[ADD_I24_I_I:%.*]] = add i64 [[MUL_I22_I_I]], -48 +// APPROX-NEXT: [[SUB_I25_I_I]] = add i64 [[ADD_I24_I_I]], [[CONV5_I23_I_I]] +// APPROX-NEXT: [[INCDEC_PTR_I26_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I6]], i64 1 +// APPROX-NEXT: [[TMP15]] = load i8, ptr [[INCDEC_PTR_I26_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP15]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I18_I_I]], !llvm.loop [[LOOP10]] // APPROX: _ZL4nanfPKc.exit: -// APPROX-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[CLEANUP_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_COND_I_I_I]] ], [ 0, [[CLEANUP_I36_I_I]] ], [ [[__R_0_I32_I_I]], [[WHILE_COND_I30_I_I]] ], [ 0, [[CLEANUP_I20_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_COND_I14_I_I]] ] +// APPROX-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ], [ 0, [[IF_THEN5_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ], [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_BODY_I_I_I]] ], [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ 0, [[IF_ELSE17_I_I_I]] ], [ [[SUB_I25_I_I]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_BODY_I18_I_I]] ] // APPROX-NEXT: [[CONV_I:%.*]] = trunc i64 [[RETVAL_0_I_I]] to i32 // APPROX-NEXT: [[BF_VALUE_I:%.*]] = and i32 [[CONV_I]], 4194303 // APPROX-NEXT: [[BF_SET9_I:%.*]] = or disjoint i32 [[BF_VALUE_I]], 2143289344 -// APPROX-NEXT: [[TMP10:%.*]] = bitcast i32 [[BF_SET9_I]] to float -// APPROX-NEXT: ret float [[TMP10]] +// APPROX-NEXT: [[TMP16:%.*]] = bitcast i32 [[BF_SET9_I]] to float +// APPROX-NEXT: ret float [[TMP16]] // // NCRDIV-LABEL: @test_nanf( // NCRDIV-NEXT: entry: // NCRDIV-NEXT: [[TMP0:%.*]] = load i8, ptr [[TAG:%.*]], align 1, !tbaa [[TBAA4]] // NCRDIV-NEXT: [[CMP_I_I:%.*]] = icmp eq i8 [[TMP0]], 48 -// NCRDIV-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I:%.*]] +// NCRDIV-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I_PREHEADER:%.*]] +// NCRDIV: while.cond.i14.i.i.preheader: +// NCRDIV-NEXT: [[TMP1:%.*]] = load i8, ptr [[TAG]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I17_I_I5:%.*]] = icmp eq i8 [[TMP1]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I17_I_I5]], label [[_ZL4NANFPKC_EXIT:%.*]], label [[WHILE_BODY_I18_I_I:%.*]] // NCRDIV: if.then.i.i: // NCRDIV-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[TAG]], i64 1 -// NCRDIV-NEXT: [[TMP1:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] -// NCRDIV-NEXT: switch i8 [[TMP1]], label [[WHILE_COND_I_I_I:%.*]] [ -// NCRDIV-NEXT: i8 120, label [[WHILE_COND_I30_I_I_PREHEADER:%.*]] -// NCRDIV-NEXT: i8 88, label [[WHILE_COND_I30_I_I_PREHEADER]] +// NCRDIV-NEXT: [[TMP2:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: switch i8 [[TMP2]], label [[WHILE_COND_I_I_I_PREHEADER:%.*]] [ +// NCRDIV-NEXT: i8 120, label [[IF_THEN5_I_I:%.*]] +// NCRDIV-NEXT: i8 88, label [[IF_THEN5_I_I]] // NCRDIV-NEXT: ] -// NCRDIV: while.cond.i30.i.i.preheader: -// NCRDIV-NEXT: br label [[WHILE_COND_I30_I_I:%.*]] -// NCRDIV: while.cond.i30.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_0_I31_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I37_I_I:%.*]], [[CLEANUP_I36_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I30_I_I_PREHEADER]] ] -// NCRDIV-NEXT: [[__R_0_I32_I_I:%.*]] = phi i64 [ [[__R_2_I_I_I:%.*]], [[CLEANUP_I36_I_I]] ], [ 0, [[WHILE_COND_I30_I_I_PREHEADER]] ] -// NCRDIV-NEXT: [[TMP2:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I31_I_I]], align 1, !tbaa [[TBAA4]] -// NCRDIV-NEXT: [[CMP_NOT_I33_I_I:%.*]] = icmp eq i8 [[TMP2]], 0 -// NCRDIV-NEXT: br i1 [[CMP_NOT_I33_I_I]], label [[_ZL4NANFPKC_EXIT:%.*]], label [[WHILE_BODY_I34_I_I:%.*]] -// NCRDIV: while.body.i34.i.i: -// NCRDIV-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], -48 -// NCRDIV-NEXT: [[OR_COND_I35_I_I:%.*]] = icmp ult i8 [[TMP3]], 10 -// NCRDIV-NEXT: br i1 [[OR_COND_I35_I_I]], label [[IF_END31_I_I_I:%.*]], label [[IF_ELSE_I_I_I:%.*]] +// NCRDIV: while.cond.i.i.i.preheader: +// NCRDIV-NEXT: [[TMP3:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I_I_I14:%.*]] = icmp eq i8 [[TMP3]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I_I_I14]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// NCRDIV: if.then5.i.i: +// NCRDIV-NEXT: [[TMP4:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I30_I_I9:%.*]] = icmp eq i8 [[TMP4]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I30_I_I9]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I31_I_I:%.*]] +// NCRDIV: while.body.i31.i.i: +// NCRDIV-NEXT: [[TMP5:%.*]] = phi i8 [ [[TMP9:%.*]], [[IF_END31_I_I_I:%.*]] ], [ [[TMP4]], [[IF_THEN5_I_I]] ] +// NCRDIV-NEXT: [[__R_0_I29_I_I11:%.*]] = phi i64 [ [[ADD28_I_I_I:%.*]], [[IF_END31_I_I_I]] ], [ 0, [[IF_THEN5_I_I]] ] +// NCRDIV-NEXT: [[__TAGP_ADDR_0_I28_I_I10:%.*]] = phi ptr [ [[INCDEC_PTR_I34_I_I:%.*]], [[IF_END31_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN5_I_I]] ] +// NCRDIV-NEXT: [[TMP6:%.*]] = add i8 [[TMP5]], -48 +// NCRDIV-NEXT: [[OR_COND_I32_I_I:%.*]] = icmp ult i8 [[TMP6]], 10 +// NCRDIV-NEXT: br i1 [[OR_COND_I32_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE_I_I_I:%.*]] // NCRDIV: if.else.i.i.i: -// NCRDIV-NEXT: [[TMP4:%.*]] = add i8 [[TMP2]], -97 -// NCRDIV-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// NCRDIV-NEXT: [[TMP7:%.*]] = add i8 [[TMP5]], -97 +// NCRDIV-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP7]], 6 // NCRDIV-NEXT: br i1 [[OR_COND33_I_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE17_I_I_I:%.*]] // NCRDIV: if.else17.i.i.i: -// NCRDIV-NEXT: [[TMP5:%.*]] = add i8 [[TMP2]], -65 -// NCRDIV-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 -// NCRDIV-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[CLEANUP_I36_I_I]] +// NCRDIV-NEXT: [[TMP8:%.*]] = add i8 [[TMP5]], -65 +// NCRDIV-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP8]], 6 +// NCRDIV-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[_ZL4NANFPKC_EXIT]] // NCRDIV: if.end31.i.i.i: -// NCRDIV-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] -// NCRDIV-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4 -// NCRDIV-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 +// NCRDIV-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I31_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] +// NCRDIV-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I29_I_I11]], 4 +// NCRDIV-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP5]] to i64 // NCRDIV-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]] -// NCRDIV-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] -// NCRDIV-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1 -// NCRDIV-NEXT: br label [[CLEANUP_I36_I_I]] -// NCRDIV: cleanup.i36.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_1_I37_I_I]] = phi ptr [ [[INCDEC_PTR_I40_I_I]], [[IF_END31_I_I_I]] ], [ [[__TAGP_ADDR_0_I31_I_I]], [[IF_ELSE17_I_I_I]] ] -// NCRDIV-NEXT: [[__R_2_I_I_I]] = phi i64 [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ [[__R_0_I32_I_I]], [[IF_ELSE17_I_I_I]] ] -// NCRDIV-NEXT: [[COND_I_I_I:%.*]] = phi i1 [ true, [[IF_END31_I_I_I]] ], [ false, [[IF_ELSE17_I_I_I]] ] -// NCRDIV-NEXT: br i1 [[COND_I_I_I]], label [[WHILE_COND_I30_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP11]] -// NCRDIV: while.cond.i.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_0_I_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I_I_I:%.*]], [[CLEANUP_I_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN_I_I]] ] -// NCRDIV-NEXT: [[__R_0_I_I_I:%.*]] = phi i64 [ [[__R_1_I_I_I:%.*]], [[CLEANUP_I_I_I]] ], [ 0, [[IF_THEN_I_I]] ] -// NCRDIV-NEXT: [[TMP6:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I_I_I]], align 1, !tbaa [[TBAA4]] -// NCRDIV-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP6]], 0 -// NCRDIV-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// NCRDIV-NEXT: [[ADD28_I_I_I]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] +// NCRDIV-NEXT: [[INCDEC_PTR_I34_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I28_I_I10]], i64 1 +// NCRDIV-NEXT: [[TMP9]] = load i8, ptr [[INCDEC_PTR_I34_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I30_I_I:%.*]] = icmp eq i8 [[TMP9]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I30_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I31_I_I]], !llvm.loop [[LOOP11]] // NCRDIV: while.body.i.i.i: -// NCRDIV-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -8 -// NCRDIV-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP7]], 48 -// NCRDIV-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]] +// NCRDIV-NEXT: [[TMP10:%.*]] = phi i8 [ [[TMP12:%.*]], [[IF_THEN_I_I_I:%.*]] ], [ [[TMP3]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[__R_0_I_I_I16:%.*]] = phi i64 [ [[SUB_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[__TAGP_ADDR_0_I_I_I15:%.*]] = phi ptr [ [[INCDEC_PTR_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], -8 +// NCRDIV-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP11]], 48 +// NCRDIV-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I]], label [[_ZL4NANFPKC_EXIT]] // NCRDIV: if.then.i.i.i: -// NCRDIV-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3 -// NCRDIV-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 +// NCRDIV-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I16]], 3 +// NCRDIV-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP10]] to i64 // NCRDIV-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48 -// NCRDIV-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] -// NCRDIV-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1 -// NCRDIV-NEXT: br label [[CLEANUP_I_I_I]] -// NCRDIV: cleanup.i.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_1_I_I_I]] = phi ptr [ [[INCDEC_PTR_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__TAGP_ADDR_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// NCRDIV-NEXT: [[__R_1_I_I_I]] = phi i64 [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// NCRDIV-NEXT: br i1 [[OR_COND_I_I_I]], label [[WHILE_COND_I_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP7]] -// NCRDIV: while.cond.i14.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_0_I15_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I21_I_I:%.*]], [[CLEANUP_I20_I_I:%.*]] ], [ [[TAG]], [[ENTRY:%.*]] ] -// NCRDIV-NEXT: [[__R_0_I16_I_I:%.*]] = phi i64 [ [[__R_1_I22_I_I:%.*]], [[CLEANUP_I20_I_I]] ], [ 0, [[ENTRY]] ] -// NCRDIV-NEXT: [[TMP8:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I15_I_I]], align 1, !tbaa [[TBAA4]] -// NCRDIV-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 -// NCRDIV-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I18_I_I:%.*]] +// NCRDIV-NEXT: [[SUB_I_I_I]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] +// NCRDIV-NEXT: [[INCDEC_PTR_I_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I15]], i64 1 +// NCRDIV-NEXT: [[TMP12]] = load i8, ptr [[INCDEC_PTR_I_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP12]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I_I_I]], !llvm.loop [[LOOP7]] // NCRDIV: while.body.i18.i.i: -// NCRDIV-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], -48 -// NCRDIV-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP9]], 10 -// NCRDIV-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]] -// NCRDIV: if.then.i24.i.i: -// NCRDIV-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10 -// NCRDIV-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 -// NCRDIV-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48 -// NCRDIV-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]] -// NCRDIV-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1 -// NCRDIV-NEXT: br label [[CLEANUP_I20_I_I]] -// NCRDIV: cleanup.i20.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_1_I21_I_I]] = phi ptr [ [[INCDEC_PTR_I29_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__TAGP_ADDR_0_I15_I_I]], [[WHILE_BODY_I18_I_I]] ] -// NCRDIV-NEXT: [[__R_1_I22_I_I]] = phi i64 [ [[SUB_I28_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_BODY_I18_I_I]] ] -// NCRDIV-NEXT: br i1 [[OR_COND_I19_I_I]], label [[WHILE_COND_I14_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP10]] +// NCRDIV-NEXT: [[TMP13:%.*]] = phi i8 [ [[TMP15:%.*]], [[IF_THEN_I21_I_I:%.*]] ], [ [[TMP1]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[__R_0_I16_I_I7:%.*]] = phi i64 [ [[SUB_I25_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[__TAGP_ADDR_0_I15_I_I6:%.*]] = phi ptr [ [[INCDEC_PTR_I26_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ [[TAG]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[TMP14:%.*]] = add i8 [[TMP13]], -48 +// NCRDIV-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP14]], 10 +// NCRDIV-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I21_I_I]], label [[_ZL4NANFPKC_EXIT]] +// NCRDIV: if.then.i21.i.i: +// NCRDIV-NEXT: [[MUL_I22_I_I:%.*]] = mul i64 [[__R_0_I16_I_I7]], 10 +// NCRDIV-NEXT: [[CONV5_I23_I_I:%.*]] = zext nneg i8 [[TMP13]] to i64 +// NCRDIV-NEXT: [[ADD_I24_I_I:%.*]] = add i64 [[MUL_I22_I_I]], -48 +// NCRDIV-NEXT: [[SUB_I25_I_I]] = add i64 [[ADD_I24_I_I]], [[CONV5_I23_I_I]] +// NCRDIV-NEXT: [[INCDEC_PTR_I26_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I6]], i64 1 +// NCRDIV-NEXT: [[TMP15]] = load i8, ptr [[INCDEC_PTR_I26_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP15]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I18_I_I]], !llvm.loop [[LOOP10]] // NCRDIV: _ZL4nanfPKc.exit: -// NCRDIV-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[CLEANUP_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_COND_I_I_I]] ], [ 0, [[CLEANUP_I36_I_I]] ], [ [[__R_0_I32_I_I]], [[WHILE_COND_I30_I_I]] ], [ 0, [[CLEANUP_I20_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_COND_I14_I_I]] ] +// NCRDIV-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ], [ 0, [[IF_THEN5_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ], [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_BODY_I_I_I]] ], [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ 0, [[IF_ELSE17_I_I_I]] ], [ [[SUB_I25_I_I]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_BODY_I18_I_I]] ] // NCRDIV-NEXT: [[CONV_I:%.*]] = trunc i64 [[RETVAL_0_I_I]] to i32 // NCRDIV-NEXT: [[BF_VALUE_I:%.*]] = and i32 [[CONV_I]], 4194303 // NCRDIV-NEXT: [[BF_SET9_I:%.*]] = or disjoint i32 [[BF_VALUE_I]], 2143289344 -// NCRDIV-NEXT: [[TMP10:%.*]] = bitcast i32 [[BF_SET9_I]] to float -// NCRDIV-NEXT: ret float [[TMP10]] +// NCRDIV-NEXT: [[TMP16:%.*]] = bitcast i32 [[BF_SET9_I]] to float +// NCRDIV-NEXT: ret float [[TMP16]] // // AMDGCNSPIRV-LABEL: @test_nanf( // AMDGCNSPIRV-NEXT: entry: @@ -4065,53 +4023,49 @@ extern "C" __device__ double test_modf(double x, double* y) { // AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[TAG]], i64 1 // AMDGCNSPIRV-NEXT: [[TMP1:%.*]] = load i8, ptr addrspace(4) [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA5]] // AMDGCNSPIRV-NEXT: switch i8 [[TMP1]], label [[WHILE_COND_I_I_I:%.*]] [ -// AMDGCNSPIRV-NEXT: i8 120, label [[WHILE_COND_I28_I_I_PREHEADER:%.*]] -// AMDGCNSPIRV-NEXT: i8 88, label [[WHILE_COND_I28_I_I_PREHEADER]] +// AMDGCNSPIRV-NEXT: i8 120, label [[IF_THEN5_I_I:%.*]] +// AMDGCNSPIRV-NEXT: i8 88, label [[IF_THEN5_I_I]] // AMDGCNSPIRV-NEXT: ] -// AMDGCNSPIRV: while.cond.i28.i.i.preheader: -// AMDGCNSPIRV-NEXT: br label [[WHILE_COND_I28_I_I:%.*]] -// AMDGCNSPIRV: while.cond.i28.i.i: -// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I29_I_I:%.*]] = phi ptr addrspace(4) [ [[__TAGP_ADDR_1_I34_I_I:%.*]], [[CLEANUP_I_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I28_I_I_PREHEADER]] ] -// AMDGCNSPIRV-NEXT: [[__R_0_I30_I_I:%.*]] = phi i64 [ [[__R_2_I_I_I:%.*]], [[CLEANUP_I_I_I]] ], [ 0, [[WHILE_COND_I28_I_I_PREHEADER]] ] -// AMDGCNSPIRV-NEXT: [[TMP2:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I29_I_I]], align 1, !tbaa [[TBAA5]] -// AMDGCNSPIRV-NEXT: [[CMP_NOT_I31_I_I:%.*]] = icmp eq i8 [[TMP2]], 0 -// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I31_I_I]], label [[_ZL4NANFPKC_EXIT:%.*]], label [[WHILE_BODY_I32_I_I:%.*]] +// AMDGCNSPIRV: if.then5.i.i: +// AMDGCNSPIRV-NEXT: [[TMP2:%.*]] = load i8, ptr addrspace(4) [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I31_I_I5:%.*]] = icmp eq i8 [[TMP2]], 0 +// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I31_I_I5]], label [[_ZL4NANFPKC_EXIT:%.*]], label [[WHILE_BODY_I32_I_I:%.*]] // AMDGCNSPIRV: while.body.i32.i.i: -// AMDGCNSPIRV-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], -48 -// AMDGCNSPIRV-NEXT: [[OR_COND_I33_I_I:%.*]] = icmp ult i8 [[TMP3]], 10 -// AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I33_I_I]], label [[IF_END31_I_I_I:%.*]], label [[IF_ELSE_I_I_I:%.*]] +// AMDGCNSPIRV-NEXT: [[TMP3:%.*]] = phi i8 [ [[TMP7:%.*]], [[IF_END31_I_I_I:%.*]] ], [ [[TMP2]], [[IF_THEN5_I_I]] ] +// AMDGCNSPIRV-NEXT: [[__R_0_I30_I_I7:%.*]] = phi i64 [ [[ADD28_I_I_I:%.*]], [[IF_END31_I_I_I]] ], [ 0, [[IF_THEN5_I_I]] ] +// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I29_I_I6:%.*]] = phi ptr addrspace(4) [ [[INCDEC_PTR_I36_I_I:%.*]], [[IF_END31_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN5_I_I]] ] +// AMDGCNSPIRV-NEXT: [[TMP4:%.*]] = add i8 [[TMP3]], -48 +// AMDGCNSPIRV-NEXT: [[OR_COND_I33_I_I:%.*]] = icmp ult i8 [[TMP4]], 10 +// AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I33_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE_I_I_I:%.*]] // AMDGCNSPIRV: if.else.i.i.i: -// AMDGCNSPIRV-NEXT: [[TMP4:%.*]] = add i8 [[TMP2]], -97 -// AMDGCNSPIRV-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// AMDGCNSPIRV-NEXT: [[TMP5:%.*]] = add i8 [[TMP3]], -97 +// AMDGCNSPIRV-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 // AMDGCNSPIRV-NEXT: br i1 [[OR_COND33_I_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE17_I_I_I:%.*]] // AMDGCNSPIRV: if.else17.i.i.i: -// AMDGCNSPIRV-NEXT: [[TMP5:%.*]] = add i8 [[TMP2]], -65 -// AMDGCNSPIRV-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 -// AMDGCNSPIRV-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[CLEANUP_I_I_I]] +// AMDGCNSPIRV-NEXT: [[TMP6:%.*]] = add i8 [[TMP3]], -65 +// AMDGCNSPIRV-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP6]], 6 +// AMDGCNSPIRV-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[_ZL4NANFPKC_EXIT]] // AMDGCNSPIRV: if.end31.i.i.i: // AMDGCNSPIRV-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I32_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] -// AMDGCNSPIRV-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I30_I_I]], 4 -// AMDGCNSPIRV-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 +// AMDGCNSPIRV-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I30_I_I7]], 4 +// AMDGCNSPIRV-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP3]] to i64 // AMDGCNSPIRV-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]] -// AMDGCNSPIRV-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] -// AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I37_I_I:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[__TAGP_ADDR_0_I29_I_I]], i64 1 -// AMDGCNSPIRV-NEXT: br label [[CLEANUP_I_I_I]] -// AMDGCNSPIRV: cleanup.i.i.i: -// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_1_I34_I_I]] = phi ptr addrspace(4) [ [[INCDEC_PTR_I37_I_I]], [[IF_END31_I_I_I]] ], [ [[__TAGP_ADDR_0_I29_I_I]], [[IF_ELSE17_I_I_I]] ] -// AMDGCNSPIRV-NEXT: [[__R_2_I_I_I]] = phi i64 [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ [[__R_0_I30_I_I]], [[IF_ELSE17_I_I_I]] ] -// AMDGCNSPIRV-NEXT: [[COND_I_I_I:%.*]] = phi i1 [ true, [[IF_END31_I_I_I]] ], [ false, [[IF_ELSE17_I_I_I]] ] -// AMDGCNSPIRV-NEXT: br i1 [[COND_I_I_I]], label [[WHILE_COND_I28_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP12]] +// AMDGCNSPIRV-NEXT: [[ADD28_I_I_I]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] +// AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I36_I_I]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[__TAGP_ADDR_0_I29_I_I6]], i64 1 +// AMDGCNSPIRV-NEXT: [[TMP7]] = load i8, ptr addrspace(4) [[INCDEC_PTR_I36_I_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I31_I_I:%.*]] = icmp eq i8 [[TMP7]], 0 +// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I31_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I32_I_I]], !llvm.loop [[LOOP12]] // AMDGCNSPIRV: while.cond.i.i.i: // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I_I_I:%.*]] = phi ptr addrspace(4) [ [[__TAGP_ADDR_1_I_I_I:%.*]], [[WHILE_BODY_I_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN_I_I]] ] // AMDGCNSPIRV-NEXT: [[__R_0_I_I_I:%.*]] = phi i64 [ [[__R_1_I_I_I:%.*]], [[WHILE_BODY_I_I_I]] ], [ 0, [[IF_THEN_I_I]] ] -// AMDGCNSPIRV-NEXT: [[TMP6:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I_I_I]], align 1, !tbaa [[TBAA5]] -// AMDGCNSPIRV-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP6]], 0 +// AMDGCNSPIRV-NEXT: [[TMP8:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I_I_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 // AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I_I_I]] // AMDGCNSPIRV: while.body.i.i.i: -// AMDGCNSPIRV-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -8 -// AMDGCNSPIRV-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP7]], 48 +// AMDGCNSPIRV-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], -8 +// AMDGCNSPIRV-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP9]], 48 // AMDGCNSPIRV-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3 -// AMDGCNSPIRV-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 +// AMDGCNSPIRV-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 // AMDGCNSPIRV-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48 // AMDGCNSPIRV-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_1_I_I_I_IDX:%.*]] = zext i1 [[OR_COND_I_I_I]] to i64 @@ -4121,14 +4075,14 @@ extern "C" __device__ double test_modf(double x, double* y) { // AMDGCNSPIRV: while.cond.i14.i.i: // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I15_I_I:%.*]] = phi ptr addrspace(4) [ [[__TAGP_ADDR_1_I25_I_I:%.*]], [[WHILE_BODY_I18_I_I:%.*]] ], [ [[TAG]], [[ENTRY:%.*]] ] // AMDGCNSPIRV-NEXT: [[__R_0_I16_I_I:%.*]] = phi i64 [ [[__R_1_I26_I_I:%.*]], [[WHILE_BODY_I18_I_I]] ], [ 0, [[ENTRY]] ] -// AMDGCNSPIRV-NEXT: [[TMP8:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I15_I_I]], align 1, !tbaa [[TBAA5]] -// AMDGCNSPIRV-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 +// AMDGCNSPIRV-NEXT: [[TMP10:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I15_I_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP10]], 0 // AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL4NANFPKC_EXIT]], label [[WHILE_BODY_I18_I_I]] // AMDGCNSPIRV: while.body.i18.i.i: -// AMDGCNSPIRV-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], -48 -// AMDGCNSPIRV-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP9]], 10 +// AMDGCNSPIRV-NEXT: [[TMP11:%.*]] = add i8 [[TMP10]], -48 +// AMDGCNSPIRV-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP11]], 10 // AMDGCNSPIRV-NEXT: [[MUL_I20_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10 -// AMDGCNSPIRV-NEXT: [[CONV5_I21_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 +// AMDGCNSPIRV-NEXT: [[CONV5_I21_I_I:%.*]] = zext nneg i8 [[TMP10]] to i64 // AMDGCNSPIRV-NEXT: [[ADD_I22_I_I:%.*]] = add i64 [[MUL_I20_I_I]], -48 // AMDGCNSPIRV-NEXT: [[SUB_I23_I_I:%.*]] = add i64 [[ADD_I22_I_I]], [[CONV5_I21_I_I]] // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_1_I25_I_I_IDX:%.*]] = zext i1 [[OR_COND_I19_I_I]] to i64 @@ -4136,12 +4090,12 @@ extern "C" __device__ double test_modf(double x, double* y) { // AMDGCNSPIRV-NEXT: [[__R_1_I26_I_I]] = select i1 [[OR_COND_I19_I_I]], i64 [[SUB_I23_I_I]], i64 [[__R_0_I16_I_I]] // AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I19_I_I]], label [[WHILE_COND_I14_I_I]], label [[_ZL4NANFPKC_EXIT]], !llvm.loop [[LOOP11]] // AMDGCNSPIRV: _ZL4nanfPKc.exit: -// AMDGCNSPIRV-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[WHILE_BODY_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_COND_I_I_I]] ], [ 0, [[CLEANUP_I_I_I]] ], [ [[__R_0_I30_I_I]], [[WHILE_COND_I28_I_I]] ], [ 0, [[WHILE_BODY_I18_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_COND_I14_I_I]] ] +// AMDGCNSPIRV-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[IF_THEN5_I_I]] ], [ 0, [[WHILE_BODY_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_COND_I_I_I]] ], [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ 0, [[IF_ELSE17_I_I_I]] ], [ 0, [[WHILE_BODY_I18_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_COND_I14_I_I]] ] // AMDGCNSPIRV-NEXT: [[CONV_I:%.*]] = trunc i64 [[RETVAL_0_I_I]] to i32 // AMDGCNSPIRV-NEXT: [[BF_VALUE_I:%.*]] = and i32 [[CONV_I]], 4194303 // AMDGCNSPIRV-NEXT: [[BF_SET9_I:%.*]] = or disjoint i32 [[BF_VALUE_I]], 2143289344 -// AMDGCNSPIRV-NEXT: [[TMP10:%.*]] = bitcast i32 [[BF_SET9_I]] to float -// AMDGCNSPIRV-NEXT: ret float [[TMP10]] +// AMDGCNSPIRV-NEXT: [[TMP12:%.*]] = bitcast i32 [[BF_SET9_I]] to float +// AMDGCNSPIRV-NEXT: ret float [[TMP12]] // extern "C" __device__ float test_nanf(const char *tag) { return nanf(tag); @@ -4151,95 +4105,89 @@ extern "C" __device__ float test_nanf(const char *tag) { // DEFAULT-NEXT: entry: // DEFAULT-NEXT: [[TMP0:%.*]] = load i8, ptr [[TAG:%.*]], align 1, !tbaa [[TBAA4]] // DEFAULT-NEXT: [[CMP_I_I:%.*]] = icmp eq i8 [[TMP0]], 48 -// DEFAULT-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I:%.*]] +// DEFAULT-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I_PREHEADER:%.*]] +// DEFAULT: while.cond.i14.i.i.preheader: +// DEFAULT-NEXT: [[TMP1:%.*]] = load i8, ptr [[TAG]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I17_I_I5:%.*]] = icmp eq i8 [[TMP1]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I17_I_I5]], label [[_ZL3NANPKC_EXIT:%.*]], label [[WHILE_BODY_I18_I_I:%.*]] // DEFAULT: if.then.i.i: // DEFAULT-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[TAG]], i64 1 -// DEFAULT-NEXT: [[TMP1:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] -// DEFAULT-NEXT: switch i8 [[TMP1]], label [[WHILE_COND_I_I_I:%.*]] [ -// DEFAULT-NEXT: i8 120, label [[WHILE_COND_I30_I_I_PREHEADER:%.*]] -// DEFAULT-NEXT: i8 88, label [[WHILE_COND_I30_I_I_PREHEADER]] +// DEFAULT-NEXT: [[TMP2:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: switch i8 [[TMP2]], label [[WHILE_COND_I_I_I_PREHEADER:%.*]] [ +// DEFAULT-NEXT: i8 120, label [[IF_THEN5_I_I:%.*]] +// DEFAULT-NEXT: i8 88, label [[IF_THEN5_I_I]] // DEFAULT-NEXT: ] -// DEFAULT: while.cond.i30.i.i.preheader: -// DEFAULT-NEXT: br label [[WHILE_COND_I30_I_I:%.*]] -// DEFAULT: while.cond.i30.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_0_I31_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I37_I_I:%.*]], [[CLEANUP_I36_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I30_I_I_PREHEADER]] ] -// DEFAULT-NEXT: [[__R_0_I32_I_I:%.*]] = phi i64 [ [[__R_2_I_I_I:%.*]], [[CLEANUP_I36_I_I]] ], [ 0, [[WHILE_COND_I30_I_I_PREHEADER]] ] -// DEFAULT-NEXT: [[TMP2:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I31_I_I]], align 1, !tbaa [[TBAA4]] -// DEFAULT-NEXT: [[CMP_NOT_I33_I_I:%.*]] = icmp eq i8 [[TMP2]], 0 -// DEFAULT-NEXT: br i1 [[CMP_NOT_I33_I_I]], label [[_ZL3NANPKC_EXIT:%.*]], label [[WHILE_BODY_I34_I_I:%.*]] -// DEFAULT: while.body.i34.i.i: -// DEFAULT-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], -48 -// DEFAULT-NEXT: [[OR_COND_I35_I_I:%.*]] = icmp ult i8 [[TMP3]], 10 -// DEFAULT-NEXT: br i1 [[OR_COND_I35_I_I]], label [[IF_END31_I_I_I:%.*]], label [[IF_ELSE_I_I_I:%.*]] +// DEFAULT: while.cond.i.i.i.preheader: +// DEFAULT-NEXT: [[TMP3:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I_I_I14:%.*]] = icmp eq i8 [[TMP3]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I_I_I14]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// DEFAULT: if.then5.i.i: +// DEFAULT-NEXT: [[TMP4:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I30_I_I9:%.*]] = icmp eq i8 [[TMP4]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I30_I_I9]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I31_I_I:%.*]] +// DEFAULT: while.body.i31.i.i: +// DEFAULT-NEXT: [[TMP5:%.*]] = phi i8 [ [[TMP9:%.*]], [[IF_END31_I_I_I:%.*]] ], [ [[TMP4]], [[IF_THEN5_I_I]] ] +// DEFAULT-NEXT: [[__R_0_I29_I_I11:%.*]] = phi i64 [ [[ADD28_I_I_I:%.*]], [[IF_END31_I_I_I]] ], [ 0, [[IF_THEN5_I_I]] ] +// DEFAULT-NEXT: [[__TAGP_ADDR_0_I28_I_I10:%.*]] = phi ptr [ [[INCDEC_PTR_I34_I_I:%.*]], [[IF_END31_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN5_I_I]] ] +// DEFAULT-NEXT: [[TMP6:%.*]] = add i8 [[TMP5]], -48 +// DEFAULT-NEXT: [[OR_COND_I32_I_I:%.*]] = icmp ult i8 [[TMP6]], 10 +// DEFAULT-NEXT: br i1 [[OR_COND_I32_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE_I_I_I:%.*]] // DEFAULT: if.else.i.i.i: -// DEFAULT-NEXT: [[TMP4:%.*]] = add i8 [[TMP2]], -97 -// DEFAULT-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// DEFAULT-NEXT: [[TMP7:%.*]] = add i8 [[TMP5]], -97 +// DEFAULT-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP7]], 6 // DEFAULT-NEXT: br i1 [[OR_COND33_I_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE17_I_I_I:%.*]] // DEFAULT: if.else17.i.i.i: -// DEFAULT-NEXT: [[TMP5:%.*]] = add i8 [[TMP2]], -65 -// DEFAULT-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 -// DEFAULT-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[CLEANUP_I36_I_I]] +// DEFAULT-NEXT: [[TMP8:%.*]] = add i8 [[TMP5]], -65 +// DEFAULT-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP8]], 6 +// DEFAULT-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[_ZL3NANPKC_EXIT]] // DEFAULT: if.end31.i.i.i: -// DEFAULT-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] -// DEFAULT-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4 -// DEFAULT-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 +// DEFAULT-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I31_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] +// DEFAULT-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I29_I_I11]], 4 +// DEFAULT-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP5]] to i64 // DEFAULT-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]] -// DEFAULT-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] -// DEFAULT-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1 -// DEFAULT-NEXT: br label [[CLEANUP_I36_I_I]] -// DEFAULT: cleanup.i36.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_1_I37_I_I]] = phi ptr [ [[INCDEC_PTR_I40_I_I]], [[IF_END31_I_I_I]] ], [ [[__TAGP_ADDR_0_I31_I_I]], [[IF_ELSE17_I_I_I]] ] -// DEFAULT-NEXT: [[__R_2_I_I_I]] = phi i64 [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ [[__R_0_I32_I_I]], [[IF_ELSE17_I_I_I]] ] -// DEFAULT-NEXT: [[COND_I_I_I:%.*]] = phi i1 [ true, [[IF_END31_I_I_I]] ], [ false, [[IF_ELSE17_I_I_I]] ] -// DEFAULT-NEXT: br i1 [[COND_I_I_I]], label [[WHILE_COND_I30_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP11]] -// DEFAULT: while.cond.i.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_0_I_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I_I_I:%.*]], [[CLEANUP_I_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN_I_I]] ] -// DEFAULT-NEXT: [[__R_0_I_I_I:%.*]] = phi i64 [ [[__R_1_I_I_I:%.*]], [[CLEANUP_I_I_I]] ], [ 0, [[IF_THEN_I_I]] ] -// DEFAULT-NEXT: [[TMP6:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I_I_I]], align 1, !tbaa [[TBAA4]] -// DEFAULT-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP6]], 0 -// DEFAULT-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// DEFAULT-NEXT: [[ADD28_I_I_I]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] +// DEFAULT-NEXT: [[INCDEC_PTR_I34_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I28_I_I10]], i64 1 +// DEFAULT-NEXT: [[TMP9]] = load i8, ptr [[INCDEC_PTR_I34_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I30_I_I:%.*]] = icmp eq i8 [[TMP9]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I30_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I31_I_I]], !llvm.loop [[LOOP11]] // DEFAULT: while.body.i.i.i: -// DEFAULT-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -8 -// DEFAULT-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP7]], 48 -// DEFAULT-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]] +// DEFAULT-NEXT: [[TMP10:%.*]] = phi i8 [ [[TMP12:%.*]], [[IF_THEN_I_I_I:%.*]] ], [ [[TMP3]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[__R_0_I_I_I16:%.*]] = phi i64 [ [[SUB_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[__TAGP_ADDR_0_I_I_I15:%.*]] = phi ptr [ [[INCDEC_PTR_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], -8 +// DEFAULT-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP11]], 48 +// DEFAULT-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I]], label [[_ZL3NANPKC_EXIT]] // DEFAULT: if.then.i.i.i: -// DEFAULT-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3 -// DEFAULT-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 +// DEFAULT-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I16]], 3 +// DEFAULT-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP10]] to i64 // DEFAULT-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48 -// DEFAULT-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] -// DEFAULT-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1 -// DEFAULT-NEXT: br label [[CLEANUP_I_I_I]] -// DEFAULT: cleanup.i.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_1_I_I_I]] = phi ptr [ [[INCDEC_PTR_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__TAGP_ADDR_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// DEFAULT-NEXT: [[__R_1_I_I_I]] = phi i64 [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// DEFAULT-NEXT: br i1 [[OR_COND_I_I_I]], label [[WHILE_COND_I_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP7]] -// DEFAULT: while.cond.i14.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_0_I15_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I21_I_I:%.*]], [[CLEANUP_I20_I_I:%.*]] ], [ [[TAG]], [[ENTRY:%.*]] ] -// DEFAULT-NEXT: [[__R_0_I16_I_I:%.*]] = phi i64 [ [[__R_1_I22_I_I:%.*]], [[CLEANUP_I20_I_I]] ], [ 0, [[ENTRY]] ] -// DEFAULT-NEXT: [[TMP8:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I15_I_I]], align 1, !tbaa [[TBAA4]] -// DEFAULT-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 -// DEFAULT-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I18_I_I:%.*]] +// DEFAULT-NEXT: [[SUB_I_I_I]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] +// DEFAULT-NEXT: [[INCDEC_PTR_I_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I15]], i64 1 +// DEFAULT-NEXT: [[TMP12]] = load i8, ptr [[INCDEC_PTR_I_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP12]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I_I_I]], !llvm.loop [[LOOP7]] // DEFAULT: while.body.i18.i.i: -// DEFAULT-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], -48 -// DEFAULT-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP9]], 10 -// DEFAULT-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]] -// DEFAULT: if.then.i24.i.i: -// DEFAULT-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10 -// DEFAULT-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 -// DEFAULT-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48 -// DEFAULT-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]] -// DEFAULT-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1 -// DEFAULT-NEXT: br label [[CLEANUP_I20_I_I]] -// DEFAULT: cleanup.i20.i.i: -// DEFAULT-NEXT: [[__TAGP_ADDR_1_I21_I_I]] = phi ptr [ [[INCDEC_PTR_I29_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__TAGP_ADDR_0_I15_I_I]], [[WHILE_BODY_I18_I_I]] ] -// DEFAULT-NEXT: [[__R_1_I22_I_I]] = phi i64 [ [[SUB_I28_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_BODY_I18_I_I]] ] -// DEFAULT-NEXT: br i1 [[OR_COND_I19_I_I]], label [[WHILE_COND_I14_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP10]] +// DEFAULT-NEXT: [[TMP13:%.*]] = phi i8 [ [[TMP15:%.*]], [[IF_THEN_I21_I_I:%.*]] ], [ [[TMP1]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[__R_0_I16_I_I7:%.*]] = phi i64 [ [[SUB_I25_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[__TAGP_ADDR_0_I15_I_I6:%.*]] = phi ptr [ [[INCDEC_PTR_I26_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ [[TAG]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// DEFAULT-NEXT: [[TMP14:%.*]] = add i8 [[TMP13]], -48 +// DEFAULT-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP14]], 10 +// DEFAULT-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I21_I_I]], label [[_ZL3NANPKC_EXIT]] +// DEFAULT: if.then.i21.i.i: +// DEFAULT-NEXT: [[MUL_I22_I_I:%.*]] = mul i64 [[__R_0_I16_I_I7]], 10 +// DEFAULT-NEXT: [[CONV5_I23_I_I:%.*]] = zext nneg i8 [[TMP13]] to i64 +// DEFAULT-NEXT: [[ADD_I24_I_I:%.*]] = add i64 [[MUL_I22_I_I]], -48 +// DEFAULT-NEXT: [[SUB_I25_I_I]] = add i64 [[ADD_I24_I_I]], [[CONV5_I23_I_I]] +// DEFAULT-NEXT: [[INCDEC_PTR_I26_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I6]], i64 1 +// DEFAULT-NEXT: [[TMP15]] = load i8, ptr [[INCDEC_PTR_I26_I_I]], align 1, !tbaa [[TBAA4]] +// DEFAULT-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP15]], 0 +// DEFAULT-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I18_I_I]], !llvm.loop [[LOOP10]] // DEFAULT: _ZL3nanPKc.exit: -// DEFAULT-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[CLEANUP_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_COND_I_I_I]] ], [ 0, [[CLEANUP_I36_I_I]] ], [ [[__R_0_I32_I_I]], [[WHILE_COND_I30_I_I]] ], [ 0, [[CLEANUP_I20_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_COND_I14_I_I]] ] +// DEFAULT-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ], [ 0, [[IF_THEN5_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ], [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_BODY_I_I_I]] ], [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ 0, [[IF_ELSE17_I_I_I]] ], [ [[SUB_I25_I_I]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_BODY_I18_I_I]] ] // DEFAULT-NEXT: [[BF_VALUE_I:%.*]] = and i64 [[RETVAL_0_I_I]], 2251799813685247 // DEFAULT-NEXT: [[BF_SET9_I:%.*]] = or disjoint i64 [[BF_VALUE_I]], 9221120237041090560 -// DEFAULT-NEXT: [[TMP10:%.*]] = bitcast i64 [[BF_SET9_I]] to double -// DEFAULT-NEXT: ret double [[TMP10]] +// DEFAULT-NEXT: [[TMP16:%.*]] = bitcast i64 [[BF_SET9_I]] to double +// DEFAULT-NEXT: ret double [[TMP16]] // // FINITEONLY-LABEL: @test_nan( // FINITEONLY-NEXT: entry: @@ -4249,189 +4197,177 @@ extern "C" __device__ float test_nanf(const char *tag) { // APPROX-NEXT: entry: // APPROX-NEXT: [[TMP0:%.*]] = load i8, ptr [[TAG:%.*]], align 1, !tbaa [[TBAA4]] // APPROX-NEXT: [[CMP_I_I:%.*]] = icmp eq i8 [[TMP0]], 48 -// APPROX-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I:%.*]] +// APPROX-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I_PREHEADER:%.*]] +// APPROX: while.cond.i14.i.i.preheader: +// APPROX-NEXT: [[TMP1:%.*]] = load i8, ptr [[TAG]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I17_I_I5:%.*]] = icmp eq i8 [[TMP1]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I17_I_I5]], label [[_ZL3NANPKC_EXIT:%.*]], label [[WHILE_BODY_I18_I_I:%.*]] // APPROX: if.then.i.i: // APPROX-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[TAG]], i64 1 -// APPROX-NEXT: [[TMP1:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] -// APPROX-NEXT: switch i8 [[TMP1]], label [[WHILE_COND_I_I_I:%.*]] [ -// APPROX-NEXT: i8 120, label [[WHILE_COND_I30_I_I_PREHEADER:%.*]] -// APPROX-NEXT: i8 88, label [[WHILE_COND_I30_I_I_PREHEADER]] +// APPROX-NEXT: [[TMP2:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: switch i8 [[TMP2]], label [[WHILE_COND_I_I_I_PREHEADER:%.*]] [ +// APPROX-NEXT: i8 120, label [[IF_THEN5_I_I:%.*]] +// APPROX-NEXT: i8 88, label [[IF_THEN5_I_I]] // APPROX-NEXT: ] -// APPROX: while.cond.i30.i.i.preheader: -// APPROX-NEXT: br label [[WHILE_COND_I30_I_I:%.*]] -// APPROX: while.cond.i30.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_0_I31_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I37_I_I:%.*]], [[CLEANUP_I36_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I30_I_I_PREHEADER]] ] -// APPROX-NEXT: [[__R_0_I32_I_I:%.*]] = phi i64 [ [[__R_2_I_I_I:%.*]], [[CLEANUP_I36_I_I]] ], [ 0, [[WHILE_COND_I30_I_I_PREHEADER]] ] -// APPROX-NEXT: [[TMP2:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I31_I_I]], align 1, !tbaa [[TBAA4]] -// APPROX-NEXT: [[CMP_NOT_I33_I_I:%.*]] = icmp eq i8 [[TMP2]], 0 -// APPROX-NEXT: br i1 [[CMP_NOT_I33_I_I]], label [[_ZL3NANPKC_EXIT:%.*]], label [[WHILE_BODY_I34_I_I:%.*]] -// APPROX: while.body.i34.i.i: -// APPROX-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], -48 -// APPROX-NEXT: [[OR_COND_I35_I_I:%.*]] = icmp ult i8 [[TMP3]], 10 -// APPROX-NEXT: br i1 [[OR_COND_I35_I_I]], label [[IF_END31_I_I_I:%.*]], label [[IF_ELSE_I_I_I:%.*]] +// APPROX: while.cond.i.i.i.preheader: +// APPROX-NEXT: [[TMP3:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I_I_I14:%.*]] = icmp eq i8 [[TMP3]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I_I_I14]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// APPROX: if.then5.i.i: +// APPROX-NEXT: [[TMP4:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I30_I_I9:%.*]] = icmp eq i8 [[TMP4]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I30_I_I9]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I31_I_I:%.*]] +// APPROX: while.body.i31.i.i: +// APPROX-NEXT: [[TMP5:%.*]] = phi i8 [ [[TMP9:%.*]], [[IF_END31_I_I_I:%.*]] ], [ [[TMP4]], [[IF_THEN5_I_I]] ] +// APPROX-NEXT: [[__R_0_I29_I_I11:%.*]] = phi i64 [ [[ADD28_I_I_I:%.*]], [[IF_END31_I_I_I]] ], [ 0, [[IF_THEN5_I_I]] ] +// APPROX-NEXT: [[__TAGP_ADDR_0_I28_I_I10:%.*]] = phi ptr [ [[INCDEC_PTR_I34_I_I:%.*]], [[IF_END31_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN5_I_I]] ] +// APPROX-NEXT: [[TMP6:%.*]] = add i8 [[TMP5]], -48 +// APPROX-NEXT: [[OR_COND_I32_I_I:%.*]] = icmp ult i8 [[TMP6]], 10 +// APPROX-NEXT: br i1 [[OR_COND_I32_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE_I_I_I:%.*]] // APPROX: if.else.i.i.i: -// APPROX-NEXT: [[TMP4:%.*]] = add i8 [[TMP2]], -97 -// APPROX-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// APPROX-NEXT: [[TMP7:%.*]] = add i8 [[TMP5]], -97 +// APPROX-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP7]], 6 // APPROX-NEXT: br i1 [[OR_COND33_I_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE17_I_I_I:%.*]] // APPROX: if.else17.i.i.i: -// APPROX-NEXT: [[TMP5:%.*]] = add i8 [[TMP2]], -65 -// APPROX-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 -// APPROX-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[CLEANUP_I36_I_I]] +// APPROX-NEXT: [[TMP8:%.*]] = add i8 [[TMP5]], -65 +// APPROX-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP8]], 6 +// APPROX-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[_ZL3NANPKC_EXIT]] // APPROX: if.end31.i.i.i: -// APPROX-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] -// APPROX-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4 -// APPROX-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 +// APPROX-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I31_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] +// APPROX-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I29_I_I11]], 4 +// APPROX-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP5]] to i64 // APPROX-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]] -// APPROX-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] -// APPROX-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1 -// APPROX-NEXT: br label [[CLEANUP_I36_I_I]] -// APPROX: cleanup.i36.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_1_I37_I_I]] = phi ptr [ [[INCDEC_PTR_I40_I_I]], [[IF_END31_I_I_I]] ], [ [[__TAGP_ADDR_0_I31_I_I]], [[IF_ELSE17_I_I_I]] ] -// APPROX-NEXT: [[__R_2_I_I_I]] = phi i64 [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ [[__R_0_I32_I_I]], [[IF_ELSE17_I_I_I]] ] -// APPROX-NEXT: [[COND_I_I_I:%.*]] = phi i1 [ true, [[IF_END31_I_I_I]] ], [ false, [[IF_ELSE17_I_I_I]] ] -// APPROX-NEXT: br i1 [[COND_I_I_I]], label [[WHILE_COND_I30_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP11]] -// APPROX: while.cond.i.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_0_I_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I_I_I:%.*]], [[CLEANUP_I_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN_I_I]] ] -// APPROX-NEXT: [[__R_0_I_I_I:%.*]] = phi i64 [ [[__R_1_I_I_I:%.*]], [[CLEANUP_I_I_I]] ], [ 0, [[IF_THEN_I_I]] ] -// APPROX-NEXT: [[TMP6:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I_I_I]], align 1, !tbaa [[TBAA4]] -// APPROX-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP6]], 0 -// APPROX-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// APPROX-NEXT: [[ADD28_I_I_I]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] +// APPROX-NEXT: [[INCDEC_PTR_I34_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I28_I_I10]], i64 1 +// APPROX-NEXT: [[TMP9]] = load i8, ptr [[INCDEC_PTR_I34_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I30_I_I:%.*]] = icmp eq i8 [[TMP9]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I30_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I31_I_I]], !llvm.loop [[LOOP11]] // APPROX: while.body.i.i.i: -// APPROX-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -8 -// APPROX-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP7]], 48 -// APPROX-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]] +// APPROX-NEXT: [[TMP10:%.*]] = phi i8 [ [[TMP12:%.*]], [[IF_THEN_I_I_I:%.*]] ], [ [[TMP3]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// APPROX-NEXT: [[__R_0_I_I_I16:%.*]] = phi i64 [ [[SUB_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ] +// APPROX-NEXT: [[__TAGP_ADDR_0_I_I_I15:%.*]] = phi ptr [ [[INCDEC_PTR_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// APPROX-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], -8 +// APPROX-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP11]], 48 +// APPROX-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I]], label [[_ZL3NANPKC_EXIT]] // APPROX: if.then.i.i.i: -// APPROX-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3 -// APPROX-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 +// APPROX-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I16]], 3 +// APPROX-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP10]] to i64 // APPROX-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48 -// APPROX-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] -// APPROX-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1 -// APPROX-NEXT: br label [[CLEANUP_I_I_I]] -// APPROX: cleanup.i.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_1_I_I_I]] = phi ptr [ [[INCDEC_PTR_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__TAGP_ADDR_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// APPROX-NEXT: [[__R_1_I_I_I]] = phi i64 [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// APPROX-NEXT: br i1 [[OR_COND_I_I_I]], label [[WHILE_COND_I_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP7]] -// APPROX: while.cond.i14.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_0_I15_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I21_I_I:%.*]], [[CLEANUP_I20_I_I:%.*]] ], [ [[TAG]], [[ENTRY:%.*]] ] -// APPROX-NEXT: [[__R_0_I16_I_I:%.*]] = phi i64 [ [[__R_1_I22_I_I:%.*]], [[CLEANUP_I20_I_I]] ], [ 0, [[ENTRY]] ] -// APPROX-NEXT: [[TMP8:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I15_I_I]], align 1, !tbaa [[TBAA4]] -// APPROX-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 -// APPROX-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I18_I_I:%.*]] +// APPROX-NEXT: [[SUB_I_I_I]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] +// APPROX-NEXT: [[INCDEC_PTR_I_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I15]], i64 1 +// APPROX-NEXT: [[TMP12]] = load i8, ptr [[INCDEC_PTR_I_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP12]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I_I_I]], !llvm.loop [[LOOP7]] // APPROX: while.body.i18.i.i: -// APPROX-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], -48 -// APPROX-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP9]], 10 -// APPROX-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]] -// APPROX: if.then.i24.i.i: -// APPROX-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10 -// APPROX-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 -// APPROX-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48 -// APPROX-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]] -// APPROX-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1 -// APPROX-NEXT: br label [[CLEANUP_I20_I_I]] -// APPROX: cleanup.i20.i.i: -// APPROX-NEXT: [[__TAGP_ADDR_1_I21_I_I]] = phi ptr [ [[INCDEC_PTR_I29_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__TAGP_ADDR_0_I15_I_I]], [[WHILE_BODY_I18_I_I]] ] -// APPROX-NEXT: [[__R_1_I22_I_I]] = phi i64 [ [[SUB_I28_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_BODY_I18_I_I]] ] -// APPROX-NEXT: br i1 [[OR_COND_I19_I_I]], label [[WHILE_COND_I14_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP10]] +// APPROX-NEXT: [[TMP13:%.*]] = phi i8 [ [[TMP15:%.*]], [[IF_THEN_I21_I_I:%.*]] ], [ [[TMP1]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// APPROX-NEXT: [[__R_0_I16_I_I7:%.*]] = phi i64 [ [[SUB_I25_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ] +// APPROX-NEXT: [[__TAGP_ADDR_0_I15_I_I6:%.*]] = phi ptr [ [[INCDEC_PTR_I26_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ [[TAG]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// APPROX-NEXT: [[TMP14:%.*]] = add i8 [[TMP13]], -48 +// APPROX-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP14]], 10 +// APPROX-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I21_I_I]], label [[_ZL3NANPKC_EXIT]] +// APPROX: if.then.i21.i.i: +// APPROX-NEXT: [[MUL_I22_I_I:%.*]] = mul i64 [[__R_0_I16_I_I7]], 10 +// APPROX-NEXT: [[CONV5_I23_I_I:%.*]] = zext nneg i8 [[TMP13]] to i64 +// APPROX-NEXT: [[ADD_I24_I_I:%.*]] = add i64 [[MUL_I22_I_I]], -48 +// APPROX-NEXT: [[SUB_I25_I_I]] = add i64 [[ADD_I24_I_I]], [[CONV5_I23_I_I]] +// APPROX-NEXT: [[INCDEC_PTR_I26_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I6]], i64 1 +// APPROX-NEXT: [[TMP15]] = load i8, ptr [[INCDEC_PTR_I26_I_I]], align 1, !tbaa [[TBAA4]] +// APPROX-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP15]], 0 +// APPROX-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I18_I_I]], !llvm.loop [[LOOP10]] // APPROX: _ZL3nanPKc.exit: -// APPROX-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[CLEANUP_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_COND_I_I_I]] ], [ 0, [[CLEANUP_I36_I_I]] ], [ [[__R_0_I32_I_I]], [[WHILE_COND_I30_I_I]] ], [ 0, [[CLEANUP_I20_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_COND_I14_I_I]] ] +// APPROX-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ], [ 0, [[IF_THEN5_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ], [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_BODY_I_I_I]] ], [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ 0, [[IF_ELSE17_I_I_I]] ], [ [[SUB_I25_I_I]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_BODY_I18_I_I]] ] // APPROX-NEXT: [[BF_VALUE_I:%.*]] = and i64 [[RETVAL_0_I_I]], 2251799813685247 // APPROX-NEXT: [[BF_SET9_I:%.*]] = or disjoint i64 [[BF_VALUE_I]], 9221120237041090560 -// APPROX-NEXT: [[TMP10:%.*]] = bitcast i64 [[BF_SET9_I]] to double -// APPROX-NEXT: ret double [[TMP10]] +// APPROX-NEXT: [[TMP16:%.*]] = bitcast i64 [[BF_SET9_I]] to double +// APPROX-NEXT: ret double [[TMP16]] // // NCRDIV-LABEL: @test_nan( // NCRDIV-NEXT: entry: // NCRDIV-NEXT: [[TMP0:%.*]] = load i8, ptr [[TAG:%.*]], align 1, !tbaa [[TBAA4]] // NCRDIV-NEXT: [[CMP_I_I:%.*]] = icmp eq i8 [[TMP0]], 48 -// NCRDIV-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I:%.*]] +// NCRDIV-NEXT: br i1 [[CMP_I_I]], label [[IF_THEN_I_I:%.*]], label [[WHILE_COND_I14_I_I_PREHEADER:%.*]] +// NCRDIV: while.cond.i14.i.i.preheader: +// NCRDIV-NEXT: [[TMP1:%.*]] = load i8, ptr [[TAG]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I17_I_I5:%.*]] = icmp eq i8 [[TMP1]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I17_I_I5]], label [[_ZL3NANPKC_EXIT:%.*]], label [[WHILE_BODY_I18_I_I:%.*]] // NCRDIV: if.then.i.i: // NCRDIV-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[TAG]], i64 1 -// NCRDIV-NEXT: [[TMP1:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] -// NCRDIV-NEXT: switch i8 [[TMP1]], label [[WHILE_COND_I_I_I:%.*]] [ -// NCRDIV-NEXT: i8 120, label [[WHILE_COND_I30_I_I_PREHEADER:%.*]] -// NCRDIV-NEXT: i8 88, label [[WHILE_COND_I30_I_I_PREHEADER]] +// NCRDIV-NEXT: [[TMP2:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: switch i8 [[TMP2]], label [[WHILE_COND_I_I_I_PREHEADER:%.*]] [ +// NCRDIV-NEXT: i8 120, label [[IF_THEN5_I_I:%.*]] +// NCRDIV-NEXT: i8 88, label [[IF_THEN5_I_I]] // NCRDIV-NEXT: ] -// NCRDIV: while.cond.i30.i.i.preheader: -// NCRDIV-NEXT: br label [[WHILE_COND_I30_I_I:%.*]] -// NCRDIV: while.cond.i30.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_0_I31_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I37_I_I:%.*]], [[CLEANUP_I36_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I30_I_I_PREHEADER]] ] -// NCRDIV-NEXT: [[__R_0_I32_I_I:%.*]] = phi i64 [ [[__R_2_I_I_I:%.*]], [[CLEANUP_I36_I_I]] ], [ 0, [[WHILE_COND_I30_I_I_PREHEADER]] ] -// NCRDIV-NEXT: [[TMP2:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I31_I_I]], align 1, !tbaa [[TBAA4]] -// NCRDIV-NEXT: [[CMP_NOT_I33_I_I:%.*]] = icmp eq i8 [[TMP2]], 0 -// NCRDIV-NEXT: br i1 [[CMP_NOT_I33_I_I]], label [[_ZL3NANPKC_EXIT:%.*]], label [[WHILE_BODY_I34_I_I:%.*]] -// NCRDIV: while.body.i34.i.i: -// NCRDIV-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], -48 -// NCRDIV-NEXT: [[OR_COND_I35_I_I:%.*]] = icmp ult i8 [[TMP3]], 10 -// NCRDIV-NEXT: br i1 [[OR_COND_I35_I_I]], label [[IF_END31_I_I_I:%.*]], label [[IF_ELSE_I_I_I:%.*]] +// NCRDIV: while.cond.i.i.i.preheader: +// NCRDIV-NEXT: [[TMP3:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I_I_I14:%.*]] = icmp eq i8 [[TMP3]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I_I_I14]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// NCRDIV: if.then5.i.i: +// NCRDIV-NEXT: [[TMP4:%.*]] = load i8, ptr [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I30_I_I9:%.*]] = icmp eq i8 [[TMP4]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I30_I_I9]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I31_I_I:%.*]] +// NCRDIV: while.body.i31.i.i: +// NCRDIV-NEXT: [[TMP5:%.*]] = phi i8 [ [[TMP9:%.*]], [[IF_END31_I_I_I:%.*]] ], [ [[TMP4]], [[IF_THEN5_I_I]] ] +// NCRDIV-NEXT: [[__R_0_I29_I_I11:%.*]] = phi i64 [ [[ADD28_I_I_I:%.*]], [[IF_END31_I_I_I]] ], [ 0, [[IF_THEN5_I_I]] ] +// NCRDIV-NEXT: [[__TAGP_ADDR_0_I28_I_I10:%.*]] = phi ptr [ [[INCDEC_PTR_I34_I_I:%.*]], [[IF_END31_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN5_I_I]] ] +// NCRDIV-NEXT: [[TMP6:%.*]] = add i8 [[TMP5]], -48 +// NCRDIV-NEXT: [[OR_COND_I32_I_I:%.*]] = icmp ult i8 [[TMP6]], 10 +// NCRDIV-NEXT: br i1 [[OR_COND_I32_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE_I_I_I:%.*]] // NCRDIV: if.else.i.i.i: -// NCRDIV-NEXT: [[TMP4:%.*]] = add i8 [[TMP2]], -97 -// NCRDIV-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// NCRDIV-NEXT: [[TMP7:%.*]] = add i8 [[TMP5]], -97 +// NCRDIV-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP7]], 6 // NCRDIV-NEXT: br i1 [[OR_COND33_I_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE17_I_I_I:%.*]] // NCRDIV: if.else17.i.i.i: -// NCRDIV-NEXT: [[TMP5:%.*]] = add i8 [[TMP2]], -65 -// NCRDIV-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 -// NCRDIV-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[CLEANUP_I36_I_I]] +// NCRDIV-NEXT: [[TMP8:%.*]] = add i8 [[TMP5]], -65 +// NCRDIV-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP8]], 6 +// NCRDIV-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[_ZL3NANPKC_EXIT]] // NCRDIV: if.end31.i.i.i: -// NCRDIV-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I34_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] -// NCRDIV-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I32_I_I]], 4 -// NCRDIV-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 +// NCRDIV-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I31_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] +// NCRDIV-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I29_I_I11]], 4 +// NCRDIV-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP5]] to i64 // NCRDIV-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]] -// NCRDIV-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] -// NCRDIV-NEXT: [[INCDEC_PTR_I40_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I31_I_I]], i64 1 -// NCRDIV-NEXT: br label [[CLEANUP_I36_I_I]] -// NCRDIV: cleanup.i36.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_1_I37_I_I]] = phi ptr [ [[INCDEC_PTR_I40_I_I]], [[IF_END31_I_I_I]] ], [ [[__TAGP_ADDR_0_I31_I_I]], [[IF_ELSE17_I_I_I]] ] -// NCRDIV-NEXT: [[__R_2_I_I_I]] = phi i64 [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ [[__R_0_I32_I_I]], [[IF_ELSE17_I_I_I]] ] -// NCRDIV-NEXT: [[COND_I_I_I:%.*]] = phi i1 [ true, [[IF_END31_I_I_I]] ], [ false, [[IF_ELSE17_I_I_I]] ] -// NCRDIV-NEXT: br i1 [[COND_I_I_I]], label [[WHILE_COND_I30_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP11]] -// NCRDIV: while.cond.i.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_0_I_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I_I_I:%.*]], [[CLEANUP_I_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN_I_I]] ] -// NCRDIV-NEXT: [[__R_0_I_I_I:%.*]] = phi i64 [ [[__R_1_I_I_I:%.*]], [[CLEANUP_I_I_I]] ], [ 0, [[IF_THEN_I_I]] ] -// NCRDIV-NEXT: [[TMP6:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I_I_I]], align 1, !tbaa [[TBAA4]] -// NCRDIV-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP6]], 0 -// NCRDIV-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I_I_I:%.*]] +// NCRDIV-NEXT: [[ADD28_I_I_I]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] +// NCRDIV-NEXT: [[INCDEC_PTR_I34_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I28_I_I10]], i64 1 +// NCRDIV-NEXT: [[TMP9]] = load i8, ptr [[INCDEC_PTR_I34_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I30_I_I:%.*]] = icmp eq i8 [[TMP9]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I30_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I31_I_I]], !llvm.loop [[LOOP11]] // NCRDIV: while.body.i.i.i: -// NCRDIV-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -8 -// NCRDIV-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP7]], 48 -// NCRDIV-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[CLEANUP_I_I_I]] +// NCRDIV-NEXT: [[TMP10:%.*]] = phi i8 [ [[TMP12:%.*]], [[IF_THEN_I_I_I:%.*]] ], [ [[TMP3]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[__R_0_I_I_I16:%.*]] = phi i64 [ [[SUB_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[__TAGP_ADDR_0_I_I_I15:%.*]] = phi ptr [ [[INCDEC_PTR_I_I_I:%.*]], [[IF_THEN_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[TMP11:%.*]] = and i8 [[TMP10]], -8 +// NCRDIV-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP11]], 48 +// NCRDIV-NEXT: br i1 [[OR_COND_I_I_I]], label [[IF_THEN_I_I_I]], label [[_ZL3NANPKC_EXIT]] // NCRDIV: if.then.i.i.i: -// NCRDIV-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3 -// NCRDIV-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 +// NCRDIV-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I16]], 3 +// NCRDIV-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP10]] to i64 // NCRDIV-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48 -// NCRDIV-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] -// NCRDIV-NEXT: [[INCDEC_PTR_I_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I]], i64 1 -// NCRDIV-NEXT: br label [[CLEANUP_I_I_I]] -// NCRDIV: cleanup.i.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_1_I_I_I]] = phi ptr [ [[INCDEC_PTR_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__TAGP_ADDR_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// NCRDIV-NEXT: [[__R_1_I_I_I]] = phi i64 [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_BODY_I_I_I]] ] -// NCRDIV-NEXT: br i1 [[OR_COND_I_I_I]], label [[WHILE_COND_I_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP7]] -// NCRDIV: while.cond.i14.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_0_I15_I_I:%.*]] = phi ptr [ [[__TAGP_ADDR_1_I21_I_I:%.*]], [[CLEANUP_I20_I_I:%.*]] ], [ [[TAG]], [[ENTRY:%.*]] ] -// NCRDIV-NEXT: [[__R_0_I16_I_I:%.*]] = phi i64 [ [[__R_1_I22_I_I:%.*]], [[CLEANUP_I20_I_I]] ], [ 0, [[ENTRY]] ] -// NCRDIV-NEXT: [[TMP8:%.*]] = load i8, ptr [[__TAGP_ADDR_0_I15_I_I]], align 1, !tbaa [[TBAA4]] -// NCRDIV-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 -// NCRDIV-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I18_I_I:%.*]] +// NCRDIV-NEXT: [[SUB_I_I_I]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] +// NCRDIV-NEXT: [[INCDEC_PTR_I_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I_I_I15]], i64 1 +// NCRDIV-NEXT: [[TMP12]] = load i8, ptr [[INCDEC_PTR_I_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP12]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I_I_I]], !llvm.loop [[LOOP7]] // NCRDIV: while.body.i18.i.i: -// NCRDIV-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], -48 -// NCRDIV-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP9]], 10 -// NCRDIV-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I24_I_I:%.*]], label [[CLEANUP_I20_I_I]] -// NCRDIV: if.then.i24.i.i: -// NCRDIV-NEXT: [[MUL_I25_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10 -// NCRDIV-NEXT: [[CONV5_I26_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 -// NCRDIV-NEXT: [[ADD_I27_I_I:%.*]] = add i64 [[MUL_I25_I_I]], -48 -// NCRDIV-NEXT: [[SUB_I28_I_I:%.*]] = add i64 [[ADD_I27_I_I]], [[CONV5_I26_I_I]] -// NCRDIV-NEXT: [[INCDEC_PTR_I29_I_I:%.*]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I]], i64 1 -// NCRDIV-NEXT: br label [[CLEANUP_I20_I_I]] -// NCRDIV: cleanup.i20.i.i: -// NCRDIV-NEXT: [[__TAGP_ADDR_1_I21_I_I]] = phi ptr [ [[INCDEC_PTR_I29_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__TAGP_ADDR_0_I15_I_I]], [[WHILE_BODY_I18_I_I]] ] -// NCRDIV-NEXT: [[__R_1_I22_I_I]] = phi i64 [ [[SUB_I28_I_I]], [[IF_THEN_I24_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_BODY_I18_I_I]] ] -// NCRDIV-NEXT: br i1 [[OR_COND_I19_I_I]], label [[WHILE_COND_I14_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP10]] +// NCRDIV-NEXT: [[TMP13:%.*]] = phi i8 [ [[TMP15:%.*]], [[IF_THEN_I21_I_I:%.*]] ], [ [[TMP1]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[__R_0_I16_I_I7:%.*]] = phi i64 [ [[SUB_I25_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[__TAGP_ADDR_0_I15_I_I6:%.*]] = phi ptr [ [[INCDEC_PTR_I26_I_I:%.*]], [[IF_THEN_I21_I_I]] ], [ [[TAG]], [[WHILE_COND_I14_I_I_PREHEADER]] ] +// NCRDIV-NEXT: [[TMP14:%.*]] = add i8 [[TMP13]], -48 +// NCRDIV-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP14]], 10 +// NCRDIV-NEXT: br i1 [[OR_COND_I19_I_I]], label [[IF_THEN_I21_I_I]], label [[_ZL3NANPKC_EXIT]] +// NCRDIV: if.then.i21.i.i: +// NCRDIV-NEXT: [[MUL_I22_I_I:%.*]] = mul i64 [[__R_0_I16_I_I7]], 10 +// NCRDIV-NEXT: [[CONV5_I23_I_I:%.*]] = zext nneg i8 [[TMP13]] to i64 +// NCRDIV-NEXT: [[ADD_I24_I_I:%.*]] = add i64 [[MUL_I22_I_I]], -48 +// NCRDIV-NEXT: [[SUB_I25_I_I]] = add i64 [[ADD_I24_I_I]], [[CONV5_I23_I_I]] +// NCRDIV-NEXT: [[INCDEC_PTR_I26_I_I]] = getelementptr inbounds nuw i8, ptr [[__TAGP_ADDR_0_I15_I_I6]], i64 1 +// NCRDIV-NEXT: [[TMP15]] = load i8, ptr [[INCDEC_PTR_I26_I_I]], align 1, !tbaa [[TBAA4]] +// NCRDIV-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP15]], 0 +// NCRDIV-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I18_I_I]], !llvm.loop [[LOOP10]] // NCRDIV: _ZL3nanPKc.exit: -// NCRDIV-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[CLEANUP_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_COND_I_I_I]] ], [ 0, [[CLEANUP_I36_I_I]] ], [ [[__R_0_I32_I_I]], [[WHILE_COND_I30_I_I]] ], [ 0, [[CLEANUP_I20_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_COND_I14_I_I]] ] +// NCRDIV-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[WHILE_COND_I_I_I_PREHEADER]] ], [ 0, [[IF_THEN5_I_I]] ], [ 0, [[WHILE_COND_I14_I_I_PREHEADER]] ], [ [[SUB_I_I_I]], [[IF_THEN_I_I_I]] ], [ 0, [[WHILE_BODY_I_I_I]] ], [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ 0, [[IF_ELSE17_I_I_I]] ], [ [[SUB_I25_I_I]], [[IF_THEN_I21_I_I]] ], [ 0, [[WHILE_BODY_I18_I_I]] ] // NCRDIV-NEXT: [[BF_VALUE_I:%.*]] = and i64 [[RETVAL_0_I_I]], 2251799813685247 // NCRDIV-NEXT: [[BF_SET9_I:%.*]] = or disjoint i64 [[BF_VALUE_I]], 9221120237041090560 -// NCRDIV-NEXT: [[TMP10:%.*]] = bitcast i64 [[BF_SET9_I]] to double -// NCRDIV-NEXT: ret double [[TMP10]] +// NCRDIV-NEXT: [[TMP16:%.*]] = bitcast i64 [[BF_SET9_I]] to double +// NCRDIV-NEXT: ret double [[TMP16]] // // AMDGCNSPIRV-LABEL: @test_nan( // AMDGCNSPIRV-NEXT: entry: @@ -4442,53 +4378,49 @@ extern "C" __device__ float test_nanf(const char *tag) { // AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I_I:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[TAG]], i64 1 // AMDGCNSPIRV-NEXT: [[TMP1:%.*]] = load i8, ptr addrspace(4) [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA5]] // AMDGCNSPIRV-NEXT: switch i8 [[TMP1]], label [[WHILE_COND_I_I_I:%.*]] [ -// AMDGCNSPIRV-NEXT: i8 120, label [[WHILE_COND_I28_I_I_PREHEADER:%.*]] -// AMDGCNSPIRV-NEXT: i8 88, label [[WHILE_COND_I28_I_I_PREHEADER]] +// AMDGCNSPIRV-NEXT: i8 120, label [[IF_THEN5_I_I:%.*]] +// AMDGCNSPIRV-NEXT: i8 88, label [[IF_THEN5_I_I]] // AMDGCNSPIRV-NEXT: ] -// AMDGCNSPIRV: while.cond.i28.i.i.preheader: -// AMDGCNSPIRV-NEXT: br label [[WHILE_COND_I28_I_I:%.*]] -// AMDGCNSPIRV: while.cond.i28.i.i: -// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I29_I_I:%.*]] = phi ptr addrspace(4) [ [[__TAGP_ADDR_1_I34_I_I:%.*]], [[CLEANUP_I_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[WHILE_COND_I28_I_I_PREHEADER]] ] -// AMDGCNSPIRV-NEXT: [[__R_0_I30_I_I:%.*]] = phi i64 [ [[__R_2_I_I_I:%.*]], [[CLEANUP_I_I_I]] ], [ 0, [[WHILE_COND_I28_I_I_PREHEADER]] ] -// AMDGCNSPIRV-NEXT: [[TMP2:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I29_I_I]], align 1, !tbaa [[TBAA5]] -// AMDGCNSPIRV-NEXT: [[CMP_NOT_I31_I_I:%.*]] = icmp eq i8 [[TMP2]], 0 -// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I31_I_I]], label [[_ZL3NANPKC_EXIT:%.*]], label [[WHILE_BODY_I32_I_I:%.*]] +// AMDGCNSPIRV: if.then5.i.i: +// AMDGCNSPIRV-NEXT: [[TMP2:%.*]] = load i8, ptr addrspace(4) [[INCDEC_PTR_I_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I31_I_I5:%.*]] = icmp eq i8 [[TMP2]], 0 +// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I31_I_I5]], label [[_ZL3NANPKC_EXIT:%.*]], label [[WHILE_BODY_I32_I_I:%.*]] // AMDGCNSPIRV: while.body.i32.i.i: -// AMDGCNSPIRV-NEXT: [[TMP3:%.*]] = add i8 [[TMP2]], -48 -// AMDGCNSPIRV-NEXT: [[OR_COND_I33_I_I:%.*]] = icmp ult i8 [[TMP3]], 10 -// AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I33_I_I]], label [[IF_END31_I_I_I:%.*]], label [[IF_ELSE_I_I_I:%.*]] +// AMDGCNSPIRV-NEXT: [[TMP3:%.*]] = phi i8 [ [[TMP7:%.*]], [[IF_END31_I_I_I:%.*]] ], [ [[TMP2]], [[IF_THEN5_I_I]] ] +// AMDGCNSPIRV-NEXT: [[__R_0_I30_I_I7:%.*]] = phi i64 [ [[ADD28_I_I_I:%.*]], [[IF_END31_I_I_I]] ], [ 0, [[IF_THEN5_I_I]] ] +// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I29_I_I6:%.*]] = phi ptr addrspace(4) [ [[INCDEC_PTR_I36_I_I:%.*]], [[IF_END31_I_I_I]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN5_I_I]] ] +// AMDGCNSPIRV-NEXT: [[TMP4:%.*]] = add i8 [[TMP3]], -48 +// AMDGCNSPIRV-NEXT: [[OR_COND_I33_I_I:%.*]] = icmp ult i8 [[TMP4]], 10 +// AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I33_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE_I_I_I:%.*]] // AMDGCNSPIRV: if.else.i.i.i: -// AMDGCNSPIRV-NEXT: [[TMP4:%.*]] = add i8 [[TMP2]], -97 -// AMDGCNSPIRV-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP4]], 6 +// AMDGCNSPIRV-NEXT: [[TMP5:%.*]] = add i8 [[TMP3]], -97 +// AMDGCNSPIRV-NEXT: [[OR_COND33_I_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 // AMDGCNSPIRV-NEXT: br i1 [[OR_COND33_I_I_I]], label [[IF_END31_I_I_I]], label [[IF_ELSE17_I_I_I:%.*]] // AMDGCNSPIRV: if.else17.i.i.i: -// AMDGCNSPIRV-NEXT: [[TMP5:%.*]] = add i8 [[TMP2]], -65 -// AMDGCNSPIRV-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP5]], 6 -// AMDGCNSPIRV-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[CLEANUP_I_I_I]] +// AMDGCNSPIRV-NEXT: [[TMP6:%.*]] = add i8 [[TMP3]], -65 +// AMDGCNSPIRV-NEXT: [[OR_COND34_I_I_I:%.*]] = icmp ult i8 [[TMP6]], 6 +// AMDGCNSPIRV-NEXT: br i1 [[OR_COND34_I_I_I]], label [[IF_END31_I_I_I]], label [[_ZL3NANPKC_EXIT]] // AMDGCNSPIRV: if.end31.i.i.i: // AMDGCNSPIRV-NEXT: [[DOTSINK:%.*]] = phi i64 [ -48, [[WHILE_BODY_I32_I_I]] ], [ -87, [[IF_ELSE_I_I_I]] ], [ -55, [[IF_ELSE17_I_I_I]] ] -// AMDGCNSPIRV-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I30_I_I]], 4 -// AMDGCNSPIRV-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP2]] to i64 +// AMDGCNSPIRV-NEXT: [[MUL24_I_I_I:%.*]] = shl i64 [[__R_0_I30_I_I7]], 4 +// AMDGCNSPIRV-NEXT: [[CONV25_I_I_I:%.*]] = zext nneg i8 [[TMP3]] to i64 // AMDGCNSPIRV-NEXT: [[ADD26_I_I_I:%.*]] = add i64 [[MUL24_I_I_I]], [[DOTSINK]] -// AMDGCNSPIRV-NEXT: [[ADD28_I_I_I:%.*]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] -// AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I37_I_I:%.*]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[__TAGP_ADDR_0_I29_I_I]], i64 1 -// AMDGCNSPIRV-NEXT: br label [[CLEANUP_I_I_I]] -// AMDGCNSPIRV: cleanup.i.i.i: -// AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_1_I34_I_I]] = phi ptr addrspace(4) [ [[INCDEC_PTR_I37_I_I]], [[IF_END31_I_I_I]] ], [ [[__TAGP_ADDR_0_I29_I_I]], [[IF_ELSE17_I_I_I]] ] -// AMDGCNSPIRV-NEXT: [[__R_2_I_I_I]] = phi i64 [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ [[__R_0_I30_I_I]], [[IF_ELSE17_I_I_I]] ] -// AMDGCNSPIRV-NEXT: [[COND_I_I_I:%.*]] = phi i1 [ true, [[IF_END31_I_I_I]] ], [ false, [[IF_ELSE17_I_I_I]] ] -// AMDGCNSPIRV-NEXT: br i1 [[COND_I_I_I]], label [[WHILE_COND_I28_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP12]] +// AMDGCNSPIRV-NEXT: [[ADD28_I_I_I]] = add i64 [[ADD26_I_I_I]], [[CONV25_I_I_I]] +// AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I36_I_I]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[__TAGP_ADDR_0_I29_I_I6]], i64 1 +// AMDGCNSPIRV-NEXT: [[TMP7]] = load i8, ptr addrspace(4) [[INCDEC_PTR_I36_I_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I31_I_I:%.*]] = icmp eq i8 [[TMP7]], 0 +// AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I31_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I32_I_I]], !llvm.loop [[LOOP12]] // AMDGCNSPIRV: while.cond.i.i.i: // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I_I_I:%.*]] = phi ptr addrspace(4) [ [[__TAGP_ADDR_1_I_I_I:%.*]], [[WHILE_BODY_I_I_I:%.*]] ], [ [[INCDEC_PTR_I_I]], [[IF_THEN_I_I]] ] // AMDGCNSPIRV-NEXT: [[__R_0_I_I_I:%.*]] = phi i64 [ [[__R_1_I_I_I:%.*]], [[WHILE_BODY_I_I_I]] ], [ 0, [[IF_THEN_I_I]] ] -// AMDGCNSPIRV-NEXT: [[TMP6:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I_I_I]], align 1, !tbaa [[TBAA5]] -// AMDGCNSPIRV-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP6]], 0 +// AMDGCNSPIRV-NEXT: [[TMP8:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I_I_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 // AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I_I_I]] // AMDGCNSPIRV: while.body.i.i.i: -// AMDGCNSPIRV-NEXT: [[TMP7:%.*]] = and i8 [[TMP6]], -8 -// AMDGCNSPIRV-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP7]], 48 +// AMDGCNSPIRV-NEXT: [[TMP9:%.*]] = and i8 [[TMP8]], -8 +// AMDGCNSPIRV-NEXT: [[OR_COND_I_I_I:%.*]] = icmp eq i8 [[TMP9]], 48 // AMDGCNSPIRV-NEXT: [[MUL_I_I_I:%.*]] = shl i64 [[__R_0_I_I_I]], 3 -// AMDGCNSPIRV-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP6]] to i64 +// AMDGCNSPIRV-NEXT: [[CONV5_I_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 // AMDGCNSPIRV-NEXT: [[ADD_I_I_I:%.*]] = add i64 [[MUL_I_I_I]], -48 // AMDGCNSPIRV-NEXT: [[SUB_I_I_I:%.*]] = add i64 [[ADD_I_I_I]], [[CONV5_I_I_I]] // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_1_I_I_I_IDX:%.*]] = zext i1 [[OR_COND_I_I_I]] to i64 @@ -4498,14 +4430,14 @@ extern "C" __device__ float test_nanf(const char *tag) { // AMDGCNSPIRV: while.cond.i14.i.i: // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_0_I15_I_I:%.*]] = phi ptr addrspace(4) [ [[__TAGP_ADDR_1_I25_I_I:%.*]], [[WHILE_BODY_I18_I_I:%.*]] ], [ [[TAG]], [[ENTRY:%.*]] ] // AMDGCNSPIRV-NEXT: [[__R_0_I16_I_I:%.*]] = phi i64 [ [[__R_1_I26_I_I:%.*]], [[WHILE_BODY_I18_I_I]] ], [ 0, [[ENTRY]] ] -// AMDGCNSPIRV-NEXT: [[TMP8:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I15_I_I]], align 1, !tbaa [[TBAA5]] -// AMDGCNSPIRV-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP8]], 0 +// AMDGCNSPIRV-NEXT: [[TMP10:%.*]] = load i8, ptr addrspace(4) [[__TAGP_ADDR_0_I15_I_I]], align 1, !tbaa [[TBAA5]] +// AMDGCNSPIRV-NEXT: [[CMP_NOT_I17_I_I:%.*]] = icmp eq i8 [[TMP10]], 0 // AMDGCNSPIRV-NEXT: br i1 [[CMP_NOT_I17_I_I]], label [[_ZL3NANPKC_EXIT]], label [[WHILE_BODY_I18_I_I]] // AMDGCNSPIRV: while.body.i18.i.i: -// AMDGCNSPIRV-NEXT: [[TMP9:%.*]] = add i8 [[TMP8]], -48 -// AMDGCNSPIRV-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP9]], 10 +// AMDGCNSPIRV-NEXT: [[TMP11:%.*]] = add i8 [[TMP10]], -48 +// AMDGCNSPIRV-NEXT: [[OR_COND_I19_I_I:%.*]] = icmp ult i8 [[TMP11]], 10 // AMDGCNSPIRV-NEXT: [[MUL_I20_I_I:%.*]] = mul i64 [[__R_0_I16_I_I]], 10 -// AMDGCNSPIRV-NEXT: [[CONV5_I21_I_I:%.*]] = zext nneg i8 [[TMP8]] to i64 +// AMDGCNSPIRV-NEXT: [[CONV5_I21_I_I:%.*]] = zext nneg i8 [[TMP10]] to i64 // AMDGCNSPIRV-NEXT: [[ADD_I22_I_I:%.*]] = add i64 [[MUL_I20_I_I]], -48 // AMDGCNSPIRV-NEXT: [[SUB_I23_I_I:%.*]] = add i64 [[ADD_I22_I_I]], [[CONV5_I21_I_I]] // AMDGCNSPIRV-NEXT: [[__TAGP_ADDR_1_I25_I_I_IDX:%.*]] = zext i1 [[OR_COND_I19_I_I]] to i64 @@ -4513,11 +4445,11 @@ extern "C" __device__ float test_nanf(const char *tag) { // AMDGCNSPIRV-NEXT: [[__R_1_I26_I_I]] = select i1 [[OR_COND_I19_I_I]], i64 [[SUB_I23_I_I]], i64 [[__R_0_I16_I_I]] // AMDGCNSPIRV-NEXT: br i1 [[OR_COND_I19_I_I]], label [[WHILE_COND_I14_I_I]], label [[_ZL3NANPKC_EXIT]], !llvm.loop [[LOOP11]] // AMDGCNSPIRV: _ZL3nanPKc.exit: -// AMDGCNSPIRV-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[WHILE_BODY_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_COND_I_I_I]] ], [ 0, [[CLEANUP_I_I_I]] ], [ [[__R_0_I30_I_I]], [[WHILE_COND_I28_I_I]] ], [ 0, [[WHILE_BODY_I18_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_COND_I14_I_I]] ] +// AMDGCNSPIRV-NEXT: [[RETVAL_0_I_I:%.*]] = phi i64 [ 0, [[IF_THEN5_I_I]] ], [ 0, [[WHILE_BODY_I_I_I]] ], [ [[__R_0_I_I_I]], [[WHILE_COND_I_I_I]] ], [ [[ADD28_I_I_I]], [[IF_END31_I_I_I]] ], [ 0, [[IF_ELSE17_I_I_I]] ], [ 0, [[WHILE_BODY_I18_I_I]] ], [ [[__R_0_I16_I_I]], [[WHILE_COND_I14_I_I]] ] // AMDGCNSPIRV-NEXT: [[BF_VALUE_I:%.*]] = and i64 [[RETVAL_0_I_I]], 2251799813685247 // AMDGCNSPIRV-NEXT: [[BF_SET9_I:%.*]] = or disjoint i64 [[BF_VALUE_I]], 9221120237041090560 -// AMDGCNSPIRV-NEXT: [[TMP10:%.*]] = bitcast i64 [[BF_SET9_I]] to double -// AMDGCNSPIRV-NEXT: ret double [[TMP10]] +// AMDGCNSPIRV-NEXT: [[TMP12:%.*]] = bitcast i64 [[BF_SET9_I]] to double +// AMDGCNSPIRV-NEXT: ret double [[TMP12]] // extern "C" __device__ double test_nan(const char *tag) { return nan(tag); @@ -4981,11 +4913,13 @@ extern "C" __device__ double test_normcdfinv(double x) { // DEFAULT-NEXT: [[ADD_I]] = fadd contract float [[__R_0_I4]], [[MUL_I]] // DEFAULT-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__A_ADDR_0_I3]], i64 4 // DEFAULT-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// DEFAULT-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP20:![0-9]+]] +// DEFAULT-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP20:![0-9]+]] +// DEFAULT: _ZL5normfiPKf.exit.loopexit: +// DEFAULT-NEXT: [[TMP1:%.*]] = tail call contract float @llvm.sqrt.f32(float [[ADD_I]]) +// DEFAULT-NEXT: br label [[_ZL5NORMFIPKF_EXIT]] // DEFAULT: _ZL5normfiPKf.exit: -// DEFAULT-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// DEFAULT-NEXT: [[TMP1:%.*]] = tail call contract noundef float @llvm.sqrt.f32(float [[__R_0_I_LCSSA]]) -// DEFAULT-NEXT: ret float [[TMP1]] +// DEFAULT-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[TMP1]], [[_ZL5NORMFIPKF_EXIT_LOOPEXIT]] ] +// DEFAULT-NEXT: ret float [[__R_0_I_LCSSA]] // // FINITEONLY-LABEL: @test_normf( // FINITEONLY-NEXT: entry: @@ -5001,11 +4935,13 @@ extern "C" __device__ double test_normcdfinv(double x) { // FINITEONLY-NEXT: [[ADD_I]] = fadd nnan ninf contract float [[__R_0_I4]], [[MUL_I]] // FINITEONLY-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__A_ADDR_0_I3]], i64 4 // FINITEONLY-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// FINITEONLY-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP20:![0-9]+]] +// FINITEONLY-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP20:![0-9]+]] +// FINITEONLY: _ZL5normfiPKf.exit.loopexit: +// FINITEONLY-NEXT: [[TMP1:%.*]] = tail call nnan ninf contract float @llvm.sqrt.f32(float [[ADD_I]]) +// FINITEONLY-NEXT: br label [[_ZL5NORMFIPKF_EXIT]] // FINITEONLY: _ZL5normfiPKf.exit: -// FINITEONLY-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// FINITEONLY-NEXT: [[TMP1:%.*]] = tail call nnan ninf contract noundef float @llvm.sqrt.f32(float [[__R_0_I_LCSSA]]) -// FINITEONLY-NEXT: ret float [[TMP1]] +// FINITEONLY-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[TMP1]], [[_ZL5NORMFIPKF_EXIT_LOOPEXIT]] ] +// FINITEONLY-NEXT: ret float [[__R_0_I_LCSSA]] // // APPROX-LABEL: @test_normf( // APPROX-NEXT: entry: @@ -5021,11 +4957,13 @@ extern "C" __device__ double test_normcdfinv(double x) { // APPROX-NEXT: [[ADD_I]] = fadd contract float [[__R_0_I4]], [[MUL_I]] // APPROX-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__A_ADDR_0_I3]], i64 4 // APPROX-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// APPROX-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP20:![0-9]+]] +// APPROX-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP20:![0-9]+]] +// APPROX: _ZL5normfiPKf.exit.loopexit: +// APPROX-NEXT: [[TMP1:%.*]] = tail call contract float @llvm.sqrt.f32(float [[ADD_I]]) +// APPROX-NEXT: br label [[_ZL5NORMFIPKF_EXIT]] // APPROX: _ZL5normfiPKf.exit: -// APPROX-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// APPROX-NEXT: [[TMP1:%.*]] = tail call contract noundef float @llvm.sqrt.f32(float [[__R_0_I_LCSSA]]) -// APPROX-NEXT: ret float [[TMP1]] +// APPROX-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[TMP1]], [[_ZL5NORMFIPKF_EXIT_LOOPEXIT]] ] +// APPROX-NEXT: ret float [[__R_0_I_LCSSA]] // // NCRDIV-LABEL: @test_normf( // NCRDIV-NEXT: entry: @@ -5041,11 +4979,13 @@ extern "C" __device__ double test_normcdfinv(double x) { // NCRDIV-NEXT: [[ADD_I]] = fadd contract float [[__R_0_I4]], [[MUL_I]] // NCRDIV-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__A_ADDR_0_I3]], i64 4 // NCRDIV-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// NCRDIV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] +// NCRDIV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] +// NCRDIV: _ZL5normfiPKf.exit.loopexit: +// NCRDIV-NEXT: [[TMP1:%.*]] = tail call contract float @llvm.sqrt.f32(float [[ADD_I]]) +// NCRDIV-NEXT: br label [[_ZL5NORMFIPKF_EXIT]] // NCRDIV: _ZL5normfiPKf.exit: -// NCRDIV-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// NCRDIV-NEXT: [[TMP1:%.*]] = tail call contract noundef float @llvm.sqrt.f32(float [[__R_0_I_LCSSA]]), !fpmath [[META22:![0-9]+]] -// NCRDIV-NEXT: ret float [[TMP1]] +// NCRDIV-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[TMP1]], [[_ZL5NORMFIPKF_EXIT_LOOPEXIT]] ] +// NCRDIV-NEXT: ret float [[__R_0_I_LCSSA]] // // AMDGCNSPIRV-LABEL: @test_normf( // AMDGCNSPIRV-NEXT: entry: @@ -5061,11 +5001,13 @@ extern "C" __device__ double test_normcdfinv(double x) { // AMDGCNSPIRV-NEXT: [[ADD_I]] = fadd contract float [[__R_0_I4]], [[MUL_I]] // AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[__A_ADDR_0_I3]], i64 4 // AMDGCNSPIRV-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// AMDGCNSPIRV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] +// AMDGCNSPIRV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5NORMFIPKF_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] +// AMDGCNSPIRV: _ZL5normfiPKf.exit.loopexit: +// AMDGCNSPIRV-NEXT: [[TMP1:%.*]] = tail call contract addrspace(4) float @llvm.sqrt.f32(float [[ADD_I]]) +// AMDGCNSPIRV-NEXT: br label [[_ZL5NORMFIPKF_EXIT]] // AMDGCNSPIRV: _ZL5normfiPKf.exit: -// AMDGCNSPIRV-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// AMDGCNSPIRV-NEXT: [[TMP1:%.*]] = tail call contract noundef addrspace(4) float @llvm.sqrt.f32(float [[__R_0_I_LCSSA]]) -// AMDGCNSPIRV-NEXT: ret float [[TMP1]] +// AMDGCNSPIRV-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[TMP1]], [[_ZL5NORMFIPKF_EXIT_LOOPEXIT]] ] +// AMDGCNSPIRV-NEXT: ret float [[__R_0_I_LCSSA]] // extern "C" __device__ float test_normf(int x, const float *y) { return normf(x, y); @@ -5085,11 +5027,13 @@ extern "C" __device__ float test_normf(int x, const float *y) { // DEFAULT-NEXT: [[ADD_I]] = fadd contract double [[__R_0_I4]], [[MUL_I]] // DEFAULT-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__A_ADDR_0_I3]], i64 8 // DEFAULT-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// DEFAULT-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] +// DEFAULT-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] +// DEFAULT: _ZL4normiPKd.exit.loopexit: +// DEFAULT-NEXT: [[TMP1:%.*]] = tail call contract double @llvm.sqrt.f64(double [[ADD_I]]) +// DEFAULT-NEXT: br label [[_ZL4NORMIPKD_EXIT]] // DEFAULT: _ZL4normiPKd.exit: -// DEFAULT-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// DEFAULT-NEXT: [[TMP1:%.*]] = tail call contract noundef double @llvm.sqrt.f64(double [[__R_0_I_LCSSA]]) -// DEFAULT-NEXT: ret double [[TMP1]] +// DEFAULT-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[TMP1]], [[_ZL4NORMIPKD_EXIT_LOOPEXIT]] ] +// DEFAULT-NEXT: ret double [[__R_0_I_LCSSA]] // // FINITEONLY-LABEL: @test_norm( // FINITEONLY-NEXT: entry: @@ -5105,11 +5049,13 @@ extern "C" __device__ float test_normf(int x, const float *y) { // FINITEONLY-NEXT: [[ADD_I]] = fadd nnan ninf contract double [[__R_0_I4]], [[MUL_I]] // FINITEONLY-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__A_ADDR_0_I3]], i64 8 // FINITEONLY-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// FINITEONLY-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] +// FINITEONLY-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] +// FINITEONLY: _ZL4normiPKd.exit.loopexit: +// FINITEONLY-NEXT: [[TMP1:%.*]] = tail call nnan ninf contract double @llvm.sqrt.f64(double [[ADD_I]]) +// FINITEONLY-NEXT: br label [[_ZL4NORMIPKD_EXIT]] // FINITEONLY: _ZL4normiPKd.exit: -// FINITEONLY-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// FINITEONLY-NEXT: [[TMP1:%.*]] = tail call nnan ninf contract noundef double @llvm.sqrt.f64(double [[__R_0_I_LCSSA]]) -// FINITEONLY-NEXT: ret double [[TMP1]] +// FINITEONLY-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[TMP1]], [[_ZL4NORMIPKD_EXIT_LOOPEXIT]] ] +// FINITEONLY-NEXT: ret double [[__R_0_I_LCSSA]] // // APPROX-LABEL: @test_norm( // APPROX-NEXT: entry: @@ -5125,11 +5071,13 @@ extern "C" __device__ float test_normf(int x, const float *y) { // APPROX-NEXT: [[ADD_I]] = fadd contract double [[__R_0_I4]], [[MUL_I]] // APPROX-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__A_ADDR_0_I3]], i64 8 // APPROX-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// APPROX-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] +// APPROX-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP21:![0-9]+]] +// APPROX: _ZL4normiPKd.exit.loopexit: +// APPROX-NEXT: [[TMP1:%.*]] = tail call contract double @llvm.sqrt.f64(double [[ADD_I]]) +// APPROX-NEXT: br label [[_ZL4NORMIPKD_EXIT]] // APPROX: _ZL4normiPKd.exit: -// APPROX-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// APPROX-NEXT: [[TMP1:%.*]] = tail call contract noundef double @llvm.sqrt.f64(double [[__R_0_I_LCSSA]]) -// APPROX-NEXT: ret double [[TMP1]] +// APPROX-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[TMP1]], [[_ZL4NORMIPKD_EXIT_LOOPEXIT]] ] +// APPROX-NEXT: ret double [[__R_0_I_LCSSA]] // // NCRDIV-LABEL: @test_norm( // NCRDIV-NEXT: entry: @@ -5145,11 +5093,13 @@ extern "C" __device__ float test_normf(int x, const float *y) { // NCRDIV-NEXT: [[ADD_I]] = fadd contract double [[__R_0_I4]], [[MUL_I]] // NCRDIV-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__A_ADDR_0_I3]], i64 8 // NCRDIV-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// NCRDIV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP23:![0-9]+]] +// NCRDIV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP22:![0-9]+]] +// NCRDIV: _ZL4normiPKd.exit.loopexit: +// NCRDIV-NEXT: [[TMP1:%.*]] = tail call contract double @llvm.sqrt.f64(double [[ADD_I]]) +// NCRDIV-NEXT: br label [[_ZL4NORMIPKD_EXIT]] // NCRDIV: _ZL4normiPKd.exit: -// NCRDIV-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// NCRDIV-NEXT: [[TMP1:%.*]] = tail call contract noundef double @llvm.sqrt.f64(double [[__R_0_I_LCSSA]]) -// NCRDIV-NEXT: ret double [[TMP1]] +// NCRDIV-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[TMP1]], [[_ZL4NORMIPKD_EXIT_LOOPEXIT]] ] +// NCRDIV-NEXT: ret double [[__R_0_I_LCSSA]] // // AMDGCNSPIRV-LABEL: @test_norm( // AMDGCNSPIRV-NEXT: entry: @@ -5165,11 +5115,13 @@ extern "C" __device__ float test_normf(int x, const float *y) { // AMDGCNSPIRV-NEXT: [[ADD_I]] = fadd contract double [[__R_0_I4]], [[MUL_I]] // AMDGCNSPIRV-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr addrspace(4) [[__A_ADDR_0_I3]], i64 8 // AMDGCNSPIRV-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// AMDGCNSPIRV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP22:![0-9]+]] +// AMDGCNSPIRV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL4NORMIPKD_EXIT_LOOPEXIT:%.*]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP22:![0-9]+]] +// AMDGCNSPIRV: _ZL4normiPKd.exit.loopexit: +// AMDGCNSPIRV-NEXT: [[TMP1:%.*]] = tail call contract addrspace(4) double @llvm.sqrt.f64(double [[ADD_I]]) +// AMDGCNSPIRV-NEXT: br label [[_ZL4NORMIPKD_EXIT]] // AMDGCNSPIRV: _ZL4normiPKd.exit: -// AMDGCNSPIRV-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] -// AMDGCNSPIRV-NEXT: [[TMP1:%.*]] = tail call contract noundef addrspace(4) double @llvm.sqrt.f64(double [[__R_0_I_LCSSA]]) -// AMDGCNSPIRV-NEXT: ret double [[TMP1]] +// AMDGCNSPIRV-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[TMP1]], [[_ZL4NORMIPKD_EXIT_LOOPEXIT]] ] +// AMDGCNSPIRV-NEXT: ret double [[__R_0_I_LCSSA]] // extern "C" __device__ double test_norm(int x, const double *y) { return norm(x, y); @@ -5707,7 +5659,7 @@ extern "C" __device__ double test_rint(double x) { // NCRDIV-NEXT: [[ADD_I]] = fadd contract float [[__R_0_I4]], [[MUL_I]] // NCRDIV-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__A_ADDR_0_I3]], i64 4 // NCRDIV-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// NCRDIV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL6RNORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP24:![0-9]+]] +// NCRDIV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL6RNORMFIPKF_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP23:![0-9]+]] // NCRDIV: _ZL6rnormfiPKf.exit: // NCRDIV-NEXT: [[__R_0_I_LCSSA:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] // NCRDIV-NEXT: [[CALL_I:%.*]] = tail call contract noundef float @__ocml_rsqrt_f32(float noundef [[__R_0_I_LCSSA]]) #[[ATTR15]] @@ -5811,7 +5763,7 @@ extern "C" __device__ float test_rnormf(int x, const float* y) { // NCRDIV-NEXT: [[ADD_I]] = fadd contract double [[__R_0_I4]], [[MUL_I]] // NCRDIV-NEXT: [[INCDEC_PTR_I]] = getelementptr inbounds nuw i8, ptr [[__A_ADDR_0_I3]], i64 8 // NCRDIV-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[DEC_I]], 0 -// NCRDIV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5RNORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP25:![0-9]+]] +// NCRDIV-NEXT: br i1 [[TOBOOL_NOT_I]], label [[_ZL5RNORMIPKD_EXIT]], label [[WHILE_BODY_I]], !llvm.loop [[LOOP24:![0-9]+]] // NCRDIV: _ZL5rnormiPKd.exit: // NCRDIV-NEXT: [[__R_0_I_LCSSA:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I]], [[WHILE_BODY_I]] ] // NCRDIV-NEXT: [[CALL_I:%.*]] = tail call contract noundef double @__ocml_rsqrt_f64(double noundef [[__R_0_I_LCSSA]]) #[[ATTR15]] @@ -6616,7 +6568,7 @@ extern "C" __device__ double test_sinpi(double x) { // // NCRDIV-LABEL: @test_sqrtf( // NCRDIV-NEXT: entry: -// NCRDIV-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.sqrt.f32(float [[X:%.*]]), !fpmath [[META22]] +// NCRDIV-NEXT: [[TMP0:%.*]] = tail call contract noundef float @llvm.sqrt.f32(float [[X:%.*]]), !fpmath [[META25:![0-9]+]] // NCRDIV-NEXT: ret float [[TMP0]] // // AMDGCNSPIRV-LABEL: @test_sqrtf( diff --git a/clang/test/Headers/__cpuidex_conflict.c b/clang/test/Headers/__cpuidex_conflict.c index 49795c4..74f4532 100644 --- a/clang/test/Headers/__cpuidex_conflict.c +++ b/clang/test/Headers/__cpuidex_conflict.c @@ -1,19 +1,17 @@ // Make sure that __cpuidex in cpuid.h doesn't conflict with the MS // extensions built in by ensuring compilation succeeds: -// RUN: %clang_cc1 %s -ffreestanding -fms-extensions -fms-compatibility \ -// RUN: -fms-compatibility-version=19.00 -triple x86_64-pc-windows-msvc -emit-llvm -o - -// %clang_cc1 %s -ffreestanding -triple x86_64-w64-windows-gnu -fms-extensions -emit-llvm -o - -// -// FIXME: See https://github.com/llvm/llvm-project/pull/121839 and -// FIXME: https://github.com/llvm/llvm-project/pull/126324 -// RUN: not %clang_cc1 %s -ffreestanding -fopenmp -fopenmp-is-target-device -aux-triple x86_64-unknown-linux-gnu +// RUN: %clang_cc1 %s -DIS_STATIC="" -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=19.00 -triple x86_64-pc-windows-msvc -emit-llvm -o - +// RUN: %clang_cc1 %s -DIS_STATIC="" -ffreestanding -triple x86_64-w64-windows-gnu -fms-extensions -emit-llvm -o - + +// Ensure that we do not run into conflicts when offloading. +// RUN: %clang_cc1 %s -DIS_STATIC=static -ffreestanding -fopenmp -fopenmp-is-target-device -aux-triple x86_64-unknown-linux-gnu typedef __SIZE_TYPE__ size_t; // We declare __cpuidex here as where the buitlin should be exposed (MSVC), the // declaration is in <intrin.h>, but <intrin.h> is not available from all the // targets that are being tested here. -void __cpuidex (int[4], int, int); +IS_STATIC void __cpuidex (int[4], int, int); #include <cpuid.h> @@ -22,4 +20,3 @@ int cpuid_info[4]; void test_cpuidex(unsigned level, unsigned count) { __cpuidex(cpuid_info, level, count); } - diff --git a/clang/test/Sema/aarch64-sme-attrs-without-sve.cpp b/clang/test/Sema/aarch64-sme-attrs-without-sve.cpp new file mode 100644 index 0000000..cc6a841 --- /dev/null +++ b/clang/test/Sema/aarch64-sme-attrs-without-sve.cpp @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sme -fsyntax-only -verify %s + +// REQUIRES: aarch64-registered-target + +#include <arm_sme.h> + +void test_streaming(svint32_t *out, svint32_t *in) __arm_streaming { + *out = *in; +} + +void test_non_streaming(svint32_t *out, svint32_t *in) { + *out = *in; // expected-error {{SVE vector type 'svint32_t' (aka '__SVInt32_t') cannot be used in a non-streaming function}} \ + expected-error {{SVE vector type 'svint32_t' (aka '__SVInt32_t') cannot be used in a non-streaming function}} +} + +// This previously led to a diagnostic that '&a' could not be used in a non-streaming function, +// even though all functions are streaming. +void test_both_streaming(int32_t *out) __arm_streaming { + svint32_t a; + [&a, &out]() __arm_streaming { + a = svdup_s32(1); + svst1(svptrue_b32(), out, a); + }(); +} + +void test_lambda_streaming(int32_t *out) { + svint32_t a; // expected-error {{SVE vector type 'svint32_t' (aka '__SVInt32_t') cannot be used in a non-streaming function}} + [&a, &out]() __arm_streaming { + a = 1; + svst1(svptrue_b32(), out, a); + }(); +} + +void test_lambda_non_streaming_capture_do_nothing() __arm_streaming { + svint32_t a; + [&a] { + // Do nothing. + }(); +} + +// Error: Non-streaming function attempts to dereference capture: +void test_lambda_non_streaming_capture_return_vector() __arm_streaming { + svint32_t a; + [&a] { + return a; // expected-error {{SVE vector type 'svint32_t' (aka '__SVInt32_t') cannot be used in a non-streaming function}} + }(); +} + +// By reference capture, only records and uses the address of `a`: +// FIXME: This should be okay. +void test_lambda_non_streaming_capture_return_address() __arm_streaming { + svint32_t a; + [&a] { + return &a; // expected-error {{SVE vector type 'svint32_t' (aka '__SVInt32_t') cannot be used in a non-streaming function}} + }(); +} diff --git a/clang/test/Sema/constexpr-void-cast.c b/clang/test/Sema/constexpr-void-cast.c index 2ffc59f..cac671e 100644 --- a/clang/test/Sema/constexpr-void-cast.c +++ b/clang/test/Sema/constexpr-void-cast.c @@ -4,15 +4,16 @@ // RUN: %clang_cc1 -x c -fsyntax-only %s -pedantic -verify=c-pedantic -std=c11 -fexperimental-new-constant-interpreter // // RUN: %clang_cc1 -x c++ -fsyntax-only %s -verify=cxx -// RUN: %clang_cc1 -x c++ -fsyntax-only %s -pedantic -verify=cxx-pedantic +// RUN: %clang_cc1 -x c++ -fsyntax-only %s -pedantic -verify=cxx,cxx-pedantic // RUN: %clang_cc1 -x c++ -fsyntax-only %s -verify=cxx -fexperimental-new-constant-interpreter -// RUN: %clang_cc1 -x c++ -fsyntax-only %s -pedantic -verify=cxx-pedantic -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -x c++ -fsyntax-only %s -pedantic -verify=cxx,cxx-pedantic -fexperimental-new-constant-interpreter // c-no-diagnostics -// cxx-no-diagnostics void f(void); struct S {char c;} s; _Static_assert(&s != (void *)&f, ""); // c-pedantic-warning {{not an integer constant expression}} \ // c-pedantic-note {{this conversion is not allowed in a constant expression}} \ + // cxx-error {{static assertion expression is not an integral constant expression}} \ + // cxx-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} \ // cxx-pedantic-warning {{'_Static_assert' is a C11 extension}} diff --git a/clang/test/Sema/warn-unreachable_crash.cpp b/clang/test/Sema/warn-unreachable_crash.cpp index 628abcc..1955c2c 100644 --- a/clang/test/Sema/warn-unreachable_crash.cpp +++ b/clang/test/Sema/warn-unreachable_crash.cpp @@ -1,16 +1,33 @@ -// RUN: %clang_cc1 -verify -Wunreachable-code %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -verify -Wunreachable-code %s +// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -target-feature +fullfp16 -verify -Wunreachable-code %s +// REQUIRES: aarch64-registered-target -// Previously this test will crash -static void test(__fp16& x) { - if (x != 0 || x != 1.0) { // expected-note{{}} no-crash - x = 0.9; - } else - x = 0.8; // expected-warning{{code will never be executed}} +// ======= __fp16 version ======= +static void test_fp16(__fp16 &x) { + if (x != 0 || x != 1.0) { // expected-note {{}} no-crash + x = 0.9; + } else + x = 0.8; // expected-warning{{code will never be executed}} } -static void test2(__fp16& x) { - if (x != 1 && x == 1.0) { // expected-note{{}} no-crash - x = 0.9; // expected-warning{{code will never be executed}} - } else - x = 0.8; +static void test_fp16_b(__fp16 &x) { + if (x != 1 && x == 1.0) { // expected-note {{}} no-crash + x = 0.9; // expected-warning{{code will never be executed}} + } else + x = 0.8; +} + +// ======= _Float16 version ======= +static void test_f16(_Float16 &x) { + if (x != 0 || x != 1.0) { // expected-note {{}} no-crash + x = 0.9; + } else + x = 0.8; // expected-warning{{code will never be executed}} +} + +static void test_f16_b(_Float16 &x) { + if (x != 1 && x == 1.0) { // expected-note {{}} no-crash + x = 0.9; // expected-warning{{code will never be executed}} + } else + x = 0.8; } diff --git a/clang/test/SemaCXX/noreturn-weverything.c b/clang/test/SemaCXX/noreturn-weverything.c new file mode 100644 index 0000000..92a587d --- /dev/null +++ b/clang/test/SemaCXX/noreturn-weverything.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -fsyntax-only %s -Weverything + +void free(void *); +typedef void (*set_free_func)(void *); +struct Method { + int nparams; + int *param; +}; +void selelem_free_method(struct Method* method, void* data) { + set_free_func free_func = 0; + for (int i = 0; i < method->nparams; ++i) + free(&method->param[i]); + if (data && free_func) + free_func(data); +} diff --git a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp b/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp index 135865c..8b469dd2 100644 --- a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp +++ b/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp @@ -80,30 +80,21 @@ struct ImplicitlyCopyable { static_assert(__is_constructible(ImplicitlyCopyable, const ImplicitlyCopyable&)); -struct Movable { // #Movable +struct Movable { template <typename T> requires __is_constructible(Movable, T) // #err-self-constraint-1 - explicit Movable(T op) noexcept; // #Movable1 - Movable(Movable&&) noexcept = default; // #Movable2 + explicit Movable(T op) noexcept; // #1 + Movable(Movable&&) noexcept = default; // #2 }; static_assert(__is_constructible(Movable, Movable&&)); static_assert(__is_constructible(Movable, const Movable&)); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(Movable, const Movable &)'}} \ -// expected-error@-1 {{call to implicitly-deleted copy constructor of 'Movable'}} \ -// expected-note@#Movable {{'Movable' defined here}} \ -// expected-note@#Movable {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const Movable' for 1st argument}} \ -// expected-note@#Movable2 {{copy constructor is implicitly deleted because 'Movable' has a user-declared move constructor}} \ -// expected-note@#Movable2 {{candidate constructor not viable: no known conversion from 'int' to 'Movable' for 1st argument}} \ -// expected-note@#Movable1 {{candidate template ignored: constraints not satisfied [with T = int]}} - +// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(Movable, const Movable &)'}} static_assert(__is_constructible(Movable, int)); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(Movable, int)'}} \ -// expected-error@-1 {{no matching constructor for initialization of 'Movable'}} \ +// expected-error@-1{{static assertion failed due to requirement '__is_constructible(Movable, int)'}} \ // expected-note@-1 2{{}} // expected-error@#err-self-constraint-1{{satisfaction of constraint '__is_constructible(Movable, T)' depends on itself}} // expected-note@#err-self-constraint-1 4{{}} -// expected-note@#Movable {{'Movable' defined here}} template <typename T> struct Members { diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp index f3ddbbf..cf33ac2 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp +++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp @@ -42,14 +42,6 @@ static constexpr bool value = __is_standard_layout(T); }; template <typename T> constexpr bool is_standard_layout_v = __is_standard_layout(T); - -template <typename... Args> -struct is_constructible { - static constexpr bool value = __is_constructible(Args...); -}; - -template <typename... Args> -constexpr bool is_constructible_v = __is_constructible(Args...); #endif #ifdef STD2 @@ -105,17 +97,6 @@ template <typename T> using is_standard_layout = __details_is_standard_layout<T>; template <typename T> constexpr bool is_standard_layout_v = __is_standard_layout(T); - -template <typename... Args> -struct __details_is_constructible{ - static constexpr bool value = __is_constructible(Args...); -}; - -template <typename... Args> -using is_constructible = __details_is_constructible<Args...>; - -template <typename... Args> -constexpr bool is_constructible_v = __is_constructible(Args...); #endif @@ -168,15 +149,6 @@ template <typename T> using is_standard_layout = __details_is_standard_layout<T>; template <typename T> constexpr bool is_standard_layout_v = is_standard_layout<T>::value; - -template <typename... Args> -struct __details_is_constructible : bool_constant<__is_constructible(Args...)> {}; - -template <typename... Args> -using is_constructible = __details_is_constructible<Args...>; - -template <typename... Args> -constexpr bool is_constructible_v = is_constructible<Args...>::value; #endif } @@ -239,15 +211,6 @@ static_assert(std::is_assignable_v<int&, void>); // expected-error@-1 {{static assertion failed due to requirement 'std::is_assignable_v<int &, void>'}} \ // expected-error@-1 {{assigning to 'int' from incompatible type 'void'}} -static_assert(std::is_constructible<int, int>::value); - -static_assert(std::is_constructible<void>::value); -// expected-error-re@-1 {{static assertion failed due to requirement 'std::{{.*}}is_constructible<void>::value'}} \ -// expected-note@-1 {{because it is a cv void type}} -static_assert(std::is_constructible_v<void>); -// expected-error@-1 {{static assertion failed due to requirement 'std::is_constructible_v<void>'}} \ -// expected-note@-1 {{because it is a cv void type}} - namespace test_namespace { using namespace std; static_assert(is_trivially_relocatable<int&>::value); @@ -293,13 +256,6 @@ namespace test_namespace { // expected-error@-1 {{static assertion failed due to requirement 'is_empty_v<int &>'}} \ // expected-note@-1 {{'int &' is not empty}} \ // expected-note@-1 {{because it is a reference type}} - - static_assert(is_constructible<void>::value); - // expected-error-re@-1 {{static assertion failed due to requirement '{{.*}}is_constructible<void>::value'}} \ - // expected-note@-1 {{because it is a cv void type}} - static_assert(is_constructible_v<void>); - // expected-error@-1 {{static assertion failed due to requirement 'is_constructible_v<void>'}} \ - // expected-note@-1 {{because it is a cv void type}} } @@ -328,15 +284,6 @@ concept C4 = std::is_assignable_v<T, U>; // #concept8 template <C4<void> T> void g4(); // #cand8 -template <typename... Args> -requires std::is_constructible<Args...>::value void f3(); // #cand5 - -template <typename... Args> -concept C3 = std::is_constructible_v<Args...>; // #concept6 - -template <C3 T> void g3(); // #cand6 - - void test() { f<int&>(); // expected-error@-1 {{no matching function for call to 'f'}} \ @@ -380,19 +327,6 @@ void test() { // expected-note@#cand8 {{because 'C4<int &, void>' evaluated to false}} \ // expected-note@#concept8 {{because 'std::is_assignable_v<int &, void>' evaluated to false}} \ // expected-error@#concept8 {{assigning to 'int' from incompatible type 'void'}} - - f3<void>(); - // expected-error@-1 {{no matching function for call to 'f3'}} \ - // expected-note@#cand5 {{candidate template ignored: constraints not satisfied [with Args = <void>]}} \ - // expected-note-re@#cand5 {{because '{{.*}}is_constructible<void>::value' evaluated to false}} \ - // expected-note@#cand5 {{because it is a cv void type}} - - g3<void>(); - // expected-error@-1 {{no matching function for call to 'g3'}} \ - // expected-note@#cand6 {{candidate template ignored: constraints not satisfied [with T = void]}} \ - // expected-note@#cand6 {{because 'void' does not satisfy 'C3'}} \ - // expected-note@#concept6 {{because 'std::is_constructible_v<void>' evaluated to false}} \ - // expected-note@#concept6 {{because it is a cv void type}} } } diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp index 54806a9..cc923d2 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp +++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp @@ -489,68 +489,6 @@ static_assert(__is_trivially_copyable(S12)); // expected-note@#tc-S12 {{'S12' defined here}} } -namespace constructible { - -struct S1 { // #c-S1 - S1(int); // #cc-S1 -}; -static_assert(__is_constructible(S1, char*)); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(constructible::S1, char *)'}} \ -// expected-error@-1 {{no matching constructor for initialization of 'S1'}} \ -// expected-note@#c-S1 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'char *' to 'const S1' for 1st argument}} \ -// expected-note@#c-S1 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'char *' to 'S1' for 1st argument}} \ -// expected-note@#cc-S1 {{candidate constructor not viable: no known conversion from 'char *' to 'int' for 1st argument; dereference the argument with *}} \ -// expected-note@#c-S1 {{'S1' defined here}} - -struct S2 { // #c-S2 - S2(int, float, double); // #cc-S2 -}; -static_assert(__is_constructible(S2, float)); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(constructible::S2, float)'}} \ -// expected-note@#c-S2 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'float' to 'const S2' for 1st argument}} \ -// expected-note@#c-S2 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'float' to 'S2' for 1st argument}} \ -// expected-error@-1 {{no matching constructor for initialization of 'S2'}} \ -// expected-note@#cc-S2 {{candidate constructor not viable: requires 3 arguments, but 1 was provided}} \ -// expected-note@#c-S2 {{'S2' defined here}} - -static_assert(__is_constructible(S2, float, void)); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(constructible::S2, float, void)'}} \ -// expected-note@#c-S2 {{candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided}} \ -// expected-note@#c-S2 {{candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided}} \ -// expected-note@-1{{because it is a cv void type}} \ -// expected-error@-1 {{no matching constructor for initialization of 'S2'}} \ -// expected-note@#cc-S2 {{candidate constructor not viable: requires 3 arguments, but 2 were provided}} \ -// expected-note@#c-S2 {{'S2' defined here}} - -static_assert(__is_constructible(int[])); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(int[])'}} \ -// expected-note@-1 {{because it is an incomplete array type}} - -static_assert(__is_constructible(void)); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(void)'}} \ -// expected-note@-1 {{because it is a cv void type}} - -static_assert(__is_constructible(void, void)); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(void, void)'}} \ -// expected-note@-1 {{because it is a cv void type}} - -static_assert(__is_constructible(const void)); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(const void)'}} \ -// expected-note@-1 {{because it is a cv void type}} - -static_assert(__is_constructible(volatile void)); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(volatile void)'}} \ -// expected-note@-1 {{because it is a cv void type}} - -static_assert(__is_constructible(int ())); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(int ())'}} \ -// expected-note@-1 {{because it is a function type}} - -static_assert(__is_constructible(void (int, float))); -// expected-error@-1 {{static assertion failed due to requirement '__is_constructible(void (int, float))'}} \ -// expected-note@-1 {{because it is a function type}} -} - namespace assignable { struct S1; static_assert(__is_assignable(S1&, const S1&)); diff --git a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl index e9ba851..e9bf4c9 100644 --- a/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/D3DCOLORtoUBYTE4-errors.hlsl @@ -25,5 +25,5 @@ struct S { int4 struct_arg(S v) { return D3DCOLORtoUBYTE4(v); // expected-error@-1 {{no matching function for call to 'D3DCOLORtoUBYTE4'}} - // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: no known conversion from 'S' to 'vector<float, 4>' (vector of 4 'float' values) for 1st argument}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function not viable: no known conversion from 'S' to 'float4' (aka 'vector<float, 4>') for 1st argument}} } diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 663bc98..d63ad01 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1228,26 +1228,26 @@ template <KnownKind T> struct KnownType { } -namespace GH115838 { +namespace CWG2369_Regression_2 { -template<typename T> concept has_x = requires(T t) {{ t.x };}; - -class Publ { public: int x = 0; }; -class Priv { private: int x = 0; }; -class Prot { protected: int x = 0; }; -class Same { protected: int x = 0; }; - -template<typename T> class D; -template<typename T> requires ( has_x<T>) class D<T>: public T { public: static constexpr bool has = 1; }; -template<typename T> requires (!has_x<T>) class D<T>: public T { public: static constexpr bool has = 0; }; +template <typename T> +concept HasFastPropertyForAttribute = + requires(T element, int name) { element.propertyForAttribute(name); }; + +template <typename OwnerType> +struct SVGPropertyOwnerRegistry { + static int fastAnimatedPropertyLookup() { + static_assert (HasFastPropertyForAttribute<OwnerType>); + return 1; + } +}; -// "Same" is identical to "Prot" but queried before used. -static_assert(!has_x<Same>, "Protected should be invisible."); -static_assert(!D<Same>::has, "Protected should be invisible."); +class SVGCircleElement { + friend SVGPropertyOwnerRegistry<SVGCircleElement>; + void propertyForAttribute(int); +}; -static_assert( D<Publ>::has, "Public should be visible."); -static_assert(!D<Priv>::has, "Private should be invisible."); -static_assert(!D<Prot>::has, "Protected should be invisible."); +int i = SVGPropertyOwnerRegistry<SVGCircleElement>::fastAnimatedPropertyLookup(); } diff --git a/clang/tools/clang-format/ClangFormat.cpp b/clang/tools/clang-format/ClangFormat.cpp index 24ad3cb..afc40e9 100644 --- a/clang/tools/clang-format/ClangFormat.cpp +++ b/clang/tools/clang-format/ClangFormat.cpp @@ -237,8 +237,8 @@ static bool parseLineRange(StringRef Input, unsigned &FromLine, static bool fillRanges(MemoryBuffer *Code, std::vector<tooling::Range> &Ranges) { - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); FileManager Files(FileSystemOptions(), InMemoryFileSystem); DiagnosticOptions DiagOpts; DiagnosticsEngine Diagnostics( @@ -511,8 +511,8 @@ static bool format(StringRef FileName, bool ErrorOnIncompleteFormat = false) { if (OutputXML) { outputXML(Replaces, FormatChanges, Status, Cursor, CursorPosition); } else { - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); FileManager Files(FileSystemOptions(), InMemoryFileSystem); DiagnosticOptions DiagOpts; diff --git a/clang/tools/clang-import-test/clang-import-test.cpp b/clang/tools/clang-import-test/clang-import-test.cpp index 7f5df92..ab021a5 100644 --- a/clang/tools/clang-import-test/clang-import-test.cpp +++ b/clang/tools/clang-import-test/clang-import-test.cpp @@ -236,7 +236,7 @@ std::unique_ptr<CodeGenerator> BuildCodeGen(CompilerInstance &CI, llvm::LLVMContext &LLVMCtx) { StringRef ModuleName("$__module"); return std::unique_ptr<CodeGenerator>(CreateLLVMCodeGen( - CI.getDiagnostics(), ModuleName, &CI.getVirtualFileSystem(), + CI.getDiagnostics(), ModuleName, CI.getVirtualFileSystemPtr(), CI.getHeaderSearchOpts(), CI.getPreprocessorOpts(), CI.getCodeGenOpts(), LLVMCtx)); } diff --git a/clang/tools/clang-installapi/ClangInstallAPI.cpp b/clang/tools/clang-installapi/ClangInstallAPI.cpp index 60e9fc4..509934e 100644 --- a/clang/tools/clang-installapi/ClangInstallAPI.cpp +++ b/clang/tools/clang-installapi/ClangInstallAPI.cpp @@ -83,10 +83,11 @@ static bool run(ArrayRef<const char *> Args, const char *ProgName) { // Create file manager for all file operations and holding in-memory generated // inputs. - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem()); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); IntrusiveRefCntPtr<clang::FileManager> FM( new FileManager(clang::FileSystemOptions(), OverlayFileSystem)); diff --git a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp index 9d34b62..1d91f5f2 100644 --- a/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp +++ b/clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp @@ -474,10 +474,10 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, const ArgList &Args, StringRef Arch = Args.getLastArgValue(OPT_arch_EQ); // Create a new file to write the linked device image to. Assume that the // input filename already has the device and architecture. - auto TempFileOrErr = - createOutputFile(sys::path::filename(ExecutableName) + "." + - Triple.getArchName() + "." + Arch, - "img"); + std::string OutputFileBase = + "." + Triple.getArchName().str() + "." + Arch.str(); + auto TempFileOrErr = createOutputFile( + sys::path::filename(ExecutableName) + OutputFileBase, "img"); if (!TempFileOrErr) return TempFileOrErr.takeError(); @@ -486,6 +486,12 @@ Expected<StringRef> clang(ArrayRef<StringRef> InputFiles, const ArgList &Args, "--no-default-config", "-o", *TempFileOrErr, + // Without -dumpdir, Clang will place auxiliary output files in the + // temporary directory of TempFileOrErr, where they will not easily be + // found by the user and might eventually be automatically removed. Tell + // Clang to instead place them alongside the final executable. + "-dumpdir", + Args.MakeArgString(ExecutableName + OutputFileBase + ".img."), Args.MakeArgString("--target=" + Triple.getTriple()), }; diff --git a/clang/tools/clang-repl/CMakeLists.txt b/clang/tools/clang-repl/CMakeLists.txt index 68d86dd..c3d14ce 100644 --- a/clang/tools/clang-repl/CMakeLists.txt +++ b/clang/tools/clang-repl/CMakeLists.txt @@ -19,14 +19,14 @@ if(MSVC) set_target_properties(clang-repl PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS 1) # RTTI/C++ symbols - set(clang_repl_exports ${clang_repl_exports} ??_7type_info@@6B@ - ?__type_info_root_node@@3U__type_info_node@@A - ?nothrow@std@@3Unothrow_t@1@B + set(clang_repl_exports ${clang_repl_exports} ??_7type_info@@6B@,DATA + ?__type_info_root_node@@3U__type_info_node@@A,DATA + ?nothrow@std@@3Unothrow_t@1@B,DATA ) # Compiler added symbols for static variables. NOT for VStudio < 2015 - set(clang_repl_exports ${clang_repl_exports} _Init_thread_abort _Init_thread_epoch - _Init_thread_footer _Init_thread_header _tls_index + set(clang_repl_exports ${clang_repl_exports} _Init_thread_abort _Init_thread_epoch,DATA + _Init_thread_footer _Init_thread_header _tls_index,DATA ) if(CMAKE_SIZEOF_VOID_P EQUAL 8) @@ -50,7 +50,10 @@ if(MSVC) endif() # List to '/EXPORT:sym0 /EXPORT:sym1 /EXPORT:sym2 ...' - list(TRANSFORM clang_repl_exports PREPEND "LINKER:/EXPORT:") + # The 'SHELL' prefix tells CMake to use a space instead of comma as the + # separator between the driver and linker options, which we need since MSVC's + # linker uses `,DATA` as a suffix to indicate that data is being exported. + list(TRANSFORM clang_repl_exports PREPEND "LINKER:SHELL:/EXPORT:") set_property(TARGET clang-repl APPEND PROPERTY LINK_OPTIONS ${clang_repl_exports}) diff --git a/clang/unittests/Analysis/MacroExpansionContextTest.cpp b/clang/unittests/Analysis/MacroExpansionContextTest.cpp index 9874ea6..af7a8d6 100644 --- a/clang/unittests/Analysis/MacroExpansionContextTest.cpp +++ b/clang/unittests/Analysis/MacroExpansionContextTest.cpp @@ -33,7 +33,8 @@ namespace { class MacroExpansionContextTest : public ::testing::Test { protected: MacroExpansionContextTest() - : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), + : InMemoryFileSystem( + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()), FileMgr(FileSystemOptions(), InMemoryFileSystem), DiagID(new DiagnosticIDs()), Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), diff --git a/clang/unittests/Basic/FileManagerTest.cpp b/clang/unittests/Basic/FileManagerTest.cpp index 88d778f..7b3e8bc 100644 --- a/clang/unittests/Basic/FileManagerTest.cpp +++ b/clang/unittests/Basic/FileManagerTest.cpp @@ -454,8 +454,7 @@ TEST_F(FileManagerTest, makeAbsoluteUsesVFS) { : StringRef("/"); llvm::sys::path::append(CustomWorkingDir, "some", "weird", "path"); - auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>( - new llvm::vfs::InMemoryFileSystem); + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); // setCurrentworkingdirectory must finish without error. ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir)); @@ -475,8 +474,7 @@ TEST_F(FileManagerTest, makeAbsoluteUsesVFS) { TEST_F(FileManagerTest, getVirtualFileFillsRealPathName) { SmallString<64> CustomWorkingDir = getSystemRoot(); - auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>( - new llvm::vfs::InMemoryFileSystem); + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); // setCurrentworkingdirectory must finish without error. ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir)); @@ -501,8 +499,7 @@ TEST_F(FileManagerTest, getVirtualFileFillsRealPathName) { TEST_F(FileManagerTest, getFileDontOpenRealPath) { SmallString<64> CustomWorkingDir = getSystemRoot(); - auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>( - new llvm::vfs::InMemoryFileSystem); + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); // setCurrentworkingdirectory must finish without error. ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir)); @@ -533,8 +530,7 @@ TEST_F(FileManagerTest, getBypassFile) { CustomWorkingDir = "/"; #endif - auto FS = IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem>( - new llvm::vfs::InMemoryFileSystem); + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); // setCurrentworkingdirectory must finish without error. ASSERT_TRUE(!FS->setCurrentWorkingDirectory(CustomWorkingDir)); diff --git a/clang/unittests/Basic/SarifTest.cpp b/clang/unittests/Basic/SarifTest.cpp index ad9f8ec..c6be7ee 100644 --- a/clang/unittests/Basic/SarifTest.cpp +++ b/clang/unittests/Basic/SarifTest.cpp @@ -41,7 +41,8 @@ static std::string serializeSarifDocument(llvm::json::Object &&Doc) { class SarifDocumentWriterTest : public ::testing::Test { protected: SarifDocumentWriterTest() - : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), + : InMemoryFileSystem( + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()), FileMgr(FileSystemOptions(), InMemoryFileSystem), DiagID(new DiagnosticIDs()), Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), diff --git a/clang/unittests/CodeGen/TestCompiler.h b/clang/unittests/CodeGen/TestCompiler.h index a6fec7f..f6fada5 100644 --- a/clang/unittests/CodeGen/TestCompiler.h +++ b/clang/unittests/CodeGen/TestCompiler.h @@ -58,7 +58,7 @@ struct TestCompiler { CG.reset(CreateLLVMCodeGen( compiler.getDiagnostics(), "main-module", - &compiler.getVirtualFileSystem(), compiler.getHeaderSearchOpts(), + compiler.getVirtualFileSystemPtr(), compiler.getHeaderSearchOpts(), compiler.getPreprocessorOpts(), compiler.getCodeGenOpts(), Context)); } diff --git a/clang/unittests/Driver/DXCModeTest.cpp b/clang/unittests/Driver/DXCModeTest.cpp index f684593..3a2e9ec 100644 --- a/clang/unittests/Driver/DXCModeTest.cpp +++ b/clang/unittests/Driver/DXCModeTest.cpp @@ -57,8 +57,8 @@ static void validateTargetProfile( TEST(DxcModeTest, TargetProfileValidation) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); InMemoryFileSystem->addFile("foo.hlsl", 0, llvm::MemoryBuffer::getMemBuffer("\n")); @@ -107,8 +107,8 @@ TEST(DxcModeTest, TargetProfileValidation) { TEST(DxcModeTest, ValidatorVersionValidation) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); InMemoryFileSystem->addFile("foo.hlsl", 0, llvm::MemoryBuffer::getMemBuffer("\n")); @@ -210,8 +210,8 @@ TEST(DxcModeTest, ValidatorVersionValidation) { } TEST(DxcModeTest, DefaultEntry) { - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); InMemoryFileSystem->addFile("foo.hlsl", 0, llvm::MemoryBuffer::getMemBuffer("\n")); diff --git a/clang/unittests/Driver/SanitizerArgsTest.cpp b/clang/unittests/Driver/SanitizerArgsTest.cpp index b8bfc68..41884c0 100644 --- a/clang/unittests/Driver/SanitizerArgsTest.cpp +++ b/clang/unittests/Driver/SanitizerArgsTest.cpp @@ -78,8 +78,7 @@ protected: private: llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> prepareFS(llvm::ArrayRef<std::string> ExtraFiles) { - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS = - new llvm::vfs::InMemoryFileSystem; + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); FS->addFile(ClangBinary, time_t(), llvm::MemoryBuffer::getMemBuffer("")); FS->addFile(InputFile, time_t(), llvm::MemoryBuffer::getMemBuffer("")); for (llvm::StringRef F : ExtraFiles) diff --git a/clang/unittests/Driver/SimpleDiagnosticConsumer.h b/clang/unittests/Driver/SimpleDiagnosticConsumer.h index c3772ba..a90524c 100644 --- a/clang/unittests/Driver/SimpleDiagnosticConsumer.h +++ b/clang/unittests/Driver/SimpleDiagnosticConsumer.h @@ -44,8 +44,8 @@ struct SimpleDiagnosticConsumer : public clang::DiagnosticConsumer { inline clang::driver::Driver diagnostic_test_driver() { llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID( new clang::DiagnosticIDs()); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); auto *DiagConsumer = new SimpleDiagnosticConsumer; clang::DiagnosticOptions DiagOpts; clang::DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer); diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp index 670090a..03f2fcf 100644 --- a/clang/unittests/Driver/ToolChainTest.cpp +++ b/clang/unittests/Driver/ToolChainTest.cpp @@ -42,8 +42,8 @@ TEST(ToolChainTest, VFSGCCInstallation) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); const char *EmptyFiles[] = { "foo.cpp", @@ -140,8 +140,8 @@ TEST(ToolChainTest, VFSGCCInstallationRelativeDir) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, "clang LLVM compiler", InMemoryFileSystem); @@ -178,8 +178,8 @@ TEST(ToolChainTest, VFSSolarisMultiGCCInstallation) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); const char *EmptyFiles[] = { // Sort entries so the latest version doesn't come first. @@ -342,8 +342,8 @@ TEST(ToolChainTest, VFSGnuLibcxxPathNoSysroot) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); const char *EmptyFiles[] = { "foo.cpp", @@ -374,8 +374,8 @@ TEST(ToolChainTest, DefaultDriverMode) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, "clang LLVM compiler", InMemoryFileSystem); @@ -520,8 +520,8 @@ TEST(ToolChainTest, CommandOutput) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, "clang LLVM compiler", InMemoryFileSystem); @@ -548,8 +548,8 @@ TEST(ToolChainTest, PostCallback) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); // The executable path must not exist. Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, @@ -601,8 +601,8 @@ TEST(ToolChainTest, UEFIDefaultDebugFormatTest) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); Driver CCDriver("/home/test/bin/clang", "x86_64-unknown-uefi", Diags, "clang LLVM compiler", InMemoryFileSystem); CCDriver.setCheckInputsExist(false); @@ -643,8 +643,7 @@ TEST(ToolChainTest, ConfigFileSearch) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( - new llvm::vfs::InMemoryFileSystem); + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); #ifdef _WIN32 const char *TestRoot = "C:\\"; @@ -721,7 +720,7 @@ TEST(ToolChainTest, ConfigFileError) { std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer( new SimpleDiagnosticConsumer()); DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false); - IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS(new FileSystemWithError); + auto FS = llvm::makeIntrusiveRefCnt<FileSystemWithError>(); Driver TheDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, "clang LLVM compiler", FS); @@ -742,8 +741,7 @@ TEST(ToolChainTest, BadConfigFile) { std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer( new SimpleDiagnosticConsumer()); DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( - new llvm::vfs::InMemoryFileSystem); + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); #ifdef _WIN32 const char *TestRoot = "C:\\"; @@ -816,8 +814,7 @@ TEST(ToolChainTest, ConfigInexistentInclude) { std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer( new SimpleDiagnosticConsumer()); DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( - new llvm::vfs::InMemoryFileSystem); + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); #ifdef _WIN32 const char *TestRoot = "C:\\"; @@ -857,8 +854,7 @@ TEST(ToolChainTest, ConfigRecursiveInclude) { std::unique_ptr<SimpleDiagnosticConsumer> DiagConsumer( new SimpleDiagnosticConsumer()); DiagnosticsEngine Diags(DiagID, DiagOpts, DiagConsumer.get(), false); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( - new llvm::vfs::InMemoryFileSystem); + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); #ifdef _WIN32 const char *TestRoot = "C:\\"; @@ -902,8 +898,7 @@ TEST(ToolChainTest, NestedConfigFile) { IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; DiagnosticsEngine Diags(DiagID, DiagOpts, new TestDiagnosticConsumer); - IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( - new llvm::vfs::InMemoryFileSystem); + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); #ifdef _WIN32 const char *TestRoot = "C:\\"; diff --git a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp index 8681c3d..53b6dd8 100644 --- a/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp +++ b/clang/unittests/Format/IntegerLiteralSeparatorTest.cpp @@ -83,6 +83,9 @@ TEST_F(IntegerLiteralSeparatorTest, SingleQuoteAsSeparator) { "d = 5678_km;\n" "h = 0xDEF_u16;", Style); + + Style.Standard = FormatStyle::LS_Cpp11; + verifyFormat("ld = 1234L;", Style); } TEST_F(IntegerLiteralSeparatorTest, UnderscoreAsSeparator) { diff --git a/clang/unittests/Frontend/ASTUnitTest.cpp b/clang/unittests/Frontend/ASTUnitTest.cpp index afa64b5..7148ca0 100644 --- a/clang/unittests/Frontend/ASTUnitTest.cpp +++ b/clang/unittests/Frontend/ASTUnitTest.cpp @@ -119,8 +119,7 @@ TEST_F(ASTUnitTest, GetBufferForFileMemoryMapping) { } TEST_F(ASTUnitTest, ModuleTextualHeader) { - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFs = - new llvm::vfs::InMemoryFileSystem(); + auto InMemoryFs = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); InMemoryFs->addFile("test.cpp", 0, llvm::MemoryBuffer::getMemBuffer(R"cpp( #include "Textual.h" void foo() {} diff --git a/clang/unittests/Frontend/PCHPreambleTest.cpp b/clang/unittests/Frontend/PCHPreambleTest.cpp index faad408..d27f793 100644 --- a/clang/unittests/Frontend/PCHPreambleTest.cpp +++ b/clang/unittests/Frontend/PCHPreambleTest.cpp @@ -62,7 +62,7 @@ public: void TearDown() override {} void ResetVFS() { - VFS = new ReadCountingInMemoryFileSystem(); + VFS = llvm::makeIntrusiveRefCnt<ReadCountingInMemoryFileSystem>(); // We need the working directory to be set to something absolute, // otherwise it ends up being inadvertently set to the current // working directory in the real file system due to a series of diff --git a/clang/unittests/Frontend/ReparseWorkingDirTest.cpp b/clang/unittests/Frontend/ReparseWorkingDirTest.cpp index 1b8051f..38ef468 100644 --- a/clang/unittests/Frontend/ReparseWorkingDirTest.cpp +++ b/clang/unittests/Frontend/ReparseWorkingDirTest.cpp @@ -28,7 +28,9 @@ class ReparseWorkingDirTest : public ::testing::Test { std::shared_ptr<PCHContainerOperations> PCHContainerOpts; public: - void SetUp() override { VFS = new vfs::InMemoryFileSystem(); } + void SetUp() override { + VFS = llvm::makeIntrusiveRefCnt<vfs::InMemoryFileSystem>(); + } void TearDown() override {} void setWorkingDirectory(StringRef Path) { diff --git a/clang/unittests/Frontend/SearchPathTest.cpp b/clang/unittests/Frontend/SearchPathTest.cpp index c74a5c7..014f482 100644 --- a/clang/unittests/Frontend/SearchPathTest.cpp +++ b/clang/unittests/Frontend/SearchPathTest.cpp @@ -41,7 +41,7 @@ class SearchPathTest : public ::testing::Test { protected: SearchPathTest() : Diags(new DiagnosticIDs(), DiagOpts, new IgnoringDiagConsumer()), - VFS(new llvm::vfs::InMemoryFileSystem), + VFS(llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()), FileMgr(FileSystemOptions(), VFS), SourceMgr(Diags, FileMgr), Invocation(std::make_unique<CompilerInvocation>()) {} diff --git a/clang/unittests/Frontend/UtilsTest.cpp b/clang/unittests/Frontend/UtilsTest.cpp index cf385a5..fc411e4 100644 --- a/clang/unittests/Frontend/UtilsTest.cpp +++ b/clang/unittests/Frontend/UtilsTest.cpp @@ -29,7 +29,7 @@ TEST(BuildCompilerInvocationTest, RecoverMultipleJobs) { clang::DiagnosticOptions DiagOpts; CreateInvocationOptions Opts; Opts.RecoverOnError = true; - Opts.VFS = new llvm::vfs::InMemoryFileSystem(); + Opts.VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); Opts.Diags = clang::CompilerInstance::createDiagnostics(*Opts.VFS, DiagOpts, &D, false); std::unique_ptr<CompilerInvocation> CI = createInvocation(Args, Opts); diff --git a/clang/unittests/Lex/HeaderSearchTest.cpp b/clang/unittests/Lex/HeaderSearchTest.cpp index 9903c12..45eb855 100644 --- a/clang/unittests/Lex/HeaderSearchTest.cpp +++ b/clang/unittests/Lex/HeaderSearchTest.cpp @@ -28,8 +28,8 @@ namespace { class HeaderSearchTest : public ::testing::Test { protected: HeaderSearchTest() - : VFS(new llvm::vfs::InMemoryFileSystem), FileMgr(FileMgrOpts, VFS), - DiagID(new DiagnosticIDs()), + : VFS(llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()), + FileMgr(FileMgrOpts, VFS), DiagID(new DiagnosticIDs()), Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions), Search(HSOpts, SourceMgr, Diags, LangOpts, Target.get()) { diff --git a/clang/unittests/Lex/PPCallbacksTest.cpp b/clang/unittests/Lex/PPCallbacksTest.cpp index af86c18..a186246 100644 --- a/clang/unittests/Lex/PPCallbacksTest.cpp +++ b/clang/unittests/Lex/PPCallbacksTest.cpp @@ -133,7 +133,8 @@ public: class PPCallbacksTest : public ::testing::Test { protected: PPCallbacksTest() - : InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), + : InMemoryFileSystem( + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()), FileMgr(FileSystemOptions(), InMemoryFileSystem), DiagID(new DiagnosticIDs()), Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()), diff --git a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp index 061cb13..dec22a2 100644 --- a/clang/unittests/Lex/PPDependencyDirectivesTest.cpp +++ b/clang/unittests/Lex/PPDependencyDirectivesTest.cpp @@ -75,7 +75,7 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) { // "head2.h" and "head3.h" have tokens following the macro check, they should // be included multiple times. - auto VFS = new llvm::vfs::InMemoryFileSystem(); + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); VFS->addFile( "head1.h", 0, llvm::MemoryBuffer::getMemBuffer("#ifndef H1_H\n#define H1_H\n#endif\n")); diff --git a/clang/unittests/Support/TimeProfilerTest.cpp b/clang/unittests/Support/TimeProfilerTest.cpp index 85d36b5..f70149d 100644 --- a/clang/unittests/Support/TimeProfilerTest.cpp +++ b/clang/unittests/Support/TimeProfilerTest.cpp @@ -46,8 +46,7 @@ std::string teardownProfiler() { bool compileFromString(StringRef Code, StringRef Standard, StringRef File, llvm::StringMap<std::string> Headers = {}) { - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS( - new llvm::vfs::InMemoryFileSystem()); + auto FS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); FS->addFile(File, 0, MemoryBuffer::getMemBuffer(Code)); for (const auto &Header : Headers) { FS->addFile(Header.getKey(), 0, diff --git a/clang/unittests/Tooling/CompilationDatabaseTest.cpp b/clang/unittests/Tooling/CompilationDatabaseTest.cpp index c1febaf..2d68e09 100644 --- a/clang/unittests/Tooling/CompilationDatabaseTest.cpp +++ b/clang/unittests/Tooling/CompilationDatabaseTest.cpp @@ -971,7 +971,8 @@ TEST_F(TargetAndModeTest, TargetAndMode) { class ExpandResponseFilesTest : public MemDBTest { public: - ExpandResponseFilesTest() : FS(new llvm::vfs::InMemoryFileSystem) {} + ExpandResponseFilesTest() + : FS(llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()) {} protected: void addFile(StringRef File, StringRef Content) { diff --git a/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp index 1cdb539..b16dd8e 100644 --- a/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp +++ b/clang/unittests/Tooling/DependencyScanning/DependencyScannerTest.cpp @@ -85,7 +85,7 @@ TEST(DependencyScanner, ScanDepsReuseFilemanager) { StringRef CWD = "/root"; FixedCompilationDatabase CDB(CWD, Compilation); - auto VFS = new llvm::vfs::InMemoryFileSystem(); + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); VFS->setCurrentWorkingDirectory(CWD); auto Sept = llvm::sys::path::get_separator(); std::string HeaderPath = @@ -134,7 +134,7 @@ TEST(DependencyScanner, ScanDepsReuseFilemanagerSkippedFile) { StringRef CWD = "/root"; FixedCompilationDatabase CDB(CWD, Compilation); - auto VFS = new llvm::vfs::InMemoryFileSystem(); + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); VFS->setCurrentWorkingDirectory(CWD); auto Sept = llvm::sys::path::get_separator(); std::string HeaderPath = @@ -176,7 +176,7 @@ TEST(DependencyScanner, ScanDepsReuseFilemanagerHasInclude) { StringRef CWD = "/root"; FixedCompilationDatabase CDB(CWD, Compilation); - auto VFS = new llvm::vfs::InMemoryFileSystem(); + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); VFS->setCurrentWorkingDirectory(CWD); auto Sept = llvm::sys::path::get_separator(); std::string HeaderPath = @@ -218,7 +218,7 @@ TEST(DependencyScanner, ScanDepsWithFS) { "test.cpp.o"}; StringRef CWD = "/root"; - auto VFS = new llvm::vfs::InMemoryFileSystem(); + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); VFS->setCurrentWorkingDirectory(CWD); auto Sept = llvm::sys::path::get_separator(); std::string HeaderPath = @@ -256,7 +256,7 @@ TEST(DependencyScanner, ScanDepsWithModuleLookup) { }; StringRef CWD = "/root"; - auto VFS = new llvm::vfs::InMemoryFileSystem(); + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); VFS->setCurrentWorkingDirectory(CWD); auto Sept = llvm::sys::path::get_separator(); std::string OtherPath = @@ -306,7 +306,7 @@ TEST(DependencyScanner, ScanDepsWithModuleLookup) { TEST(DependencyScanner, ScanDepsWithDiagConsumer) { StringRef CWD = "/root"; - auto VFS = new llvm::vfs::InMemoryFileSystem(); + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); VFS->setCurrentWorkingDirectory(CWD); auto Sept = llvm::sys::path::get_separator(); std::string HeaderPath = diff --git a/clang/unittests/Tooling/RefactoringTest.cpp b/clang/unittests/Tooling/RefactoringTest.cpp index 35d1143..aff7523e 100644 --- a/clang/unittests/Tooling/RefactoringTest.cpp +++ b/clang/unittests/Tooling/RefactoringTest.cpp @@ -1035,8 +1035,7 @@ static constexpr bool usesWindowsPaths() { TEST(DeduplicateByFileTest, PathsWithDots) { std::map<std::string, Replacements> FileToReplaces; - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS( - new llvm::vfs::InMemoryFileSystem()); + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); FileManager FileMgr(FileSystemOptions(), VFS); StringRef Path1 = usesWindowsPaths() ? "a\\b\\..\\.\\c.h" : "a/b/.././c.h"; StringRef Path2 = usesWindowsPaths() ? "a\\c.h" : "a/c.h"; @@ -1051,8 +1050,7 @@ TEST(DeduplicateByFileTest, PathsWithDots) { TEST(DeduplicateByFileTest, PathWithDotSlash) { std::map<std::string, Replacements> FileToReplaces; - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS( - new llvm::vfs::InMemoryFileSystem()); + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); FileManager FileMgr(FileSystemOptions(), VFS); StringRef Path1 = usesWindowsPaths() ? ".\\a\\b\\c.h" : "./a/b/c.h"; StringRef Path2 = usesWindowsPaths() ? "a\\b\\c.h" : "a/b/c.h"; @@ -1067,8 +1065,7 @@ TEST(DeduplicateByFileTest, PathWithDotSlash) { TEST(DeduplicateByFileTest, NonExistingFilePath) { std::map<std::string, Replacements> FileToReplaces; - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS( - new llvm::vfs::InMemoryFileSystem()); + auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); FileManager FileMgr(FileSystemOptions(), VFS); StringRef Path1 = usesWindowsPaths() ? ".\\a\\b\\c.h" : "./a/b/c.h"; StringRef Path2 = usesWindowsPaths() ? "a\\b\\c.h" : "a/b/c.h"; diff --git a/clang/unittests/Tooling/RewriterTestContext.h b/clang/unittests/Tooling/RewriterTestContext.h index 2d697e2..c478b3f 100644 --- a/clang/unittests/Tooling/RewriterTestContext.h +++ b/clang/unittests/Tooling/RewriterTestContext.h @@ -51,9 +51,11 @@ class RewriterTestContext { RewriterTestContext() : Diagnostics(IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), DiagOpts), - InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem), + InMemoryFileSystem( + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()), OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())), + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem())), Files(FileSystemOptions(), OverlayFileSystem), Sources(Diagnostics, Files), Rewrite(Sources, Options) { Diagnostics.setClient(&DiagnosticPrinter, false); diff --git a/clang/unittests/Tooling/Syntax/TokensTest.cpp b/clang/unittests/Tooling/Syntax/TokensTest.cpp index b5f4445..a643738 100644 --- a/clang/unittests/Tooling/Syntax/TokensTest.cpp +++ b/clang/unittests/Tooling/Syntax/TokensTest.cpp @@ -252,7 +252,7 @@ public: llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags = new DiagnosticsEngine(new DiagnosticIDs, DiagOpts); IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS = - new llvm::vfs::InMemoryFileSystem; + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); llvm::IntrusiveRefCntPtr<FileManager> FileMgr = new FileManager(FileSystemOptions(), FS); llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr = diff --git a/clang/unittests/Tooling/Syntax/TreeTestBase.h b/clang/unittests/Tooling/Syntax/TreeTestBase.h index 6110cff..01ff07b 100644 --- a/clang/unittests/Tooling/Syntax/TreeTestBase.h +++ b/clang/unittests/Tooling/Syntax/TreeTestBase.h @@ -44,7 +44,7 @@ protected: IntrusiveRefCntPtr<DiagnosticsEngine> Diags = new DiagnosticsEngine(new DiagnosticIDs, DiagOpts); IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> FS = - new llvm::vfs::InMemoryFileSystem; + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); IntrusiveRefCntPtr<FileManager> FileMgr = new FileManager(FileSystemOptions(), FS); IntrusiveRefCntPtr<SourceManager> SourceMgr = diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp index 32af4b6..c72676f 100644 --- a/clang/unittests/Tooling/ToolingTest.cpp +++ b/clang/unittests/Tooling/ToolingTest.cpp @@ -153,8 +153,8 @@ TEST(buildASTFromCode, ReportsErrors) { } TEST(buildASTFromCode, FileSystem) { - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); InMemoryFileSystem->addFile("included_file.h", 0, llvm::MemoryBuffer::getMemBufferCopy("class X;")); std::unique_ptr<ASTUnit> AST = buildASTFromCodeWithArgs( @@ -188,10 +188,11 @@ TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) { } TEST(ToolInvocation, TestMapVirtualFile) { - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem()); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); llvm::IntrusiveRefCntPtr<FileManager> Files( new FileManager(FileSystemOptions(), OverlayFileSystem)); @@ -214,10 +215,11 @@ TEST(ToolInvocation, TestVirtualModulesCompilation) { // mapped module.modulemap is found on the include path. In the future, expand // this test to run a full modules enabled compilation, so we make sure we can // rerun modules compilations with a virtual file system. - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem()); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); llvm::IntrusiveRefCntPtr<FileManager> Files( new FileManager(FileSystemOptions(), OverlayFileSystem)); @@ -240,10 +242,11 @@ TEST(ToolInvocation, TestVirtualModulesCompilation) { } TEST(ToolInvocation, DiagnosticsEngineProperlyInitializedForCC1Construction) { - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem()); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); llvm::IntrusiveRefCntPtr<FileManager> Files( new FileManager(FileSystemOptions(), OverlayFileSystem)); @@ -269,10 +272,11 @@ TEST(ToolInvocation, DiagnosticsEngineProperlyInitializedForCC1Construction) { } TEST(ToolInvocation, CustomDiagnosticOptionsOverwriteParsedOnes) { - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem()); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); llvm::IntrusiveRefCntPtr<FileManager> Files( new FileManager(FileSystemOptions(), OverlayFileSystem)); @@ -315,10 +319,11 @@ struct DiagnosticConsumerExpectingSourceManager : public DiagnosticConsumer { }; TEST(ToolInvocation, DiagConsumerExpectingSourceManager) { - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem()); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); llvm::IntrusiveRefCntPtr<FileManager> Files( new FileManager(FileSystemOptions(), OverlayFileSystem)); @@ -341,10 +346,11 @@ TEST(ToolInvocation, DiagConsumerExpectingSourceManager) { } TEST(ToolInvocation, CC1Args) { - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem()); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); llvm::IntrusiveRefCntPtr<FileManager> Files( new FileManager(FileSystemOptions(), OverlayFileSystem)); @@ -361,10 +367,11 @@ TEST(ToolInvocation, CC1Args) { } TEST(ToolInvocation, CC1ArgsInvalid) { - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem()); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); llvm::IntrusiveRefCntPtr<FileManager> Files( new FileManager(FileSystemOptions(), OverlayFileSystem)); @@ -398,7 +405,7 @@ struct CommandLineExtractorTest : public ::testing::Test { public: CommandLineExtractorTest() - : InMemoryFS(new llvm::vfs::InMemoryFileSystem), + : InMemoryFS(llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()), Diags(CompilerInstance::createDiagnostics(*InMemoryFS, DiagOpts)), Driver("clang", llvm::sys::getDefaultTargetTriple(), *Diags, "clang LLVM compiler", overlayRealFS(InMemoryFS)) {} @@ -755,10 +762,11 @@ TEST(ClangToolTest, NoOutputCommands) { TEST(ClangToolTest, BaseVirtualFileSystemUsage) { FixedCompilationDatabase Compilations("/", std::vector<std::string>()); - llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFileSystem( - new llvm::vfs::OverlayFileSystem(llvm::vfs::getRealFileSystem())); - llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( - new llvm::vfs::InMemoryFileSystem); + auto OverlayFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>( + llvm::vfs::getRealFileSystem()); + auto InMemoryFileSystem = + llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>(); OverlayFileSystem->pushOverlay(InMemoryFileSystem); InMemoryFileSystem->addFile( diff --git a/clang/utils/TableGen/NeonEmitter.cpp b/clang/utils/TableGen/NeonEmitter.cpp index d4fb56e..89891fd 100644 --- a/clang/utils/TableGen/NeonEmitter.cpp +++ b/clang/utils/TableGen/NeonEmitter.cpp @@ -1401,14 +1401,12 @@ void Intrinsic::emitBodyAsBuiltinCall() { if (LocalCK == ClassB || (T.isHalf() && !T.isScalarForMangling())) { CastToType.makeInteger(8, true); Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")"; - } else if (LocalCK == ClassI) { - if (CastToType.isInteger()) { - CastToType.makeSigned(); - Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")"; - } + } else if (LocalCK == ClassI && + (CastToType.isInteger() || CastToType.isPoly())) { + CastToType.makeSigned(); + Arg = "__builtin_bit_cast(" + CastToType.str() + ", " + Arg + ")"; } } - S += Arg + ", "; } |