From be4c7d480f9bd2d6ca8d7b7bafb8000a1b4c9d4b Mon Sep 17 00:00:00 2001 From: bruteforceboy Date: Fri, 11 Jul 2025 11:01:43 +0300 Subject: [PATCH 1/2] [CIR][CodeGen] Fix catch-all dispatch and multiple destructor calls --- .../CIR/Dialect/Builder/CIRBaseBuilder.h | 23 ++- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 137 ++--------------- .../clang/CIR/Dialect/IR/CIREnumAttr.td | 38 +++++ clang/include/clang/CIR/Dialect/IR/CIROps.td | 59 ++++---- clang/include/clang/CIR/Dialect/IR/CIRTypes.h | 50 ++++++- .../include/clang/CIR/Dialect/IR/CIRTypes.td | 76 ++++++++-- clang/lib/CIR/CodeGen/CIRGenBuilder.cpp | 4 +- clang/lib/CIR/CodeGen/CIRGenBuilder.h | 36 ++++- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 4 +- clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 60 ++++++++ clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp | 3 +- clang/lib/CIR/CodeGen/CIRGenCleanup.cpp | 15 +- clang/lib/CIR/CodeGen/CIRGenDecl.cpp | 6 +- clang/lib/CIR/CodeGen/CIRGenException.cpp | 24 ++- clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 16 +- clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp | 6 +- clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 6 +- clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 2 +- clang/lib/CIR/CodeGen/CIRGenModule.cpp | 29 ++-- clang/lib/CIR/CodeGen/CIRGenModule.h | 3 +- clang/lib/CIR/CodeGen/CIRGenTypeCache.h | 4 +- clang/lib/CIR/CodeGen/TargetInfo.cpp | 10 +- clang/lib/CIR/CodeGen/TargetInfo.h | 10 +- clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 59 ++------ clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 21 +-- clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 140 +++++++++++------- .../TargetLowering/LowerFunction.cpp | 10 +- .../TargetLowering/TargetLoweringInfo.h | 5 +- .../TargetLowering/Targets/AArch64.cpp | 15 +- .../TargetLowering/Targets/NVPTX.cpp | 15 +- .../TargetLowering/Targets/SPIR.cpp | 15 +- .../Transforms/TargetLowering/Targets/X86.cpp | 15 +- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 44 +++--- .../ThroughMLIR/LowerCIRLoopToSCF.cpp | 2 +- clang/test/CIR/CodeGen/X86/avx-builtins.c | 3 + .../CIR/CodeGen/X86/avx10_2bf16-builtins.c | 15 ++ .../test/CIR/CodeGen/X86/avx512bw-builtins.c | 29 ++++ clang/test/CIR/CodeGen/X86/avx512f-builtins.c | 48 ++++++ .../CIR/CodeGen/X86/avx512fp16-builtins.c | 16 ++ .../test/CIR/CodeGen/X86/avx512vl-builtins.c | 70 +++++++++ .../CIR/CodeGen/X86/avx512vlbw-buiiltins.c | 53 +++++++ clang/test/CIR/CodeGen/X86/bmi-builtins.c | 5 +- clang/test/CIR/CodeGen/X86/builtins-x86.c | 47 ------ clang/test/CIR/CodeGen/X86/lzcnt-builtins.c | 3 + clang/test/CIR/CodeGen/X86/mmx-builtins.c | 3 + clang/test/CIR/CodeGen/X86/pause.c | 22 +++ clang/test/CIR/CodeGen/X86/rd-builtins.c | 3 +- clang/test/CIR/CodeGen/X86/sse-builtins.c | 11 ++ clang/test/CIR/CodeGen/X86/sse2-builtins.c | 27 ++++ clang/test/CIR/CodeGen/X86/sse41-builtins.c | 2 + clang/test/CIR/CodeGen/X86/x86_64-xsave.c | 5 +- .../test/CIR/CodeGen/conditional-cleanup.cpp | 4 - clang/test/CIR/CodeGen/try-catch-dtors.cpp | 82 +++++++++- clang/test/CIR/IR/invalid.cir | 15 +- 54 files changed, 928 insertions(+), 497 deletions(-) create mode 100644 clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td create mode 100644 clang/test/CIR/CodeGen/X86/avx10_2bf16-builtins.c create mode 100644 clang/test/CIR/CodeGen/X86/avx512bw-builtins.c create mode 100644 clang/test/CIR/CodeGen/X86/avx512f-builtins.c create mode 100644 clang/test/CIR/CodeGen/X86/avx512fp16-builtins.c create mode 100644 clang/test/CIR/CodeGen/X86/avx512vl-builtins.c create mode 100644 clang/test/CIR/CodeGen/X86/avx512vlbw-buiiltins.c delete mode 100644 clang/test/CIR/CodeGen/X86/builtins-x86.c create mode 100644 clang/test/CIR/CodeGen/X86/pause.c diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h index 45bd1a8ebb8f..cb404205f019 100644 --- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h +++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h @@ -93,27 +93,24 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { return cir::IntType::get(getContext(), N, true); } - cir::AddressSpaceAttr getAddrSpaceAttr(clang::LangAS langAS) { - if (langAS == clang::LangAS::Default) - return {}; - return cir::AddressSpaceAttr::get(getContext(), langAS); + cir::PointerType getPointerTo(mlir::Type ty) { + return cir::PointerType::get(ty); } - cir::PointerType getPointerTo(mlir::Type ty, - cir::AddressSpaceAttr cirAS = {}) { - return cir::PointerType::get(ty, cirAS); + cir::PointerType getPointerTo(mlir::Type ty, cir::AddressSpace as) { + return cir::PointerType::get(ty, as); } cir::PointerType getPointerTo(mlir::Type ty, clang::LangAS langAS) { - return getPointerTo(ty, getAddrSpaceAttr(langAS)); + return getPointerTo(ty, cir::toCIRAddressSpace(langAS)); } cir::PointerType getVoidPtrTy(clang::LangAS langAS = clang::LangAS::Default) { return getPointerTo(cir::VoidType::get(getContext()), langAS); } - cir::PointerType getVoidPtrTy(cir::AddressSpaceAttr cirAS) { - return getPointerTo(cir::VoidType::get(getContext()), cirAS); + cir::PointerType getVoidPtrTy(cir::AddressSpace as) { + return getPointerTo(cir::VoidType::get(getContext()), as); } cir::MethodAttr getMethodAttr(cir::MethodType ty, cir::FuncOp methodFuncOp) { @@ -396,7 +393,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { mlir::Value createGetGlobal(mlir::Location loc, cir::GlobalOp global, bool threadLocal = false) { return create( - loc, getPointerTo(global.getSymType(), global.getAddrSpaceAttr()), + loc, getPointerTo(global.getSymType(), global.getAddrSpace()), global.getName(), threadLocal); } @@ -774,9 +771,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder { auto methodFuncInputTypes = methodFuncTy.getInputs(); auto objectPtrTy = mlir::cast(objectPtr.getType()); - auto objectPtrAddrSpace = mlir::cast_if_present( - objectPtrTy.getAddrSpace()); - auto adjustedThisTy = getVoidPtrTy(objectPtrAddrSpace); + auto adjustedThisTy = getVoidPtrTy(objectPtrTy.getAddrSpace()); llvm::SmallVector calleeFuncInputTypes{adjustedThisTy}; calleeFuncInputTypes.insert(calleeFuncInputTypes.end(), diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 0def5436f7b9..5ea69e8db0b3 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -14,7 +14,7 @@ #define MLIR_CIR_DIALECT_CIR_ATTRS include "mlir/IR/BuiltinAttributeInterfaces.td" -include "mlir/IR/EnumAttr.td" +include "clang/CIR/Dialect/IR/CIREnumAttr.td" include "clang/CIR/Dialect/IR/CIRDialect.td" include "clang/CIR/Dialect/IR/CIRAttrConstraints.td" @@ -45,21 +45,6 @@ class CIR_TypedAttr traits = []> let assemblyFormat = [{}]; } -class CIR_I32EnumAttr cases> - : I32EnumAttr { - let cppNamespace = "::cir"; -} - -class CIR_I64EnumAttr cases> - : I64EnumAttr { - let cppNamespace = "::cir"; -} - -class CIR_EnumAttr traits = []> - : EnumAttr { - let assemblyFormat = "`<` $value `>`"; -} - class CIRUnitAttr traits = []> : CIR_Attr { let returnType = "bool"; @@ -972,133 +957,41 @@ def DynamicCastInfoAttr // AddressSpaceAttr //===----------------------------------------------------------------------===// -def AS_OffloadPrivate : I32EnumAttrCase<"offload_private", 1>; -def AS_OffloadLocal : I32EnumAttrCase<"offload_local", 2>; -def AS_OffloadGlobal : I32EnumAttrCase<"offload_global", 3>; -def AS_OffloadConstant : I32EnumAttrCase<"offload_constant", 4>; -def AS_OffloadGeneric : I32EnumAttrCase<"offload_generic", 5>; -def AS_Target : I32EnumAttrCase<"target", 6>; - -def AddressSpaceAttr : CIR_Attr<"AddressSpace", "addrspace"> { - - let summary = "Address space attribute for pointer types"; - let description = [{ - The address space attribute is used in pointer types. It essentially - provides a unified model on top of `clang::LangAS`, rather than LLVM address - spaces. - - The representation is further simplified: `LangAS::Default` is encoded as - a null attribute; many address spaces from different offloading languages - are unified as `offload_*`; etc. - - The meaning of `value` parameter is defined as an extensible enum `Kind`, - which encodes target AS as offset to the last language AS. - }]; - - let parameters = (ins "int32_t":$value); - - let assemblyFormat = [{ - `<` $value `>` - }]; - +def CIR_AddressSpaceAttr : CIR_EnumAttr { let builders = [ AttrBuilder<(ins "clang::LangAS":$langAS), [{ - assert(langAS != clang::LangAS::Default && - "Default address space is encoded as null attribute"); - return $_get($_ctxt, getValueFromLangAS(langAS).value()); + return $_get($_ctxt, cir::toCIRAddressSpace(langAS)); }]> ]; - let cppNamespace = "::cir"; - - // The following codes implement these conversions: - // clang::LangAS -> int32_t <-> text-form CIR - - // CIR_PointerType manipulates the parse- and stringify- methods to provide - // simplified assembly format `custom`. - - list langASCases = [ - AS_OffloadPrivate, AS_OffloadLocal, AS_OffloadGlobal, AS_OffloadConstant, - AS_OffloadGeneric - ]; + let assemblyFormat = [{ + `` custom($value) + }]; - I32EnumAttrCase targetASCase = AS_Target; + let defaultValue = "cir::AddressSpace::Default"; let extraClassDeclaration = [{ - static constexpr char kTargetKeyword[] = "}]#targetASCase.symbol#[{"; - static constexpr int32_t kFirstTargetASValue = }]#targetASCase.value#[{; - bool isLang() const; bool isTarget() const; unsigned getTargetValue() const; - - /// Convert a clang LangAS to its corresponding CIR AS storage value. This - /// helper does not perform any language-specific mappings (e.g. determining - /// the default AS for offloading languages), so these must be handled in - /// the caller. - static std::optional getValueFromLangAS(clang::LangAS v); - - /// Helper methods for the assembly format `custom`. - static std::optional parseValueFromString(llvm::StringRef s); - static std::optional stringifyValue(int32_t v); - - struct Kind { - }]#!interleave( - !foreach(case, langASCases, - "static constexpr int32_t "#case.symbol#" = "#case.value#";" - ), "\n" - )#[{ - }; + unsigned getAsUnsignedValue() const; }]; let extraClassDefinition = [{ + unsigned $cppClass::getAsUnsignedValue() const { + return static_cast(getValue()); + } + bool $cppClass::isLang() const { - return !isTarget(); + return cir::isLangAddressSpace(getValue()); } bool $cppClass::isTarget() const { - return getValue() >= kFirstTargetASValue; + return cir::isTargetAddressSpace(getValue()); } unsigned $cppClass::getTargetValue() const { - assert(isTarget() && "Not a target address space"); - return getValue() - kFirstTargetASValue; - } - - std::optional - $cppClass::parseValueFromString(llvm::StringRef str) { - return llvm::StringSwitch<::std::optional>(str) - }] - # - !interleave( - !foreach(case, langASCases, - ".Case(\""#case.symbol# "\", "#case.value # ")\n" - ), - "\n" - ) - # - [{ - // Target address spaces are not parsed here - .Default(std::nullopt); - } - - std::optional - $cppClass::stringifyValue(int32_t value) { - switch (value) { - }] - # - !interleave( - !foreach(case, langASCases, - "case "#case.value - # ": return \""#case.symbol # "\";" ), - "\n" - ) - # - [{ - default: - // Target address spaces are not processed here - return std::nullopt; - } + return cir::getTargetAddressSpaceValue(getValue()); } }]; } diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td new file mode 100644 index 000000000000..98b8a31d2a18 --- /dev/null +++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines the CIR dialect enum base classes +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_CIR_DIALECT_IR_CIRENUMATTR_TD +#define CLANG_CIR_DIALECT_IR_CIRENUMATTR_TD + +include "mlir/IR/EnumAttr.td" + +class CIR_I32EnumAttr cases> + : I32EnumAttr { + let cppNamespace = "::cir"; +} + +class CIR_I64EnumAttr cases> + : I64EnumAttr { + let cppNamespace = "::cir"; +} + +class CIR_EnumAttr traits = []> + : EnumAttr { + let assemblyFormat = "`<` $value `>`"; +} + +class CIR_DefaultValuedEnumParameter + : EnumParameter { + let defaultValue = value; +} + +#endif // CLANG_CIR_DIALECT_IR_CIRENUMATTR_TD diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 81a45d148453..a2b2e2f5a4fb 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2347,7 +2347,6 @@ def ForOp : CIR_Op<"for", [CIR_LoopOpInterface, NoRegionArguments]> { // currently handy as part of forwarding appropriate linkage types for LLVM // lowering, specially useful for C++ support. - /// An enumeration for the kinds of linkage for global values. def CIR_GlobalLinkageKind : CIR_I32EnumAttr< "GlobalLinkageKind", "linkage kind", [ @@ -2396,10 +2395,11 @@ def CIR_TLSModel : CIR_I32EnumAttr<"TLS_Model", "TLS model", [ I32EnumAttrCase<"LocalExec", 3, "tls_local_exec"> ]>; -def GlobalOp : CIR_Op<"global", - [DeclareOpInterfaceMethods, - DeclareOpInterfaceMethods, - NoRegionArguments]> { +def CIR_GlobalOp : CIR_Op<"global", [ + DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods, + NoRegionArguments +]> { let summary = "Declares or defines a global variable"; let description = [{ The `cir.global` operation declares or defines a named global variable. @@ -2431,26 +2431,33 @@ def GlobalOp : CIR_Op<"global", // Note that both sym_name and sym_visibility are tied to Symbol trait. // TODO: sym_visibility can possibly be represented by implementing the // necessary Symbol's interface in terms of linkage instead. - let arguments = (ins SymbolNameAttr:$sym_name, - DefaultValuedAttr< - CIR_VisibilityAttr, - "VisibilityKind::Default" - >:$global_visibility, - OptionalAttr:$sym_visibility, - TypeAttr:$sym_type, - CIR_GlobalLinkageKind:$linkage, - OptionalAttr:$addr_space, - OptionalAttr:$tls_model, - // Note this can also be a FlatSymbolRefAttr - OptionalAttr:$initial_value, - UnitAttr:$comdat, - UnitAttr:$constant, - UnitAttr:$dso_local, - OptionalAttr:$alignment, - OptionalAttr:$ast, - OptionalAttr:$section, - OptionalAttr:$annotations); + let arguments = (ins + SymbolNameAttr:$sym_name, + DefaultValuedAttr< + CIR_VisibilityAttr, + "VisibilityKind::Default" + >:$global_visibility, + OptionalAttr:$sym_visibility, + TypeAttr:$sym_type, + CIR_GlobalLinkageKind:$linkage, + DefaultValuedAttr< + CIR_AddressSpaceAttr, + "AddressSpace::Default" + >:$addr_space, + OptionalAttr:$tls_model, + // Note this can also be a FlatSymbolRefAttr + OptionalAttr:$initial_value, + UnitAttr:$comdat, + UnitAttr:$constant, + UnitAttr:$dso_local, + OptionalAttr:$alignment, + OptionalAttr:$ast, + OptionalAttr:$section, + OptionalAttr:$annotations + ); + let regions = (region AnyRegion:$ctorRegion, AnyRegion:$dtorRegion); + let assemblyFormat = [{ ($sym_visibility^)? (`` $global_visibility^)? @@ -2459,7 +2466,7 @@ def GlobalOp : CIR_Op<"global", (`comdat` $comdat^)? ($tls_model^)? (`dso_local` $dso_local^)? - (`addrspace` `(` custom($addr_space)^ `)`)? + ( `addrspace` `(` $addr_space^ `)` )? $sym_name custom($sym_type, $initial_value, $ctorRegion, $dtorRegion) ($annotations^)? @@ -2483,7 +2490,7 @@ def GlobalOp : CIR_Op<"global", // CIR defaults to external linkage. CArg<"cir::GlobalLinkageKind", "cir::GlobalLinkageKind::ExternalLinkage">:$linkage, - CArg<"cir::AddressSpaceAttr", "{}">:$addrSpace, + CArg<"cir::AddressSpace", "cir::AddressSpace::Default">:$addrSpace, CArg<"llvm::function_ref", "nullptr">:$ctorBuilder, CArg<"llvm::function_ref", diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h index 4a0fe7f40ff5..b7cf95d08ca8 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MLIR_DIALECT_CIR_IR_CIRTYPES_H_ -#define MLIR_DIALECT_CIR_IR_CIRTYPES_H_ +#ifndef CLANG_CIR_DIALECT_IR_CIRTYPES_H +#define CLANG_CIR_DIALECT_IR_CIRTYPES_H #include "mlir/IR/BuiltinAttributes.h" #include "mlir/IR/Types.h" @@ -30,12 +30,44 @@ bool isValidFundamentalIntWidth(unsigned width); // Returns true if the type is a CIR sized type. bool isSized(mlir::Type ty); -} // namespace cir +//===----------------------------------------------------------------------===// +// AddressSpace helpers +//===----------------------------------------------------------------------===// + +cir::AddressSpace toCIRAddressSpace(clang::LangAS langAS); + +constexpr unsigned getAsUnsignedValue(cir::AddressSpace as) { + return static_cast(as); +} + +inline constexpr unsigned TargetAddressSpaceOffset = + cir::getMaxEnumValForAddressSpace(); + +// Target address space is used for target-specific address spaces that are not +// part of the enum. Its value is represented as an offset from the maximum +// value of the enum. Make sure that it is always the last enum value. +static_assert(getAsUnsignedValue(cir::AddressSpace::Target) == + cir::getMaxEnumValForAddressSpace(), + "Target address space must be the last enum value"); -mlir::ParseResult parseAddrSpaceAttribute(mlir::AsmParser &p, - mlir::Attribute &addrSpaceAttr); -void printAddrSpaceAttribute(mlir::AsmPrinter &p, - mlir::Attribute addrSpaceAttr); +constexpr bool isTargetAddressSpace(cir::AddressSpace as) { + return getAsUnsignedValue(as) >= cir::getMaxEnumValForAddressSpace(); +} + +constexpr bool isLangAddressSpace(cir::AddressSpace as) { + return !isTargetAddressSpace(as); +} + +constexpr unsigned getTargetAddressSpaceValue(cir::AddressSpace as) { + assert(isTargetAddressSpace(as) && "expected target address space"); + return getAsUnsignedValue(as) - TargetAddressSpaceOffset; +} + +constexpr cir::AddressSpace computeTargetAddressSpace(unsigned v) { + return static_cast(v + TargetAddressSpaceOffset); +} + +} // namespace cir //===----------------------------------------------------------------------===// // CIR Dialect Tablegen'd Types @@ -45,9 +77,11 @@ namespace cir { #include "clang/CIR/Dialect/IR/CIRTypeConstraints.h.inc" +class AddressSpaceAttr; + } // namespace cir #define GET_TYPEDEF_CLASSES #include "clang/CIR/Dialect/IR/CIROpsTypes.h.inc" -#endif // MLIR_DIALECT_CIR_IR_CIRTYPES_H_ +#endif // CLANG_CIR_DIALECT_IR_CIRTYPES_H diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td index b09d477bab3e..47cb8a302465 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td @@ -14,6 +14,7 @@ #define MLIR_CIR_DIALECT_CIR_TYPES include "clang/CIR/Dialect/IR/CIRDialect.td" +include "clang/CIR/Dialect/IR/CIREnumAttr.td" include "clang/CIR/Dialect/IR/CIRTypeConstraints.td" include "clang/CIR/Interfaces/ASTAttrInterfaces.td" include "clang/CIR/Interfaces/CIRTypeInterfaces.td" @@ -199,45 +200,90 @@ def CIR_ComplexType : CIR_Type<"Complex", "complex", [ // PointerType //===----------------------------------------------------------------------===// +def CIR_AddressSpace : CIR_I32EnumAttr< + "AddressSpace", "address space kind", [ + I32EnumAttrCase<"Default", 0, "default">, + I32EnumAttrCase<"OffloadPrivate", 1, "offload_private">, + I32EnumAttrCase<"OffloadLocal", 2, "offload_local">, + I32EnumAttrCase<"OffloadGlobal", 3, "offload_global">, + I32EnumAttrCase<"OffloadConstant", 4, "offload_constant">, + I32EnumAttrCase<"OffloadGeneric", 5, "offload_generic">, + I32EnumAttrCase<"Target", 6, "target"> +]> { + let description = [{ + The `address_space` attribute is used to represent address spaces for + pointer types in CIR. It provides a unified model on top of `clang::LangAS` + and simplifies the representation of address spaces. + + The `value` parameter is an extensible enum, which encodes target address + space as an offset to the last language address space. For that reason, the + attribute is implemented as custom AddressSpaceAttr, which provides custom + printer and parser for the `value` parameter. + }]; + + let genSpecializedAttr = 0; +} + def CIR_PointerType : CIR_Type<"Pointer", "ptr", [ DeclareTypeInterfaceMethods, DeclareTypeInterfaceMethods ]> { let summary = "CIR pointer type"; let description = [{ - `CIR.ptr` is a type returned by any op generating a pointer in C++. + The `!cir.ptr` type is a typed pointer type. It is used to represent + pointers to objects in C/C++. The type of the pointed-to object is given by + the `pointee` parameter. The `addrSpace` parameter is an optional address + space attribute that specifies the address space of the pointer. If not + specified, the pointer is assumed to be in the default address space. + + The `!cir.ptr` type can point to any type, including fundamental types, + records, arrays, vectors, functions, and other pointers. It can also point + to incomplete types, such as incomplete records. + + Note: Data-member pointers and method pointers are represented by + `!cir.data_member` and `!cir.method` types, respectively not by + `!cir.ptr` type. + + Examples: + + ```mlir + !cir.ptr> + !cir.ptr + !cir.ptr> + !cir.ptr, addrspace(offload_private)> + !cir.ptr, addrspace(target<1>)> + ``` }]; let parameters = (ins "mlir::Type":$pointee, - // FIXME(cir): Currently unable to directly use AddressSpaceAttr because of - // cyclic dep. Workaround with the top type and verifier. - OptionalParameter<"mlir::Attribute">:$addrSpace + CIR_DefaultValuedEnumParameter< + CIR_AddressSpace, + "cir::AddressSpace::Default" + >:$addrSpace ); + let skipDefaultBuilders = 1; let builders = [ TypeBuilderWithInferredContext<(ins "mlir::Type":$pointee, - CArg<"mlir::Attribute", "{}">:$addrSpace), [{ - return $_get(pointee.getContext(), pointee, addrSpace); + CArg<"cir::AddressSpace", "cir::AddressSpace::Default">:$addrSpace), [{ + return $_get(pointee.getContext(), pointee, addrSpace); }]>, TypeBuilder<(ins "mlir::Type":$pointee, - CArg<"mlir::Attribute", "{}">:$addrSpace), [{ - return $_get($_ctxt, pointee, addrSpace); + CArg<"cir::AddressSpace", "cir::AddressSpace::Default">:$addrSpace), [{ + return $_get($_ctxt, pointee, addrSpace); }]> ]; let assemblyFormat = [{ - `<` $pointee ( `,` `addrspace` `(` - custom($addrSpace)^ - `)` )? `>` + `<` + $pointee + ( `,` `addrspace` `(` custom($addrSpace)^ `)` )? + `>` }]; - let genVerifyDecl = 1; - - let skipDefaultBuilders = 1; - let extraClassDeclaration = [{ template bool isPtrTo() const { diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp index 672bc4fa0717..437db1a7fdd8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp @@ -17,10 +17,8 @@ mlir::Value CIRGenBuilderTy::maybeBuildArrayDecay(mlir::Location loc, auto arrayTy = ::mlir::dyn_cast(arrayPtrTy.getPointee()); if (arrayTy) { - auto addrSpace = ::mlir::cast_if_present( - arrayPtrTy.getAddrSpace()); cir::PointerType flatPtrTy = - getPointerTo(arrayTy.getElementType(), addrSpace); + getPointerTo(arrayTy.getElementType(), arrayPtrTy.getAddrSpace()); return create(loc, flatPtrTy, cir::CastKind::array_to_ptrdecay, arrayPtr); } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index d83e04ec22b1..aaeaa3ea5701 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -745,7 +745,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { [[nodiscard]] cir::GlobalOp createGlobal(mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConst, cir::GlobalLinkageKind linkage, - cir::AddressSpaceAttr addrSpace = {}) { + cir::AddressSpace addrSpace = cir::AddressSpace::Default) { mlir::OpBuilder::InsertionGuard guard(*this); setInsertionPointToStart(module.getBody()); return create(loc, name, type, isConst, linkage, addrSpace); @@ -754,11 +754,10 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { /// Creates a versioned global variable. If the symbol is already taken, an ID /// will be appended to the symbol. The returned global must always be queried /// for its name so it can be referenced correctly. - [[nodiscard]] cir::GlobalOp - createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc, - mlir::StringRef name, mlir::Type type, bool isConst, - cir::GlobalLinkageKind linkage, - cir::AddressSpaceAttr addrSpace = {}) { + [[nodiscard]] cir::GlobalOp createVersionedGlobal( + mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name, + mlir::Type type, bool isConst, cir::GlobalLinkageKind linkage, + cir::AddressSpace addrSpace = cir::AddressSpace::Default) { // Create a unique name if the given name is already taken. std::string uniqueName; if (unsigned version = GlobalsVersioning[name.str()]++) @@ -895,6 +894,31 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { return CIRBaseBuilderTy::createStore(loc, flag, dst); } + /// Create a call to a masked store intrinsic. + /// \p loc - expression location + /// \p val - data to be stored + /// \p ptr - base pointer for the store + /// \p alignment - alignment of the destination location + /// \p mask - vector of booleans which indicates what vector lanes should + /// be accessed in memory + mlir::Value createMaskedStore(mlir::Location loc, mlir::Value val, + mlir::Value ptr, llvm::Align alignment, + mlir::Value mask) { + mlir::Type dataTy = val.getType(); + + assert(mlir::isa(dataTy) && "val should be a vector"); + assert(mask && "mask should not be all-ones (null)"); + + auto alignmentValue = create( + loc, cir::IntAttr::get(getUInt32Ty(), alignment.value())); + + mlir::Value ops[] = {val, ptr, alignmentValue, mask}; + + return create(loc, getStringAttr("masked.store"), + getVoidTy(), ops) + .getResult(); + } + cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1, mlir::Value vec2, llvm::ArrayRef maskAttrs) { diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 00d835f2360a..683a438e7a75 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1652,8 +1652,8 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // the AST level this is handled within CreateTempAlloca et al., but for the // builtin / dynamic alloca we have to handle it here. assert(!cir::MissingFeatures::addressSpace()); - auto AAS = getCIRAllocaAddressSpace(); - auto EAS = builder.getAddrSpaceAttr( + cir::AddressSpace AAS = getCIRAllocaAddressSpace(); + cir::AddressSpace EAS = cir::toCIRAddressSpace( E->getType()->getPointeeType().getAddressSpace()); if (EAS != AAS) { assert(false && "Non-default address space for alloca NYI"); diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 0433a2b45e62..593fa9349acd 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -74,6 +74,40 @@ static int64_t getIntValueFromConstOp(mlir::Value val) { .getSExtValue(); } +// Convert the mask from an integer type to a vector of i1. +static mlir::Value getMaskVecValue(CIRGenFunction &cgf, mlir::Value mask, + unsigned numElts, mlir::Location loc) { + cir::VectorType maskTy = + cir::VectorType::get(cgf.getBuilder().getSIntNTy(1), + cast(mask.getType()).getWidth()); + + mlir::Value maskVec = cgf.getBuilder().createBitcast(mask, maskTy); + + // If we have less than 8 elements, then the starting mask was an i8 and + // we need to extract down to the right number of elements. + if (numElts < 8) { + llvm::SmallVector indices; + for (unsigned i = 0; i != numElts; ++i) + indices.push_back(i); + maskVec = cgf.getBuilder().createVecShuffle(loc, maskVec, maskVec, indices); + } + + return maskVec; +} + +static mlir::Value emitX86MaskedStore(CIRGenFunction &cgf, + ArrayRef ops, + llvm::Align alignment, + mlir::Location loc) { + mlir::Value ptr = ops[0]; + + mlir::Value maskVec = getMaskVecValue( + cgf, ops[2], cast(ops[1].getType()).getSize(), loc); + + return cgf.getBuilder().createMaskedStore(loc, ops[1], ptr, alignment, + maskVec); +} + mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E) { if (BuiltinID == Builtin::BI__builtin_cpu_is) @@ -368,5 +402,31 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned BuiltinID, builder.getStringAttr("x86.xgetbv"), builder.getUInt64Ty(), Ops) .getResult(); + case X86::BI__builtin_ia32_storedqudi128_mask: + case X86::BI__builtin_ia32_storedqusi128_mask: + case X86::BI__builtin_ia32_storedquhi128_mask: + case X86::BI__builtin_ia32_storedquqi128_mask: + case X86::BI__builtin_ia32_storeupd128_mask: + case X86::BI__builtin_ia32_storeups128_mask: + case X86::BI__builtin_ia32_storedqudi256_mask: + case X86::BI__builtin_ia32_storedqusi256_mask: + case X86::BI__builtin_ia32_storedquhi256_mask: + case X86::BI__builtin_ia32_storedquqi256_mask: + case X86::BI__builtin_ia32_storeupd256_mask: + case X86::BI__builtin_ia32_storeups256_mask: + case X86::BI__builtin_ia32_storedqudi512_mask: + case X86::BI__builtin_ia32_storedqusi512_mask: + case X86::BI__builtin_ia32_storedquhi512_mask: + case X86::BI__builtin_ia32_storedquqi512_mask: + case X86::BI__builtin_ia32_storeupd512_mask: + case X86::BI__builtin_ia32_storeups512_mask: + return emitX86MaskedStore(*this, Ops, llvm::Align(1), + getLoc(E->getExprLoc())); + case X86::BI__builtin_ia32_storesbf16128_mask: + case X86::BI__builtin_ia32_storesh128_mask: + case X86::BI__builtin_ia32_storess128_mask: + case X86::BI__builtin_ia32_storesd128_mask: + return emitX86MaskedStore(*this, Ops, llvm::Align(1), + getLoc(E->getExprLoc())); } } diff --git a/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp b/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp index fbc34255c6a4..dba29d8cab83 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCUDANV.cpp @@ -314,7 +314,8 @@ mlir::Operation *CIRGenNVCUDARuntime::getKernelHandle(cir::FuncOp fn, fn->getLoc(), globalName, fn.getFunctionType(), [&] { return CIRGenModule::createGlobalOp( cgm, fn->getLoc(), globalName, - builder.getPointerTo(fn.getFunctionType()), true, /* addrSpace=*/{}, + builder.getPointerTo(fn.getFunctionType()), true, + cir::AddressSpace::Default, /*insertPoint=*/nullptr, fn.getLinkage()); }); diff --git a/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp b/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp index 242aee079f22..84f479a3c832 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp @@ -643,12 +643,17 @@ void CIRGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) { // We only actually emit the cleanup code if the cleanup is either // active or was used before it was deactivated. if (EHActiveFlag.isValid() || IsActive) { - cleanupFlags.setIsForEHCleanup(); - mlir::OpBuilder::InsertionGuard guard(builder); - auto yield = cast(ehEntry->getTerminator()); - builder.setInsertionPoint(yield); - emitCleanup(*this, Fn, cleanupFlags, EHActiveFlag); + + // We skip the cleanups at the end of CIR scopes as they will be handled + // later. This prevents cases like multiple destructor calls for the same + // object. + if (!isa(yield->getParentOp())) { + cleanupFlags.setIsForEHCleanup(); + mlir::OpBuilder::InsertionGuard guard(builder); + builder.setInsertionPoint(yield); + emitCleanup(*this, Fn, cleanupFlags, EHActiveFlag); + } } if (CPI) diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp index f04631e22aee..47293b081bf0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp @@ -22,6 +22,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/ExprCXX.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIRDataLayout.h" #include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" @@ -470,8 +471,7 @@ CIRGenModule::getOrCreateStaticVarDecl(const VarDecl &D, Name = getStaticDeclName(*this, D); mlir::Type LTy = getTypes().convertTypeForMem(Ty); - cir::AddressSpaceAttr AS = - builder.getAddrSpaceAttr(getGlobalVarAddressSpace(&D)); + cir::AddressSpace AS = cir::toCIRAddressSpace(getGlobalVarAddressSpace(&D)); // OpenCL variables in local address space and CUDA shared // variables cannot have an initializer. @@ -586,7 +586,7 @@ cir::GlobalOp CIRGenFunction::addInitializerToStaticVarDecl( // Given those constraints, thread in the GetGlobalOp and update it // directly. GVAddr.getAddr().setType( - getBuilder().getPointerTo(Init.getType(), GV.getAddrSpaceAttr())); + getBuilder().getPointerTo(Init.getType(), GV.getAddrSpace())); } bool NeedsDtor = diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp index b438f9aae0f5..881f00211a69 100644 --- a/clang/lib/CIR/CodeGen/CIRGenException.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp @@ -418,7 +418,7 @@ static void emitCatchDispatchBlock(CIRGenFunction &CGF, // that catch-all as the dispatch block. if (catchScope.getNumHandlers() == 1 && catchScope.getHandler(0).isCatchAll()) { - // assert(dispatchBlock == catchScope.getHandler(0).Block); + assert(dispatchBlock == catchScope.getHandler(0).Block); return; } @@ -786,13 +786,21 @@ CIRGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si, case EHScope::Catch: { // LLVM does some optimization with branches here, CIR just keep track of // the corresponding calls. - assert(callWithExceptionCtx && "expected call information"); - { - mlir::OpBuilder::InsertionGuard guard(getBuilder()); - assert(callWithExceptionCtx.getCleanup().empty() && - "one per call: expected empty region at this point"); - dispatchBlock = builder.createBlock(&callWithExceptionCtx.getCleanup()); - builder.createYield(callWithExceptionCtx.getLoc()); + EHCatchScope &catchScope = cast(scope); + if (catchScope.getNumHandlers() == 1 && + catchScope.getHandler(0).isCatchAll()) { + dispatchBlock = catchScope.getHandler(0).Block; + assert(dispatchBlock); + } else { + assert(callWithExceptionCtx && "expected call information"); + { + mlir::OpBuilder::InsertionGuard guard(getBuilder()); + assert(callWithExceptionCtx.getCleanup().empty() && + "one per call: expected empty region at this point"); + dispatchBlock = + builder.createBlock(&callWithExceptionCtx.getCleanup()); + builder.createYield(callWithExceptionCtx.getLoc()); + } } break; } diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 2ab018aa82f6..fc7ad46937d4 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -24,6 +24,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/GlobalDecl.h" #include "clang/Basic/Builtins.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" @@ -921,9 +922,8 @@ static LValue emitGlobalVarDeclLValue(CIRGenFunction &CGF, const Expr *E, auto V = CGF.CGM.getAddrOfGlobalVar(VD); auto RealVarTy = CGF.convertTypeForMem(VD->getType()); - cir::PointerType realPtrTy = CGF.getBuilder().getPointerTo( - RealVarTy, cast_if_present( - cast(V.getType()).getAddrSpace())); + cir::PointerType realPtrTy = cir::PointerType::get( + RealVarTy, cast(V.getType()).getAddrSpace()); if (realPtrTy != V.getType()) V = CGF.getBuilder().createBitcast(V.getLoc(), V, realPtrTy); @@ -2027,9 +2027,10 @@ LValue CIRGenFunction::emitCastLValue(const CastExpr *E) { case CK_AddressSpaceConversion: { LValue LV = emitLValue(E->getSubExpr()); QualType DestTy = getContext().getPointerType(E->getType()); - auto SrcAS = - builder.getAddrSpaceAttr(E->getSubExpr()->getType().getAddressSpace()); - auto DestAS = builder.getAddrSpaceAttr(E->getType().getAddressSpace()); + cir::AddressSpace SrcAS = + cir::toCIRAddressSpace(E->getSubExpr()->getType().getAddressSpace()); + cir::AddressSpace DestAS = + cir::toCIRAddressSpace(E->getType().getAddressSpace()); mlir::Value V = getTargetHooks().performAddrSpaceCast( *this, LV.getPointer(), SrcAS, DestAS, convertType(DestTy)); return makeAddrLValue(Address(V, convertTypeForMem(E->getType()), @@ -3080,8 +3081,7 @@ Address CIRGenFunction::CreateTempAlloca(mlir::Type Ty, CharUnits Align, // be different from the type defined by the language. For example, // in C++ the auto variables are in the default address space. Therefore // cast alloca to the default address space when necessary. - if (auto ASTAS = - builder.getAddrSpaceAttr(CGM.getLangTempAllocaAddressSpace()); + if (auto ASTAS = cir::toCIRAddressSpace(CGM.getLangTempAllocaAddressSpace()); getCIRAllocaAddressSpace() != ASTAS) { llvm_unreachable("Requires address space cast which is NYI"); } diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp index e16d169d19f5..cdd7a9a42408 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp @@ -426,10 +426,8 @@ void AggExprEmitter::emitArrayInit(Address DestPtr, cir::ArrayType AType, QualType elementPtrType = CGF.getContext().getPointerType(elementType); auto cirElementType = CGF.convertType(elementType); - auto cirAddrSpace = mlir::cast_if_present( - DestPtr.getType().getAddrSpace()); - auto cirElementPtrType = - CGF.getBuilder().getPointerTo(cirElementType, cirAddrSpace); + auto cirElementPtrType = CGF.getBuilder().getPointerTo( + cirElementType, DestPtr.getType().getAddrSpace()); auto loc = CGF.getLoc(ExprToVisit->getSourceRange()); // Cast from cir.ptr to cir.ptr diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 94606775c6b5..fcd169187704 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -1659,10 +1659,10 @@ mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { } // Since target may map different address spaces in AST to the same address // space, an address space conversion may end up as a bitcast. - auto SrcAS = CGF.builder.getAddrSpaceAttr( + cir::AddressSpace SrcAS = cir::toCIRAddressSpace( E->getType()->getPointeeType().getAddressSpace()); - auto DestAS = CGF.builder.getAddrSpaceAttr( - DestTy->getPointeeType().getAddressSpace()); + cir::AddressSpace DestAS = + cir::toCIRAddressSpace(DestTy->getPointeeType().getAddressSpace()); return CGF.CGM.getTargetCIRGenInfo().performAddrSpaceCast( CGF, Visit(E), SrcAS, DestAS, convertType(DestTy)); } diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp index a65d02821de4..a5f9fba96967 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp @@ -1415,7 +1415,7 @@ void CIRGenFunction::StartFunction(GlobalDecl gd, QualType retTy, if (CurFuncDecl) if ([[maybe_unused]] const auto *vecWidth = CurFuncDecl->getAttr()) - llvm_unreachable("NYI"); + LargestVectorWidth = vecWidth->getVectorWidth(); if (CGM.shouldEmitConvergenceTokens()) llvm_unreachable("NYI"); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 09d2609cd7b3..701cc3a1ad46 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -825,7 +825,7 @@ mlir::Value CIRGenModule::getGlobalValue(const Decl *d) { cir::GlobalOp CIRGenModule::createGlobalOp(CIRGenModule &cgm, mlir::Location loc, StringRef name, mlir::Type t, bool isConstant, - cir::AddressSpaceAttr addrSpace, + cir::AddressSpace addrSpace, mlir::Operation *insertPoint, cir::GlobalLinkageKind linkage) { cir::GlobalOp g; @@ -996,10 +996,8 @@ void CIRGenModule::replaceGlobal(cir::GlobalOp oldSym, cir::GlobalOp newSym) { // If the types does not match, update all references to Old to the new type. auto oldTy = oldSym.getSymType(); auto newTy = newSym.getSymType(); - cir::AddressSpaceAttr oldAS = oldSym.getAddrSpaceAttr(); - cir::AddressSpaceAttr newAS = newSym.getAddrSpaceAttr(); // TODO(cir): If the AS differs, we should also update all references. - if (oldAS != newAS) { + if (oldSym.getAddrSpace() != newSym.getAddrSpace()) { llvm_unreachable("NYI"); } @@ -1098,9 +1096,9 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty, entry = dyn_cast_or_null(v); } - cir::AddressSpaceAttr cirAS = builder.getAddrSpaceAttr(langAS); + cir::AddressSpace cirAS = cir::toCIRAddressSpace(langAS); if (entry) { - auto entryCIRAS = entry.getAddrSpaceAttr(); + cir::AddressSpace entryCIRAS = entry.getAddrSpace(); if (WeakRefReferences.erase(entry)) { if (d && !d->hasAttr()) { auto lt = cir::GlobalLinkageKind::ExternalLinkage; @@ -1154,7 +1152,7 @@ CIRGenModule::getOrCreateCIRGlobal(StringRef mangledName, mlir::Type ty, return entry; } - auto declCIRAS = builder.getAddrSpaceAttr(getGlobalVarAddressSpace(d)); + auto declCIRAS = cir::toCIRAddressSpace(getGlobalVarAddressSpace(d)); // TODO(cir): do we need to strip pointer casts for Entry? auto loc = getLoc(d->getSourceRange()); @@ -1274,7 +1272,7 @@ mlir::Value CIRGenModule::getAddrOfGlobalVar(const VarDecl *d, mlir::Type ty, bool tlsAccess = d->getTLSKind() != VarDecl::TLS_None; auto g = getOrCreateCIRGlobal(d, ty, isForDefinition); - auto ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpaceAttr()); + auto ptrTy = builder.getPointerTo(g.getSymType(), g.getAddrSpace()); return builder.create(getLoc(d->getSourceRange()), ptrTy, g.getSymName(), tlsAccess); } @@ -1288,7 +1286,8 @@ CIRGenModule::getAddrOfGlobalVarAttr(const VarDecl *d, mlir::Type ty, ty = getTypes().convertTypeForMem(astTy); auto globalOp = getOrCreateCIRGlobal(d, ty, isForDefinition); - auto ptrTy = builder.getPointerTo(globalOp.getSymType()); + auto ptrTy = + builder.getPointerTo(globalOp.getSymType(), globalOp.getAddrSpace()); return builder.getGlobalViewAttr(ptrTy, globalOp); } @@ -1758,14 +1757,14 @@ static cir::GlobalOp generateStringLiteral(mlir::Location loc, mlir::TypedAttr c, cir::GlobalLinkageKind lt, CIRGenModule &cgm, StringRef globalName, CharUnits alignment) { - cir::AddressSpaceAttr addrSpaceAttr = - cgm.getBuilder().getAddrSpaceAttr(cgm.getGlobalConstantAddressSpace()); + cir::AddressSpace addrSpace = + cir::toCIRAddressSpace(cgm.getGlobalConstantAddressSpace()); // Create a global variable for this string // FIXME(cir): check for insertion point in module level. auto gv = CIRGenModule::createGlobalOp(cgm, loc, globalName, c.getType(), !cgm.getLangOpts().WritableStrings, - addrSpaceAttr); + addrSpace); // Set up extra information and add to the module gv.setAlignmentAttr(cgm.getSize(alignment)); @@ -1861,8 +1860,8 @@ CIRGenModule::getAddrOfConstantStringFromLiteral(const StringLiteral *s, auto gv = getGlobalForStringLiteral(s, name); auto arrayTy = mlir::dyn_cast(gv.getSymType()); assert(arrayTy && "String literal must be array"); - auto ptrTy = getBuilder().getPointerTo(arrayTy.getElementType(), - gv.getAddrSpaceAttr()); + auto ptrTy = + getBuilder().getPointerTo(arrayTy.getElementType(), gv.getAddrSpace()); return builder.getGlobalViewAttr(ptrTy, gv); } @@ -1972,7 +1971,7 @@ CIRGenModule::getAddrOfGlobalTemporary(const MaterializeTemporaryExpr *expr, linkage = cir::GlobalLinkageKind::InternalLinkage; } } - auto targetAS = builder.getAddrSpaceAttr(addrSpace); + cir::AddressSpace targetAS = cir::toCIRAddressSpace(addrSpace); auto loc = getLoc(expr->getSourceRange()); auto gv = createGlobalOp(*this, loc, name, type, isConstant, targetAS, diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index e96220ea395a..50d8c3cda18c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -260,7 +260,8 @@ class CIRGenModule : public CIRGenTypeCache { static cir::GlobalOp createGlobalOp( CIRGenModule &cgm, mlir::Location loc, llvm::StringRef name, mlir::Type t, - bool isConstant = false, cir::AddressSpaceAttr addrSpace = {}, + bool isConstant = false, + cir::AddressSpace addrSpace = cir::AddressSpace::Default, mlir::Operation *insertPoint = nullptr, cir::GlobalLinkageKind linkage = cir::GlobalLinkageKind::ExternalLinkage); diff --git a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h index 551bc74861b6..c83d60673f23 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypeCache.h +++ b/clang/lib/CIR/CodeGen/CIRGenTypeCache.h @@ -106,7 +106,7 @@ struct CIRGenTypeCache { unsigned char SizeAlignInBytes; }; - cir::AddressSpaceAttr CIRAllocaAddressSpace; + cir::AddressSpace CIRAllocaAddressSpace; clang::CharUnits getSizeSize() const { return clang::CharUnits::fromQuantity(SizeSizeInBytes); @@ -121,7 +121,7 @@ struct CIRGenTypeCache { return clang::CharUnits::fromQuantity(PointerAlignInBytes); } - cir::AddressSpaceAttr getCIRAllocaAddressSpace() const { + cir::AddressSpace getCIRAllocaAddressSpace() const { return CIRAllocaAddressSpace; } }; diff --git a/clang/lib/CIR/CodeGen/TargetInfo.cpp b/clang/lib/CIR/CodeGen/TargetInfo.cpp index 17129bb813fb..d7e57cfc5a87 100644 --- a/clang/lib/CIR/CodeGen/TargetInfo.cpp +++ b/clang/lib/CIR/CodeGen/TargetInfo.cpp @@ -266,10 +266,8 @@ class CommonSPIRTargetCIRGenInfo : public TargetCIRGenInfo { CommonSPIRTargetCIRGenInfo(std::unique_ptr ABIInfo) : TargetCIRGenInfo(std::move(ABIInfo)) {} - cir::AddressSpaceAttr getCIRAllocaAddressSpace() const override { - return cir::AddressSpaceAttr::get( - &getABIInfo().CGT.getMLIRContext(), - cir::AddressSpaceAttr::Kind::offload_private); + cir::AddressSpace getCIRAllocaAddressSpace() const override { + return cir::AddressSpace::OffloadPrivate; } cir::CallingConv getOpenCLKernelCallingConv() const override { @@ -664,8 +662,8 @@ TargetCIRGenInfo::getGlobalVarAddressSpace(CIRGenModule &CGM, } mlir::Value TargetCIRGenInfo::performAddrSpaceCast( - CIRGenFunction &CGF, mlir::Value Src, cir::AddressSpaceAttr SrcAddr, - cir::AddressSpaceAttr DestAddr, mlir::Type DestTy, bool IsNonNull) const { + CIRGenFunction &CGF, mlir::Value Src, cir::AddressSpace SrcAddr, + cir::AddressSpace DestAddr, mlir::Type DestTy, bool IsNonNull) const { // Since target may map different address spaces in AST to the same address // space, an address space conversion may end up as a bitcast. if (auto globalOp = Src.getDefiningOp()) diff --git a/clang/lib/CIR/CodeGen/TargetInfo.h b/clang/lib/CIR/CodeGen/TargetInfo.h index b941cbb5742f..21f3b0a0637d 100644 --- a/clang/lib/CIR/CodeGen/TargetInfo.h +++ b/clang/lib/CIR/CodeGen/TargetInfo.h @@ -101,10 +101,8 @@ class TargetCIRGenInfo { const clang::VarDecl *D) const; /// Get the CIR address space for alloca. - virtual cir::AddressSpaceAttr getCIRAllocaAddressSpace() const { - // Return the null attribute, which means the target does not care about the - // alloca address space. - return {}; + virtual cir::AddressSpace getCIRAllocaAddressSpace() const { + return cir::AddressSpace::Default; } /// Perform address space cast of an expression of pointer type. @@ -114,8 +112,8 @@ class TargetCIRGenInfo { /// \param DestTy is the destination pointer type. /// \param IsNonNull is the flag indicating \p V is known to be non null. virtual mlir::Value performAddrSpaceCast(CIRGenFunction &CGF, mlir::Value V, - cir::AddressSpaceAttr SrcAddr, - cir::AddressSpaceAttr DestAddr, + cir::AddressSpace SrcAddr, + cir::AddressSpace DestAddr, mlir::Type DestTy, bool IsNonNull = false) const; diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index 30cc71d7b234..e18676c23e4d 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -72,6 +72,19 @@ static mlir::ParseResult parseConstPtr(mlir::AsmParser &parser, static void printConstPtr(mlir::AsmPrinter &p, mlir::IntegerAttr value); +//===----------------------------------------------------------------------===// +// AddressSpaceAttr +//===----------------------------------------------------------------------===// + +mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p, + cir::AddressSpace &addrSpace); + +void printAddressSpaceValue(mlir::AsmPrinter &p, cir::AddressSpace addrSpace); + +//===----------------------------------------------------------------------===// +// Tablegen defined attributes +//===----------------------------------------------------------------------===// + #define GET_ATTRDEF_CLASSES #include "clang/CIR/Dialect/IR/CIROpsAttributes.cpp.inc" @@ -562,52 +575,6 @@ LogicalResult DynamicCastInfoAttr::verify( return success(); } -//===----------------------------------------------------------------------===// -// AddressSpaceAttr definitions -//===----------------------------------------------------------------------===// - -std::optional -AddressSpaceAttr::getValueFromLangAS(clang::LangAS langAS) { - using clang::LangAS; - switch (langAS) { - case LangAS::Default: - // Default address space should be encoded as a null attribute. - return std::nullopt; - case LangAS::opencl_global: - return Kind::offload_global; - case LangAS::opencl_local: - case LangAS::cuda_shared: - // Local means local among the work-group (OpenCL) or block (CUDA). - // All threads inside the kernel can access local memory. - return Kind::offload_local; - case LangAS::cuda_device: - return Kind::offload_global; - case LangAS::opencl_constant: - case LangAS::cuda_constant: - return Kind::offload_constant; - case LangAS::opencl_private: - return Kind::offload_private; - case LangAS::opencl_generic: - return Kind::offload_generic; - case LangAS::opencl_global_device: - case LangAS::opencl_global_host: - case LangAS::sycl_global: - case LangAS::sycl_global_device: - case LangAS::sycl_global_host: - case LangAS::sycl_local: - case LangAS::sycl_private: - case LangAS::ptr32_sptr: - case LangAS::ptr32_uptr: - case LangAS::ptr64: - case LangAS::hlsl_groupshared: - case LangAS::wasm_funcref: - llvm_unreachable("NYI"); - default: - // Target address space offset arithmetics - return clang::toTargetAddressSpace(langAS) + kFirstTargetASValue; - } -} - //===----------------------------------------------------------------------===// // CIR Dialect //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index fe70e8c9236b..5f97a5de0c67 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2105,16 +2105,6 @@ static void printConstant(OpAsmPrinter &p, Attribute value) { p.printAttribute(value); } -static ParseResult -parseGlobalOpAddrSpace(OpAsmParser &p, cir::AddressSpaceAttr &addrSpaceAttr) { - return parseAddrSpaceAttribute(p, addrSpaceAttr); -} - -static void printGlobalOpAddrSpace(OpAsmPrinter &p, cir::GlobalOp op, - cir::AddressSpaceAttr addrSpaceAttr) { - printAddrSpaceAttribute(p, addrSpaceAttr); -} - static void printGlobalOpTypeAndInitialValue(OpAsmPrinter &p, cir::GlobalOp op, TypeAttr type, Attribute initAttr, mlir::Region &ctorRegion, @@ -2287,7 +2277,7 @@ LogicalResult cir::GlobalOp::verify() { void cir::GlobalOp::build( OpBuilder &odsBuilder, OperationState &odsState, llvm::StringRef sym_name, Type sym_type, bool isConstant, cir::GlobalLinkageKind linkage, - cir::AddressSpaceAttr addrSpace, + cir::AddressSpace addrSpace, function_ref ctorBuilder, function_ref dtorBuilder) { odsState.addAttribute(getSymNameAttrName(odsState.name), @@ -2302,8 +2292,9 @@ void cir::GlobalOp::build( cir::GlobalLinkageKindAttr::get(odsBuilder.getContext(), linkage); odsState.addAttribute(getLinkageAttrName(odsState.name), linkageAttr); - if (addrSpace) - odsState.addAttribute(getAddrSpaceAttrName(odsState.name), addrSpace); + odsState.addAttribute( + getAddrSpaceAttrName(odsState.name), + cir::AddressSpaceAttr::get(odsBuilder.getContext(), addrSpace)); Region *ctorRegion = odsState.addRegion(); if (ctorBuilder) { @@ -2366,10 +2357,10 @@ cir::GetGlobalOp::verifySymbolUses(SymbolTableCollection &symbolTable) { << "' does not reference a valid cir.global or cir.func"; mlir::Type symTy; - cir::AddressSpaceAttr symAddrSpace{}; + cir::AddressSpace symAddrSpace{}; if (auto g = dyn_cast(op)) { symTy = g.getSymType(); - symAddrSpace = g.getAddrSpaceAttr(); + symAddrSpace = g.getAddrSpace(); // Verify that for thread local global access, the global needs to // be marked with tls bits. if (getTls() && !g.getTlsModel()) diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp index 4d35b4aebbf0..09ad0f3b9f51 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -13,6 +13,7 @@ #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/IR/CIRTypesDetails.h" #include "clang/CIR/MissingFeatures.h" @@ -61,10 +62,15 @@ parseFuncTypeParams(mlir::AsmParser &p, llvm::SmallVector ¶ms, static void printFuncTypeParams(mlir::AsmPrinter &p, mlir::ArrayRef params, bool isVarArg); -static mlir::ParseResult parsePointerAddrSpace(mlir::AsmParser &p, - mlir::Attribute &addrSpaceAttr); -static void printPointerAddrSpace(mlir::AsmPrinter &p, - mlir::Attribute addrSpaceAttr); + +//===----------------------------------------------------------------------===// +// AddressSpace +//===----------------------------------------------------------------------===// + +mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p, + cir::AddressSpace &addrSpace); + +void printAddressSpaceValue(mlir::AsmPrinter &p, cir::AddressSpace addrSpace); //===----------------------------------------------------------------------===// // Get autogenerated stuff @@ -897,67 +903,91 @@ MethodType::getABIAlignment(const mlir::DataLayout &dataLayout, } //===----------------------------------------------------------------------===// -// PointerType Definitions +// AddressSpace definitions //===----------------------------------------------------------------------===// -mlir::LogicalResult -PointerType::verify(llvm::function_ref emitError, - mlir::Type pointee, mlir::Attribute addrSpace) { - if (addrSpace && !mlir::isa(addrSpace)) - return emitError() << "unexpected addrspace attribute type"; - return mlir::success(); -} - -mlir::ParseResult parseAddrSpaceAttribute(mlir::AsmParser &p, - mlir::Attribute &addrSpaceAttr) { - using cir::AddressSpaceAttr; - auto attrLoc = p.getCurrentLocation(); - - llvm::StringRef addrSpaceKind; - if (mlir::failed(p.parseOptionalKeyword(&addrSpaceKind))) - return p.emitError(attrLoc, "expected keyword for addrspace kind"); - - if (addrSpaceKind == AddressSpaceAttr::kTargetKeyword) { - int64_t targetValue = -1; - if (p.parseLess() || p.parseInteger(targetValue) || p.parseGreater()) { - return mlir::failure(); - } - addrSpaceAttr = AddressSpaceAttr::get( - p.getContext(), AddressSpaceAttr::kFirstTargetASValue + targetValue); - } else { - std::optional value = - AddressSpaceAttr::parseValueFromString(addrSpaceKind); - // not target AS, must be wrong keyword if no value - if (!value.has_value()) - return p.emitError(attrLoc, - "invalid addrspace kind keyword: " + addrSpaceKind); - - addrSpaceAttr = AddressSpaceAttr::get(p.getContext(), *value); +cir::AddressSpace cir::toCIRAddressSpace(clang::LangAS langAS) { + using clang::LangAS; + switch (langAS) { + case LangAS::Default: + return AddressSpace::Default; + case LangAS::opencl_global: + return AddressSpace::OffloadGlobal; + case LangAS::opencl_local: + case LangAS::cuda_shared: + // Local means local among the work-group (OpenCL) or block (CUDA). + // All threads inside the kernel can access local memory. + return AddressSpace::OffloadLocal; + case LangAS::cuda_device: + return AddressSpace::OffloadGlobal; + case LangAS::opencl_constant: + case LangAS::cuda_constant: + return AddressSpace::OffloadConstant; + case LangAS::opencl_private: + return AddressSpace::OffloadPrivate; + case LangAS::opencl_generic: + return AddressSpace::OffloadGeneric; + case LangAS::opencl_global_device: + case LangAS::opencl_global_host: + case LangAS::sycl_global: + case LangAS::sycl_global_device: + case LangAS::sycl_global_host: + case LangAS::sycl_local: + case LangAS::sycl_private: + case LangAS::ptr32_sptr: + case LangAS::ptr32_uptr: + case LangAS::ptr64: + case LangAS::hlsl_groupshared: + case LangAS::wasm_funcref: + llvm_unreachable("NYI"); + default: + // Target address space offset arithmetics + return static_cast(clang::toTargetAddressSpace(langAS) + + cir::getMaxEnumValForAddressSpace()); } - - return mlir::success(); } -void printAddrSpaceAttribute(mlir::AsmPrinter &p, - mlir::Attribute rawAddrSpaceAttr) { - using cir::AddressSpaceAttr; - auto addrSpaceAttr = mlir::cast(rawAddrSpaceAttr); - if (addrSpaceAttr.isTarget()) { - p << AddressSpaceAttr::kTargetKeyword << "<" - << addrSpaceAttr.getTargetValue() << ">"; +mlir::ParseResult parseAddressSpaceValue(mlir::AsmParser &p, + cir::AddressSpace &addrSpace) { + llvm::SMLoc loc = p.getCurrentLocation(); + mlir::FailureOr result = + mlir::FieldParser::parse(p); + if (mlir::failed(result)) + return p.emitError(loc, "expected address space keyword"); + + // Address space is either a target address space or a regular one. + // - If it is a target address space, we expect a value to follow in the form + // of ``, where value is an integer that represents the target address + // space value. This value is kept in the address space enum as an offset + // from the maximum address space value, which is defined in + // `cir::getMaxEnumValForAddressSpace()`. This allows us to use + // the same enum for both regular and target address spaces. + // - Otherwise, we just use the parsed value. + if (cir::isTargetAddressSpace(result.value())) { + if (p.parseLess()) + return p.emitError(loc, "expected '<' after target address space"); + + int64_t targetValue; + if (p.parseInteger(targetValue) || p.parseGreater()) + return p.emitError(loc, "expected target address space value"); + + addrSpace = cir::computeTargetAddressSpace(targetValue); } else { - p << AddressSpaceAttr::stringifyValue(addrSpaceAttr.getValue()); + addrSpace = result.value(); } -} -mlir::ParseResult parsePointerAddrSpace(mlir::AsmParser &p, - mlir::Attribute &addrSpaceAttr) { - return parseAddrSpaceAttribute(p, addrSpaceAttr); + return mlir::success(); } -void printPointerAddrSpace(mlir::AsmPrinter &p, - mlir::Attribute rawAddrSpaceAttr) { - printAddrSpaceAttribute(p, rawAddrSpaceAttr); +// Prints the address space value in the form of: +// - `target` for target address spaces +// - or just the address space name for regular address spaces. +void printAddressSpaceValue(mlir::AsmPrinter &p, cir::AddressSpace addrSpace) { + if (cir::isTargetAddressSpace(addrSpace)) + p << cir::stringifyEnum(cir::AddressSpace::Target) << '<' + << cir::getTargetAddressSpaceValue(addrSpace) << '>'; + else + p << cir::stringifyEnum(addrSpace); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp index ff9c9dc295b9..32f660024125 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerFunction.cpp @@ -375,7 +375,7 @@ mlir::Value createCoercedNonFundamental(mlir::Value src, mlir::Type ty, auto oldAlloca = mlir::dyn_cast(addr.getDefiningOp()); auto alloca = bld.create( - src.getLoc(), bld.getType(ty), ty, + src.getLoc(), cir::PointerType::get(ty), ty, /*name=*/llvm::StringRef(""), oldAlloca.getAlignmentAttr()); auto tySize = LF.LM.getDataLayout().getTypeStoreSize(ty); @@ -582,7 +582,7 @@ llvm::LogicalResult LowerFunction::buildFunctionProlog( // FIXME(cir): Get the original name of the argument, as well as the // proper alignment for the given type being allocated. auto Alloca = rewriter.create( - Fn.getLoc(), rewriter.getType(Ty), Ty, + Fn.getLoc(), cir::PointerType::get(Ty), Ty, /*name=*/llvm::StringRef(""), /*alignment=*/rewriter.getI64IntegerAttr(4)); @@ -673,7 +673,7 @@ llvm::LogicalResult LowerFunction::buildFunctionProlog( cir_cconv_assert(!ArgI.getIndirectByVal() && "For truly ABI indirect arguments"); - auto ptrTy = rewriter.getType(Arg.getType()); + auto ptrTy = cir::PointerType::get(Arg.getType()); mlir::Value arg = SrcFn.getArgument(ArgNo); cir_cconv_assert(arg.hasOneUse()); auto *firstStore = *arg.user_begin(); @@ -683,7 +683,7 @@ llvm::LogicalResult LowerFunction::buildFunctionProlog( auto align = LM.getDataLayout().getABITypeAlign(ptrTy); auto alignAttr = rewriter.getI64IntegerAttr(align.value()); auto newAlloca = rewriter.create( - Fn.getLoc(), rewriter.getType(ptrTy), ptrTy, + Fn.getLoc(), cir::PointerType::get(ptrTy), ptrTy, /*name=*/llvm::StringRef(""), /*alignment=*/alignAttr); @@ -1008,7 +1008,7 @@ mlir::Value createAlloca(mlir::Location loc, mlir::Type type, auto align = CGF.LM.getDataLayout().getABITypeAlign(type); auto alignAttr = CGF.getRewriter().getI64IntegerAttr(align.value()); return CGF.getRewriter().create( - loc, CGF.getRewriter().getType(type), type, + loc, cir::PointerType::get(type), type, /*name=*/llvm::StringRef(""), alignAttr); } diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.h b/clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.h index 8d33ef2e5dca..114d8cc0f697 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.h +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.h @@ -31,8 +31,9 @@ class TargetLoweringInfo { virtual ~TargetLoweringInfo(); const ABIInfo &getABIInfo() const { return *Info; } - virtual unsigned getTargetAddrSpaceFromCIRAddrSpace( - cir::AddressSpaceAttr addressSpaceAttr) const = 0; + + virtual unsigned + getTargetAddrSpaceFromCIRAddrSpace(cir::AddressSpace addrSpace) const = 0; }; } // namespace cir diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/AArch64.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/AArch64.cpp index 6751bd7d99a0..9a8edf39d738 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/AArch64.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/AArch64.cpp @@ -62,14 +62,13 @@ class AArch64TargetLoweringInfo : public TargetLoweringInfo { } unsigned getTargetAddrSpaceFromCIRAddrSpace( - cir::AddressSpaceAttr addressSpaceAttr) const override { - using Kind = cir::AddressSpaceAttr::Kind; - switch (addressSpaceAttr.getValue()) { - case Kind::offload_private: - case Kind::offload_local: - case Kind::offload_global: - case Kind::offload_constant: - case Kind::offload_generic: + cir::AddressSpace addrSpace) const override { + switch (addrSpace) { + case cir::AddressSpace::OffloadPrivate: + case cir::AddressSpace::OffloadLocal: + case cir::AddressSpace::OffloadGlobal: + case cir::AddressSpace::OffloadConstant: + case cir::AddressSpace::OffloadGeneric: return 0; default: cir_cconv_unreachable("Unknown CIR address space for this target"); diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/NVPTX.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/NVPTX.cpp index 4f6a76dadabb..00f961d38666 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/NVPTX.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/NVPTX.cpp @@ -45,18 +45,17 @@ class NVPTXTargetLoweringInfo : public TargetLoweringInfo { : TargetLoweringInfo(std::make_unique(lt)) {} unsigned getTargetAddrSpaceFromCIRAddrSpace( - cir::AddressSpaceAttr addressSpaceAttr) const override { - using Kind = cir::AddressSpaceAttr::Kind; - switch (addressSpaceAttr.getValue()) { - case Kind::offload_private: + cir::AddressSpace addrSpace) const override { + switch (addrSpace) { + case cir::AddressSpace::OffloadPrivate: return 0; - case Kind::offload_local: + case cir::AddressSpace::OffloadLocal: return 3; - case Kind::offload_global: + case cir::AddressSpace::OffloadGlobal: return 1; - case Kind::offload_constant: + case cir::AddressSpace::OffloadConstant: return 4; - case Kind::offload_generic: + case cir::AddressSpace::OffloadGeneric: return 0; default: cir_cconv_unreachable("Unknown CIR address space for this target"); diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/SPIR.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/SPIR.cpp index deffd8d27a05..0a4dc640decd 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/SPIR.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/SPIR.cpp @@ -42,18 +42,17 @@ class SPIRVTargetLoweringInfo : public TargetLoweringInfo { : TargetLoweringInfo(std::make_unique(LT)) {} unsigned getTargetAddrSpaceFromCIRAddrSpace( - cir::AddressSpaceAttr addressSpaceAttr) const override { - using Kind = cir::AddressSpaceAttr::Kind; - switch (addressSpaceAttr.getValue()) { - case Kind::offload_private: + cir::AddressSpace addrSpace) const override { + switch (addrSpace) { + case cir::AddressSpace::OffloadPrivate: return 0; - case Kind::offload_local: + case cir::AddressSpace::OffloadLocal: return 3; - case Kind::offload_global: + case cir::AddressSpace::OffloadGlobal: return 1; - case Kind::offload_constant: + case cir::AddressSpace::OffloadConstant: return 2; - case Kind::offload_generic: + case cir::AddressSpace::OffloadGeneric: return 4; default: cir_cconv_unreachable("Unknown CIR address space for this target"); diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/X86.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/X86.cpp index 4a198dd6091f..ec8c880ef3ab 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/X86.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/X86.cpp @@ -110,14 +110,13 @@ class X86_64TargetLoweringInfo : public TargetLoweringInfo { } unsigned getTargetAddrSpaceFromCIRAddrSpace( - cir::AddressSpaceAttr addressSpaceAttr) const override { - using Kind = cir::AddressSpaceAttr::Kind; - switch (addressSpaceAttr.getValue()) { - case Kind::offload_private: - case Kind::offload_local: - case Kind::offload_global: - case Kind::offload_constant: - case Kind::offload_generic: + cir::AddressSpace addrSpace) const override { + switch (addrSpace) { + case cir::AddressSpace::OffloadPrivate: + case cir::AddressSpace::OffloadLocal: + case cir::AddressSpace::OffloadGlobal: + case cir::AddressSpace::OffloadConstant: + case cir::AddressSpace::OffloadGeneric: return 0; default: cir_cconv_unreachable("Unknown CIR address space for this target"); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 0a42a90aa1d6..db53b1eea463 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -43,6 +43,7 @@ #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Export.h" +#include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" @@ -349,7 +350,7 @@ unsigned getGlobalOpTargetAddrSpace(mlir::ConversionPatternRewriter &rewriter, const mlir::TypeConverter *converter, cir::GlobalOp op) { auto tempPtrTy = cir::PointerType::get(rewriter.getContext(), op.getSymType(), - op.getAddrSpaceAttr()); + op.getAddrSpace()); return cast(converter->convertType(tempPtrTy)) .getAddressSpace(); } @@ -4422,32 +4423,31 @@ std::unique_ptr prepareLowerModule(mlir::ModuleOp module) { return cir::createLowerModule(module, rewriter); } +static unsigned +getTargetAddrSpaceFromCIRAddrSpace(cir::AddressSpace addrSpace, + cir::LowerModule *lowerModule) { + if (addrSpace == cir::AddressSpace::Default) + return 0; // Default address space is always 0 in LLVM. + + if (cir::isTargetAddressSpace(addrSpace)) + return cir::getTargetAddressSpaceValue(addrSpace); + + assert(lowerModule && "CIR AS map is not available"); + return lowerModule->getTargetLoweringInfo() + .getTargetAddrSpaceFromCIRAddrSpace(addrSpace); +} + // FIXME: change the type of lowerModule to `LowerModule &` to have better // lambda capturing experience. Also blocked by makeTripleAlwaysPresent. void prepareTypeConverter(mlir::LLVMTypeConverter &converter, mlir::DataLayout &dataLayout, cir::LowerModule *lowerModule) { - converter.addConversion( - [&, lowerModule](cir::PointerType type) -> mlir::Type { - // Drop pointee type since LLVM dialect only allows opaque pointers. - - auto addrSpace = - mlir::cast_if_present(type.getAddrSpace()); - // Null addrspace attribute indicates the default addrspace. - if (!addrSpace) - return mlir::LLVM::LLVMPointerType::get(type.getContext()); - - assert(lowerModule && "CIR AS map is not available"); - // Pass through target addrspace and map CIR addrspace to LLVM addrspace - // by querying the target info. - unsigned targetAS = - addrSpace.isTarget() - ? addrSpace.getTargetValue() - : lowerModule->getTargetLoweringInfo() - .getTargetAddrSpaceFromCIRAddrSpace(addrSpace); - - return mlir::LLVM::LLVMPointerType::get(type.getContext(), targetAS); - }); + converter.addConversion([&, + lowerModule](cir::PointerType type) -> mlir::Type { + unsigned addrSpace = + getTargetAddrSpaceFromCIRAddrSpace(type.getAddrSpace(), lowerModule); + return mlir::LLVM::LLVMPointerType::get(type.getContext(), addrSpace); + }); converter.addConversion( [&, lowerModule](cir::DataMemberType type) -> mlir::Type { assert(lowerModule && "CXXABI is not available"); diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRLoopToSCF.cpp b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRLoopToSCF.cpp index a1ef4a286464..1b826dfa7a36 100644 --- a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRLoopToSCF.cpp +++ b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRLoopToSCF.cpp @@ -464,7 +464,7 @@ class CIRWhileOpLowering : public mlir::OpConversionPattern { rewriter.setInsertionPointToStart(whileOp.getAfterBody()); auto boolTy = rewriter.getType(); - auto boolPtrTy = rewriter.getType(boolTy); + auto boolPtrTy = cir::PointerType::get(boolTy); auto alignment = rewriter.getI64IntegerAttr(4); auto condAlloca = rewriter.create(loc, boolPtrTy, boolTy, "condition", alignment); diff --git a/clang/test/CIR/CodeGen/X86/avx-builtins.c b/clang/test/CIR/CodeGen/X86/avx-builtins.c index 6c2617d9486a..ba615ec25807 100644 --- a/clang/test/CIR/CodeGen/X86/avx-builtins.c +++ b/clang/test/CIR/CodeGen/X86/avx-builtins.c @@ -18,6 +18,9 @@ // RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx -fno-signed-char -fclangir -emit-llvm -o %t.ll -Wall -Werror // RUN: FileCheck --check-prefixes=LLVM-CHECK,LLVM-X64 --input-file=%t.ll %s +// This test mimics clang/test/CodeGen/X86/avx-builtins.c, which eventually +// CIR shall be able to support fully. + #include int test_mm256_extract_epi8(__m256i A) { diff --git a/clang/test/CIR/CodeGen/X86/avx10_2bf16-builtins.c b/clang/test/CIR/CodeGen/X86/avx10_2bf16-builtins.c new file mode 100644 index 000000000000..10839e89f757 --- /dev/null +++ b/clang/test/CIR/CodeGen/X86/avx10_2bf16-builtins.c @@ -0,0 +1,15 @@ +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx10.2-256 -fclangir -emit-cir -o %t.cir -Wno-invalid-feature-combination -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx10.2-256 -fclangir -emit-llvm -o %t.ll -Wno-invalid-feature-combination -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +#include + +void test_mm_mask_store_sbh(void *__P, __mmask8 __U, __m128bh __A) { + // CIR-LABEL: _mm_mask_store_sbh + // CIR: cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 8>) -> !void + + // LLVM-LABEL: @test_mm_mask_store_sbh + // LLVM: call void @llvm.masked.store.v8bf16.p0(<8 x bfloat> %{{.*}}, ptr %{{.*}}, i32 1, <8 x i1> %{{.*}}) + _mm_mask_store_sbh(__P, __U, __A); +} diff --git a/clang/test/CIR/CodeGen/X86/avx512bw-builtins.c b/clang/test/CIR/CodeGen/X86/avx512bw-builtins.c new file mode 100644 index 000000000000..bb19344c2407 --- /dev/null +++ b/clang/test/CIR/CodeGen/X86/avx512bw-builtins.c @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512bw -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512bw -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512bw -fno-signed-char -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512bw -fno-signed-char -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +#include + +void test_mm512_mask_storeu_epi16(void *__P, __mmask32 __U, __m512i __A) { + // CIR-LABEL: _mm512_mask_storeu_epi16 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 32>) -> !void + + // LLVM-LABEL: @test_mm512_mask_storeu_epi16 + // LLVM: @llvm.masked.store.v32i16.p0(<32 x i16> %{{.*}}, ptr %{{.*}}, i32 1, <32 x i1> %{{.*}}) + return _mm512_mask_storeu_epi16(__P, __U, __A); +} + +void test_mm512_mask_storeu_epi8(void *__P, __mmask64 __U, __m512i __A) { + // CIR-LABEL: _mm512_mask_storeu_epi8 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<{{!s8i|!u8i}} x 64>, !cir.ptr>, !u32i, !cir.vector x 64>) -> !void + + // LLVM-LABEL: @test_mm512_mask_storeu_epi8 + // LLVM: @llvm.masked.store.v64i8.p0(<64 x i8> %{{.*}}, ptr %{{.*}}, i32 1, <64 x i1> %{{.*}}) + return _mm512_mask_storeu_epi8(__P, __U, __A); +} diff --git a/clang/test/CIR/CodeGen/X86/avx512f-builtins.c b/clang/test/CIR/CodeGen/X86/avx512f-builtins.c new file mode 100644 index 000000000000..a8d0425a2e59 --- /dev/null +++ b/clang/test/CIR/CodeGen/X86/avx512f-builtins.c @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512f -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512f -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512f -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512f -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +#include + +void test_mm512_mask_storeu_epi64(void *__P, __mmask8 __U, __m512i __A) { + // CIR-LABEL: _mm512_mask_storeu_epi64 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr, !u32i, !cir.vector x 8>) -> !void + + // LLVM-LABEL: test_mm512_mask_storeu_epi64 + // LLVM: @llvm.masked.store.v8i64.p0(<8 x i64> %{{.*}}, ptr %{{.*}}, i32 1, <8 x i1> %{{.*}}) + return _mm512_mask_storeu_epi64(__P, __U, __A); +} + +void test_mm512_mask_storeu_epi32(void *__P, __mmask16 __U, __m512i __A) { + // CIR-LABEL: _mm512_mask_storeu_epi32 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr, !u32i, !cir.vector x 16>) -> !void + + // LLVM-LABEL: test_mm512_mask_storeu_epi32 + // LLVM: @llvm.masked.store.v16i32.p0(<16 x i32> %{{.*}}, ptr %{{.*}}, i32 1, <16 x i1> %{{.*}}) + return _mm512_mask_storeu_epi32(__P, __U, __A); +} + +void test_mm_mask_store_ss(float * __P, __mmask8 __U, __m128 __A){ + // CIR-LABEL: _mm_mask_store_ss + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 4>) -> !void + + // LLVM-LABEL: test_mm_mask_store_ss + // LLVM: call void @llvm.masked.store.v4f32.p0(<4 x float> %{{.*}}, ptr %{{.*}}, i32 1, <4 x i1> %{{.*}}) + + _mm_mask_store_ss(__P, __U, __A); +} + +void test_mm_mask_store_sd(double * __P, __mmask8 __U, __m128d __A){ + // CIR-LABEL: _mm_mask_store_sd + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 2>) -> !void + + // LLVM-LABEL: test_mm_mask_store_sd + // LLVM: call void @llvm.masked.store.v2f64.p0(<2 x double> %{{.*}}, ptr %{{.*}}, i32 1, <2 x i1> %{{.*}}) + _mm_mask_store_sd(__P, __U, __A); +} diff --git a/clang/test/CIR/CodeGen/X86/avx512fp16-builtins.c b/clang/test/CIR/CodeGen/X86/avx512fp16-builtins.c new file mode 100644 index 000000000000..a58e4f87cfa5 --- /dev/null +++ b/clang/test/CIR/CodeGen/X86/avx512fp16-builtins.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512fp16 -fclangir -emit-cir -o %t.cir -Wall -Werror +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512fp16 -fclangir -emit-llvm -o %t.ll -Wall -Werror +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + + +#include + +void test_mm_mask_store_sh(void *__P, __mmask8 __U, __m128h __A) { + // CIR-LABEL: _mm_mask_store_sh + // CIR: cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 8>) -> !void + + // LLVM-LABEL: @test_mm_mask_store_sh + // LLVM: call void @llvm.masked.store.v8f16.p0(<8 x half> %{{.*}}, ptr %{{.*}}, i32 1, <8 x i1> %{{.*}}) + _mm_mask_store_sh(__P, __U, __A); +} diff --git a/clang/test/CIR/CodeGen/X86/avx512vl-builtins.c b/clang/test/CIR/CodeGen/X86/avx512vl-builtins.c new file mode 100644 index 000000000000..2d02f5e658a6 --- /dev/null +++ b/clang/test/CIR/CodeGen/X86/avx512vl-builtins.c @@ -0,0 +1,70 @@ +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512f -target-feature +avx512vl -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512f -target-feature +avx512vl -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + + +#include + +void test_mm_mask_storeu_epi64(void *__P, __mmask8 __U, __m128i __A) { + // CIR-LABEL: _mm_mask_storeu_epi64 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 2>) + + // LLVM-LABEL: @test_mm_mask_storeu_epi64 + // LLVM: @llvm.masked.store.v2i64.p0(<2 x i64> %{{.*}}, ptr %{{.*}}, i32 1, <2 x i1> %{{.*}}) + return _mm_mask_storeu_epi64(__P, __U, __A); +} + +void test_mm_mask_storeu_epi32(void *__P, __mmask8 __U, __m128i __A) { + // CIR-LABEL: _mm_mask_storeu_epi32 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 4>) + + // LLVM-LABEL: @test_mm_mask_storeu_epi32 + // LLVM: @llvm.masked.store.v4i32.p0(<4 x i32> %{{.*}}, ptr %{{.*}}, i32 1, <4 x i1> %{{.*}}) + return _mm_mask_storeu_epi32(__P, __U, __A); +} + +void test_mm_mask_storeu_pd(void *__P, __mmask8 __U, __m128d __A) { + // CIR-LABEL: _mm_mask_storeu_pd + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 2>) + + // LLVM-LABEL: @test_mm_mask_storeu_pd + // LLVM: @llvm.masked.store.v2f64.p0(<2 x double> %{{.*}}, ptr %{{.*}}, i32 1, <2 x i1> %{{.*}}) + return _mm_mask_storeu_pd(__P, __U, __A); +} + +void test_mm_mask_storeu_ps(void *__P, __mmask8 __U, __m128 __A) { + // CIR-LABEL: _mm_mask_storeu_ps + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 4>) + + // LLVM-LABEL: @test_mm_mask_storeu_ps + // LLVM: @llvm.masked.store.v4f32.p0(<4 x float> %{{.*}}, ptr %{{.*}}, i32 1, <4 x i1> %{{.*}}) + return _mm_mask_storeu_ps(__P, __U, __A); +} + +void test_mm256_mask_storeu_epi32(void *__P, __mmask8 __U, __m256i __A) { + // CIR-LABEL: _mm256_mask_storeu_epi32 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 8>) + + // LLVM-LABEL: @test_mm256_mask_storeu_epi32 + // LLVM: @llvm.masked.store.v8i32.p0(<8 x i32> %{{.*}}, ptr %{{.*}}, i32 1, <8 x i1> %{{.*}}) + return _mm256_mask_storeu_epi32(__P, __U, __A); +} + +void test_mm256_mask_storeu_epi64(void *__P, __mmask8 __U, __m256i __A) { + // CIR-LABEL: _mm256_mask_storeu_epi64 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 4>) + + // LLVM-LABEL: @test_mm256_mask_storeu_epi64 + // LLVM: @llvm.masked.store.v4i64.p0(<4 x i64> %{{.*}}, ptr %{{.*}}, i32 1, <4 x i1> %{{.*}}) + return _mm256_mask_storeu_epi64(__P, __U, __A); +} + +void test_mm256_mask_storeu_ps(void *__P, __mmask8 __U, __m256 __A) { + // CIR-LABEL: _mm256_mask_storeu_ps + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 8>) -> !void + + // LLVM-LABEL: @test_mm256_mask_storeu_ps + // LLVM: @llvm.masked.store.v8f32.p0(<8 x float> %{{.*}}, ptr %{{.*}}, i32 1, <8 x i1> %{{.*}}) + return _mm256_mask_storeu_ps(__P, __U, __A); +} diff --git a/clang/test/CIR/CodeGen/X86/avx512vlbw-buiiltins.c b/clang/test/CIR/CodeGen/X86/avx512vlbw-buiiltins.c new file mode 100644 index 000000000000..6f778d6316b3 --- /dev/null +++ b/clang/test/CIR/CodeGen/X86/avx512vlbw-buiiltins.c @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512bw -target-feature +avx512vl -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512bw -target-feature +avx512vl -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx512bw -target-feature +avx512vl -fno-signed-char -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx10.1-512 -target-feature +avx512vl -fclangir -emit-cir -o %t.cir -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +avx10.1-512 -target-feature +avx512vl -fclangir -emit-llvm -o %t.ll -Wall -Werror -Wsign-conversion +// RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s + + +#include + +void test_mm_mask_storeu_epi16(void *__P, __mmask8 __U, __m128i __A) { + // CIR-LABEL: _mm_mask_storeu_epi16 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 8>) + + // LLVM-LABEL: @test_mm_mask_storeu_epi16 + // LLVM: @llvm.masked.store.v8i16.p0(<8 x i16> %{{.*}}, ptr %{{.*}}, i32 1, <8 x i1> %{{.*}}) + return _mm_mask_storeu_epi16(__P, __U, __A); +} + +void test_mm_mask_storeu_epi8(void *__P, __mmask16 __U, __m128i __A) { + // CIR-LABEL: _mm_mask_storeu_epi8 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<{{!s8i|!u8i}} x 16>, !cir.ptr>, !u32i, !cir.vector x 16>) + + // LLVM-LABEL: @test_mm_mask_storeu_epi8 + // LLVM: @llvm.masked.store.v16i8.p0(<16 x i8> %{{.*}}, ptr %{{.*}}, i32 1, <16 x i1> %{{.*}}) + return _mm_mask_storeu_epi8(__P, __U, __A); +} + +void test_mm256_mask_storeu_epi8(void *__P, __mmask32 __U, __m256i __A) { + // CIR-LABEL: _mm256_mask_storeu_epi8 + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector<{{!s8i|!u8i}} x 32>, !cir.ptr>, !u32i, !cir.vector x 32>) -> !void + + // LLVM-LABEL: @test_mm256_mask_storeu_epi8 + // LLVM: @llvm.masked.store.v32i8.p0(<32 x i8> %{{.*}}, ptr %{{.*}}, i32 1, <32 x i1> %{{.*}}) + return _mm256_mask_storeu_epi8(__P, __U, __A); +} + +void test_mm256_mask_storeu_pd(void *__P, __mmask8 __U, __m256d __A) { + // CIR-LABEL: _mm256_mask_storeu_pd + // CIR: %{{.*}} = cir.llvm.intrinsic "masked.store" %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : (!cir.vector, !cir.ptr>, !u32i, !cir.vector x 4>) -> !void + + // LLVM-LABEL: @test_mm256_mask_storeu_pd + // LLVM: @llvm.masked.store.v4f64.p0(<4 x double> %{{.*}}, ptr %{{.*}}, i32 1, <4 x i1> %{{.*}}) + return _mm256_mask_storeu_pd(__P, __U, __A); +} diff --git a/clang/test/CIR/CodeGen/X86/bmi-builtins.c b/clang/test/CIR/CodeGen/X86/bmi-builtins.c index 52d555bcd59f..6e5873bfd339 100644 --- a/clang/test/CIR/CodeGen/X86/bmi-builtins.c +++ b/clang/test/CIR/CodeGen/X86/bmi-builtins.c @@ -3,6 +3,9 @@ // RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s // RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s +// This test mimics clang/test/CodeGen/X86/bmi-builtins.c, which eventually +// CIR shall be able to support fully. + #include unsigned short test__tzcnt_u16(unsigned short __X) { @@ -29,4 +32,4 @@ unsigned long long test__tzcnt_u64(unsigned long long __X) { // CIR: {{%.*}} = cir.llvm.intrinsic "cttz" {{%.*}} : (!u64i, !cir.bool) -> !u64i // LLVM: i64 @llvm.cttz.i64(i64 %{{.*}}, i1 false) } -#endif \ No newline at end of file +#endif diff --git a/clang/test/CIR/CodeGen/X86/builtins-x86.c b/clang/test/CIR/CodeGen/X86/builtins-x86.c deleted file mode 100644 index c8d00aaf3bf2..000000000000 --- a/clang/test/CIR/CodeGen/X86/builtins-x86.c +++ /dev/null @@ -1,47 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s -// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s -// RUN: %clang_cc1 -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s -// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s - -// This test mimics clang/test/CodeGen/builtins-x86.c, which eventually -// CIR shall be able to support fully. - -void test_mm_clflush(const void* tmp_vCp) { - // CIR-LABEL: test_mm_clflush - // LLVM-LABEL: test_mm_clflush - _mm_clflush(tmp_vCp); - // CIR: {{%.*}} = cir.llvm.intrinsic "x86.sse2.clflush" {{%.*}} : (!cir.ptr) -> !void - // LLVM: call void @llvm.x86.sse2.clflush(ptr {{%.*}}) -} - -void test_mm_lfence() { - // CIR-LABEL: test_mm_lfence - // LLVM-LABEL: test_mm_lfence - _mm_lfence(); - // CIR: {{%.*}} = cir.llvm.intrinsic "x86.sse2.lfence" : () -> !void - // LLVM: call void @llvm.x86.sse2.lfence() -} - -void test_mm_pause() { - // CIR-LABEL: test_mm_pause - // LLVM-LABEL: test_mm_pause - _mm_pause(); - // CIR: {{%.*}} = cir.llvm.intrinsic "x86.sse2.pause" : () -> !void - // LLVM: call void @llvm.x86.sse2.pause() -} - -void test_mm_mfence() { - // CIR-LABEL: test_mm_mfence - // LLVM-LABEL: test_mm_mfence - _mm_mfence(); - // CIR: {{%.*}} = cir.llvm.intrinsic "x86.sse2.mfence" : () -> !void - // LLVM: call void @llvm.x86.sse2.mfence() -} - -void test_mm_sfence() { - // CIR-LABEL: test_mm_sfence - // LLVM-LABEL: test_mm_sfence - _mm_sfence(); - // CIR: {{%.*}} = cir.llvm.intrinsic "x86.sse.sfence" : () -> !void - // LLVM: call void @llvm.x86.sse.sfence() -} diff --git a/clang/test/CIR/CodeGen/X86/lzcnt-builtins.c b/clang/test/CIR/CodeGen/X86/lzcnt-builtins.c index 6055afbf9ba8..384be85f9916 100644 --- a/clang/test/CIR/CodeGen/X86/lzcnt-builtins.c +++ b/clang/test/CIR/CodeGen/X86/lzcnt-builtins.c @@ -3,6 +3,9 @@ // RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s // RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s +// This test mimics clang/test/CodeGen/X86/lzcnt-builtins.c, which eventually +// CIR shall be able to support fully. + #include unsigned int test_lzcnt_u32(unsigned int __X) diff --git a/clang/test/CIR/CodeGen/X86/mmx-builtins.c b/clang/test/CIR/CodeGen/X86/mmx-builtins.c index 6643ec20201c..3b75c00995b7 100644 --- a/clang/test/CIR/CodeGen/X86/mmx-builtins.c +++ b/clang/test/CIR/CodeGen/X86/mmx-builtins.c @@ -8,6 +8,9 @@ // RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +ssse3 -fno-signed-char -fclangir -emit-llvm -o %t.ll -Wall -Werror // RUN: FileCheck --check-prefix=LLVM-CHECK --implicit-check-not=x86mmx --input-file=%t.ll %s +// This test mimics clang/test/CodeGen/X86/mmx-builtins.c, which eventually +// CIR shall be able to support fully. + #include int test_mm_extract_pi16(__m64 a) { diff --git a/clang/test/CIR/CodeGen/X86/pause.c b/clang/test/CIR/CodeGen/X86/pause.c new file mode 100644 index 000000000000..67a0d6770c51 --- /dev/null +++ b/clang/test/CIR/CodeGen/X86/pause.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -Wno-implicit-function-declaration -target-feature +sse2 -fclangir -emit-cir -o %t.cir %s +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -Wno-implicit-function-declaration -target-feature +sse2 -fclangir -emit-llvm -o %t.ll %s +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s + +// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -Wno-implicit-function-declaration -target-feature -sse2 -fclangir -emit-cir -o %t.cir %s +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -ffreestanding -triple x86_64-unknown-linux -Wno-implicit-function-declaration -target-feature -sse2 -fclangir -emit-llvm -o %t.ll %s +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s + +// This test mimics clang/test/CodeGen/X86/pause.c, which eventually +// CIR shall be able to support fully. + +#include + +void test_mm_pause(void) { + // CIR-LABEL: test_mm_pause + // LLVM-LABEL: test_mm_pause + _mm_pause(); + // CIR: {{%.*}} = cir.llvm.intrinsic "x86.sse2.pause" : () -> !void + // LLVM: call void @llvm.x86.sse2.pause() +} diff --git a/clang/test/CIR/CodeGen/X86/rd-builtins.c b/clang/test/CIR/CodeGen/X86/rd-builtins.c index 8f8902199b10..2c279ceba24c 100644 --- a/clang/test/CIR/CodeGen/X86/rd-builtins.c +++ b/clang/test/CIR/CodeGen/X86/rd-builtins.c @@ -8,7 +8,7 @@ #include -unsigned long long test_rdtsc() { +int test_rdtsc(void) { // CIR-LABEL: @test_rdtsc // LLVM-LABEL: @test_rdtsc return __rdtsc(); @@ -32,4 +32,3 @@ unsigned long long test_rdtscp(unsigned int *a) { // LLVM: store i32 [[TSC_AUX]], ptr %{{.*}} // LLVM: [[TSC:%.*]] = extractvalue { i64, i32 } [[RDTSCP]], 0 } - diff --git a/clang/test/CIR/CodeGen/X86/sse-builtins.c b/clang/test/CIR/CodeGen/X86/sse-builtins.c index 08e805bce334..8b2c8fd1eb38 100644 --- a/clang/test/CIR/CodeGen/X86/sse-builtins.c +++ b/clang/test/CIR/CodeGen/X86/sse-builtins.c @@ -8,6 +8,9 @@ // RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse -fclangir -emit-llvm -o %t.ll -Wall -Werror // RUN: FileCheck --check-prefixes=LLVM --input-file=%t.ll %s +// This test mimics clang/test/CodeGen/X86/sse-builtins.c, which eventually +// CIR shall be able to support fully. + #include @@ -18,3 +21,11 @@ void test_mm_prefetch(char const* p) { // CIR: cir.prefetch(%{{.*}} : !cir.ptr) locality(0) read // LLVM: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 0, i32 1) } + +void test_mm_sfence(void) { + // CIR-LABEL: test_mm_sfence + // LLVM-LABEL: test_mm_sfence + _mm_sfence(); + // CIR: {{%.*}} = cir.llvm.intrinsic "x86.sse.sfence" : () -> !void + // LLVM: call void @llvm.x86.sse.sfence() +} diff --git a/clang/test/CIR/CodeGen/X86/sse2-builtins.c b/clang/test/CIR/CodeGen/X86/sse2-builtins.c index 873d72a021f4..2524357da6a9 100644 --- a/clang/test/CIR/CodeGen/X86/sse2-builtins.c +++ b/clang/test/CIR/CodeGen/X86/sse2-builtins.c @@ -8,8 +8,19 @@ // RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse2 -fno-signed-char -fclangir -emit-llvm -o %t.ll -Wall -Werror // RUN: FileCheck --check-prefixes=LLVM-CHECK --input-file=%t.ll %s +// This test mimics clang/test/CodeGen/X86/sse2-builtins.c, which eventually +// CIR shall be able to support fully. + #include +void test_mm_clflush(void* A) { + // CIR-LABEL: test_mm_clflush + // LLVM-LABEL: test_mm_clflush + _mm_clflush(A); + // CIR-CHECK: {{%.*}} = cir.llvm.intrinsic "x86.sse2.clflush" {{%.*}} : (!cir.ptr) -> !void + // LLVM-CHECK: call void @llvm.x86.sse2.clflush(ptr {{%.*}}) +} + // Lowering to pextrw requires optimization. int test_mm_extract_epi16(__m128i A) { @@ -22,3 +33,19 @@ int test_mm_extract_epi16(__m128i A) { // LLVM-CHECK: zext i16 %{{.*}} to i32 return _mm_extract_epi16(A, 1); } + +void test_mm_lfence(void) { + // CIR-CHECK-LABEL: test_mm_lfence + // LLVM-CHECK-LABEL: test_mm_lfence + _mm_lfence(); + // CIR-CHECK: {{%.*}} = cir.llvm.intrinsic "x86.sse2.lfence" : () -> !void + // LLVM-CHECK: call void @llvm.x86.sse2.lfence() +} + +void test_mm_mfence(void) { + // CIR-CHECK-LABEL: test_mm_mfence + // LLVM-CHECK-LABEL: test_mm_mfence + _mm_mfence(); + // CIR-CHECK: {{%.*}} = cir.llvm.intrinsic "x86.sse2.mfence" : () -> !void + // LLVM-CHECK: call void @llvm.x86.sse2.mfence() +} diff --git a/clang/test/CIR/CodeGen/X86/sse41-builtins.c b/clang/test/CIR/CodeGen/X86/sse41-builtins.c index 59ab4b4d2bd9..814ff7bbe7eb 100644 --- a/clang/test/CIR/CodeGen/X86/sse41-builtins.c +++ b/clang/test/CIR/CodeGen/X86/sse41-builtins.c @@ -8,6 +8,8 @@ // RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-unknown-linux -target-feature +sse4.1 -fno-signed-char -fclangir -emit-llvm -o %t.ll -Wall -Werror // RUN: FileCheck --check-prefix=LLVM-CHECK --input-file=%t.ll %s +// This test mimics clang/test/CodeGen/X86/sse41-builtins.c, which eventually +// CIR shall be able to support fully. #include diff --git a/clang/test/CIR/CodeGen/X86/x86_64-xsave.c b/clang/test/CIR/CodeGen/X86/x86_64-xsave.c index bfa8377df521..afcd324144ee 100644 --- a/clang/test/CIR/CodeGen/X86/x86_64-xsave.c +++ b/clang/test/CIR/CodeGen/X86/x86_64-xsave.c @@ -43,6 +43,9 @@ // RUN: %clang_cc1 %s -DTEST_XSAVES -O0 -triple=x86_64-unknown-linux -target-feature +xsave -target-feature +xsaves -fno-signed-char -fclangir -emit-llvm -o %t.ll -Wall -Wno-unused-but-set-variable -Werror // RUN: FileCheck --check-prefix=LLVM-XSAVES --input-file=%t.ll %s +// This test mimics clang/test/CodeGen/X86/x86_64-xsave.c, which eventually +// CIR shall be able to support fully. + // Don't include mm_malloc.h, it's system specific. #define __MM_MALLOC_H #include @@ -333,4 +336,4 @@ void test(void) { // LLVM-XSETBV: call void @llvm.x86.xsetbv (void)_xsetbv(tmp_Ui, tmp_ULLi); #endif -} \ No newline at end of file +} diff --git a/clang/test/CIR/CodeGen/conditional-cleanup.cpp b/clang/test/CIR/CodeGen/conditional-cleanup.cpp index 2397bce547e2..b61b6c2e555c 100644 --- a/clang/test/CIR/CodeGen/conditional-cleanup.cpp +++ b/clang/test/CIR/CodeGen/conditional-cleanup.cpp @@ -218,10 +218,6 @@ namespace test7 { // CIR_EH: cir.if %[[VAL_41]] { // CIR_EH: cir.call @_ZN5test71AD1Ev(%[[VAL_2]]) : (!cir.ptr) -> () // CIR_EH: } -// CIR_EH: %[[VAL_42:.*]] = cir.load{{.*}} %[[VAL_3]] : !cir.ptr, !cir.bool -// CIR_EH: cir.if %[[VAL_42]] { -// CIR_EH: cir.call @_ZN5test71AD1Ev(%[[VAL_2]]) : (!cir.ptr) -> () -// CIR_EH: } // CIR_EH: %[[VAL_43:.*]] = cir.load{{.*}} %[[VAL_1]] : !cir.ptr, !cir.bool // CIR_EH: cir.if %[[VAL_43]] { // CIR_EH: cir.call @_ZdlPvm(%[[VAL_16]], %[[VAL_15]]) : (!cir.ptr, !u64i) -> () diff --git a/clang/test/CIR/CodeGen/try-catch-dtors.cpp b/clang/test/CIR/CodeGen/try-catch-dtors.cpp index ef333bf7c2c8..972077abec0e 100644 --- a/clang/test/CIR/CodeGen/try-catch-dtors.cpp +++ b/clang/test/CIR/CodeGen/try-catch-dtors.cpp @@ -367,8 +367,88 @@ void d() { // CIR: cir.resume // CIR: }] // CIR: cir.call @_ZN1CD1Ev(%[[V2]]) : (!cir.ptr) -> () extra(#fn_attr) -// CIR: cir.call @_ZN1CD1Ev(%[[V1]]) : (!cir.ptr) -> () extra(#fn_attr) // CIR: } // CIR: cir.call @_ZN1CD1Ev(%[[V1]]) : (!cir.ptr) -> () extra(#fn_attr) // CIR: cir.call @_ZN1CD1Ev(%[[V0]]) : (!cir.ptr) -> () extra(#fn_attr) // CIR: cir.return + +template class a; + +template <> class a { +public: + struct b { + typedef a c; + }; +}; + +template class a { +public: + template a(d) noexcept; + ~a(); +}; + +struct e { + using f = a::b::c; +}; + +template using g = e::f; + +template void i(h); + +class j { + +public: + using k = g; +}; + +class l { +public: + template l(m p1, n) : l(p1, 0, a()) {} + template l(m, n, h o) { + try { + j::k p(o); + i(p); + } catch (...) { + } + } +}; + +class G { +public: + template G(q p1, n) : r(p1, 0) {} + l r; +}; + +class s : G { +public: + int t; + s() : G(t, 0) {} +}; + +void fn3() { s(); } + +// CIR: cir.func linkonce_odr @_ZN1lC2Iii1aIvEEET_T0_T1_ +// CIR: cir.scope +// CIR: %[[V5:.*]] = cir.alloca !rec_a3Cint3E, !cir.ptr +// CIR: %[[V6:.*]] = cir.alloca !rec_a3Cvoid3E, !cir.ptr +// CIR: cir.try { +// CIR: cir.copy {{.*}} to %[[V6]] : !cir.ptr +// CIR: %[[V7:.*]] = cir.load align(1) %[[V6]] : !cir.ptr, !rec_a3Cvoid3E +// CIR: cir.call @_ZN1aIiEC1IS_IvEEET_(%[[V5]], %[[V7]]) : (!cir.ptr, !rec_a3Cvoid3E) -> () +// CIR: cir.scope { +// CIR: %[[V8:.*]] = cir.alloca !rec_a3Cint3E, !cir.ptr +// CIR: cir.copy %[[V5]] to %[[V8]] : !cir.ptr +// CIR: %[[V9:.*]] = cir.load align(1) %[[V8]] : !cir.ptr, !rec_a3Cint3E +// CIR: cir.call exception @_Z1iI1aIiEEvT_(%[[V9]]) : (!rec_a3Cint3E) -> () cleanup { +// CIR: cir.call @_ZN1aIiED1Ev(%[[V8]]) : (!cir.ptr) -> () +// CIR: cir.call @_ZN1aIiED1Ev(%[[V5]]) : (!cir.ptr) -> () +// CIR: cir.yield +// CIR: } +// CIR: cir.call @_ZN1aIiED1Ev(%[[V8]]) : (!cir.ptr) -> () +// CIR: } +// CIR: cir.call @_ZN1aIiED1Ev(%[[V5]]) : (!cir.ptr) -> () +// CIR: cir.yield +// CIR: } catch [type #cir.all { +// CIR: %[[V7:.*]] = cir.catch_param -> !cir.ptr +// CIR: cir.yield +// CIR: }] diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index 38ba656587a0..5f92c1a9d439 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -1232,28 +1232,35 @@ cir.func @bad_goto() -> () { // ----- !u64i = !cir.int -cir.func @address_space1(%p : !cir.ptr) { // expected-error {{expected keyword for addrspace kind}} +// expected-error@below {{expected address space keyword}} +// expected-error@below {{expected keyword for address space kind}} +cir.func @address_space1(%p : !cir.ptr) { cir.return } // ----- !u64i = !cir.int -cir.func @address_space2(%p : !cir.ptr)>) { // expected-error {{expected integer value}} +// expected-error@below {{expected target address space value}} +// expected-error@below {{expected integer value}} +cir.func @address_space2(%p : !cir.ptr)>) { cir.return } // ----- !u64i = !cir.int -cir.func @address_space3(%p : !cir.ptr) { // expected-error {{expected '<'}} +// expected-error@below {{expected '<'}} +cir.func @address_space3(%p : !cir.ptr) { cir.return } // ----- !u64i = !cir.int -cir.func @address_space4(%p : !cir.ptr) { // expected-error {{invalid addrspace kind keyword: foobar}} +// expected-error@below {{invalid address space kind specification: foobar}} +// expected-error@below {{expected address space keyword}} +cir.func @address_space4(%p : !cir.ptr) { cir.return } From f4ad43c57317fd842bc1e7b4c2120f50fdf4c6f2 Mon Sep 17 00:00:00 2001 From: bruteforceboy Date: Fri, 11 Jul 2025 11:45:57 +0300 Subject: [PATCH 2/2] update test with CIR-NEXT --- clang/test/CIR/CodeGen/try-catch-dtors.cpp | 58 +++++++++++----------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/clang/test/CIR/CodeGen/try-catch-dtors.cpp b/clang/test/CIR/CodeGen/try-catch-dtors.cpp index 972077abec0e..468e534a6118 100644 --- a/clang/test/CIR/CodeGen/try-catch-dtors.cpp +++ b/clang/test/CIR/CodeGen/try-catch-dtors.cpp @@ -351,26 +351,26 @@ void d() { } // CIR: %[[V0:.*]] = cir.alloca !rec_C, !cir.ptr, ["a"] {alignment = 1 : i64} -// CIR: %[[V1:.*]] = cir.alloca !rec_C, !cir.ptr, ["b"] {alignment = 1 : i64} -// CIR: cir.scope { -// CIR: %[[V2:.*]] = cir.alloca !rec_C, !cir.ptr, ["agg.tmp0"] {alignment = 1 : i64} -// CIR: cir.copy %[[V1]] to %[[V2]] : !cir.ptr -// CIR: %[[V3:.*]] = cir.load{{.*}} %[[V2]] : !cir.ptr, !rec_C -// CIR: cir.try synthetic cleanup { -// CIR: cir.call exception @_ZN1CaSES_(%[[V0]], %[[V3]]) : (!cir.ptr, !rec_C) -> () cleanup { -// CIR: cir.call @_ZN1CD1Ev(%[[V2]]) : (!cir.ptr) -> () extra(#fn_attr) -// CIR: cir.call @_ZN1CD1Ev(%[[V1]]) : (!cir.ptr) -> () extra(#fn_attr) -// CIR: cir.yield -// CIR: } -// CIR: cir.yield -// CIR: } catch [#cir.unwind { -// CIR: cir.resume -// CIR: }] -// CIR: cir.call @_ZN1CD1Ev(%[[V2]]) : (!cir.ptr) -> () extra(#fn_attr) -// CIR: } -// CIR: cir.call @_ZN1CD1Ev(%[[V1]]) : (!cir.ptr) -> () extra(#fn_attr) -// CIR: cir.call @_ZN1CD1Ev(%[[V0]]) : (!cir.ptr) -> () extra(#fn_attr) -// CIR: cir.return +// CIR-NEXT: %[[V1:.*]] = cir.alloca !rec_C, !cir.ptr, ["b"] {alignment = 1 : i64} +// CIR-NEXT: cir.scope { +// CIR-NEXT: %[[V2:.*]] = cir.alloca !rec_C, !cir.ptr, ["agg.tmp0"] {alignment = 1 : i64} +// CIR-NEXT: cir.copy %[[V1]] to %[[V2]] : !cir.ptr +// CIR-NEXT: %[[V3:.*]] = cir.load{{.*}} %[[V2]] : !cir.ptr, !rec_C +// CIR-NEXT: cir.try synthetic cleanup { +// CIR-NEXT: cir.call exception @_ZN1CaSES_(%[[V0]], %[[V3]]) : (!cir.ptr, !rec_C) -> () cleanup { +// CIR-NEXT: cir.call @_ZN1CD1Ev(%[[V2]]) : (!cir.ptr) -> () extra(#fn_attr) +// CIR-NEXT: cir.call @_ZN1CD1Ev(%[[V1]]) : (!cir.ptr) -> () extra(#fn_attr) +// CIR-NEXT: cir.yield +// CIR-NEXT: } +// CIR-NEXT: cir.yield +// CIR-NEXT: } catch [#cir.unwind { +// CIR-NEXT: cir.resume +// CIR-NEXT: }] +// CIR-NEXT: cir.call @_ZN1CD1Ev(%[[V2]]) : (!cir.ptr) -> () extra(#fn_attr) +// CIR-NEXT: } +// CIR-NEXT: cir.call @_ZN1CD1Ev(%[[V1]]) : (!cir.ptr) -> () extra(#fn_attr) +// CIR-NEXT: cir.call @_ZN1CD1Ev(%[[V0]]) : (!cir.ptr) -> () extra(#fn_attr) +// CIR-NEXT: cir.return template class a; @@ -439,15 +439,15 @@ void fn3() { s(); } // CIR: %[[V8:.*]] = cir.alloca !rec_a3Cint3E, !cir.ptr // CIR: cir.copy %[[V5]] to %[[V8]] : !cir.ptr // CIR: %[[V9:.*]] = cir.load align(1) %[[V8]] : !cir.ptr, !rec_a3Cint3E -// CIR: cir.call exception @_Z1iI1aIiEEvT_(%[[V9]]) : (!rec_a3Cint3E) -> () cleanup { -// CIR: cir.call @_ZN1aIiED1Ev(%[[V8]]) : (!cir.ptr) -> () -// CIR: cir.call @_ZN1aIiED1Ev(%[[V5]]) : (!cir.ptr) -> () -// CIR: cir.yield -// CIR: } -// CIR: cir.call @_ZN1aIiED1Ev(%[[V8]]) : (!cir.ptr) -> () -// CIR: } -// CIR: cir.call @_ZN1aIiED1Ev(%[[V5]]) : (!cir.ptr) -> () -// CIR: cir.yield +// CIR-NEXT: cir.call exception @_Z1iI1aIiEEvT_(%[[V9]]) : (!rec_a3Cint3E) -> () cleanup { +// CIR-NEXT: cir.call @_ZN1aIiED1Ev(%[[V8]]) : (!cir.ptr) -> () +// CIR-NEXT: cir.call @_ZN1aIiED1Ev(%[[V5]]) : (!cir.ptr) -> () +// CIR-NEXT: cir.yield +// CIR-NEXT: } +// CIR-NEXT: cir.call @_ZN1aIiED1Ev(%[[V8]]) : (!cir.ptr) -> () +// CIR-NEXT: } +// CIR-NEXT: cir.call @_ZN1aIiED1Ev(%[[V5]]) : (!cir.ptr) -> () +// CIR-NEXT: cir.yield // CIR: } catch [type #cir.all { // CIR: %[[V7:.*]] = cir.catch_param -> !cir.ptr // CIR: cir.yield