27 changes: 27 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -2741,6 +2741,33 @@ An error will be given if:
}];
}

def AMDGPUMaxNumWorkGroupsDocs : Documentation {
let Category = DocCatAMDGPUAttributes;
let Content = [{
This attribute specifies the max number of work groups when the kernel
is dispatched.

Clang supports the
``__attribute__((amdgpu_max_num_work_groups(<x>, <y>, <z>)))`` or
``[[clang::amdgpu_max_num_work_groups(<x>, <y>, <z>)]]`` attribute for the
AMDGPU target. This attribute may be attached to HIP or OpenCL kernel function
definitions and is an optimization hint.

The ``<x>`` parameter specifies the maximum number of work groups in the x dimension.
Similarly ``<y>`` and ``<z>`` are for the y and z dimensions respectively.
Each of the three values must be greater than 0 when provided. The ``<x>`` parameter
is required, while ``<y>`` and ``<z>`` are optional with default value of 1.

If specified, the AMDGPU target backend might be able to produce better machine
code.

An error will be given if:
- Specified values violate subtarget specifications;
- Specified values are not compatible with values provided through other
attributes.
}];
}

def DocCatCallingConvs : DocumentationCategory<"Calling Conventions"> {
let Content = [{
Clang supports several different calling conventions, depending on the target
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/InstallAPI/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "clang/InstallAPI/MachO.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/TextAPI/InterfaceFile.h"

namespace clang {
namespace installapi {
Expand All @@ -25,7 +25,7 @@ class FrontendRecordsSlice;
struct InstallAPIContext {

/// Library attributes that are typically passed as linker inputs.
llvm::MachO::RecordsSlice::BinaryAttrs BA;
BinaryAttrs BA;

/// All headers that represent a library.
HeaderSeq InputHeaders;
Expand All @@ -49,7 +49,7 @@ struct InstallAPIContext {
llvm::StringRef OutputLoc{};

/// What encoding to write output as.
llvm::MachO::FileType FT = llvm::MachO::FileType::TBD_V5;
FileType FT = FileType::TBD_V5;

/// Populate entries of headers that should be included for TextAPI
/// generation.
Expand Down
94 changes: 0 additions & 94 deletions clang/include/clang/InstallAPI/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,100 +25,6 @@
namespace clang {
namespace installapi {

using SymbolFlags = llvm::MachO::SymbolFlags;
using RecordLinkage = llvm::MachO::RecordLinkage;
using GlobalRecord = llvm::MachO::GlobalRecord;
using ObjCContainerRecord = llvm::MachO::ObjCContainerRecord;
using ObjCInterfaceRecord = llvm::MachO::ObjCInterfaceRecord;
using ObjCCategoryRecord = llvm::MachO::ObjCCategoryRecord;
using ObjCIVarRecord = llvm::MachO::ObjCIVarRecord;

// Represents a collection of frontend records for a library that are tied to a
// darwin target triple.
class FrontendRecordsSlice : public llvm::MachO::RecordsSlice {
public:
FrontendRecordsSlice(const llvm::Triple &T)
: llvm::MachO::RecordsSlice({T}) {}

/// Add non-ObjC global record with attributes from AST.
///
/// \param Name The name of symbol.
/// \param Linkage The linkage of symbol.
/// \param GV The kind of global.
/// \param Avail The availability information tied to the active target
/// triple.
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \param Flags The flags that describe attributes of the symbol.
/// \param Inlined Whether declaration is inlined, only applicable to
/// functions.
/// \return The non-owning pointer to added record in slice.
GlobalRecord *addGlobal(StringRef Name, RecordLinkage Linkage,
GlobalRecord::Kind GV,
const clang::AvailabilityInfo Avail, const Decl *D,
const HeaderType Access,
SymbolFlags Flags = SymbolFlags::None,
bool Inlined = false);

/// Add ObjC Class record with attributes from AST.
///
/// \param Name The name of class, not symbol.
/// \param Linkage The linkage of symbol.
/// \param Avail The availability information tied to the active target
/// triple.
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \param IsEHType Whether declaration has an exception attribute.
/// \return The non-owning pointer to added record in slice.
ObjCInterfaceRecord *addObjCInterface(StringRef Name, RecordLinkage Linkage,
const clang::AvailabilityInfo Avail,
const Decl *D, HeaderType Access,
bool IsEHType);

/// Add ObjC Category record with attributes from AST.
///
/// \param ClassToExtend The name of class that is extended by category, not
/// symbol.
/// \param CategoryName The name of category, not symbol.
/// \param Avail The availability information tied
/// to the active target triple.
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \return The non-owning pointer to added record in slice.
ObjCCategoryRecord *addObjCCategory(StringRef ClassToExtend,
StringRef CategoryName,
const clang::AvailabilityInfo Avail,
const Decl *D, HeaderType Access);

/// Add ObjC IVar record with attributes from AST.
///
/// \param Container The owning pointer for instance variable.
/// \param Name The name of ivar, not symbol.
/// \param Linkage The linkage of symbol.
/// \param Avail The availability information tied to the active target
/// triple.
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \param AC The access control tied to the ivar declaration.
/// \return The non-owning pointer to added record in slice.
ObjCIVarRecord *addObjCIVar(ObjCContainerRecord *Container,
StringRef IvarName, RecordLinkage Linkage,
const clang::AvailabilityInfo Avail,
const Decl *D, HeaderType Access,
const clang::ObjCIvarDecl::AccessControl AC);

private:
/// Frontend information captured about records.
struct FrontendAttrs {
const AvailabilityInfo Avail;
const Decl *D;
const HeaderType Access;
};

/// Mapping of records stored in slice to their frontend attributes.
llvm::DenseMap<llvm::MachO::Record *, FrontendAttrs> FrontendRecords;
};

/// Create a buffer that contains all headers to scan
/// for global symbols with.
std::unique_ptr<llvm::MemoryBuffer> createInputBuffer(InstallAPIContext &Ctx);
Expand Down
108 changes: 108 additions & 0 deletions clang/include/clang/InstallAPI/FrontendRecords.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
//===- InstallAPI/FrontendRecords.h ------------------------------*- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_INSTALLAPI_FRONTENDRECORDS_H
#define LLVM_CLANG_INSTALLAPI_FRONTENDRECORDS_H

#include "clang/AST/Availability.h"
#include "clang/AST/DeclObjC.h"
#include "clang/InstallAPI/MachO.h"

namespace clang {
namespace installapi {

/// Frontend information captured about records.
struct FrontendAttrs {
const AvailabilityInfo Avail;
const Decl *D;
const HeaderType Access;
};

// Represents a collection of frontend records for a library that are tied to a
// darwin target triple.
class FrontendRecordsSlice : public llvm::MachO::RecordsSlice {
public:
FrontendRecordsSlice(const llvm::Triple &T)
: llvm::MachO::RecordsSlice({T}) {}

/// Add non-ObjC global record with attributes from AST.
///
/// \param Name The name of symbol.
/// \param Linkage The linkage of symbol.
/// \param GV The kind of global.
/// \param Avail The availability information tied to the active target
/// triple.
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \param Flags The flags that describe attributes of the symbol.
/// \param Inlined Whether declaration is inlined, only applicable to
/// functions.
/// \return The non-owning pointer to added record in slice.
GlobalRecord *addGlobal(StringRef Name, RecordLinkage Linkage,
GlobalRecord::Kind GV,
const clang::AvailabilityInfo Avail, const Decl *D,
const HeaderType Access,
SymbolFlags Flags = SymbolFlags::None,
bool Inlined = false);

/// Add ObjC Class record with attributes from AST.
///
/// \param Name The name of class, not symbol.
/// \param Linkage The linkage of symbol.
/// \param Avail The availability information tied to the active target
/// triple.
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \param IsEHType Whether declaration has an exception attribute.
/// \return The non-owning pointer to added record in slice.
ObjCInterfaceRecord *addObjCInterface(StringRef Name, RecordLinkage Linkage,
const clang::AvailabilityInfo Avail,
const Decl *D, HeaderType Access,
bool IsEHType);

/// Add ObjC Category record with attributes from AST.
///
/// \param ClassToExtend The name of class that is extended by category, not
/// symbol.
/// \param CategoryName The name of category, not symbol.
/// \param Avail The availability information tied
/// to the active target triple.
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \return The non-owning pointer to added record in slice.
ObjCCategoryRecord *addObjCCategory(StringRef ClassToExtend,
StringRef CategoryName,
const clang::AvailabilityInfo Avail,
const Decl *D, HeaderType Access);

/// Add ObjC IVar record with attributes from AST.
///
/// \param Container The owning pointer for instance variable.
/// \param Name The name of ivar, not symbol.
/// \param Linkage The linkage of symbol.
/// \param Avail The availability information tied to the active target
/// triple.
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \param AC The access control tied to the ivar declaration.
/// \return The non-owning pointer to added record in slice.
ObjCIVarRecord *addObjCIVar(ObjCContainerRecord *Container,
StringRef IvarName, RecordLinkage Linkage,
const clang::AvailabilityInfo Avail,
const Decl *D, HeaderType Access,
const clang::ObjCIvarDecl::AccessControl AC);

private:
/// Mapping of records stored in slice to their frontend attributes.
llvm::DenseMap<Record *, FrontendAttrs> FrontendRecords;
};

} // namespace installapi
} // namespace clang

#endif // LLVM_CLANG_INSTALLAPI_FRONTENDRECORDS_H
40 changes: 40 additions & 0 deletions clang/include/clang/InstallAPI/MachO.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//===- InstallAPI/MachO.h ---------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Imports and forward declarations for llvm::MachO types.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_INSTALLAPI_MACHO_H
#define LLVM_CLANG_INSTALLAPI_MACHO_H

#include "llvm/TextAPI/Architecture.h"
#include "llvm/TextAPI/InterfaceFile.h"
#include "llvm/TextAPI/PackedVersion.h"
#include "llvm/TextAPI/Platform.h"
#include "llvm/TextAPI/RecordVisitor.h"
#include "llvm/TextAPI/Target.h"
#include "llvm/TextAPI/TextAPIWriter.h"
#include "llvm/TextAPI/Utils.h"

using SymbolFlags = llvm::MachO::SymbolFlags;
using RecordLinkage = llvm::MachO::RecordLinkage;
using Record = llvm::MachO::Record;
using GlobalRecord = llvm::MachO::GlobalRecord;
using ObjCContainerRecord = llvm::MachO::ObjCContainerRecord;
using ObjCInterfaceRecord = llvm::MachO::ObjCInterfaceRecord;
using ObjCCategoryRecord = llvm::MachO::ObjCCategoryRecord;
using ObjCIVarRecord = llvm::MachO::ObjCIVarRecord;
using Records = llvm::MachO::Records;
using BinaryAttrs = llvm::MachO::RecordsSlice::BinaryAttrs;
using SymbolSet = llvm::MachO::SymbolSet;
using FileType = llvm::MachO::FileType;
using PackedVersion = llvm::MachO::PackedVersion;
using Target = llvm::MachO::Target;

#endif // LLVM_CLANG_INSTALLAPI_MACHO_H
9 changes: 8 additions & 1 deletion clang/include/clang/Interpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ class Interpreter {
// An optional parser for CUDA offloading
std::unique_ptr<IncrementalParser> DeviceParser;

llvm::Error CreateExecutor();
unsigned InitPTUSize = 0;

// This member holds the last result of the value printing. It's a class
Expand All @@ -114,6 +113,14 @@ class Interpreter {
// That's useful for testing and out-of-tree clients.
Interpreter(std::unique_ptr<CompilerInstance> CI, llvm::Error &Err);

// Create the internal IncrementalExecutor, or re-create it after calling
// ResetExecutor().
llvm::Error CreateExecutor();

// Delete the internal IncrementalExecutor. This causes a hard shutdown of the
// JIT engine. In particular, it doesn't run cleanup or destructors.
void ResetExecutor();

// Lazily construct the RuntimeInterfaceBuilder. The provided instance will be
// used for the entire lifetime of the interpreter. The default implementation
// targets the in-process __clang_Interpreter runtime. Override this to use a
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -3911,6 +3911,16 @@ class Sema final {
void addAMDGPUWavesPerEUAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *Min, Expr *Max);

/// Create an AMDGPUMaxNumWorkGroupsAttr attribute.
AMDGPUMaxNumWorkGroupsAttr *
CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI, Expr *XExpr,
Expr *YExpr, Expr *ZExpr);

/// addAMDGPUMaxNumWorkGroupsAttr - Adds an amdgpu_max_num_work_groups
/// attribute to a particular declaration.
void addAMDGPUMaxNumWorkGroupsAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *XExpr, Expr *YExpr, Expr *ZExpr);

DLLImportAttr *mergeDLLImportAttr(Decl *D, const AttributeCommonInfo &CI);
DLLExportAttr *mergeDLLExportAttr(Decl *D, const AttributeCommonInfo &CI);
MSInheritanceAttr *mergeMSInheritanceAttr(Decl *D,
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class ExplodedNodeSet;
class ExprEngine;
struct EvalCallOptions;
class MemRegion;
struct NodeBuilderContext;
class NodeBuilderContext;
class ObjCMethodCall;
class RegionAndSymbolInvalidationTraits;
class SVal;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class CoreEngine {
friend class ExprEngine;
friend class IndirectGotoNodeBuilder;
friend class NodeBuilder;
friend struct NodeBuilderContext;
friend class NodeBuilderContext;
friend class SwitchNodeBuilder;

public:
Expand Down Expand Up @@ -193,12 +193,12 @@ class CoreEngine {
DataTag::Factory &getDataTags() { return DataTags; }
};

// TODO: Turn into a class.
struct NodeBuilderContext {
class NodeBuilderContext {
const CoreEngine &Eng;
const CFGBlock *Block;
const LocationContext *LC;

public:
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B,
const LocationContext *L)
: Eng(E), Block(B), LC(L) {
Expand All @@ -208,9 +208,15 @@ struct NodeBuilderContext {
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
: NodeBuilderContext(E, B, N->getLocationContext()) {}

/// Return the CoreEngine associated with this builder.
const CoreEngine &getEngine() const { return Eng; }

/// Return the CFGBlock associated with this builder.
const CFGBlock *getBlock() const { return Block; }

/// Return the location context associated with this builder.
const LocationContext *getLocationContext() const { return LC; }

/// Returns the number of times the current basic block has been
/// visited on the exploded graph path.
unsigned blockCount() const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class ExplodedNodeSet;
class ExplodedNode;
class IndirectGotoNodeBuilder;
class MemRegion;
struct NodeBuilderContext;
class NodeBuilderContext;
class NodeBuilderWithSinks;
class ProgramState;
class ProgramStateManager;
Expand Down
13 changes: 8 additions & 5 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,14 @@ namespace {
}

QualType Expr::getEnumCoercedType(const ASTContext &Ctx) const {
if (isa<EnumType>(this->getType()))
return this->getType();
else if (const auto *ECD = this->getEnumConstantDecl())
return Ctx.getTypeDeclType(cast<EnumDecl>(ECD->getDeclContext()));
return this->getType();
if (isa<EnumType>(getType()))
return getType();
if (const auto *ECD = getEnumConstantDecl()) {
const auto *ED = cast<EnumDecl>(ECD->getDeclContext());
if (ED->isCompleteDefinition())
return Ctx.getTypeDeclType(ED);
}
return getType();
}

SourceLocation Expr::getExprLoc() const {
Expand Down
105 changes: 93 additions & 12 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2959,6 +2959,8 @@ bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
const Expr *SubExpr = E->getSubExpr();
if (SubExpr->getType()->isAnyComplexType())
return this->VisitComplexUnaryOperator(E);
std::optional<PrimType> T = classify(SubExpr->getType());

switch (E->getOpcode()) {
Expand Down Expand Up @@ -3109,16 +3111,97 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
return false;
return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
case UO_Real: // __real x
if (T)
return this->delegate(SubExpr);
return this->emitComplexReal(SubExpr);
assert(T);
return this->delegate(SubExpr);
case UO_Imag: { // __imag x
if (T) {
if (!this->discard(SubExpr))
assert(T);
if (!this->discard(SubExpr))
return false;
return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
}
case UO_Extension:
return this->delegate(SubExpr);
case UO_Coawait:
assert(false && "Unhandled opcode");
}

return false;
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator(
const UnaryOperator *E) {
const Expr *SubExpr = E->getSubExpr();
assert(SubExpr->getType()->isAnyComplexType());

if (DiscardResult)
return this->discard(SubExpr);

std::optional<PrimType> ResT = classify(E);
auto prepareResult = [=]() -> bool {
if (!ResT && !Initializing) {
std::optional<unsigned> LocalIndex =
allocateLocal(SubExpr, /*IsExtended=*/false);
if (!LocalIndex)
return false;
return this->emitGetPtrLocal(*LocalIndex, E);
}

return true;
};

// The offset of the temporary, if we created one.
unsigned SubExprOffset = ~0u;
auto createTemp = [=, &SubExprOffset]() -> bool {
SubExprOffset = this->allocateLocalPrimitive(SubExpr, PT_Ptr, true, false);
if (!this->visit(SubExpr))
return false;
return this->emitSetLocal(PT_Ptr, SubExprOffset, E);
};

PrimType ElemT = classifyComplexElementType(SubExpr->getType());
auto getElem = [=](unsigned Offset, unsigned Index) -> bool {
if (!this->emitGetLocal(PT_Ptr, Offset, E))
return false;
return this->emitArrayElemPop(ElemT, Index, E);
};

switch (E->getOpcode()) {
case UO_Minus:
if (!prepareResult())
return false;
if (!createTemp())
return false;
for (unsigned I = 0; I != 2; ++I) {
if (!getElem(SubExprOffset, I))
return false;
if (!this->emitNeg(ElemT, E))
return false;
if (!this->emitInitElem(ElemT, I, E))
return false;
return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
}
break;

case UO_Plus: // +x
case UO_AddrOf: // &x
case UO_Deref: // *x
return this->delegate(SubExpr);

case UO_LNot:
if (!this->visit(SubExpr))
return false;
if (!this->emitComplexBoolCast(SubExpr))
return false;
if (!this->emitInvBool(E))
return false;
if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)
return this->emitCast(PT_Bool, ET, E);
return true;

case UO_Real:
return this->emitComplexReal(SubExpr);

case UO_Imag:
if (!this->visit(SubExpr))
return false;

Expand All @@ -3131,14 +3214,12 @@ bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
// Since our _Complex implementation does not map to a primitive type,
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E);
}
case UO_Extension:
return this->delegate(SubExpr);
case UO_Coawait:
assert(false && "Unhandled opcode");

default:
return this->emitInvalid(E);
}

return false;
return true;
}

template <class Emitter>
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitGNUNullExpr(const GNUNullExpr *E);
bool VisitCXXThisExpr(const CXXThisExpr *E);
bool VisitUnaryOperator(const UnaryOperator *E);
bool VisitComplexUnaryOperator(const UnaryOperator *E);
bool VisitDeclRefExpr(const DeclRefExpr *E);
bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E);
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Basic/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,12 @@ int clang::hasAttribute(AttributeCommonInfo::Syntax Syntax,
// attributes. We support those, but not through the typical attribute
// machinery that goes through TableGen. We support this in all OpenMP modes
// so long as double square brackets are enabled.
if (LangOpts.OpenMP && ScopeName == "omp")
return (Name == "directive" || Name == "sequence") ? 1 : 0;
//
// Other OpenMP attributes (e.g. [[omp::assume]]) are handled via the
// regular attribute parsing machinery.
if (LangOpts.OpenMP && ScopeName == "omp" &&
(Name == "directive" || Name == "sequence"))
return 1;

int res = hasAttributeImpl(Syntax, Name, ScopeName, Target, LangOpts);
if (res)
Expand Down
96 changes: 59 additions & 37 deletions clang/lib/CodeGen/CGAtomic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,12 +194,14 @@ namespace {
RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot,
SourceLocation loc, bool AsValue) const;

/// Converts a rvalue to integer value.
llvm::Value *convertRValueToInt(RValue RVal) const;
llvm::Value *getScalarRValValueOrNull(RValue RVal) const;

RValue ConvertIntToValueOrAtomic(llvm::Value *IntVal,
AggValueSlot ResultSlot,
SourceLocation Loc, bool AsValue) const;
/// Converts an rvalue to integer value if needed.
llvm::Value *convertRValueToInt(RValue RVal, bool CastFP = true) const;

RValue ConvertToValueOrAtomic(llvm::Value *IntVal, AggValueSlot ResultSlot,
SourceLocation Loc, bool AsValue,
bool CastFP = true) const;

/// Copy an atomic r-value into atomic-layout memory.
void emitCopyIntoMemory(RValue rvalue) const;
Expand Down Expand Up @@ -261,7 +263,8 @@ namespace {
void EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
llvm::AtomicOrdering AO, bool IsVolatile);
/// Emits atomic load as LLVM instruction.
llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile);
llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile,
bool CastFP = true);
/// Emits atomic compare-and-exchange op as a libcall.
llvm::Value *EmitAtomicCompareExchangeLibcall(
llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,
Expand Down Expand Up @@ -1396,12 +1399,13 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
LVal.getBaseInfo(), TBAAAccessInfo()));
}

RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
AggValueSlot ResultSlot,
SourceLocation Loc,
bool AsValue) const {
RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val,
AggValueSlot ResultSlot,
SourceLocation Loc, bool AsValue,
bool CastFP) const {
// Try not to in some easy cases.
assert(IntVal->getType()->isIntegerTy() && "Expected integer value");
assert((Val->getType()->isIntegerTy() || Val->getType()->isIEEELikeFPTy()) &&
"Expected integer or floating point value");
if (getEvaluationKind() == TEK_Scalar &&
(((!LVal.isBitField() ||
LVal.getBitFieldInfo().Size == ValueSizeInBits) &&
Expand All @@ -1410,13 +1414,14 @@ RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
auto *ValTy = AsValue
? CGF.ConvertTypeForMem(ValueTy)
: getAtomicAddress().getElementType();
if (ValTy->isIntegerTy()) {
assert(IntVal->getType() == ValTy && "Different integer types.");
return RValue::get(CGF.EmitFromMemory(IntVal, ValueTy));
if (ValTy->isIntegerTy() || (!CastFP && ValTy->isIEEELikeFPTy())) {
assert((!ValTy->isIntegerTy() || Val->getType() == ValTy) &&
"Different integer types.");
return RValue::get(CGF.EmitFromMemory(Val, ValueTy));
} else if (ValTy->isPointerTy())
return RValue::get(CGF.Builder.CreateIntToPtr(IntVal, ValTy));
else if (llvm::CastInst::isBitCastable(IntVal->getType(), ValTy))
return RValue::get(CGF.Builder.CreateBitCast(IntVal, ValTy));
return RValue::get(CGF.Builder.CreateIntToPtr(Val, ValTy));
else if (llvm::CastInst::isBitCastable(Val->getType(), ValTy))
return RValue::get(CGF.Builder.CreateBitCast(Val, ValTy));
}

// Create a temporary. This needs to be big enough to hold the
Expand All @@ -1433,8 +1438,7 @@ RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,

// Slam the integer into the temporary.
Address CastTemp = castToAtomicIntPointer(Temp);
CGF.Builder.CreateStore(IntVal, CastTemp)
->setVolatile(TempIsVolatile);
CGF.Builder.CreateStore(Val, CastTemp)->setVolatile(TempIsVolatile);

return convertAtomicTempToRValue(Temp, ResultSlot, Loc, AsValue);
}
Expand All @@ -1453,9 +1457,11 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
}

llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,
bool IsVolatile) {
bool IsVolatile, bool CastFP) {
// Okay, we're doing this natively.
Address Addr = getAtomicAddressAsAtomicIntPointer();
Address Addr = getAtomicAddress();
if (!(Addr.getElementType()->isIEEELikeFPTy() && !CastFP))
Addr = castToAtomicIntPointer(Addr);
llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load");
Load->setAtomic(AO);

Expand Down Expand Up @@ -1515,15 +1521,16 @@ RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
}

// Okay, we're doing this natively.
auto *Load = EmitAtomicLoadOp(AO, IsVolatile);
auto *Load = EmitAtomicLoadOp(AO, IsVolatile, /*CastFP=*/false);

// If we're ignoring an aggregate return, don't do anything.
if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored())
return RValue::getAggregate(Address::invalid(), false);

// Okay, turn that back into the original value or atomic (for non-simple
// lvalues) type.
return ConvertIntToValueOrAtomic(Load, ResultSlot, Loc, AsValue);
return ConvertToValueOrAtomic(Load, ResultSlot, Loc, AsValue,
/*CastFP=*/false);
}

/// Emit a load from an l-value of atomic type. Note that the r-value
Expand Down Expand Up @@ -1586,12 +1593,18 @@ Address AtomicInfo::materializeRValue(RValue rvalue) const {
return TempLV.getAddress(CGF);
}

llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal) const {
llvm::Value *AtomicInfo::getScalarRValValueOrNull(RValue RVal) const {
if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple()))
return RVal.getScalarVal();
return nullptr;
}

llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal, bool CastFP) const {
// If we've got a scalar value of the right size, try to avoid going
// through memory.
if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple())) {
llvm::Value *Value = RVal.getScalarVal();
if (isa<llvm::IntegerType>(Value->getType()))
// through memory. Floats get casted if needed by AtomicExpandPass.
if (llvm::Value *Value = getScalarRValValueOrNull(RVal)) {
if (isa<llvm::IntegerType>(Value->getType()) ||
(!CastFP && Value->getType()->isIEEELikeFPTy()))
return CGF.EmitToMemory(Value, ValueTy);
else {
llvm::IntegerType *InputIntTy = llvm::IntegerType::get(
Expand Down Expand Up @@ -1677,8 +1690,8 @@ std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,
Failure, IsWeak);
return std::make_pair(
ConvertIntToValueOrAtomic(Res.first, AggValueSlot::ignored(),
SourceLocation(), /*AsValue=*/false),
ConvertToValueOrAtomic(Res.first, AggValueSlot::ignored(),
SourceLocation(), /*AsValue=*/false),
Res.second);
}

Expand Down Expand Up @@ -1787,8 +1800,8 @@ void AtomicInfo::EmitAtomicUpdateOp(
requiresMemSetZero(getAtomicAddress().getElementType())) {
CGF.Builder.CreateStore(PHI, NewAtomicIntAddr);
}
auto OldRVal = ConvertIntToValueOrAtomic(PHI, AggValueSlot::ignored(),
SourceLocation(), /*AsValue=*/false);
auto OldRVal = ConvertToValueOrAtomic(PHI, AggValueSlot::ignored(),
SourceLocation(), /*AsValue=*/false);
EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr);
auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr);
// Try to write new value using cmpxchg operation.
Expand Down Expand Up @@ -1953,13 +1966,22 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
}

// Okay, we're doing this natively.
llvm::Value *intValue = atomics.convertRValueToInt(rvalue);
llvm::Value *ValToStore =
atomics.convertRValueToInt(rvalue, /*CastFP=*/false);

// Do the atomic store.
Address addr = atomics.castToAtomicIntPointer(atomics.getAtomicAddress());
intValue = Builder.CreateIntCast(
intValue, addr.getElementType(), /*isSigned=*/false);
llvm::StoreInst *store = Builder.CreateStore(intValue, addr);
Address Addr = atomics.getAtomicAddress();
bool ShouldCastToInt = true;
if (llvm::Value *Value = atomics.getScalarRValValueOrNull(rvalue))
if (isa<llvm::IntegerType>(Value->getType()) ||
Value->getType()->isIEEELikeFPTy())
ShouldCastToInt = false;
if (ShouldCastToInt) {
Addr = atomics.castToAtomicIntPointer(Addr);
ValToStore = Builder.CreateIntCast(ValToStore, Addr.getElementType(),
/*isSigned=*/false);
}
llvm::StoreInst *store = Builder.CreateStore(ValToStore, Addr);

if (AO == llvm::AtomicOrdering::Acquire)
AO = llvm::AtomicOrdering::Monotonic;
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5460,7 +5460,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
}

// OpenCL v2.0, s6.13.17 - Enqueue kernel function.
// It contains four different overload formats specified in Table 6.13.17.1.
// Table 6.13.17.1 specifies four overload forms of enqueue_kernel.
// The code below expands the builtin call to a call to one of the following
// functions that an OpenCL runtime library will have to provide:
// __enqueue_kernel_basic
// __enqueue_kernel_varargs
// __enqueue_kernel_basic_events
// __enqueue_kernel_events_varargs
case Builtin::BIenqueue_kernel: {
StringRef Name; // Generated function call name
unsigned NumArgs = E->getNumArgs();
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2647,6 +2647,9 @@ void CGOpenMPRuntime::emitDistributeStaticInit(
void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF,
SourceLocation Loc,
OpenMPDirectiveKind DKind) {
assert(DKind == OMPD_distribute || DKind == OMPD_for ||
DKind == OMPD_sections &&
"Expected distribute, for, or sections directive kind");
if (!CGF.HaveInsertPoint())
return;
// Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid);
Expand Down
15 changes: 9 additions & 6 deletions clang/lib/CodeGen/CGStmtOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2910,10 +2910,10 @@ void CodeGenFunction::EmitOMPOuterLoop(
EmitBlock(LoopExit.getBlock());

// Tell the runtime we are done.
auto &&CodeGen = [DynamicOrOrdered, &S](CodeGenFunction &CGF) {
auto &&CodeGen = [DynamicOrOrdered, &S, &LoopArgs](CodeGenFunction &CGF) {
if (!DynamicOrOrdered)
CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
S.getDirectiveKind());
LoopArgs.DKind);
};
OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
}
Expand Down Expand Up @@ -3019,6 +3019,7 @@ void CodeGenFunction::EmitOMPForOuterLoop(
OuterLoopArgs.Cond = S.getCond();
OuterLoopArgs.NextLB = S.getNextLowerBound();
OuterLoopArgs.NextUB = S.getNextUpperBound();
OuterLoopArgs.DKind = LoopArgs.DKind;
EmitOMPOuterLoop(DynamicOrOrdered, IsMonotonic, S, LoopScope, OuterLoopArgs,
emitOMPLoopBodyWithStopPoint, CodeGenOrdered);
}
Expand Down Expand Up @@ -3080,6 +3081,7 @@ void CodeGenFunction::EmitOMPDistributeOuterLoop(
OuterLoopArgs.NextUB = isOpenMPLoopBoundSharingDirective(S.getDirectiveKind())
? S.getCombinedNextUpperBound()
: S.getNextUpperBound();
OuterLoopArgs.DKind = OMPD_distribute;

EmitOMPOuterLoop(/* DynamicOrOrdered = */ false, /* IsMonotonic = */ false, S,
LoopScope, OuterLoopArgs, CodeGenLoopContent,
Expand Down Expand Up @@ -3452,15 +3454,16 @@ bool CodeGenFunction::EmitOMPWorksharingLoop(
// Tell the runtime we are done.
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
S.getDirectiveKind());
OMPD_for);
};
OMPCancelStack.emitExit(*this, S.getDirectiveKind(), CodeGen);
} else {
// Emit the outer loop, which requests its work chunk [LB..UB] from
// runtime and runs the inner loop to process it.
const OMPLoopArguments LoopArguments(
OMPLoopArguments LoopArguments(
LB.getAddress(*this), UB.getAddress(*this), ST.getAddress(*this),
IL.getAddress(*this), Chunk, EUB);
LoopArguments.DKind = OMPD_for;
EmitOMPForOuterLoop(ScheduleKind, IsMonotonic, S, LoopScope, Ordered,
LoopArguments, CGDispatchBounds);
}
Expand Down Expand Up @@ -4082,7 +4085,7 @@ void CodeGenFunction::EmitSections(const OMPExecutableDirective &S) {
// Tell the runtime we are done.
auto &&CodeGen = [&S](CodeGenFunction &CGF) {
CGF.CGM.getOpenMPRuntime().emitForStaticFinish(CGF, S.getEndLoc(),
S.getDirectiveKind());
OMPD_sections);
};
CGF.OMPCancelStack.emitExit(CGF, S.getDirectiveKind(), CodeGen);
CGF.EmitOMPReductionClauseFinal(S, /*ReductionKind=*/OMPD_parallel);
Expand Down Expand Up @@ -5782,7 +5785,7 @@ void CodeGenFunction::EmitOMPDistributeLoop(const OMPLoopDirective &S,
});
EmitBlock(LoopExit.getBlock());
// Tell the runtime we are done.
RT.emitForStaticFinish(*this, S.getEndLoc(), S.getDirectiveKind());
RT.emitForStaticFinish(*this, S.getEndLoc(), OMPD_distribute);
} else {
// Emit the outer loop, which requests its work chunk [LB..UB] from
// runtime and runs the inner loop to process it.
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -3831,6 +3831,8 @@ class CodeGenFunction : public CodeGenTypeCache {
Expr *NextLB = nullptr;
/// Update of UB after a whole chunk has been executed
Expr *NextUB = nullptr;
/// Distinguish between the for distribute and sections
OpenMPDirectiveKind DKind = llvm::omp::OMPD_unknown;
OMPLoopArguments() = default;
OMPLoopArguments(Address LB, Address UB, Address ST, Address IL,
llvm::Value *Chunk = nullptr, Expr *EUB = nullptr,
Expand Down
23 changes: 23 additions & 0 deletions clang/lib/CodeGen/Targets/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,29 @@ void AMDGPUTargetCodeGenInfo::setFunctionDeclAttributes(
if (NumVGPR != 0)
F->addFnAttr("amdgpu-num-vgpr", llvm::utostr(NumVGPR));
}

if (const auto *Attr = FD->getAttr<AMDGPUMaxNumWorkGroupsAttr>()) {
uint32_t X = Attr->getMaxNumWorkGroupsX()
->EvaluateKnownConstInt(M.getContext())
.getExtValue();
// Y and Z dimensions default to 1 if not specified
uint32_t Y = Attr->getMaxNumWorkGroupsY()
? Attr->getMaxNumWorkGroupsY()
->EvaluateKnownConstInt(M.getContext())
.getExtValue()
: 1;
uint32_t Z = Attr->getMaxNumWorkGroupsZ()
? Attr->getMaxNumWorkGroupsZ()
->EvaluateKnownConstInt(M.getContext())
.getExtValue()
: 1;

llvm::SmallString<32> AttrVal;
llvm::raw_svector_ostream OS(AttrVal);
OS << X << ',' << Y << ',' << Z;

F->addFnAttr("amdgpu-max-num-workgroups", AttrVal.str());
}
}

/// Emits control constants used to change per-architecture behaviour in the
Expand Down
35 changes: 26 additions & 9 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2687,8 +2687,8 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
}
}

static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range) {
StringRef RangeStr = "";
static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range,
StringRef Option) {
switch (Range) {
case LangOptions::ComplexRangeKind::CX_Limited:
return "-fcx-limited-range";
Expand All @@ -2697,17 +2697,32 @@ static StringRef EnumComplexRangeToStr(LangOptions::ComplexRangeKind Range) {
return "-fcx-fortran-rules";
break;
default:
return RangeStr;
return Option;
break;
}
}

static void EmitComplexRangeDiag(const Driver &D,
LangOptions::ComplexRangeKind Range1,
LangOptions::ComplexRangeKind Range2) {
if (Range1 != Range2 && Range1 != LangOptions::ComplexRangeKind::CX_None)
D.Diag(clang::diag::warn_drv_overriding_option)
<< EnumComplexRangeToStr(Range1) << EnumComplexRangeToStr(Range2);
LangOptions::ComplexRangeKind Range2,
StringRef Option = StringRef()) {
if (Range1 != Range2 && Range1 != LangOptions::ComplexRangeKind::CX_None) {
bool NegateFortranOption = false;
bool NegateLimitedOption = false;
if (!Option.empty()) {
NegateFortranOption =
Range1 == LangOptions::ComplexRangeKind::CX_Fortran &&
Option == "-fno-cx-fortran-rules";
NegateLimitedOption =
Range1 == LangOptions::ComplexRangeKind::CX_Limited &&
Option == "-fno-cx-limited-range";
}
if (Option.empty() ||
(!Option.empty() && !NegateFortranOption && !NegateLimitedOption))
D.Diag(clang::diag::warn_drv_overriding_option)
<< EnumComplexRangeToStr(Range1, Option)
<< EnumComplexRangeToStr(Range2, Option);
}
}

static std::string
Expand Down Expand Up @@ -2815,7 +2830,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
break;
}
case options::OPT_fno_cx_limited_range:
EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full);
EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full,
"-fno-cx-limited-range");
Range = LangOptions::ComplexRangeKind::CX_Full;
break;
case options::OPT_fcx_fortran_rules: {
Expand All @@ -2824,7 +2840,8 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
break;
}
case options::OPT_fno_cx_fortran_rules:
EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full);
EmitComplexRangeDiag(D, Range, LangOptions::ComplexRangeKind::CX_Full,
"-fno-cx-fortran-rules");
Range = LangOptions::ComplexRangeKind::CX_Full;
break;
case options::OPT_ffp_model_EQ: {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/InstallAPI/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "clang/InstallAPI/Frontend.h"
#include "clang/AST/Availability.h"
#include "clang/InstallAPI/FrontendRecords.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/InstallAPI/Visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "clang/AST/ParentMapContext.h"
#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/Linkage.h"
#include "clang/InstallAPI/Frontend.h"
#include "clang/InstallAPI/FrontendRecords.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/DataLayout.h"
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,10 @@ Interpreter::Parse(llvm::StringRef Code) {
llvm::Error Interpreter::CreateExecutor() {
const clang::TargetInfo &TI =
getCompilerInstance()->getASTContext().getTargetInfo();
if (IncrExecutor)
return llvm::make_error<llvm::StringError>("Operation failed. "
"Execution engine exists",
std::error_code());
llvm::Error Err = llvm::Error::success();
auto Executor = std::make_unique<IncrementalExecutor>(*TSCtx, Err, TI);
if (!Err)
Expand All @@ -383,6 +387,8 @@ llvm::Error Interpreter::CreateExecutor() {
return Err;
}

void Interpreter::ResetExecutor() { IncrExecutor.reset(); }

llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
assert(T.TheModule);
if (!IncrExecutor) {
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4634,7 +4634,9 @@ bool Parser::ParseCXX11AttributeArgs(
return true;
}

if (ScopeName && ScopeName->isStr("omp")) {
// [[omp::directive]] and [[omp::sequence]] need special handling.
if (ScopeName && ScopeName->isStr("omp") &&
(AttrName->isStr("directive") || AttrName->isStr("sequence"))) {
Diag(AttrNameLoc, getLangOpts().OpenMP >= 51
? diag::warn_omp51_compat_attributes
: diag::ext_omp_attributes);
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaCodeComplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,10 @@ getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
// Filter out names reserved for the implementation if they come from a
// system header.
static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
// Debuggers want access to all identifiers, including reserved ones.
if (SemaRef.getLangOpts().DebuggerSupport)
return false;

ReservedIdentifierStatus Status = ND->isReserved(SemaRef.getLangOpts());
// Ignore reserved names for compiler provided decls.
if (isReservedInAllContexts(Status) && ND->getLocation().isInvalid())
Expand Down
62 changes: 62 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8079,6 +8079,65 @@ static void handleAMDGPUNumVGPRAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
D->addAttr(::new (S.Context) AMDGPUNumVGPRAttr(S.Context, AL, NumVGPR));
}

static bool
checkAMDGPUMaxNumWorkGroupsArguments(Sema &S, Expr *XExpr, Expr *YExpr,
Expr *ZExpr,
const AMDGPUMaxNumWorkGroupsAttr &Attr) {
if (S.DiagnoseUnexpandedParameterPack(XExpr) ||
(YExpr && S.DiagnoseUnexpandedParameterPack(YExpr)) ||
(ZExpr && S.DiagnoseUnexpandedParameterPack(ZExpr)))
return true;

// Accept template arguments for now as they depend on something else.
// We'll get to check them when they eventually get instantiated.
if (XExpr->isValueDependent() || (YExpr && YExpr->isValueDependent()) ||
(ZExpr && ZExpr->isValueDependent()))
return false;

uint32_t NumWG = 0;
Expr *Exprs[3] = {XExpr, YExpr, ZExpr};
for (int i = 0; i < 3; i++) {
if (Exprs[i]) {
if (!checkUInt32Argument(S, Attr, Exprs[i], NumWG, i,
/*StrictlyUnsigned=*/true))
return true;
if (NumWG == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_is_zero)
<< &Attr << Exprs[i]->getSourceRange();
return true;
}
}
}

return false;
}

AMDGPUMaxNumWorkGroupsAttr *
Sema::CreateAMDGPUMaxNumWorkGroupsAttr(const AttributeCommonInfo &CI,
Expr *XExpr, Expr *YExpr, Expr *ZExpr) {
AMDGPUMaxNumWorkGroupsAttr TmpAttr(Context, CI, XExpr, YExpr, ZExpr);

if (checkAMDGPUMaxNumWorkGroupsArguments(*this, XExpr, YExpr, ZExpr, TmpAttr))
return nullptr;

return ::new (Context)
AMDGPUMaxNumWorkGroupsAttr(Context, CI, XExpr, YExpr, ZExpr);
}

void Sema::addAMDGPUMaxNumWorkGroupsAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *XExpr, Expr *YExpr,
Expr *ZExpr) {
if (auto *Attr = CreateAMDGPUMaxNumWorkGroupsAttr(CI, XExpr, YExpr, ZExpr))
D->addAttr(Attr);
}

static void handleAMDGPUMaxNumWorkGroupsAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
Expr *YExpr = (AL.getNumArgs() > 1) ? AL.getArgAsExpr(1) : nullptr;
Expr *ZExpr = (AL.getNumArgs() > 2) ? AL.getArgAsExpr(2) : nullptr;
S.addAMDGPUMaxNumWorkGroupsAttr(D, AL, AL.getArgAsExpr(0), YExpr, ZExpr);
}

static void handleX86ForceAlignArgPointerAttr(Sema &S, Decl *D,
const ParsedAttr &AL) {
// If we try to apply it to a function pointer, don't warn, but don't
Expand Down Expand Up @@ -9183,6 +9242,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
case ParsedAttr::AT_AMDGPUNumVGPR:
handleAMDGPUNumVGPRAttr(S, D, AL);
break;
case ParsedAttr::AT_AMDGPUMaxNumWorkGroups:
handleAMDGPUMaxNumWorkGroupsAttr(S, D, AL);
break;
case ParsedAttr::AT_AVRSignal:
handleAVRSignalAttr(S, D, AL);
break;
Expand Down
29 changes: 27 additions & 2 deletions clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8516,6 +8516,9 @@ class BuiltinCandidateTypeSet {
/// candidates.
TypeSet MatrixTypes;

/// The set of _BitInt types that will be used in the built-in candidates.
TypeSet BitIntTypes;

/// A flag indicating non-record types are viable candidates
bool HasNonRecordTypes;

Expand Down Expand Up @@ -8564,6 +8567,7 @@ class BuiltinCandidateTypeSet {
}
llvm::iterator_range<iterator> vector_types() { return VectorTypes; }
llvm::iterator_range<iterator> matrix_types() { return MatrixTypes; }
llvm::iterator_range<iterator> bitint_types() { return BitIntTypes; }

bool containsMatrixType(QualType Ty) const { return MatrixTypes.count(Ty); }
bool hasNonRecordTypes() { return HasNonRecordTypes; }
Expand Down Expand Up @@ -8735,6 +8739,9 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,
} else if (Ty->isEnumeralType()) {
HasArithmeticOrEnumeralTypes = true;
EnumerationTypes.insert(Ty);
} else if (Ty->isBitIntType()) {
HasArithmeticOrEnumeralTypes = true;
BitIntTypes.insert(Ty);
} else if (Ty->isVectorType()) {
// We treat vector types as arithmetic types in many contexts as an
// extension.
Expand Down Expand Up @@ -8913,7 +8920,7 @@ class BuiltinOperatorOverloadBuilder {
SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes;
OverloadCandidateSet &CandidateSet;

static constexpr int ArithmeticTypesCap = 24;
static constexpr int ArithmeticTypesCap = 26;
SmallVector<CanQualType, ArithmeticTypesCap> ArithmeticTypes;

// Define some indices used to iterate over the arithmetic types in
Expand Down Expand Up @@ -8955,6 +8962,20 @@ class BuiltinOperatorOverloadBuilder {
(S.Context.getAuxTargetInfo() &&
S.Context.getAuxTargetInfo()->hasInt128Type()))
ArithmeticTypes.push_back(S.Context.UnsignedInt128Ty);

/// We add candidates for the unique, unqualified _BitInt types present in
/// the candidate type set. The candidate set already handled ensuring the
/// type is unqualified and canonical, but because we're adding from N
/// different sets, we need to do some extra work to unique things. Insert
/// the candidates into a unique set, then move from that set into the list
/// of arithmetic types.
llvm::SmallSetVector<CanQualType, 2> BitIntCandidates;
llvm::for_each(CandidateTypes, [&BitIntCandidates](
BuiltinCandidateTypeSet &Candidate) {
for (QualType BitTy : Candidate.bitint_types())
BitIntCandidates.insert(CanQualType::CreateUnsafe(BitTy));
});
llvm::move(BitIntCandidates, std::back_inserter(ArithmeticTypes));
LastPromotedIntegralType = ArithmeticTypes.size();
LastPromotedArithmeticType = ArithmeticTypes.size();
// End of promoted types.
Expand All @@ -8975,7 +8996,11 @@ class BuiltinOperatorOverloadBuilder {
// End of integral types.
// FIXME: What about complex? What about half?

assert(ArithmeticTypes.size() <= ArithmeticTypesCap &&
// We don't know for sure how many bit-precise candidates were involved, so
// we subtract those from the total when testing whether we're under the
// cap or not.
assert(ArithmeticTypes.size() - BitIntCandidates.size() <=
ArithmeticTypesCap &&
"Enough inline storage for all arithmetic types.");
}

Expand Down
29 changes: 29 additions & 0 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,29 @@ static void instantiateDependentAMDGPUWavesPerEUAttr(
S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr);
}

static void instantiateDependentAMDGPUMaxNumWorkGroupsAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const AMDGPUMaxNumWorkGroupsAttr &Attr, Decl *New) {
EnterExpressionEvaluationContext Unevaluated(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);

ExprResult ResultX = S.SubstExpr(Attr.getMaxNumWorkGroupsX(), TemplateArgs);
if (!ResultX.isUsable())
return;
ExprResult ResultY = S.SubstExpr(Attr.getMaxNumWorkGroupsY(), TemplateArgs);
if (!ResultY.isUsable())
return;
ExprResult ResultZ = S.SubstExpr(Attr.getMaxNumWorkGroupsZ(), TemplateArgs);
if (!ResultZ.isUsable())
return;

Expr *XExpr = ResultX.getAs<Expr>();
Expr *YExpr = ResultY.getAs<Expr>();
Expr *ZExpr = ResultZ.getAs<Expr>();

S.addAMDGPUMaxNumWorkGroupsAttr(New, Attr, XExpr, YExpr, ZExpr);
}

// This doesn't take any template parameters, but we have a custom action that
// needs to happen when the kernel itself is instantiated. We need to run the
// ItaniumMangler to mark the names required to name this kernel.
Expand Down Expand Up @@ -792,6 +815,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
*AMDGPUFlatWorkGroupSize, New);
}

if (const auto *AMDGPUMaxNumWorkGroups =
dyn_cast<AMDGPUMaxNumWorkGroupsAttr>(TmplAttr)) {
instantiateDependentAMDGPUMaxNumWorkGroupsAttr(
*this, TemplateArgs, *AMDGPUMaxNumWorkGroups, New);
}

if (const auto *ParamAttr = dyn_cast<HLSLParamModifierAttr>(TmplAttr)) {
instantiateDependentHLSLParamModifierAttr(*this, TemplateArgs, ParamAttr,
New);
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/StaticAnalyzer/Core/CoreEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,8 +625,8 @@ ExplodedNode* NodeBuilder::generateNodeImpl(const ProgramPoint &Loc,
bool MarkAsSink) {
HasGeneratedNodes = true;
bool IsNew;
ExplodedNode *N = C.Eng.G.getNode(Loc, State, MarkAsSink, &IsNew);
N->addPredecessor(FromN, C.Eng.G);
ExplodedNode *N = C.getEngine().G.getNode(Loc, State, MarkAsSink, &IsNew);
N->addPredecessor(FromN, C.getEngine().G);
Frontier.erase(FromN);

if (!IsNew)
Expand Down Expand Up @@ -655,7 +655,7 @@ ExplodedNode *BranchNodeBuilder::generateNode(ProgramStateRef State,
if (!isFeasible(branch))
return nullptr;

ProgramPoint Loc = BlockEdge(C.Block, branch ? DstT:DstF,
ProgramPoint Loc = BlockEdge(C.getBlock(), branch ? DstT : DstF,
NodePred->getLocationContext());
ExplodedNode *Succ = generateNodeImpl(Loc, State, NodePred);
return Succ;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ class DependencyScanningAction : public tooling::ToolAction {
DisableFree(DisableFree), ModuleName(ModuleName) {}

bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
FileManager *FileMgr,
FileManager *DriverFileMgr,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) override {
// Make a deep copy of the original Clang invocation.
Expand Down Expand Up @@ -342,12 +342,13 @@ class DependencyScanningAction : public tooling::ToolAction {
ScanInstance.getHeaderSearchOpts().ModulesIncludeVFSUsage =
any(OptimizeArgs & ScanningOptimizations::VFS);

ScanInstance.setFileManager(FileMgr);
// Support for virtual file system overlays.
FileMgr->setVirtualFileSystem(createVFSFromCompilerInvocation(
auto FS = createVFSFromCompilerInvocation(
ScanInstance.getInvocation(), ScanInstance.getDiagnostics(),
FileMgr->getVirtualFileSystemPtr()));
DriverFileMgr->getVirtualFileSystemPtr());

// Create a new FileManager to match the invocation's FileSystemOptions.
auto *FileMgr = ScanInstance.createFileManager(FS);
ScanInstance.createSourceManager(*FileMgr);

// Store the list of prebuilt module files into header search options. This
Expand Down Expand Up @@ -624,9 +625,8 @@ bool DependencyScanningWorker::computeDependencies(
ModifiedCommandLine ? *ModifiedCommandLine : CommandLine;
auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS;

FileSystemOptions FSOpts;
FSOpts.WorkingDir = WorkingDirectory.str();
auto FileMgr = llvm::makeIntrusiveRefCnt<FileManager>(FSOpts, FinalFS);
auto FileMgr =
llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions{}, FinalFS);

std::vector<const char *> FinalCCommandLine(FinalCommandLine.size(), nullptr);
llvm::transform(FinalCommandLine, FinalCCommandLine.begin(),
Expand Down
5 changes: 5 additions & 0 deletions clang/test/AST/Interp/complex.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,8 @@ void blah() {
_Static_assert((0.0 + 0.0j) == (0.0 + 0.0j), "");
_Static_assert((0.0 + 0.0j) != (0.0 + 0.0j), ""); // both-error {{static assertion}} \
// both-note {{evaluates to}}

const _Complex float FC = {0.0f, 0.0f};
_Static_assert(!FC, "");
const _Complex float FI = {0, 0};
_Static_assert(!FI, "");
30 changes: 30 additions & 0 deletions clang/test/ClangScanDeps/working-directory-option.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Test that -working-directory works even when it differs from the working
// directory of the filesystem.

// RUN: rm -rf %t
// RUN: mkdir -p %t/other
// RUN: split-file %s %t
// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json

// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-full \
// RUN: > %t/deps.json

// RUN: cat %t/deps.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t

// CHECK: "file-deps": [
// CHECK-NEXT: "[[PREFIX]]/cwd/t.c"
// CHECK-NEXT: "[[PREFIX]]/cwd/relative/h1.h"
// CHECK-NEXT: ]
// CHECK-NEXT: "input-file": "[[PREFIX]]/cwd/t.c"

//--- cdb.json.template
[{
"directory": "DIR/other",
"command": "clang -c t.c -I relative -working-directory DIR/cwd",
"file": "DIR/cwd/t.c"
}]

//--- cwd/relative/h1.h

//--- cwd/t.c
#include "h1.h"
7 changes: 6 additions & 1 deletion clang/test/CodeCompletion/ordinary-name.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ typedef struct t _TYPEDEF;
void foo() {
int y;
// RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -code-completion-at=%s:%(line-1):9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1-NOT: __builtin_va_list
// CHECK-CC1-NOT: __INTEGER_TYPE
// CHECK-CC1: _Imaginary
// CHECK-CC1: _MyPrivateType
Expand All @@ -15,4 +16,8 @@ void foo() {
// CHECK-CC1: y

// PR8744
// RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -code-completion-at=%s:%(line-17):11 %s
// RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -code-completion-at=%s:%(line-18):11 %s

// RUN: %clang_cc1 -isystem %S/Inputs -fsyntax-only -fdebugger-support -code-completion-at=%s:%(line-15):9 %s -o - | FileCheck -check-prefix=CHECK-DBG %s
// CHECK-DBG: __builtin_va_list
// CHECK-DBG: __INTEGER_TYPE
164 changes: 164 additions & 0 deletions clang/test/CodeGen/SystemZ/atomic_fp_load_store.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// RUN: %clang_cc1 -triple s390x-linux-gnu -O1 -emit-llvm %s -o - | FileCheck %s
//
// Test that floating point atomic stores and loads do not get casted to/from
// integer.

#include <stdatomic.h>

_Atomic float Af;
_Atomic double Ad;
_Atomic long double Ald;

//// Atomic stores of floating point values.
void fun0(float Arg) {
// CHECK-LABEL: @fun0
// CHECK: store atomic float %Arg, ptr @Af seq_cst, align 4
Af = Arg;
}

void fun1(double Arg) {
// CHECK-LABEL: @fun1
// CHECK: store atomic double %Arg, ptr @Ad seq_cst, align 8
Ad = Arg;
}

void fun2(long double Arg) {
// CHECK-LABEL: @fun2
// CHECK: store atomic fp128 %Arg, ptr @Ald seq_cst, align 16
Ald = Arg;
}

void fun3(_Atomic float *Dst, float Arg) {
// CHECK-LABEL: @fun
// CHECK: store atomic float %Arg, ptr %Dst seq_cst, align 4
*Dst = Arg;
}

void fun4(_Atomic double *Dst, double Arg) {
// CHECK-LABEL: @fun4
// CHECK: store atomic double %Arg, ptr %Dst seq_cst, align 8
*Dst = Arg;
}

void fun5(_Atomic long double *Dst, long double Arg) {
// CHECK-LABEL: @fun5
// CHECK: store atomic fp128 %Arg, ptr %Dst seq_cst, align 16
*Dst = Arg;
}

//// Atomic loads of floating point values.
float fun6() {
// CHECK-LABEL: @fun6
// CHECK: %atomic-load = load atomic float, ptr @Af seq_cst, align 4
return Af;
}

float fun7() {
// CHECK-LABEL: @fun7
// CHECK: %atomic-load = load atomic double, ptr @Ad seq_cst, align 8
return Ad;
}

float fun8() {
// CHECK-LABEL: @fun8
// CHECK: %atomic-load = load atomic fp128, ptr @Ald seq_cst, align 16
return Ald;
}

float fun9(_Atomic float *Src) {
// CHECK-LABEL: @fun9
// CHECK: %atomic-load = load atomic float, ptr %Src seq_cst, align 4
return *Src;
}

double fun10(_Atomic double *Src) {
// CHECK-LABEL: @fun10
// CHECK: %atomic-load = load atomic double, ptr %Src seq_cst, align 8
return *Src;
}

long double fun11(_Atomic long double *Src) {
// CHECK-LABEL: @fun11
// CHECK: %atomic-load = load atomic fp128, ptr %Src seq_cst, align 16
return *Src;
}

//// Same, but with 'volatile' as well:

_Atomic volatile float Af_vol;
_Atomic volatile double Ad_vol;
_Atomic volatile long double Ald_vol;

//// Atomic volatile stores of floating point values.
void fun0_vol(float Arg) {
// CHECK-LABEL: @fun0_vol
// CHECK: store atomic volatile float %Arg, ptr @Af_vol seq_cst, align 4
Af_vol = Arg;
}

void fun1_vol(double Arg) {
// CHECK-LABEL: @fun1_vol
// CHECK: store atomic volatile double %Arg, ptr @Ad_vol seq_cst, align 8
Ad_vol = Arg;
}

void fun2_vol(long double Arg) {
// CHECK-LABEL: @fun2_vol
// CHECK: store atomic volatile fp128 %Arg, ptr @Ald_vol seq_cst, align 16
Ald_vol = Arg;
}

void fun3_vol(_Atomic volatile float *Dst, float Arg) {
// CHECK-LABEL: @fun3_vol
// CHECK: store atomic volatile float %Arg, ptr %Dst seq_cst, align 4
*Dst = Arg;
}

void fun4_vol(_Atomic volatile double *Dst, double Arg) {
// CHECK-LABEL: @fun4_vol
// CHECK: store atomic volatile double %Arg, ptr %Dst seq_cst, align 8
*Dst = Arg;
}

void fun5_vol(_Atomic volatile long double *Dst, long double Arg) {
// CHECK-LABEL: @fun5_vol
// CHECK: store atomic volatile fp128 %Arg, ptr %Dst seq_cst, align 16
*Dst = Arg;
}

//// Atomic volatile loads of floating point values.
float fun6_vol() {
// CHECK-LABEL: @fun6_vol
// CHECK: %atomic-load = load atomic volatile float, ptr @Af_vol seq_cst, align 4
return Af_vol;
}

float fun7_vol() {
// CHECK-LABEL: @fun7_vol
// CHECK: %atomic-load = load atomic volatile double, ptr @Ad_vol seq_cst, align 8
return Ad_vol;
}

float fun8_vol() {
// CHECK-LABEL: @fun8_vol
// CHECK: %atomic-load = load atomic volatile fp128, ptr @Ald_vol seq_cst, align 16
return Ald_vol;
}

float fun9_vol(_Atomic volatile float *Src) {
// CHECK-LABEL: @fun9_vol
// CHECK: %atomic-load = load atomic volatile float, ptr %Src seq_cst, align 4
return *Src;
}

double fun10_vol(_Atomic volatile double *Src) {
// CHECK-LABEL: @fun10_vol
// CHECK: %atomic-load = load atomic volatile double, ptr %Src seq_cst, align 8
return *Src;
}

long double fun11_vol(_Atomic volatile long double *Src) {
// CHECK-LABEL: @fun11_vol
// CHECK: %atomic-load = load atomic volatile fp128, ptr %Src seq_cst, align 16
return *Src;
}
3 changes: 1 addition & 2 deletions clang/test/CodeGen/atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,5 @@ void force_global_uses(void) {
(void)glob_int;
// CHECK: load atomic i32, ptr @[[GLOB_INT]] seq_cst
(void)glob_flt;
// CHECK: %[[LOCAL_FLT:.+]] = load atomic i32, ptr @[[GLOB_FLT]] seq_cst
// CHECK-NEXT: bitcast i32 %[[LOCAL_FLT]] to float
// CHECK: load atomic float, ptr @[[GLOB_FLT]] seq_cst
}
8 changes: 3 additions & 5 deletions clang/test/CodeGen/c11atomics-ios.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@ void testFloat(_Atomic(float) *fp) {
_Atomic(float) x = 2.0f;

// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[FP]]
// CHECK-NEXT: [[T2:%.*]] = load atomic i32, ptr [[T0]] seq_cst, align 4
// CHECK-NEXT: [[T3:%.*]] = bitcast i32 [[T2]] to float
// CHECK-NEXT: store float [[T3]], ptr [[F]]
// CHECK-NEXT: [[T2:%.*]] = load atomic float, ptr [[T0]] seq_cst, align 4
// CHECK-NEXT: store float [[T2]], ptr [[F]]
float f = *fp;

// CHECK-NEXT: [[T0:%.*]] = load float, ptr [[F]], align 4
// CHECK-NEXT: [[T1:%.*]] = load ptr, ptr [[FP]], align 4
// CHECK-NEXT: [[T2:%.*]] = bitcast float [[T0]] to i32
// CHECK-NEXT: store atomic i32 [[T2]], ptr [[T1]] seq_cst, align 4
// CHECK-NEXT: store atomic float [[T0]], ptr [[T1]] seq_cst, align 4
*fp = f;

// CHECK-NEXT: ret void
Expand Down
35 changes: 35 additions & 0 deletions clang/test/CodeGenCUDA/amdgpu-kernel-attrs.cu
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,53 @@ __attribute__((amdgpu_num_vgpr(64))) // expected-no-diagnostics
__global__ void num_vgpr_64() {
// CHECK: define{{.*}} amdgpu_kernel void @_Z11num_vgpr_64v() [[NUM_VGPR_64:#[0-9]+]]
}
__attribute__((amdgpu_max_num_work_groups(32, 4, 2))) // expected-no-diagnostics
__global__ void max_num_work_groups_32_4_2() {
// CHECK: define{{.*}} amdgpu_kernel void @_Z26max_num_work_groups_32_4_2v() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]]
}
__attribute__((amdgpu_max_num_work_groups(32))) // expected-no-diagnostics
__global__ void max_num_work_groups_32() {
// CHECK: define{{.*}} amdgpu_kernel void @_Z22max_num_work_groups_32v() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]]
}
__attribute__((amdgpu_max_num_work_groups(32,1))) // expected-no-diagnostics
__global__ void max_num_work_groups_32_1() {
// CHECK: define{{.*}} amdgpu_kernel void @_Z24max_num_work_groups_32_1v() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]]
}



template<unsigned a>
__attribute__((amdgpu_max_num_work_groups(a, 4, 2)))
__global__ void template_a_4_2_max_num_work_groups() {}
template __global__ void template_a_4_2_max_num_work_groups<32>();
// CHECK: define{{.*}} amdgpu_kernel void @_Z34template_a_4_2_max_num_work_groupsILj32EEvv() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]]

template<unsigned a>
__attribute__((amdgpu_max_num_work_groups(32, a, 2)))
__global__ void template_32_a_2_max_num_work_groups() {}
template __global__ void template_32_a_2_max_num_work_groups<4>();
// CHECK: define{{.*}} amdgpu_kernel void @_Z35template_32_a_2_max_num_work_groupsILj4EEvv() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]]

template<unsigned a>
__attribute__((amdgpu_max_num_work_groups(32, 4, a)))
__global__ void template_32_4_a_max_num_work_groups() {}
template __global__ void template_32_4_a_max_num_work_groups<2>();
// CHECK: define{{.*}} amdgpu_kernel void @_Z35template_32_4_a_max_num_work_groupsILj2EEvv() [[MAX_NUM_WORK_GROUPS_32_4_2:#[0-9]+]]

// Make sure this is silently accepted on other targets.
// NAMD-NOT: "amdgpu-flat-work-group-size"
// NAMD-NOT: "amdgpu-waves-per-eu"
// NAMD-NOT: "amdgpu-num-vgpr"
// NAMD-NOT: "amdgpu-num-sgpr"
// NAMD-NOT: "amdgpu-max-num-work-groups"

// DEFAULT-DAG: attributes [[FLAT_WORK_GROUP_SIZE_DEFAULT]] = {{.*}}"amdgpu-flat-work-group-size"="1,1024"{{.*}}"uniform-work-group-size"="true"
// MAX1024-DAG: attributes [[FLAT_WORK_GROUP_SIZE_DEFAULT]] = {{.*}}"amdgpu-flat-work-group-size"="1,1024"
// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64]] = {{.*}}"amdgpu-flat-work-group-size"="32,64"
// CHECK-DAG: attributes [[WAVES_PER_EU_2]] = {{.*}}"amdgpu-waves-per-eu"="2"
// CHECK-DAG: attributes [[NUM_SGPR_32]] = {{.*}}"amdgpu-num-sgpr"="32"
// CHECK-DAG: attributes [[NUM_VGPR_64]] = {{.*}}"amdgpu-num-vgpr"="64"
// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_4_2]] = {{.*}}"amdgpu-max-num-workgroups"="32,4,2"
// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_1_1]] = {{.*}}"amdgpu-max-num-workgroups"="32,1,1"

// NOUB-NOT: "uniform-work-group-size"="true"
47 changes: 47 additions & 0 deletions clang/test/CodeGenOpenCL/amdgpu-attrs.cl
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,46 @@ kernel void reqd_work_group_size_32_2_1_flat_work_group_size_16_128() {
// CHECK: define{{.*}} amdgpu_kernel void @reqd_work_group_size_32_2_1_flat_work_group_size_16_128() [[FLAT_WORK_GROUP_SIZE_16_128:#[0-9]+]]
}

__attribute__((amdgpu_max_num_work_groups(1, 1, 1))) // expected-no-diagnostics
kernel void max_num_work_groups_1_1_1() {
// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_1_1_1() [[MAX_NUM_WORK_GROUPS_1_1_1:#[0-9]+]]
}

__attribute__((amdgpu_max_num_work_groups(32, 1, 1))) // expected-no-diagnostics
kernel void max_num_work_groups_32_1_1() {
// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32_1_1() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]]
}

__attribute__((amdgpu_max_num_work_groups(32, 8, 1))) // expected-no-diagnostics
kernel void max_num_work_groups_32_8_1() {
// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32_8_1() [[MAX_NUM_WORK_GROUPS_32_8_1:#[0-9]+]]
}

__attribute__((amdgpu_max_num_work_groups(1, 1, 32))) // expected-no-diagnostics
kernel void max_num_work_groups_1_1_32() {
// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_1_1_32() [[MAX_NUM_WORK_GROUPS_1_1_32:#[0-9]+]]
}

__attribute__((amdgpu_max_num_work_groups(1, 8, 32))) // expected-no-diagnostics
kernel void max_num_work_groups_1_8_32() {
// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_1_8_32() [[MAX_NUM_WORK_GROUPS_1_8_32:#[0-9]+]]
}

__attribute__((amdgpu_max_num_work_groups(4, 8, 32))) // expected-no-diagnostics
kernel void max_num_work_groups_4_8_32() {
// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_4_8_32() [[MAX_NUM_WORK_GROUPS_4_8_32:#[0-9]+]]
}

__attribute__((amdgpu_max_num_work_groups(32))) // expected-no-diagnostics
kernel void max_num_work_groups_32() {
// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]]
}

__attribute__((amdgpu_max_num_work_groups(32,1))) // expected-no-diagnostics
kernel void max_num_work_groups_32_1() {
// CHECK: define{{.*}} amdgpu_kernel void @max_num_work_groups_32_1() [[MAX_NUM_WORK_GROUPS_32_1_1:#[0-9]+]]
}

void a_function() {
// CHECK: define{{.*}} void @a_function() [[A_FUNCTION:#[0-9]+]]
}
Expand Down Expand Up @@ -189,5 +229,12 @@ kernel void default_kernel() {
// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_NUM_SGPR_32_NUM_VGPR_64]] = {{.*}} "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2"
// CHECK-DAG: attributes [[FLAT_WORK_GROUP_SIZE_32_64_WAVES_PER_EU_2_4_NUM_SGPR_32_NUM_VGPR_64]] = {{.*}} "amdgpu-flat-work-group-size"="32,64" "amdgpu-num-sgpr"="32" "amdgpu-num-vgpr"="64" "amdgpu-waves-per-eu"="2,4"

// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_1_1_1]] = {{.*}} "amdgpu-max-num-workgroups"="1,1,1"
// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_1_1]] = {{.*}} "amdgpu-max-num-workgroups"="32,1,1"
// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_32_8_1]] = {{.*}} "amdgpu-max-num-workgroups"="32,8,1"
// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_1_1_32]] = {{.*}} "amdgpu-max-num-workgroups"="1,1,32"
// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_1_8_32]] = {{.*}} "amdgpu-max-num-workgroups"="1,8,32"
// CHECK-DAG: attributes [[MAX_NUM_WORK_GROUPS_4_8_32]] = {{.*}} "amdgpu-max-num-workgroups"="4,8,32"

// CHECK-DAG: attributes [[A_FUNCTION]] = {{.*}}
// CHECK-DAG: attributes [[DEFAULT_KERNEL_ATTRS]] = {{.*}} "amdgpu-flat-work-group-size"="1,256"
23 changes: 18 additions & 5 deletions clang/test/Driver/range.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,23 @@
// RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=FRTRN %s

// RUN: %clang -### -target x86_64 -fcx-fortran-rules -c %s 2>&1 \
// RUN: -fno-cx-fortran-rules | FileCheck --check-prefix=FULL %s

// RUN: %clang -### -target x86_64 -fcx-fortran-rules -fno-cx-limited-range \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN3 %s

// RUN: %clang -### -target x86_64 -fno-cx-fortran-rules -c %s 2>&1 \
// RUN: | FileCheck %s

// RUN: %clang -### -target x86_64 -fcx-limited-range \
// RUN: -fcx-fortran-rules -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=WARN1 %s
// RUN: %clang -### -target x86_64 -fcx-limited-range -fcx-fortran-rules \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN1 %s

// RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-fortran-rules \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=WARN4 %s

// RUN: %clang -### -target x86_64 -fcx-limited-range -fno-cx-limited-range \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s

// RUN: %clang -### -target x86_64 -fcx-fortran-rules \
// RUN: -fcx-limited-range -c %s 2>&1 \
Expand All @@ -32,8 +43,8 @@
// RUN: %clang -### -target x86_64 -fcx-limited-range -ffast-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=LMTD %s

// RUN: %clang -### -target x86_64 -ffast-math -fno-cx-limited-range -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=FULL %s
// RUN: %clang -### -target x86_64 -ffast-math -fno-cx-limited-range \
// RUN: -c %s 2>&1 | FileCheck --check-prefix=FULL %s

// RUN: %clang -### -Werror -target x86_64 -fcx-limited-range -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=LMTD %s
Expand All @@ -50,3 +61,5 @@
// CHECK-NOT: -complex-range=fortran
// WARN1: warning: overriding '-fcx-limited-range' option with '-fcx-fortran-rules' [-Woverriding-option]
// WARN2: warning: overriding '-fcx-fortran-rules' option with '-fcx-limited-range' [-Woverriding-option]
// WARN3: warning: overriding '-fcx-fortran-rules' option with '-fno-cx-limited-range' [-Woverriding-option]
// WARN4: warning: overriding '-fcx-limited-range' option with '-fno-cx-fortran-rules' [-Woverriding-option]
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

// CHECK: #pragma clang attribute supports the following attributes:
// CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUMaxNumWorkGroups (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function)
// CHECK-NEXT: AMDGPUWavesPerEU (SubjectMatchRule_function)
Expand Down
2 changes: 1 addition & 1 deletion clang/test/OpenMP/amdgcn_target_device_vla.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ int main() {
// CHECK: omp.loop.exit:
// CHECK-NEXT: [[TMP34:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR_ASCAST]], align 8
// CHECK-NEXT: [[TMP35:%.*]] = load i32, ptr [[TMP34]], align 4
// CHECK-NEXT: call void @__kmpc_distribute_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB2]] to ptr), i32 [[TMP35]])
// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB3]] to ptr), i32 [[TMP35]])
// CHECK-NEXT: br label [[OMP_PRECOND_END]]
// CHECK: omp.precond.end:
// CHECK-NEXT: ret void
Expand Down
2 changes: 1 addition & 1 deletion clang/test/OpenMP/amdgpu_target_with_aligned_attribute.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ void write_to_aligned_array(int *a, int N) {
// CHECK-AMD: omp.loop.exit:
// CHECK-AMD-NEXT: [[TMP17:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR_ASCAST]], align 8
// CHECK-AMD-NEXT: [[TMP18:%.*]] = load i32, ptr [[TMP17]], align 4
// CHECK-AMD-NEXT: call void @__kmpc_distribute_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB2]] to ptr), i32 [[TMP18]])
// CHECK-AMD-NEXT: call void @__kmpc_for_static_fini(ptr addrspacecast (ptr addrspace(1) @[[GLOB3]] to ptr), i32 [[TMP18]])
// CHECK-AMD-NEXT: br label [[OMP_PRECOND_END]]
// CHECK-AMD: omp.precond.end:
// CHECK-AMD-NEXT: ret void
Expand Down
10 changes: 4 additions & 6 deletions clang/test/OpenMP/atomic_read_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,11 @@ int main(void) {
// CHECK: store i64
#pragma omp atomic read
ullv = ullx;
// CHECK: load atomic i32, ptr {{.*}} monotonic, align 4
// CHECK: bitcast i32 {{.*}} to float
// CHECK: load atomic float, ptr {{.*}} monotonic, align 4
// CHECK: store float
#pragma omp atomic read
fv = fx;
// CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
// CHECK: bitcast i64 {{.*}} to double
// CHECK: load atomic double, ptr {{.*}} monotonic, align 8
// CHECK: store double
#pragma omp atomic read
dv = dx;
Expand Down Expand Up @@ -194,11 +192,11 @@ int main(void) {
// CHECK: store i64
#pragma omp atomic read
lv = cix;
// CHECK: load atomic i32, ptr {{.*}} monotonic, align 4
// CHECK: load atomic float, ptr {{.*}} monotonic, align 4
// CHECK: store i64
#pragma omp atomic read
ulv = fx;
// CHECK: load atomic i64, ptr {{.*}} monotonic, align 8
// CHECK: load atomic double, ptr {{.*}} monotonic, align 8
// CHECK: store i64
#pragma omp atomic read
llv = dx;
Expand Down
13 changes: 5 additions & 8 deletions clang/test/OpenMP/atomic_write_codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,11 @@ int main(void) {
#pragma omp atomic write
ullx = ullv;
// CHECK: load float, ptr
// CHECK: bitcast float {{.*}} to i32
// CHECK: store atomic i32 {{.*}}, ptr {{.*}} monotonic, align 4
// CHECK: store atomic float {{.*}}, ptr {{.*}} monotonic, align 4
#pragma omp atomic write
fx = fv;
// CHECK: load double, ptr
// CHECK: bitcast double {{.*}} to i64
// CHECK: store atomic i64 {{.*}}, ptr {{.*}} monotonic, align 8
// CHECK: store atomic double {{.*}}, ptr {{.*}} monotonic, align 8
#pragma omp atomic write
dx = dv;
// CHECK: [[LD:%.+]] = load x86_fp80, ptr
Expand Down Expand Up @@ -215,11 +213,11 @@ int main(void) {
#pragma omp atomic write
cix = lv;
// CHECK: load i64, ptr
// CHECK: store atomic i32 %{{.+}}, ptr {{.*}} monotonic, align 4
// CHECK: store atomic float %{{.+}}, ptr {{.*}} monotonic, align 4
#pragma omp atomic write
fx = ulv;
// CHECK: load i64, ptr
// CHECK: store atomic i64 %{{.+}}, ptr {{.*}} monotonic, align 8
// CHECK: store atomic double %{{.+}}, ptr {{.*}} monotonic, align 8
#pragma omp atomic write
dx = llv;
// CHECK: load i64, ptr
Expand Down Expand Up @@ -491,8 +489,7 @@ int main(void) {
float2x.x = ulv;
// CHECK: call i32 @llvm.read_register.i32(
// CHECK: sitofp i32 %{{.+}} to double
// CHECK: bitcast double %{{.+}} to i64
// CHECK: store atomic i64 %{{.+}}, ptr @{{.+}} seq_cst, align 8
// CHECK: store atomic double %{{.+}}, ptr @{{.+}} seq_cst, align 8
// CHECK: call{{.*}} @__kmpc_flush(
#pragma omp atomic write seq_cst
dv = rix;
Expand Down
13 changes: 13 additions & 0 deletions clang/test/OpenMP/attr-assume.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %clang_cc1 -fsyntax-only -fopenmp -verify %s
[[omp::assume(3)]] void f1(); // expected-error {{expected string literal as argument of 'assume' attribute}}
[[omp::assume(int)]] void f2(); // expected-error {{expected string literal as argument of 'assume' attribute}}
[[omp::assume(for)]] void f3(); // expected-error {{expected string literal as argument of 'assume' attribute}}
[[omp::assume("QQQQ")]] void f4(); // expected-warning {{unknown assumption string 'QQQQ'; attribute is potentially ignored}}
[[omp::assume("omp_no_openmp")]] void f5();
[[omp::assume("omp_noopenmp")]] void f6(); // expected-warning {{unknown assumption string 'omp_noopenmp' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp'?}}
[[omp::assume("omp_no_openmp_routine")]] void f7(); // expected-warning {{unknown assumption string 'omp_no_openmp_routine' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp_routines'?}}
[[omp::assume("omp_no_openmp1")]] void f8(); // expected-warning {{unknown assumption string 'omp_no_openmp1' may be misspelled; attribute is potentially ignored, did you mean 'omp_no_openmp'?}}
[[omp::assume("omp_no_openmp", "omp_no_openmp")]] void f9(); // expected-error {{'assume' attribute takes one argument}}

[[omp::assume(3)]] int g1; // expected-error {{expected string literal as argument of 'assume' attribute}}
[[omp::assume("omp_no_openmp")]] int g2; // expected-warning {{'assume' attribute only applies to functions and Objective-C methods}}
2 changes: 1 addition & 1 deletion clang/test/OpenMP/bug60602.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ int kernel_within_loop(int *a, int *b, int N, int num_iters) {
// CHECK: omp.loop.exit:
// CHECK-NEXT: [[TMP22:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
// CHECK-NEXT: [[TMP23:%.*]] = load i32, ptr [[TMP22]], align 4
// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB3]], i32 [[TMP23]])
// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP23]])
// CHECK-NEXT: br label [[OMP_PRECOND_END]]
// CHECK: omp.precond.end:
// CHECK-NEXT: ret void
Expand Down
64 changes: 32 additions & 32 deletions clang/test/OpenMP/distribute_parallel_for_codegen.cpp

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
//
//
Expand Down Expand Up @@ -748,7 +748,7 @@ int main() {
// CHECK3: omp.inner.for.end:
// CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK3: omp.loop.exit:
// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP5]])
// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP5]])
// CHECK3-NEXT: ret void
//
//
Expand Down Expand Up @@ -1167,7 +1167,7 @@ int main() {
// CHECK8: omp.loop.exit:
// CHECK8-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
// CHECK8-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
// CHECK8-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR4]]
// CHECK8-NEXT: [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR4]], i32 0, i32 0
// CHECK8-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN12]], i64 2
Expand Down Expand Up @@ -1612,7 +1612,7 @@ int main() {
// CHECK8: omp.loop.exit:
// CHECK8-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
// CHECK8-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
// CHECK8-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
// CHECK8-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR6]]) #[[ATTR4]]
// CHECK8-NEXT: [[ARRAY_BEGIN12:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR4]], i32 0, i32 0
// CHECK8-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN12]], i64 2
Expand Down Expand Up @@ -2080,7 +2080,7 @@ int main() {
// CHECK10: omp.loop.exit:
// CHECK10-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
// CHECK10-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
// CHECK10-NEXT: call void @_ZN1SIfED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR4]]
// CHECK10-NEXT: [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S], ptr [[S_ARR3]], i32 0, i32 0
// CHECK10-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[ARRAY_BEGIN10]], i32 2
Expand Down Expand Up @@ -2519,7 +2519,7 @@ int main() {
// CHECK10: omp.loop.exit:
// CHECK10-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
// CHECK10-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
// CHECK10-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
// CHECK10-NEXT: call void @_ZN1SIiED1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[VAR5]]) #[[ATTR4]]
// CHECK10-NEXT: [[ARRAY_BEGIN10:%.*]] = getelementptr inbounds [2 x %struct.S.0], ptr [[S_ARR3]], i32 0, i32 0
// CHECK10-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_S_0]], ptr [[ARRAY_BEGIN10]], i32 2
Expand Down
16 changes: 8 additions & 8 deletions clang/test/OpenMP/distribute_parallel_for_if_codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
//
//
Expand Down Expand Up @@ -472,7 +472,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
//
//
Expand Down Expand Up @@ -740,7 +740,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
//
//
Expand Down Expand Up @@ -883,7 +883,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
//
//
Expand Down Expand Up @@ -1040,7 +1040,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
//
//
Expand Down Expand Up @@ -1306,7 +1306,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
//
//
Expand Down Expand Up @@ -1449,7 +1449,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
//
//
Expand Down Expand Up @@ -1606,6 +1606,6 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
//
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]])
// CHECK1-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
// CHECK1-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
// CHECK1-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
Expand Down Expand Up @@ -708,7 +708,7 @@ int main() {
// CHECK3: omp.inner.for.end:
// CHECK3-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK3: omp.loop.exit:
// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP8]])
// CHECK3-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP8]])
// CHECK3-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
// CHECK3-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
// CHECK3-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
Expand Down Expand Up @@ -1153,7 +1153,7 @@ int main() {
// CHECK9: omp.loop.exit:
// CHECK9-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
// CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
// CHECK9-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
// CHECK9-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
// CHECK9-NEXT: br i1 [[TMP24]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
Expand Down Expand Up @@ -1636,7 +1636,7 @@ int main() {
// CHECK9: omp.loop.exit:
// CHECK9-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 8
// CHECK9-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
// CHECK9-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
// CHECK9-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
// CHECK9-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
Expand Down Expand Up @@ -2139,7 +2139,7 @@ int main() {
// CHECK11: omp.loop.exit:
// CHECK11-NEXT: [[TMP21:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
// CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[TMP21]], align 4
// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP22]])
// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP22]])
// CHECK11-NEXT: [[TMP23:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
// CHECK11-NEXT: [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
// CHECK11-NEXT: br i1 [[TMP24]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
Expand Down Expand Up @@ -2616,7 +2616,7 @@ int main() {
// CHECK11: omp.loop.exit:
// CHECK11-NEXT: [[TMP20:%.*]] = load ptr, ptr [[DOTGLOBAL_TID__ADDR]], align 4
// CHECK11-NEXT: [[TMP21:%.*]] = load i32, ptr [[TMP20]], align 4
// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP21]])
// CHECK11-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP21]])
// CHECK11-NEXT: [[TMP22:%.*]] = load i32, ptr [[DOTOMP_IS_LAST]], align 4
// CHECK11-NEXT: [[TMP23:%.*]] = icmp ne i32 [[TMP22]], 0
// CHECK11-NEXT: br i1 [[TMP23]], label [[DOTOMP_LASTPRIVATE_THEN:%.*]], label [[DOTOMP_LASTPRIVATE_DONE:%.*]]
Expand Down
48 changes: 24 additions & 24 deletions clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
// CHECK1: terminate.lpad:
// CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -547,7 +547,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
// CHECK1: terminate.lpad:
// CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -879,7 +879,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
// CHECK1: terminate.lpad:
// CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -1026,7 +1026,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
// CHECK1: terminate.lpad:
// CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -1173,7 +1173,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
// CHECK1: terminate.lpad:
// CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -1335,7 +1335,7 @@ int main() {
// CHECK1: omp.inner.for.end:
// CHECK1-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK1: omp.loop.exit:
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK1-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK1-NEXT: ret void
// CHECK1: terminate.lpad:
// CHECK1-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -1638,7 +1638,7 @@ int main() {
// CHECK5: omp.inner.for.end:
// CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK5: omp.loop.exit:
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK5-NEXT: ret void
// CHECK5: terminate.lpad:
// CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -1799,7 +1799,7 @@ int main() {
// CHECK5: omp.inner.for.end:
// CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK5: omp.loop.exit:
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK5-NEXT: ret void
// CHECK5: terminate.lpad:
// CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -2122,7 +2122,7 @@ int main() {
// CHECK5: omp.inner.for.end:
// CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK5: omp.loop.exit:
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK5-NEXT: ret void
// CHECK5: terminate.lpad:
// CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -2269,7 +2269,7 @@ int main() {
// CHECK5: omp.inner.for.end:
// CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK5: omp.loop.exit:
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK5-NEXT: ret void
// CHECK5: terminate.lpad:
// CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -2416,7 +2416,7 @@ int main() {
// CHECK5: omp.inner.for.end:
// CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK5: omp.loop.exit:
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK5-NEXT: ret void
// CHECK5: terminate.lpad:
// CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -2578,7 +2578,7 @@ int main() {
// CHECK5: omp.inner.for.end:
// CHECK5-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK5: omp.loop.exit:
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK5-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK5-NEXT: ret void
// CHECK5: terminate.lpad:
// CHECK5-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -2890,7 +2890,7 @@ int main() {
// CHECK9: omp.inner.for.end:
// CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK9: omp.loop.exit:
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK9-NEXT: ret void
// CHECK9: terminate.lpad:
// CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -3051,7 +3051,7 @@ int main() {
// CHECK9: omp.inner.for.end:
// CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK9: omp.loop.exit:
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK9-NEXT: ret void
// CHECK9: terminate.lpad:
// CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -3383,7 +3383,7 @@ int main() {
// CHECK9: omp.inner.for.end:
// CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK9: omp.loop.exit:
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK9-NEXT: ret void
// CHECK9: terminate.lpad:
// CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -3530,7 +3530,7 @@ int main() {
// CHECK9: omp.inner.for.end:
// CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK9: omp.loop.exit:
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK9-NEXT: ret void
// CHECK9: terminate.lpad:
// CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -3677,7 +3677,7 @@ int main() {
// CHECK9: omp.inner.for.end:
// CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK9: omp.loop.exit:
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK9-NEXT: ret void
// CHECK9: terminate.lpad:
// CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -3839,7 +3839,7 @@ int main() {
// CHECK9: omp.inner.for.end:
// CHECK9-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK9: omp.loop.exit:
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK9-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK9-NEXT: ret void
// CHECK9: terminate.lpad:
// CHECK9-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -4142,7 +4142,7 @@ int main() {
// CHECK13: omp.inner.for.end:
// CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK13: omp.loop.exit:
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK13-NEXT: ret void
// CHECK13: terminate.lpad:
// CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -4303,7 +4303,7 @@ int main() {
// CHECK13: omp.inner.for.end:
// CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK13: omp.loop.exit:
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK13-NEXT: ret void
// CHECK13: terminate.lpad:
// CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -4626,7 +4626,7 @@ int main() {
// CHECK13: omp.inner.for.end:
// CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK13: omp.loop.exit:
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK13-NEXT: ret void
// CHECK13: terminate.lpad:
// CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -4773,7 +4773,7 @@ int main() {
// CHECK13: omp.inner.for.end:
// CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK13: omp.loop.exit:
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK13-NEXT: ret void
// CHECK13: terminate.lpad:
// CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -4920,7 +4920,7 @@ int main() {
// CHECK13: omp.inner.for.end:
// CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK13: omp.loop.exit:
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK13-NEXT: ret void
// CHECK13: terminate.lpad:
// CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down Expand Up @@ -5082,7 +5082,7 @@ int main() {
// CHECK13: omp.inner.for.end:
// CHECK13-NEXT: br label [[OMP_LOOP_EXIT:%.*]]
// CHECK13: omp.loop.exit:
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB1]], i32 [[TMP3]])
// CHECK13-NEXT: call void @__kmpc_for_static_fini(ptr @[[GLOB2]], i32 [[TMP3]])
// CHECK13-NEXT: ret void
// CHECK13: terminate.lpad:
// CHECK13-NEXT: [[TMP11:%.*]] = landingpad { ptr, i32 }
Expand Down
Loading