[clang] [llvm] [ValueTracking] Return true for AddrSpaceCast in canCreateUndefOrPoison (PR #144686)
https://github.com/wenju-he updated https://github.com/llvm/llvm-project/pull/144686 >From b5c9a4834accbac18664f1431acc5204c0527fa8 Mon Sep 17 00:00:00 2001 From: Wenju He Date: Wed, 18 Jun 2025 14:21:09 +0200 Subject: [PATCH 1/4] [InstCombine] Don't folder select to or if value argument is user of invalid addrspacecast inst In our downstream GPU target, following IR is valid before instcombine although the second addrspacecast causes UB. define i1 @test(ptr addrspace(1) noundef %v) { %0 = addrspacecast ptr addrspace(1) %v to ptr addrspace(4) %1 = call i32 @llvm..isaddr.shared(ptr addrspace(4) %0) %2 = icmp eq i32 %1, 0 %3 = addrspacecast ptr addrspace(4) %0 to ptr addrspace(3) %4 = select i1 %2, ptr addrspace(3) null, ptr addrspace(3) %3 %5 = icmp eq ptr addrspace(3) %4, null ret i1 %5 } We have a custom optimization that replaces invalid addrspacecast with poison, and IR is still valid since `select` stops poison propagation. However, instcombine pass optimizes `select` to `or`: %0 = addrspacecast ptr addrspace(1) %v to ptr addrspace(4) %1 = call i32 @llvm..isaddr.shared(ptr addrspace(4) %0) %2 = icmp eq i32 %1, 0 %3 = addrspacecast ptr addrspace(1) %v to ptr addrspace(3) %4 = icmp eq ptr addrspace(3) %3, null %5 = or i1 %2, %4 ret i1 %5 The transform is invalid for our target. --- .../InstCombine/InstCombineSelect.cpp | 35 +++ .../InstCombine/AMDGPU/addrspacecast.ll | 23 2 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/AMDGPU/addrspacecast.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 73ba0f78e8053..a2335640f917b 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -3194,8 +3194,23 @@ static Instruction *foldNestedSelects(SelectInst &OuterSelVal, /// Return true if V is poison or \p Expected given that ValAssumedPoison is /// already poison. For example, if ValAssumedPoison is `icmp samesign X, 10` /// and V is `icmp ne X, 5`, impliesPoisonOrCond returns true. -static bool impliesPoisonOrCond(const Value *ValAssumedPoison, const Value *V, -bool Expected) { +static bool impliesPoisonOrCond( +const Value *ValAssumedPoison, const Value *V, bool Expected, +llvm::function_ref isValidAddrSpaceCast) { + // Handle the case that ValAssumedPoison is `icmp eq ptr addrspace(3) X, null` + // and X is `addrspacecast ptr addrspace(1) Y to ptr addrspace(3)`. Target can + // replace X with poison if the addrspacecast is invalid. However, `V` might + // not be poison. + if (auto *ICmp = dyn_cast(ValAssumedPoison)) { +auto CanCreatePoison = [&](Value *Op) { + auto *ASC = dyn_cast(Op); + return ASC && !isValidAddrSpaceCast(ASC->getDestAddressSpace(), + ASC->getSrcAddressSpace()); +}; +if (llvm::any_of(ICmp->operands(), CanCreatePoison)) + return false; + } + if (impliesPoison(ValAssumedPoison, V)) return true; @@ -3241,17 +3256,23 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) { auto *Zero = ConstantInt::getFalse(SelType); Value *A, *B, *C, *D; + auto IsValidAddrSpaceCast = [&](unsigned FromAS, unsigned ToAS) { +return isValidAddrSpaceCast(FromAS, ToAS); + }; + // Folding select to and/or i1 isn't poison safe in general. impliesPoison // checks whether folding it does not convert a well-defined value into // poison. if (match(TrueVal, m_One())) { -if (impliesPoisonOrCond(FalseVal, CondVal, /*Expected=*/false)) { +if (impliesPoisonOrCond(FalseVal, CondVal, /*Expected=*/false, +IsValidAddrSpaceCast)) { // Change: A = select B, true, C --> A = or B, C return BinaryOperator::CreateOr(CondVal, FalseVal); } if (match(CondVal, m_OneUse(m_Select(m_Value(A), m_One(), m_Value(B && -impliesPoisonOrCond(FalseVal, B, /*Expected=*/false)) { +impliesPoisonOrCond(FalseVal, B, /*Expected=*/false, +IsValidAddrSpaceCast)) { // (A || B) || C --> A || (B | C) return replaceInstUsesWith( SI, Builder.CreateLogicalOr(A, Builder.CreateOr(B, FalseVal))); @@ -3287,13 +3308,15 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) { } if (match(FalseVal, m_Zero())) { -if (impliesPoisonOrCond(TrueVal, CondVal, /*Expected=*/true)) { +if (impliesPoisonOrCond(TrueVal, CondVal, /*Expected=*/true, +IsValidAddrSpaceCast)) { // Change: A = select B, C, false --> A = and B, C return BinaryOperator::CreateAnd(CondVal, TrueVal); } if (match(CondVal, m_OneUse(m_Select(m_Value(A), m_Value(B), m_Zero( && -impliesPoisonOrCond(True
[clang] [llvm] [ValueTracking] Return true for AddrSpaceCast in canCreateUndefOrPoison (PR #144686)
@@ -10211,8 +10210,18 @@ bool AANoUndef::isImpliedByIR(Attributor &A, const IRPosition &IRP, return true; Value &Val = IRP.getAssociatedValue(); + auto IsTargetGuaranteedNotPoison = [&](Value &V) { +if (auto *ASC = dyn_cast(&V)) { + const auto *TTI = A.getInfoCache().getTargetTransformInfoForFunction( + *ASC->getFunction()); + return ASC && TTI->isValidAddrSpaceCast(ASC->getSrcAddressSpace(), + ASC->getDestAddressSpace()); +} +return false; + }; if (IRP.getPositionKind() != IRPosition::IRP_RETURNED && - isGuaranteedNotToBeUndefOrPoison(&Val)) { + (isGuaranteedNotToBeUndefOrPoison(&Val) || + IsTargetGuaranteedNotPoison(Val))) { nikic wrote: This is incorrect, it will not handle poison introduced higher up the chain if it ends in an addrspacecast. It's also sub-optimal, because it will not handle known-valid addrspacecasts higher up the chain. This needs to be handled fully inside canCreateUndefOrPoison. https://github.com/llvm/llvm-project/pull/144686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [ValueTracking] Return true for AddrSpaceCast in canCreateUndefOrPoison (PR #144686)
nikic wrote: For the purposes of this PR, I think you should only change canCreateUndefOrPoison to return true and just eat the regressions. We can follow up with using isValidAddrSpaceCast() in a followup, because it will be less straightforward. I'm not willing to accept direct use of TTI in ValueTracking without laundering it through an abstraction first (see https://discourse.llvm.org/t/constant-propagation-for-target-specific-intrinsics/85881/5). https://github.com/llvm/llvm-project/pull/144686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [ValueTracking] Return true for AddrSpaceCast in canCreateUndefOrPoison (PR #144686)
wenju-he wrote: > For the purposes of this PR, I think you should only change > canCreateUndefOrPoison to return true and just eat the regressions. We can > follow up with using isValidAddrSpaceCast() in a followup, because it will be > less straightforward. I'm not willing to accept direct use of TTI in > ValueTracking without laundering it through an abstraction first (see > https://discourse.llvm.org/t/constant-propagation-for-target-specific-intrinsics/85881/5). thanks @nikic Shall I file an issue for the task of using isValidAddrSpaceCast()? https://github.com/llvm/llvm-project/pull/144686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Clean up enum attributes (PR #144999)
https://github.com/xlauko ready_for_review https://github.com/llvm/llvm-project/pull/144999 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Clean up enum attributes (PR #144999)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Henrich Lauko (xlauko) Changes This mirrors incubator changes from https://github.com/llvm/clangir/pull/1678 - Create CIR specific EnumAttr bases and prefix enum attributes with CIR_ that automatically puts enum to cir namespace - Removes unnecessary enum case definitions - Unifies naming of enum values to use capitals consistently and make enumerations to start from 0 --- Patch is 22.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144999.diff 2 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.td (+22-15) - (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+189-235) ``diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 9e01dde379d7a..03e970db2847d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -47,6 +47,16 @@ class CIR_I32EnumAttr cases> 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"; @@ -330,36 +340,33 @@ def ConstComplexAttr : CIR_Attr<"ConstComplex", "const_complex", // VisibilityAttr //===--===// -def CIR_VisibilityKind : I32EnumAttr<"VisibilityKind", "C/C++ visibility", [ - I32EnumAttrCase<"Default", 1, "default">, - I32EnumAttrCase<"Hidden", 2, "hidden">, - I32EnumAttrCase<"Protected", 3, "protected"> +def CIR_VisibilityKind : CIR_I32EnumAttr<"VisibilityKind", "C/C++ visibility", [ + I32EnumAttrCase<"Default", 0, "default">, + I32EnumAttrCase<"Hidden", 1, "hidden">, + I32EnumAttrCase<"Protected", 2, "protected"> ]> { let genSpecializedAttr = 0; - let cppNamespace = "::cir"; } -def CIR_VisibilityAttr : CIR_Attr<"Visibility", "visibility"> { +def CIR_VisibilityAttr : CIR_EnumAttr { let summary = "Visibility attribute"; let description = [{ Visibility attributes. }]; - let parameters = (ins "VisibilityKind":$value); - let assemblyFormat = [{ -$value - }]; + let cppClassName = "VisibilityAttr"; + let skipDefaultBuilders = 1; let builders = [ -AttrBuilder<(ins CArg<"VisibilityKind", "cir::VisibilityKind::Default">:$value), [{ +AttrBuilder<(ins CArg<"VisibilityKind", + "cir::VisibilityKind::Default">:$value), [{ return $_get($_ctxt, value); }]> ]; - let skipDefaultBuilders = 1; - - // Make DefaultValuedAttr accept VisibilityKind as default value ($0). - let constBuilderCall = "cir::VisibilityAttr::get($_builder.getContext(), $0)"; + let assemblyFormat = [{ +$value + }]; let extraClassDeclaration = [{ bool isDefault() const { return getValue() == VisibilityKind::Default; }; diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 852d3aa131148..f978bd9a96bcf 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -91,94 +91,80 @@ def SameFirstOperandAndResultType : // CastOp //===--===// -// CK_Dependent -def CK_BitCast : I32EnumAttrCase<"bitcast", 1>; -// CK_LValueBitCast -// CK_LValueToRValueBitCast -// CK_LValueToRValue -// CK_NoOp -// CK_BaseToDerived -// CK_DerivedToBase -// CK_UncheckedDerivedToBase -// CK_Dynamic -// CK_ToUnion -def CK_ArrayToPointerDecay : I32EnumAttrCase<"array_to_ptrdecay", 11>; -// CK_FunctionToPointerDecay -// CK_NullToPointer -// CK_NullToMemberPointer -// CK_BaseToDerivedMemberPointer -// CK_DerivedToBaseMemberPointer -def CK_MemberPointerToBoolean : I32EnumAttrCase<"member_ptr_to_bool", 17>; -// CK_ReinterpretMemberPointer -// CK_UserDefinedConversion -// CK_ConstructorConversion -def CK_IntegralToPointer : I32EnumAttrCase<"int_to_ptr", 21>; -def CK_PointerToIntegral : I32EnumAttrCase<"ptr_to_int", 22>; -def CK_PointerToBoolean : I32EnumAttrCase<"ptr_to_bool", 23>; -// CK_ToVoid -// CK_MatrixCast -// CK_VectorSplat -def CK_IntegralCast : I32EnumAttrCase<"integral", 27>; -def CK_IntegralToBoolean : I32EnumAttrCase<"int_to_bool", 28>; -def CK_IntegralToFloating : I32EnumAttrCase<"int_to_float", 29>; -// CK_FloatingToFixedPoint -// CK_FixedPointToFloating -// CK_FixedPointCast -// CK_FixedPointToIntegral -// CK_IntegralToFixedPoint -// CK_FixedPointToBoolean -def CK_FloatingToIntegral : I32EnumAttrCase<"float_to_int", 36>; -def CK_FloatingToBoolean : I32EnumAttrCase<"float_to_bool", 37>; -def CK_BooleanToSignedIntegral : I32EnumAttrCase<"bool_to_int", 38>; -def CK_FloatingCast : I32EnumAttrCase<"floating", 39>; -// CK_CPointerToObjCPointerCast -// CK_BlockPointerToObjCPoint
[clang] Reapply "Reapply "[clang][bytecode] Allocate IntegralAP and Floating … (PR #145014)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff HEAD~1 HEAD --extensions cpp,h -- clang/lib/AST/ByteCode/ByteCodeEmitter.cpp clang/lib/AST/ByteCode/Compiler.cpp clang/lib/AST/ByteCode/Compiler.h clang/lib/AST/ByteCode/Descriptor.cpp clang/lib/AST/ByteCode/Disasm.cpp clang/lib/AST/ByteCode/Floating.h clang/lib/AST/ByteCode/Integral.h clang/lib/AST/ByteCode/IntegralAP.h clang/lib/AST/ByteCode/Interp.cpp clang/lib/AST/ByteCode/Interp.h clang/lib/AST/ByteCode/InterpBuiltin.cpp clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp clang/lib/AST/ByteCode/InterpState.h clang/lib/AST/ByteCode/PrimType.h clang/lib/AST/ByteCode/Program.h clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp clang/test/AST/ByteCode/builtin-functions.cpp `` View the diff from clang-format here. ``diff diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 66d3e6d79..c2ad387ed 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -2729,9 +2729,9 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS, if (!S.noteUndefinedBehavior()) return false; RHS = -RHS; -return DoShift( -S, OpPC, LHS, RHS, Result); +return DoShift < LT, RT, + Dir == ShiftDir::Left ? ShiftDir::Right + : ShiftDir::Left > (S, OpPC, LHS, RHS, Result); } if (!CheckShift(S, OpPC, LHS, RHS, Bits)) @@ -2810,9 +2810,9 @@ inline bool DoShiftAP(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS, if (!S.noteUndefinedBehavior()) return false; RHS = -RHS; -return DoShiftAP( -S, OpPC, LHS, RHS, Result); +return DoShiftAP < LT, RT, + Dir == ShiftDir::Left ? ShiftDir::Right + : ShiftDir::Left > (S, OpPC, LHS, RHS, Result); } if (!CheckShift(S, OpPC, LHS, RHS, Bits)) `` https://github.com/llvm/llvm-project/pull/145014 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Reapply "Reapply "[clang][bytecode] Allocate IntegralAP and Floating … (PR #145014)
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/145014 …types usi… (#144676)" This reverts commit 68471d29eed2c49f9b439e505b3f24d387d54f97. IntegralAP contains a union: union { uint64_t *Memory = nullptr; uint64_t Val; }; On 64bit systems, both Memory and Val have the same size. However, on 32 bit system, Val is 64bit and Memory only 32bit. Which means the default initializer for Memory will only zero half of Val. We fixed this by zero-initializing Val explicitly in the IntegralAP(unsigned BitWidth) constructor. See also the discussion in https://github.com/llvm/llvm-project/pull/144246 >From ecb0d278deacb05285c746ceac86a8ce69854ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Thu, 19 Jun 2025 09:22:21 +0200 Subject: [PATCH] =?UTF-8?q?Reapply=20"Reapply=20"[clang][bytecode]=20Alloc?= =?UTF-8?q?ate=20IntegralAP=20and=20Floating=20types=20usi=E2=80=A6=20(#14?= =?UTF-8?q?4676)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 68471d29eed2c49f9b439e505b3f24d387d54f97. IntegralAP contains a union: union { uint64_t *Memory = nullptr; uint64_t Val; }; On 64bit systems, both Memory and Val have the same size. However, on 32 bit system, Val is 64bit and Memory only 32bit. Which means the default initializer for Memory will only zero half of Val. We fixed this by zero-initializing Val explicitly in the IntegralAP(unsigned BitWidth) constructor. --- clang/lib/AST/ByteCode/ByteCodeEmitter.cpp| 3 +- clang/lib/AST/ByteCode/Compiler.cpp | 113 +++--- clang/lib/AST/ByteCode/Compiler.h | 1 + clang/lib/AST/ByteCode/Descriptor.cpp | 2 +- clang/lib/AST/ByteCode/Disasm.cpp | 59 ++- clang/lib/AST/ByteCode/Floating.h | 252 - clang/lib/AST/ByteCode/Integral.h | 3 + clang/lib/AST/ByteCode/IntegralAP.h | 236 ++-- clang/lib/AST/ByteCode/Interp.cpp | 106 +- clang/lib/AST/ByteCode/Interp.h | 337 ++ clang/lib/AST/ByteCode/InterpBuiltin.cpp | 55 ++- .../lib/AST/ByteCode/InterpBuiltinBitCast.cpp | 4 +- clang/lib/AST/ByteCode/InterpState.h | 30 ++ clang/lib/AST/ByteCode/Opcodes.td | 14 +- clang/lib/AST/ByteCode/PrimType.h | 17 + clang/lib/AST/ByteCode/Program.h | 24 +- .../ByteCode/builtin-bit-cast-long-double.cpp | 10 +- clang/test/AST/ByteCode/builtin-functions.cpp | 12 +- 18 files changed, 925 insertions(+), 353 deletions(-) diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp index d91d5f16fc7a9..965e235036031 100644 --- a/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp +++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.cpp @@ -176,7 +176,8 @@ static void emitSerialized(std::vector &Code, const T &Val, } // Access must be aligned! - size_t ValPos = align(Code.size()); + assert(aligned(Code.size())); + size_t ValPos = Code.size(); Size = align(Size); assert(aligned(ValPos + Size)); Code.resize(ValPos + Size); diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 9fe4803ce98ec..c5ac40210e477 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -748,7 +748,8 @@ bool Compiler::VisitFloatingLiteral(const FloatingLiteral *E) { if (DiscardResult) return true; - return this->emitConstFloat(E->getValue(), E); + APFloat F = E->getValue(); + return this->emitFloat(F, E); } template @@ -4185,13 +4186,14 @@ bool Compiler::visitZeroInitializer(PrimType T, QualType QT, nullptr, E); case PT_MemberPtr: return this->emitNullMemberPtr(0, nullptr, E); - case PT_Float: -return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E); + case PT_Float: { +APFloat F = APFloat::getZero(Ctx.getFloatSemantics(QT)); +return this->emitFloat(F, E); + } case PT_FixedPoint: { auto Sem = Ctx.getASTContext().getFixedPointSemantics(E->getType()); return this->emitConstFixedPoint(FixedPoint::zero(Sem), E); } -llvm_unreachable("Implement"); } llvm_unreachable("unknown primitive type"); } @@ -4674,10 +4676,7 @@ VarCreationState Compiler::visitVarDecl(const VarDecl *VD, if (!visitInitializer(Init)) return false; - if (!this->emitFinishInit(Init)) -return false; - - return this->emitPopPtr(Init); + return this->emitFinishInitGlobal(Init); }; DeclScope LocalScope(this, VD); @@ -4698,51 +4697,45 @@ VarCreationState Compiler::visitVarDecl(const VarDecl *VD, return false; return !Init || (checkDecl() && initGlobal(*GlobalIndex)); - } else { -InitLinkScope ILS(this, InitLink::Decl(VD)); - -if (VarT) { - unsigned Offset = this->allocateLocalPrimitive( - VD,
[clang] [llvm] [ValueTracking] Return true for AddrSpaceCast in canCreateUndefOrPoison (PR #144686)
https://github.com/nikic approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/144686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang-tools-extra] [clangd] Improve Markup Rendering (PR #140498)
mccakit wrote: ping @kadircet https://github.com/llvm/llvm-project/pull/140498 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][bytecode] Allocate IntegralAP and Floating types using an allocator (PR #144246)
Timm =?utf-8?q?Bäder?= , Timm =?utf-8?q?Bäder?= Message-ID: In-Reply-To: DavidSpickett wrote: When applied to 7c15edb306932e41c159f3d69c161ed0d89d47b7, this fixes the problem and passes check-clang. Reland in whatever way you prefer (no need for extra review), as you know, the bot will rapidly find out if there are problems. I just ask that you include a note in the commit message describing what was added from last time it was landed, in case we have an issue like this in future. https://github.com/llvm/llvm-project/pull/144246 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
https://github.com/Meinersbur commented: Thanks for the work and sorry I could not have a look into it earlier https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Ast importer visitors (PR #138838)
@@ -7359,6 +7549,150 @@ ExpectedStmt ASTNodeImporter::VisitExpr(Expr *E) { return make_error(ASTImportError::UnsupportedConstruct); } +ExpectedStmt ASTNodeImporter::VisitRequiresExpr(RequiresExpr* E) { + Error Err = Error::success(); + auto RequiresKWLoc = importChecked(Err, E->getRequiresKWLoc()); + auto RParenLoc = importChecked(Err, E->getRParenLoc()); + auto RBraceLoc = importChecked(Err, E->getRBraceLoc()); + + auto Body = importChecked(Err, E->getBody()); + auto LParenLoc = importChecked(Err, E->getLParenLoc()); + if (Err) +return std::move(Err); + SmallVector LocalParameters(E->getLocalParameters().size()); + if (Error Err = ImportArrayChecked(E->getLocalParameters(), LocalParameters.begin())) +return std::move(Err); + SmallVector Requirements( + E->getRequirements().size()); + if (Error Err = ImportArrayChecked(E->getRequirements(), Requirements.begin())) +return std::move(Err); + return RequiresExpr::Create(Importer.getToContext(), RequiresKWLoc, Body, + LParenLoc, LocalParameters, RParenLoc, + Requirements, RBraceLoc); +} + +ExpectedDecl ASTNodeImporter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl* D) { + DeclContext *DC, *LexicalDC; + Error Err = ImportDeclContext(D, DC, LexicalDC); + auto RequiresLoc = importChecked(Err, D->getLocation()); + if (Err) +return std::move(Err); + + RequiresExprBodyDecl *To; + if (GetImportedOrCreateDecl(To, D, Importer.getToContext(), DC, RequiresLoc)) +return To; + To->setLexicalDeclContext(LexicalDC); + LexicalDC->addDeclInternal(To); + return To; +} balazske wrote: There is a section in the file for all of the visit functions for `Decl` types. The new visit functions with `Decl` should be moved into this place (at the start or end of it). https://github.com/llvm/llvm-project/pull/138838 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Ast importer visitors (PR #138838)
https://github.com/balazske edited https://github.com/llvm/llvm-project/pull/138838 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -15499,6 +15836,496 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective( buildPreInits(Context, PreInits)); } +StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef Clauses, +Stmt *AStmt, +SourceLocation StartLoc, +SourceLocation EndLoc) { + + ASTContext &Context = getASTContext(); + DeclContext *CurrContext = SemaRef.CurContext; + Scope *CurScope = SemaRef.getCurScope(); + CaptureVars CopyTransformer(SemaRef); + + // Ensure the structured block is not empty + if (!AStmt) +return StmtError(); + + unsigned NumLoops = 1; + unsigned LoopSeqSize = 1; + + // Defer transformation in dependent contexts + // The NumLoopNests argument is set to a placeholder 1 (even though + // using looprange fuse could yield up to 3 top level loop nests) + // because a dependent context could prevent determining its true value + if (CurrContext->isDependentContext()) { +return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses, +NumLoops, LoopSeqSize, AStmt, nullptr, +nullptr); + } + + // Validate that the potential loop sequence is transformable for fusion + // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops + SmallVector LoopHelpers; + SmallVector LoopStmts; + SmallVector> OriginalInits; + SmallVector> TransformsPreInits; + SmallVector> LoopSequencePreInits; + SmallVector LoopCategories; + if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, LoopSeqSize, NumLoops, + LoopHelpers, LoopStmts, OriginalInits, + TransformsPreInits, LoopSequencePreInits, + LoopCategories, Context)) +return StmtError(); + + // Handle clauses, which can be any of the following: [looprange, apply] + const OMPLoopRangeClause *LRC = + OMPExecutableDirective::getSingleClause(Clauses); + + // The clause arguments are invalidated if any error arises + // such as non-constant or non-positive arguments + if (LRC && (!LRC->getFirst() || !LRC->getCount())) +return StmtError(); + + // Delayed semantic check of LoopRange constraint + // Evaluates the loop range arguments and returns the first and count values + auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count, + uint64_t &FirstVal, + uint64_t &CountVal) { +llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context); +llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context); +FirstVal = FirstInt.getZExtValue(); +CountVal = CountInt.getZExtValue(); + }; + + // OpenMP [6.0, Restrictions] + // first + count - 1 must not evaluate to a value greater than the + // loop sequence length of the associated canonical loop sequence. + auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal, + unsigned NumLoops) -> bool { +return FirstVal + CountVal - 1 <= NumLoops; + }; + uint64_t FirstVal = 1, CountVal = 0, LastVal = LoopSeqSize; + + // Validates the loop range after evaluating the semantic information + // and ensures that the range is valid for the given loop sequence size. + // Expressions are evaluated at compile time to obtain constant values. + if (LRC) { +EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal, + CountVal); +if (CountVal == 1) + SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion) + << getOpenMPDirectiveName(OMPD_fuse); + +if (!ValidLoopRange(FirstVal, CountVal, LoopSeqSize)) { + SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange) + << getOpenMPDirectiveName(OMPD_fuse) << (FirstVal + CountVal - 1) + << LoopSeqSize; + return StmtError(); +} + +LastVal = FirstVal + CountVal - 1; + } + + // Complete fusion generates a single canonical loop nest + // However looprange clause generates several loop nests + unsigned NumLoopNests = LRC ? LoopSeqSize - CountVal + 1 : 1; + + // Emit a warning for redundant loop fusion when the sequence contains only + // one loop. + if (LoopSeqSize == 1) +SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion) +<< getOpenMPDirectiveName(OMPD_fuse); + + assert(LoopHelpers.size() == LoopSeqSize && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + assert(OriginalInits.size() == LoopSeqSize && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + + // Select the type with the largest bit width among all induction variables + QualType IVType = LoopHel
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -1479,7 +1492,109 @@ class SemaOpenMP : public SemaBase { bool checkTransformableLoopNest( OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops, SmallVectorImpl &LoopHelpers, - Stmt *&Body, SmallVectorImpl> &OriginalInits); + Stmt *&Body, SmallVectorImpl> &OriginalInits); + + /// @brief Categories of loops encountered during semantic OpenMP loop + /// analysis + /// + /// This enumeration identifies the structural category of a loop or sequence + /// of loops analyzed in the context of OpenMP transformations and directives. + /// This categorization helps differentiate between original source loops + /// and the structures resulting from applying OpenMP loop transformations. + enum class OMPLoopCategory { + +/// @var OMPLoopCategory::RegularLoop +/// Represents a standard canonical loop nest found in the +/// original source code or an intact loop after transformations +/// (i.e Post/Pre loops of a loopranged fusion) +RegularLoop, + +/// @var OMPLoopCategory::TransformSingleLoop +/// Represents the resulting loop structure when an OpenMP loop +// transformation, generates a single, top-level loop +TransformSingleLoop, + +/// @var OMPLoopCategory::TransformLoopSequence +/// Represents the resulting loop structure when an OpenMP loop +/// transformation +/// generates a sequence of two or more canonical loop nests +TransformLoopSequence + }; + + /// The main recursive process of `checkTransformableLoopSequence` that + /// performs grammatical parsing of a canonical loop sequence. It extracts + /// key information, such as the number of top-level loops, loop statements, + /// helper expressions, and other relevant loop-related data, all in a single + /// execution to avoid redundant traversals. This analysis flattens inner + /// Loop Sequences + /// + /// \param LoopSeqStmtThe AST of the original statement. + /// \param LoopSeqSize[out] Number of top level canonical loops. + /// \param NumLoops [out] Number of total canonical loops (nested too). + /// \param LoopHelpers[out] The multiple loop analyses results. + /// \param ForStmts [out] The multiple Stmt of each For loop. + /// \param OriginalInits [out] The raw original initialization statements + /// of each belonging to a loop of the loop sequence + /// \param TransformPreInits [out] The multiple collection of statements and + /// declarations that must have been executed/declared + /// before entering the loop (each belonging to a + /// particular loop transformation, nullptr otherwise) + /// \param LoopSequencePreInits [out] Additional general collection of loop + /// transformation related statements and declarations + /// not bounded to a particular loop that must be + /// executed before entering the loop transformation + /// \param LoopCategories [out] A sequence of OMPLoopCategory values, + /// one for each loop or loop transformation node + /// successfully analyzed. + /// \param Context + /// \param Kind The loop transformation directive kind. + /// \return Whether the original statement is both syntactically and + /// semantically correct according to OpenMP 6.0 canonical loop + /// sequence definition. + bool analyzeLoopSequence( + Stmt *LoopSeqStmt, unsigned &LoopSeqSize, unsigned &NumLoops, + SmallVectorImpl &LoopHelpers, + SmallVectorImpl &ForStmts, + SmallVectorImpl> &OriginalInits, + SmallVectorImpl> &TransformsPreInits, + SmallVectorImpl> &LoopSequencePreInits, Meinersbur wrote: SmallVector of SmallVector is usually not a good idea, wastes a lot if space. Consider `SmallVectorImpl>` and/or declare a struct that contains this information for each item in the loop sequence https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -0,0 +1,50 @@ +// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines + +#ifndef HEADER +#define HEADER + +#include +#include + +int main() { + printf("do\n"); +#pragma omp fuse + { +for (int i = 5; i <= 25; i += 5) + printf("i=%d\n", i); +for (int j = 10; j < 100; j += 10) + printf("j=%d\n", j); +for (int k = 10; k > 0; --k) + printf("k=%d\n", k); Meinersbur wrote: Nice test. I hope these end2end tests were as useful for you as they were for me https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -11612,6 +11612,18 @@ def note_omp_implicit_dsa : Note< "implicitly determined as %0">; def err_omp_loop_var_dsa : Error< "loop iteration variable in the associated loop of 'omp %1' directive may not be %0, predetermined as %2">; +def err_omp_not_canonical_loop : Error < Meinersbur wrote: ```suggestion def err_omp_not_canonical_loop : Error< ``` [nit] consistent use of whitespace in this file https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -0,0 +1,400 @@ +// Check no warnings/errors +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -std=c++20 -fopenmp-version=60 -fsyntax-only -verify %s +// expected-no-diagnostics + +// Check AST and unparsing +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -std=c++20 -fopenmp-version=60 -ast-dump %s | FileCheck %s --check-prefix=DUMP +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -std=c++20 -fopenmp-version=60 -ast-print %s | FileCheck %s --check-prefix=PRINT + +// Check same results after serialization round-trip +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -std=c++20 -fopenmp-version=60 -emit-pch -o %t %s +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -std=c++20 -fopenmp-version=60 -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -std=c++20 -fopenmp-version=60 -include-pch %t -ast-print%s | FileCheck %s --check-prefix=PRINT + +#ifndef HEADER +#define HEADER + +// placeholder for loop body code +extern "C" void body(...); + +// PRINT-LABEL: void foo1( +// DUMP-LABEL: FunctionDecl {{.*}} foo1 +void foo1() { +// PRINT: #pragma omp fuse +// DUMP: OMPFuseDirective +#pragma omp fuse +// PRINT: { +// DUMP: CompoundStmt +{ +// PRINT: for (int i = 0; i < 10; i += 2) +// DUMP: ForStmt +for (int i = 0; i < 10; i += 2) +// PRINT: body(i) +// DUMP: CallExpr +body(i); +// PRINT: for (int j = 10; j > 0; --j) +// DUMP: ForStmt +for (int j = 10; j > 0; --j) +// PRINT: body(j) +// DUMP: CallExpr +body(j); +// PRINT: for (int k = 0; k <= 10; ++k) +// DUMP: ForStmt +for (int k = 0; k <= 10; ++k) +// PRINT: body(k) +// DUMP: CallExpr +body(k); + +} + +} + +// PRINT-LABEL: void foo2( +// DUMP-LABEL: FunctionDecl {{.*}} foo2 +void foo2() { +// PRINT: #pragma omp unroll partial(4) +// DUMP: OMPUnrollDirective +// DUMP-NEXT: OMPPartialClause +// DUMP-NEXT: ConstantExpr +// DUMP-NEXT: value: Int 4 +// DUMP-NEXT: IntegerLiteral {{.*}} 4 +#pragma omp unroll partial(4) +// PRINT: #pragma omp fuse +// DUMP-NEXT: OMPFuseDirective +#pragma omp fuse +// PRINT: { +// DUMP: CompoundStmt +{ +// PRINT: for (int i = 0; i < 10; i += 2) +// DUMP: ForStmt +for (int i = 0; i < 10; i += 2) +// PRINT: body(i) +// DUMP: CallExpr +body(i); +// PRINT: for (int j = 10; j > 0; --j) +// DUMP: ForStmt +for (int j = 10; j > 0; --j) +// PRINT: body(j) +// DUMP: CallExpr +body(j); +} + +} + +//PRINT-LABEL: void foo3( +//DUMP-LABEL: FunctionTemplateDecl {{.*}} foo3 +template +void foo3() { +// PRINT: #pragma omp fuse +// DUMP: OMPFuseDirective +#pragma omp fuse +// PRINT: { +// DUMP: CompoundStmt +{ +// PRINT: #pragma omp unroll partial(Factor1) +// DUMP: OMPUnrollDirective +#pragma omp unroll partial(Factor1) +// PRINT: for (int i = 0; i < 12; i += 1) +// DUMP: ForStmt +for (int i = 0; i < 12; i += 1) +// PRINT: body(i) +// DUMP: CallExpr +body(i); +// PRINT: #pragma omp unroll partial(Factor2) +// DUMP: OMPUnrollDirective +#pragma omp unroll partial(Factor2) +// PRINT: for (int k = 0; k <= 10; ++k) +// DUMP: ForStmt +for (int k = 0; k <= 10; ++k) +// PRINT: body(k) +// DUMP: CallExpr +body(k); + +} +} + +// Also test instantiating the template. +void tfoo3() { +foo3<4,2>(); +} + +//PRINT-LABEL: void foo4( +//DUMP-LABEL: FunctionTemplateDecl {{.*}} foo4 +template +void foo4(int start, int end) { +// PRINT: #pragma omp fuse +// DUMP: OMPFuseDirective +#pragma omp fuse +// PRINT: { +// DUMP: CompoundStmt +{ +// PRINT: for (T i = start; i < end; i += Step) +// DUMP: ForStmt +for (T i = start; i < end; i += Step) +// PRINT: body(i) +// DUMP: CallExpr +body(i); + +// PRINT: for (T j = end; j > start; j -= Step) +// DUMP: ForStmt +for (T j = end; j > start; j -= Step) { +// PRINT: body(j) +// DUMP: CallExpr +body(j); +} + +} +} + +// Also test instantiating the template. +void tfoo4() { +foo4(0, 64); +} + + + +// PRINT-LABEL: void foo5( +// DUMP-LABEL: FunctionDecl {{.*}} foo5 +void foo5() { +double arr[128], arr2[128]; +// PRINT: #pragma omp fuse +// DUMP: OMPFuseDirective +#pragma omp fuse +// PRINT: { +// DUMP: CompoundStmt +{ +// PRINT-NEXT: for (auto &&a : arr) +// DUMP-N
[clang] [llvm] Ast importer visitors (PR #138838)
@@ -1363,6 +1364,26 @@ extern const internal::VariadicDynCastAllOfMatcher extern const internal::VariadicDynCastAllOfMatcher conceptDecl; +/// Matches concept requirement. +/// +/// Example matches requirement expression balazske wrote: It is better to tell exactly the matching part (`requires(T p) { *p; }` if correct). https://github.com/llvm/llvm-project/pull/138838 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -973,6 +976,9 @@ class OMPLoopTransformationDirective : public OMPLoopBasedDirective { /// Set the number of loops generated by this loop transformation. void setNumGeneratedLoops(unsigned Num) { NumGeneratedLoops = Num; } + /// Set the number of top level canonical loop nests generated by this loop Meinersbur wrote: [nit] empty line for separating functions https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -15499,6 +15836,496 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective( buildPreInits(Context, PreInits)); } +StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef Clauses, +Stmt *AStmt, +SourceLocation StartLoc, +SourceLocation EndLoc) { + + ASTContext &Context = getASTContext(); + DeclContext *CurrContext = SemaRef.CurContext; + Scope *CurScope = SemaRef.getCurScope(); + CaptureVars CopyTransformer(SemaRef); + + // Ensure the structured block is not empty + if (!AStmt) +return StmtError(); + + unsigned NumLoops = 1; + unsigned LoopSeqSize = 1; + + // Defer transformation in dependent contexts + // The NumLoopNests argument is set to a placeholder 1 (even though + // using looprange fuse could yield up to 3 top level loop nests) + // because a dependent context could prevent determining its true value + if (CurrContext->isDependentContext()) { +return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses, +NumLoops, LoopSeqSize, AStmt, nullptr, +nullptr); + } + + // Validate that the potential loop sequence is transformable for fusion + // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops + SmallVector LoopHelpers; + SmallVector LoopStmts; + SmallVector> OriginalInits; + SmallVector> TransformsPreInits; + SmallVector> LoopSequencePreInits; + SmallVector LoopCategories; + if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, LoopSeqSize, NumLoops, + LoopHelpers, LoopStmts, OriginalInits, + TransformsPreInits, LoopSequencePreInits, + LoopCategories, Context)) +return StmtError(); + + // Handle clauses, which can be any of the following: [looprange, apply] + const OMPLoopRangeClause *LRC = + OMPExecutableDirective::getSingleClause(Clauses); + + // The clause arguments are invalidated if any error arises + // such as non-constant or non-positive arguments + if (LRC && (!LRC->getFirst() || !LRC->getCount())) +return StmtError(); + + // Delayed semantic check of LoopRange constraint + // Evaluates the loop range arguments and returns the first and count values + auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count, + uint64_t &FirstVal, + uint64_t &CountVal) { +llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context); +llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context); +FirstVal = FirstInt.getZExtValue(); +CountVal = CountInt.getZExtValue(); + }; + + // OpenMP [6.0, Restrictions] + // first + count - 1 must not evaluate to a value greater than the + // loop sequence length of the associated canonical loop sequence. + auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal, + unsigned NumLoops) -> bool { +return FirstVal + CountVal - 1 <= NumLoops; + }; + uint64_t FirstVal = 1, CountVal = 0, LastVal = LoopSeqSize; + + // Validates the loop range after evaluating the semantic information + // and ensures that the range is valid for the given loop sequence size. + // Expressions are evaluated at compile time to obtain constant values. + if (LRC) { +EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal, + CountVal); +if (CountVal == 1) + SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion) + << getOpenMPDirectiveName(OMPD_fuse); + +if (!ValidLoopRange(FirstVal, CountVal, LoopSeqSize)) { + SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange) + << getOpenMPDirectiveName(OMPD_fuse) << (FirstVal + CountVal - 1) + << LoopSeqSize; + return StmtError(); +} + +LastVal = FirstVal + CountVal - 1; + } + + // Complete fusion generates a single canonical loop nest + // However looprange clause generates several loop nests + unsigned NumLoopNests = LRC ? LoopSeqSize - CountVal + 1 : 1; + + // Emit a warning for redundant loop fusion when the sequence contains only + // one loop. + if (LoopSeqSize == 1) +SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion) +<< getOpenMPDirectiveName(OMPD_fuse); + + assert(LoopHelpers.size() == LoopSeqSize && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + assert(OriginalInits.size() == LoopSeqSize && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + + // Select the type with the largest bit width among all induction variables + QualType IVType = LoopHel
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -14189,10 +14196,49 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective( getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); } +/// Overloaded base case function +template static bool tryHandleAs(T *t, F &&) { + return false; +} + +/// +/// Tries to recursively cast `t` to one of the given types and invokes `f` if +/// successful. +/// +/// @tparam Class The first type to check. +/// @tparam Rest The remaining types to check. +/// @tparam T The base type of `t`. +/// @tparam F The callable type for the function to invoke upon a successful +/// cast. +/// @param t The object to be checked. +/// @param f The function to invoke if `t` matches `Class`. +/// @return `true` if `t` matched any type and `f` was called, otherwise +/// `false`. +template +static bool tryHandleAs(T *t, F &&f) { + if (Class *c = dyn_cast(t)) { +f(c); +return true; + } + return tryHandleAs(t, std::forward(f)); +} + +/// Updates OriginalInits by checking Transform against loop transformation +/// directives and appending their pre-inits if a match is found. +static void updatePreInits(OMPLoopBasedDirective *Transform, + SmallVectorImpl> &PreInits) { + if (!tryHandleAs( + Transform, [&PreInits](auto *Dir) { +appendFlattenedStmtList(PreInits.back(), Dir->getPreInits()); Meinersbur wrote: Consider introducing `getPreInits` as a member of `OMPLoopBasedDirective`. It might still call its derived classes function. The the established pattern is a switch case over `getStmtClass()` instead of polymorphic lambdas. https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -14219,27 +14265,320 @@ bool SemaOpenMP::checkTransformableLoopNest( return false; }, [&OriginalInits](OMPLoopBasedDirective *Transform) { -Stmt *DependentPreInits; -if (auto *Dir = dyn_cast(Transform)) - DependentPreInits = Dir->getPreInits(); -else if (auto *Dir = dyn_cast(Transform)) - DependentPreInits = Dir->getPreInits(); -else if (auto *Dir = dyn_cast(Transform)) - DependentPreInits = Dir->getPreInits(); -else if (auto *Dir = dyn_cast(Transform)) - DependentPreInits = Dir->getPreInits(); -else if (auto *Dir = dyn_cast(Transform)) - DependentPreInits = Dir->getPreInits(); -else - llvm_unreachable("Unhandled loop transformation"); - -appendFlattenedStmtList(OriginalInits.back(), DependentPreInits); +updatePreInits(Transform, OriginalInits); }); assert(OriginalInits.back().empty() && "No preinit after innermost loop"); OriginalInits.pop_back(); return Result; } +/// Counts the total number of nested loops, including the outermost loop (the +/// original loop). PRECONDITION of this visitor is that it must be invoked from +/// the original loop to be analyzed. The traversal is stop for Decl's and +/// Expr's given that they may contain inner loops that must not be counted. +/// +/// Example AST structure for the code: +/// +/// int main() { +/// #pragma omp fuse +/// { +/// for (int i = 0; i < 100; i++) {<-- Outer loop +/// []() { +/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP +/// }; +/// for(int j = 0; j < 5; ++j) {}<-- Inner loop +/// } +/// for (int r = 0; i < 100; i++) {<-- Outer loop +/// struct LocalClass { +/// void bar() { +/// for(int j = 0; j < 100; j++) {} <-- NOT A LOOP +/// } +/// }; +/// for(int k = 0; k < 10; ++k) {}<-- Inner loop +/// {x = 5; for(k = 0; k < 10; ++k) x += k; x}; <-- NOT A LOOP +/// } +/// } +/// } +/// Result: Loop 'i' contains 2 loops, Loop 'r' also contains 2 loops +class NestedLoopCounterVisitor : public DynamicRecursiveASTVisitor { +private: + unsigned NestedLoopCount = 0; + +public: + explicit NestedLoopCounterVisitor() = default; + + unsigned getNestedLoopCount() const { return NestedLoopCount; } + + bool VisitForStmt(ForStmt *FS) override { +++NestedLoopCount; +return true; + } + + bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override { +++NestedLoopCount; +return true; + } + + bool TraverseStmt(Stmt *S) override { +if (!S) + return true; + +// Skip traversal of all expressions, including special cases like +// LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions +// may contain inner statements (and even loops), but they are not part +// of the syntactic body of the surrounding loop structure. +// Therefore must not be counted +if (isa(S)) + return true; + +// Only recurse into CompoundStmt (block {}) and loop bodies +if (isa(S)) { + return DynamicRecursiveASTVisitor::TraverseStmt(S); +} + +// Stop traversal of the rest of statements, that break perfect +// loop nesting, such as control flow (IfStmt, SwitchStmt...) +return true; + } + + bool TraverseDecl(Decl *D) override { +// Stop in the case of finding a declaration, it is not important +// in order to find nested loops (Possible CXXRecordDecl, RecordDecl, +// FunctionDecl...) +return true; + } +}; + +bool SemaOpenMP::analyzeLoopSequence( +Stmt *LoopSeqStmt, unsigned &LoopSeqSize, unsigned &NumLoops, +SmallVectorImpl &LoopHelpers, +SmallVectorImpl &ForStmts, +SmallVectorImpl> &OriginalInits, +SmallVectorImpl> &TransformsPreInits, +SmallVectorImpl> &LoopSequencePreInits, +SmallVectorImpl &LoopCategories, ASTContext &Context, +OpenMPDirectiveKind Kind) { + + VarsWithInheritedDSAType TmpDSA; + /// Helper Lambda to handle storing initialization and body statements for + /// both ForStmt and CXXForRangeStmt + auto StoreLoopStatements = [&](Stmt *LoopStmt) { +if (auto *For = dyn_cast(LoopStmt)) { + OriginalInits.back().push_back(For->getInit()); + ForStmts.push_back(For); +} else { + auto *CXXFor = cast(LoopStmt); + OriginalInits.back().push_back(CXXFor->getBeginStmt()); + ForStmts.push_back(CXXFor); +} + }; + + /// Helper lambda functions to encapsulate the processing of different + /// derivations of the canonical loop sequence grammar + /// Modularized code for handling loop generation and transformations + auto AnalyzeLoopGeneration = [&](Stmt *Child) { +auto *LoopTransform = dyn_cast(Child); +Stmt *TransformedStmt = LoopTransform->getTransformedStmt(); +unsigned NumGeneratedLoopNests = LoopTrans
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -22,6 +22,7 @@ #include "clang/AST/DeclOpenMP.h" #include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/OpenMPClause.h" +#include "clang/AST/RecursiveASTVisitor.h" Meinersbur wrote: [nit] unused https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -11516,6 +11516,21 @@ def note_omp_implicit_dsa : Note< "implicitly determined as %0">; def err_omp_loop_var_dsa : Error< "loop iteration variable in the associated loop of 'omp %1' directive may not be %0, predetermined as %2">; +def warn_omp_different_loop_ind_var_types : Warning < + "loop sequence following '#pragma omp %0' contains induction variables of differing types: %1 and %2">, + InGroup; +def err_omp_not_canonical_loop : Error < + "loop after '#pragma omp %0' is not in canonical form">; +def err_omp_not_a_loop_sequence : Error < + "statement after '#pragma omp %0' must be a loop sequence containing canonical loops or loop-generating constructs">; +def err_omp_empty_loop_sequence : Error < + "loop sequence after '#pragma omp %0' must contain at least 1 canonical loop or loop-generating construct">; +def err_omp_invalid_looprange : Error < + "loop range in '#pragma omp %0' exceeds the number of available loops: " + "range end '%1' is greater than the total number of loops '%2'">; Meinersbur wrote: I think he means that "exceeds the number of available loops" and "range end '%1' is greater than the total number of loops '%2'" are redundant. (of the err_omp_invalid_looprange definition). Proposal: "looprange clause selection exceeds number of loops in loop sequence" (or similar) I don't think mentioning '#pragma omp %0' is necessary, it is already pointed to by the SourceLocation. %1 and %2 are numbers, not necessary to put them in quotes https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -15499,6 +15836,496 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective( buildPreInits(Context, PreInits)); } +StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef Clauses, +Stmt *AStmt, +SourceLocation StartLoc, +SourceLocation EndLoc) { + + ASTContext &Context = getASTContext(); + DeclContext *CurrContext = SemaRef.CurContext; + Scope *CurScope = SemaRef.getCurScope(); + CaptureVars CopyTransformer(SemaRef); + + // Ensure the structured block is not empty + if (!AStmt) +return StmtError(); + + unsigned NumLoops = 1; + unsigned LoopSeqSize = 1; + + // Defer transformation in dependent contexts + // The NumLoopNests argument is set to a placeholder 1 (even though + // using looprange fuse could yield up to 3 top level loop nests) + // because a dependent context could prevent determining its true value + if (CurrContext->isDependentContext()) { +return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses, +NumLoops, LoopSeqSize, AStmt, nullptr, +nullptr); + } + + // Validate that the potential loop sequence is transformable for fusion + // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops + SmallVector LoopHelpers; + SmallVector LoopStmts; + SmallVector> OriginalInits; + SmallVector> TransformsPreInits; + SmallVector> LoopSequencePreInits; + SmallVector LoopCategories; + if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, LoopSeqSize, NumLoops, + LoopHelpers, LoopStmts, OriginalInits, + TransformsPreInits, LoopSequencePreInits, + LoopCategories, Context)) +return StmtError(); + + // Handle clauses, which can be any of the following: [looprange, apply] + const OMPLoopRangeClause *LRC = + OMPExecutableDirective::getSingleClause(Clauses); + + // The clause arguments are invalidated if any error arises + // such as non-constant or non-positive arguments + if (LRC && (!LRC->getFirst() || !LRC->getCount())) +return StmtError(); + + // Delayed semantic check of LoopRange constraint + // Evaluates the loop range arguments and returns the first and count values + auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count, + uint64_t &FirstVal, + uint64_t &CountVal) { +llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context); +llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context); +FirstVal = FirstInt.getZExtValue(); +CountVal = CountInt.getZExtValue(); + }; + + // OpenMP [6.0, Restrictions] + // first + count - 1 must not evaluate to a value greater than the + // loop sequence length of the associated canonical loop sequence. + auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal, + unsigned NumLoops) -> bool { +return FirstVal + CountVal - 1 <= NumLoops; + }; + uint64_t FirstVal = 1, CountVal = 0, LastVal = LoopSeqSize; + + // Validates the loop range after evaluating the semantic information + // and ensures that the range is valid for the given loop sequence size. + // Expressions are evaluated at compile time to obtain constant values. + if (LRC) { +EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal, + CountVal); +if (CountVal == 1) + SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion) + << getOpenMPDirectiveName(OMPD_fuse); + +if (!ValidLoopRange(FirstVal, CountVal, LoopSeqSize)) { + SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange) + << getOpenMPDirectiveName(OMPD_fuse) << (FirstVal + CountVal - 1) + << LoopSeqSize; + return StmtError(); +} + +LastVal = FirstVal + CountVal - 1; + } + + // Complete fusion generates a single canonical loop nest + // However looprange clause generates several loop nests + unsigned NumLoopNests = LRC ? LoopSeqSize - CountVal + 1 : 1; + + // Emit a warning for redundant loop fusion when the sequence contains only + // one loop. + if (LoopSeqSize == 1) +SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion) +<< getOpenMPDirectiveName(OMPD_fuse); + + assert(LoopHelpers.size() == LoopSeqSize && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + assert(OriginalInits.size() == LoopSeqSize && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + + // Select the type with the largest bit width among all induction variables + QualType IVType = LoopHel
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -0,0 +1,211 @@ +// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -std=c++20 -fopenmp -fopenmp-version=60 -fsyntax-only -Wuninitialized -verify %s + +void func() { + +// expected-error@+2 {{statement after '#pragma omp fuse' must be a loop sequence containing canonical loops or loop-generating constructs}} +#pragma omp fuse +; + +// expected-error@+2 {{statement after '#pragma omp fuse' must be a for loop}} +#pragma omp fuse +{int bar = 0;} + +// expected-error@+4 {{statement after '#pragma omp fuse' must be a for loop}} +#pragma omp fuse +{ +for(int i = 0; i < 10; ++i); +int x = 2; +} + +// expected-error@+2 {{statement after '#pragma omp fuse' must be a loop sequence containing canonical loops or loop-generating constructs}} +#pragma omp fuse +#pragma omp for +for (int i = 0; i < 7; ++i) +; + +{ +// expected-error@+2 {{expected statement}} +#pragma omp fuse +} + +// expected-warning@+1 {{extra tokens at the end of '#pragma omp fuse' are ignored}} +#pragma omp fuse foo +{ +for (int i = 0; i < 7; ++i) +; +for(int j = 0; j < 100; ++j); + +} + + +// expected-error@+1 {{unexpected OpenMP clause 'final' in directive '#pragma omp fuse'}} +#pragma omp fuse final(0) +{ +for (int i = 0; i < 7; ++i) +; +for(int j = 0; j < 100; ++j); + +} + +//expected-error@+4 {{loop after '#pragma omp fuse' is not in canonical form}} +//expected-error@+3 {{increment clause of OpenMP for loop must perform simple addition or subtraction on loop variable 'i'}} +#pragma omp fuse +{ +for(int i = 0; i < 10; i*=2) { +; +} +for(int j = 0; j < 100; ++j); +} + +//expected-error@+2 {{loop sequence after '#pragma omp fuse' must contain at least 1 canonical loop or loop-generating construct}} +#pragma omp fuse +{} + +//expected-error@+3 {{statement after '#pragma omp fuse' must be a for loop}} +#pragma omp fuse +{ +#pragma omp unroll full +for(int i = 0; i < 10; ++i); + +for(int j = 0; j < 10; ++j); +} + +//expected-warning@+2 {{loop range in '#pragma omp fuse' contains only a single loop, resulting in redundant fusion}} +#pragma omp fuse +{ +for(int i = 0; i < 10; ++i); +} + +//expected-warning@+1 {{loop range in '#pragma omp fuse' contains only a single loop, resulting in redundant fusion}} +#pragma omp fuse looprange(1, 1) +{ +for(int i = 0; i < 10; ++i); +for(int j = 0; j < 100; ++j); +} + +//expected-error@+1 {{argument to 'looprange' clause must be a strictly positive integer value}} +#pragma omp fuse looprange(1, -1) +{ +for(int i = 0; i < 10; ++i); +for(int j = 0; j < 100; ++j); +} + +//expected-error@+1 {{argument to 'looprange' clause must be a strictly positive integer value}} +#pragma omp fuse looprange(1, 0) +{ +for(int i = 0; i < 10; ++i); +for(int j = 0; j < 100; ++j); +} + +const int x = 1; +constexpr int y = 4; +//expected-error@+1 {{loop range in '#pragma omp fuse' exceeds the number of available loops: range end '4' is greater than the total number of loops '3'}} +#pragma omp fuse looprange(x,y) +{ +for(int i = 0; i < 10; ++i); +for(int j = 0; j < 100; ++j); +for(int k = 0; k < 50; ++k); +} + +//expected-error@+1 {{loop range in '#pragma omp fuse' exceeds the number of available loops: range end '420' is greater than the total number of loops '3'}} +#pragma omp fuse looprange(1,420) +{ +for(int i = 0; i < 10; ++i); +for(int j = 0; j < 100; ++j); +for(int k = 0; k < 50; ++k); +} + +//expected-error@+1 {{loop range in '#pragma omp fuse' exceeds the number of available loops: range end '6' is greater than the total number of loops '5'}} +#pragma omp fuse looprange(1,6) +{ +for(int i = 0; i < 10; ++i); +for(int j = 0; j < 100; ++j); +for(int k = 0; k < 50; ++k); +// This fusion results in 2 loops +#pragma omp fuse looprange(1,2) +{ +for(int i = 0; i < 10; ++i); +for(int j = 0; j < 100; ++j); +for(int k = 0; k < 50; ++k); +} +} + +//expected-error@+1 {{loop range in '#pragma omp fuse' exceeds the number of available loops: range end '4' is greater than the total number of loops '3'}} +#pragma omp fuse looprange(2,3) +{ +#pragma omp unroll partial(2) +for(int i = 0; i < 10; ++i); + +#pragma omp reverse +for(int j = 0; j < 10; ++j); + +#pragma omp fuse +{ +{ +#pragma omp reverse +for(int j = 0; j < 10; ++j); +} +for(int k
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
https://github.com/Meinersbur edited https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [ValueTracking] Return true for AddrSpaceCast in canCreateUndefOrPoison (PR #144686)
wenju-he wrote: > For the purposes of this PR, I think you should only change > canCreateUndefOrPoison to return true and just eat the regressions. done. Please let me know if we should add FIXME for the regression in clang/test/CodeGenOpenCL/amdgcn-buffer-rsrc-type.cl and llvm/test/Transforms/Attributor/reduced/aapointer_info_map_invalidation.ll The change in clang/test/CodeGenOpenCL/as_type.cl should not be a regression since spir isn't a concrete target. https://github.com/llvm/llvm-project/pull/144686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Clean up enum attributes (PR #144999)
xlauko wrote: * **#144999** https://app.graphite.dev/github/pr/llvm/llvm-project/144999?utm_source=stack-comment-icon"; target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/144999?utm_source=stack-comment-view-in-graphite"; target="_blank">(View in Graphite) * `main` This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn more about https://stacking.dev/?utm_source=stack-comment";>stacking. https://github.com/llvm/llvm-project/pull/144999 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Clean up enum attributes (PR #144999)
llvmbot wrote: @llvm/pr-subscribers-clangir Author: Henrich Lauko (xlauko) Changes This mirrors incubator changes from https://github.com/llvm/clangir/pull/1678 - Create CIR specific EnumAttr bases and prefix enum attributes with CIR_ that automatically puts enum to cir namespace - Removes unnecessary enum case definitions - Unifies naming of enum values to use capitals consistently and make enumerations to start from 0 --- Patch is 22.92 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144999.diff 2 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIRAttrs.td (+22-15) - (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+189-235) ``diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 9e01dde379d7a..03e970db2847d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -47,6 +47,16 @@ class CIR_I32EnumAttr cases> 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"; @@ -330,36 +340,33 @@ def ConstComplexAttr : CIR_Attr<"ConstComplex", "const_complex", // VisibilityAttr //===--===// -def CIR_VisibilityKind : I32EnumAttr<"VisibilityKind", "C/C++ visibility", [ - I32EnumAttrCase<"Default", 1, "default">, - I32EnumAttrCase<"Hidden", 2, "hidden">, - I32EnumAttrCase<"Protected", 3, "protected"> +def CIR_VisibilityKind : CIR_I32EnumAttr<"VisibilityKind", "C/C++ visibility", [ + I32EnumAttrCase<"Default", 0, "default">, + I32EnumAttrCase<"Hidden", 1, "hidden">, + I32EnumAttrCase<"Protected", 2, "protected"> ]> { let genSpecializedAttr = 0; - let cppNamespace = "::cir"; } -def CIR_VisibilityAttr : CIR_Attr<"Visibility", "visibility"> { +def CIR_VisibilityAttr : CIR_EnumAttr { let summary = "Visibility attribute"; let description = [{ Visibility attributes. }]; - let parameters = (ins "VisibilityKind":$value); - let assemblyFormat = [{ -$value - }]; + let cppClassName = "VisibilityAttr"; + let skipDefaultBuilders = 1; let builders = [ -AttrBuilder<(ins CArg<"VisibilityKind", "cir::VisibilityKind::Default">:$value), [{ +AttrBuilder<(ins CArg<"VisibilityKind", + "cir::VisibilityKind::Default">:$value), [{ return $_get($_ctxt, value); }]> ]; - let skipDefaultBuilders = 1; - - // Make DefaultValuedAttr accept VisibilityKind as default value ($0). - let constBuilderCall = "cir::VisibilityAttr::get($_builder.getContext(), $0)"; + let assemblyFormat = [{ +$value + }]; let extraClassDeclaration = [{ bool isDefault() const { return getValue() == VisibilityKind::Default; }; diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 852d3aa131148..f978bd9a96bcf 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -91,94 +91,80 @@ def SameFirstOperandAndResultType : // CastOp //===--===// -// CK_Dependent -def CK_BitCast : I32EnumAttrCase<"bitcast", 1>; -// CK_LValueBitCast -// CK_LValueToRValueBitCast -// CK_LValueToRValue -// CK_NoOp -// CK_BaseToDerived -// CK_DerivedToBase -// CK_UncheckedDerivedToBase -// CK_Dynamic -// CK_ToUnion -def CK_ArrayToPointerDecay : I32EnumAttrCase<"array_to_ptrdecay", 11>; -// CK_FunctionToPointerDecay -// CK_NullToPointer -// CK_NullToMemberPointer -// CK_BaseToDerivedMemberPointer -// CK_DerivedToBaseMemberPointer -def CK_MemberPointerToBoolean : I32EnumAttrCase<"member_ptr_to_bool", 17>; -// CK_ReinterpretMemberPointer -// CK_UserDefinedConversion -// CK_ConstructorConversion -def CK_IntegralToPointer : I32EnumAttrCase<"int_to_ptr", 21>; -def CK_PointerToIntegral : I32EnumAttrCase<"ptr_to_int", 22>; -def CK_PointerToBoolean : I32EnumAttrCase<"ptr_to_bool", 23>; -// CK_ToVoid -// CK_MatrixCast -// CK_VectorSplat -def CK_IntegralCast : I32EnumAttrCase<"integral", 27>; -def CK_IntegralToBoolean : I32EnumAttrCase<"int_to_bool", 28>; -def CK_IntegralToFloating : I32EnumAttrCase<"int_to_float", 29>; -// CK_FloatingToFixedPoint -// CK_FixedPointToFloating -// CK_FixedPointCast -// CK_FixedPointToIntegral -// CK_IntegralToFixedPoint -// CK_FixedPointToBoolean -def CK_FloatingToIntegral : I32EnumAttrCase<"float_to_int", 36>; -def CK_FloatingToBoolean : I32EnumAttrCase<"float_to_bool", 37>; -def CK_BooleanToSignedIntegral : I32EnumAttrCase<"bool_to_int", 38>; -def CK_FloatingCast : I32EnumAttrCase<"floating", 39>; -// CK_CPointerToObjCPointerCast -// CK_BlockPointerToObjCPoi
[clang] [CIR] Clean up enum attributes (PR #144999)
https://github.com/xlauko created https://github.com/llvm/llvm-project/pull/144999 This mirrors incubator changes from https://github.com/llvm/clangir/pull/1678 - Create CIR specific EnumAttr bases and prefix enum attributes with CIR_ that automatically puts enum to cir namespace - Removes unnecessary enum case definitions - Unifies naming of enum values to use capitals consistently and make enumerations to start from 0 >From b52596a41e945ae2b2670378d82d00189a1427e2 Mon Sep 17 00:00:00 2001 From: xlauko Date: Fri, 20 Jun 2025 10:53:46 +0200 Subject: [PATCH] [CIR] Clean up enum attributes This mirrors incubator changes from https://github.com/llvm/clangir/pull/1678 - Create CIR specific EnumAttr bases and prefix enum attributes with CIR_ that automatically puts enum to cir namespace - Removes unnecessary enum case definitions - Unifies naming of enum values to use capitals consistently and make enumerations to start from 0 --- .../include/clang/CIR/Dialect/IR/CIRAttrs.td | 37 +- clang/include/clang/CIR/Dialect/IR/CIROps.td | 424 -- 2 files changed, 211 insertions(+), 250 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td index 9e01dde379d7a..03e970db2847d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td +++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td @@ -47,6 +47,16 @@ class CIR_I32EnumAttr cases> 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"; @@ -330,36 +340,33 @@ def ConstComplexAttr : CIR_Attr<"ConstComplex", "const_complex", // VisibilityAttr //===--===// -def CIR_VisibilityKind : I32EnumAttr<"VisibilityKind", "C/C++ visibility", [ - I32EnumAttrCase<"Default", 1, "default">, - I32EnumAttrCase<"Hidden", 2, "hidden">, - I32EnumAttrCase<"Protected", 3, "protected"> +def CIR_VisibilityKind : CIR_I32EnumAttr<"VisibilityKind", "C/C++ visibility", [ + I32EnumAttrCase<"Default", 0, "default">, + I32EnumAttrCase<"Hidden", 1, "hidden">, + I32EnumAttrCase<"Protected", 2, "protected"> ]> { let genSpecializedAttr = 0; - let cppNamespace = "::cir"; } -def CIR_VisibilityAttr : CIR_Attr<"Visibility", "visibility"> { +def CIR_VisibilityAttr : CIR_EnumAttr { let summary = "Visibility attribute"; let description = [{ Visibility attributes. }]; - let parameters = (ins "VisibilityKind":$value); - let assemblyFormat = [{ -$value - }]; + let cppClassName = "VisibilityAttr"; + let skipDefaultBuilders = 1; let builders = [ -AttrBuilder<(ins CArg<"VisibilityKind", "cir::VisibilityKind::Default">:$value), [{ +AttrBuilder<(ins CArg<"VisibilityKind", + "cir::VisibilityKind::Default">:$value), [{ return $_get($_ctxt, value); }]> ]; - let skipDefaultBuilders = 1; - - // Make DefaultValuedAttr accept VisibilityKind as default value ($0). - let constBuilderCall = "cir::VisibilityAttr::get($_builder.getContext(), $0)"; + let assemblyFormat = [{ +$value + }]; let extraClassDeclaration = [{ bool isDefault() const { return getValue() == VisibilityKind::Default; }; diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 852d3aa131148..f978bd9a96bcf 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -91,94 +91,80 @@ def SameFirstOperandAndResultType : // CastOp //===--===// -// CK_Dependent -def CK_BitCast : I32EnumAttrCase<"bitcast", 1>; -// CK_LValueBitCast -// CK_LValueToRValueBitCast -// CK_LValueToRValue -// CK_NoOp -// CK_BaseToDerived -// CK_DerivedToBase -// CK_UncheckedDerivedToBase -// CK_Dynamic -// CK_ToUnion -def CK_ArrayToPointerDecay : I32EnumAttrCase<"array_to_ptrdecay", 11>; -// CK_FunctionToPointerDecay -// CK_NullToPointer -// CK_NullToMemberPointer -// CK_BaseToDerivedMemberPointer -// CK_DerivedToBaseMemberPointer -def CK_MemberPointerToBoolean : I32EnumAttrCase<"member_ptr_to_bool", 17>; -// CK_ReinterpretMemberPointer -// CK_UserDefinedConversion -// CK_ConstructorConversion -def CK_IntegralToPointer : I32EnumAttrCase<"int_to_ptr", 21>; -def CK_PointerToIntegral : I32EnumAttrCase<"ptr_to_int", 22>; -def CK_PointerToBoolean : I32EnumAttrCase<"ptr_to_bool", 23>; -// CK_ToVoid -// CK_MatrixCast -// CK_VectorSplat -def CK_IntegralCast : I32EnumAttrCase<"integral", 27>; -def CK_IntegralToBoolean : I32EnumAttrCase<"int_to_bool", 28>; -def CK_IntegralToFloating : I32EnumAttrCase<"int_to_float", 29>; -// CK_FloatingToFixedPoint -// CK_FixedPointToFloating -// CK_FixedPointCast -//
[clang] [llvm] [ValueTracking] Return true for AddrSpaceCast in canCreateUndefOrPoison (PR #144686)
https://github.com/nikic edited https://github.com/llvm/llvm-project/pull/144686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [ValueTracking] Return true for AddrSpaceCast in canCreateUndefOrPoison (PR #144686)
@@ -0,0 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -passes=instcombine %s | FileCheck %s + +; Check that `select B, true, C` isn't optimized to `or B, C`. nikic wrote: ```suggestion ; Check that `select B, true, C` isn't optimized to `or B, C`, ; because the invalid addrspacecast %asc.shared may introduce poison. ``` https://github.com/llvm/llvm-project/pull/144686 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] DRAFT: [flang][OpenMP] Remove experimental warning (PR #144915)
https://github.com/kparzysz approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/144915 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] DRAFT: [flang][OpenMP] Remove experimental warning (PR #144915)
https://github.com/tblah updated https://github.com/llvm/llvm-project/pull/144915 >From e41a93accace06b39e8421fddbfd7673a3b429dc Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Thu, 19 Jun 2025 14:57:04 + Subject: [PATCH 1/2] DRAFT: [flang][OpenMP] Remove experimental warning RFC: https://discourse.llvm.org/t/rfc-removing-the-openmp-experimental-warning-for-llvm-21/86455 Fixes: #110008 --- .../clang/Basic/DiagnosticDriverKinds.td | 4 ++-- clang/lib/Driver/ToolChains/Flang.cpp | 19 --- flang/test/Driver/fopenmp.f90 | 4 ++-- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 29f6480ba935c..68f87ebb1b39f 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -143,8 +143,8 @@ def warn_drv_unsupported_option_for_processor : Warning< def warn_drv_unsupported_openmp_library : Warning< "the library '%0=%1' is not supported, OpenMP will not be enabled">, InGroup; -def warn_openmp_experimental : Warning< - "OpenMP support in flang is still experimental">, +def warn_openmp_incomplete : Warning< + "OpenMP support for version %0 in flang is still incomplete">, InGroup; def err_drv_invalid_thread_model_for_target : Error< diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 47d0e345086b2..04613457cb20a 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -11,6 +11,7 @@ #include "clang/Basic/CodeGenOptions.h" #include "clang/Driver/CommonArgs.h" +#include "clang/Driver/OptionUtils.h" #include "clang/Driver/Options.h" #include "llvm/Frontend/Debug/Options.h" #include "llvm/Support/Path.h" @@ -772,6 +773,13 @@ static void renderRemarksOptions(const ArgList &Args, ArgStringList &CmdArgs, } } +static std::string OpenMPVersionToString(int Version) { + int Major = Version / 10; + int Minor = Version % 10; + + return llvm::Twine{Major}.concat(".").concat(llvm::Twine{Minor}).str(); +} + void Flang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, const ArgList &Args, const char *LinkingOutput) const { @@ -906,9 +914,14 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_fopenmp_force_usm)) CmdArgs.push_back("-fopenmp-force-usm"); - // TODO: OpenMP support isn't "done" yet, so for now we warn that it - // is experimental. - D.Diag(diag::warn_openmp_experimental); + + // TODO: OpenMP support for newer versions of the standard is incomplete. + if (int Version = + getLastArgIntValue(Args, options::OPT_fopenmp_version_EQ, 0)) { +if (Version >= 40) + D.Diag(diag::warn_openmp_incomplete) + << OpenMPVersionToString(Version); + } // FIXME: Clang supports a whole bunch more flags here. break; diff --git a/flang/test/Driver/fopenmp.f90 b/flang/test/Driver/fopenmp.f90 index b3c3547800bdb..b170e77372d50 100644 --- a/flang/test/Driver/fopenmp.f90 +++ b/flang/test/Driver/fopenmp.f90 @@ -74,6 +74,6 @@ ! CHECK-LD-ANYMD: "{{.*}}ld{{(.exe)?}}" ! CHECK-LD-ANYMD: "-l{{(omp|gomp|iomp5md)}}" ! -! RUN: %flang -fopenmp -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-EXPERIMENTAL +! RUN: %flang -fopenmp -fopenmp-version=40 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-EXPERIMENTAL ! -! CHECK-EXPERIMENTAL: flang{{.*}}: warning: OpenMP support in flang is still experimental +! CHECK-EXPERIMENTAL: flang{{.*}}: warning: OpenMP support for version 4.0 in flang is still incomplete >From 172de0a91e81e57fab623ccd8b2b413e20b2dfc2 Mon Sep 17 00:00:00 2001 From: Tom Eccles Date: Fri, 20 Jun 2025 11:33:03 + Subject: [PATCH 2/2] s/EXPERIMENTAL/INCOMPLETE/ --- flang/test/Driver/fopenmp.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flang/test/Driver/fopenmp.f90 b/flang/test/Driver/fopenmp.f90 index b170e77372d50..3a150aa657953 100644 --- a/flang/test/Driver/fopenmp.f90 +++ b/flang/test/Driver/fopenmp.f90 @@ -74,6 +74,6 @@ ! CHECK-LD-ANYMD: "{{.*}}ld{{(.exe)?}}" ! CHECK-LD-ANYMD: "-l{{(omp|gomp|iomp5md)}}" ! -! RUN: %flang -fopenmp -fopenmp-version=40 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-EXPERIMENTAL +! RUN: %flang -fopenmp -fopenmp-version=40 -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-INCOMPLETE ! -! CHECK-EXPERIMENTAL: flang{{.*}}: warning: OpenMP support for version 4.0 in flang is still incomplete +! CHECK-INCOMPLETE: flang{{.*}}: warning: OpenMP support for version 4.0 in flang is still incomplete ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Ast importer visitors (PR #138838)
https://github.com/ganenkokb-yandex updated https://github.com/llvm/llvm-project/pull/138838 >From 6a4d62ce1c72639d7fe82565744b3e8808dce4c3 Mon Sep 17 00:00:00 2001 From: Evianaive <153540...@qq.com> Date: Tue, 25 Mar 2025 01:54:06 +0800 Subject: [PATCH 01/19] Implement missing visit function --- clang/lib/AST/ASTImporter.cpp | 285 +- 1 file changed, 284 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 5c44353d8b987..d8767a48ad27d 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -68,6 +68,7 @@ #include #include #include +#include "ExprConcepts.h" namespace clang { @@ -564,6 +565,9 @@ namespace clang { ExpectedDecl VisitVarTemplateDecl(VarTemplateDecl *D); ExpectedDecl VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); ExpectedDecl VisitFunctionTemplateDecl(FunctionTemplateDecl *D); +ExpectedDecl VisitConceptDecl(ConceptDecl* D); +ExpectedDecl VisitRequiresExprBodyDecl(RequiresExprBodyDecl* E); +ExpectedDecl VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl* D); // Importing statements ExpectedStmt VisitStmt(Stmt *S); @@ -680,6 +684,8 @@ namespace clang { ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E); ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E); ExpectedStmt VisitCXXFoldExpr(CXXFoldExpr *E); +ExpectedStmt VisitRequiresExpr(RequiresExpr* E); +ExpectedStmt VisitConceptSpecializationExpr(ConceptSpecializationExpr* E); // Helper for chaining together multiple imports. If an error is detected, // subsequent imports will return default constructed nodes, so that failure @@ -1063,6 +1069,168 @@ Expected ASTNodeImporter::import(const LambdaCapture &From) { EllipsisLoc); } +template<> +Expected ASTNodeImporter::import(concepts::Requirement* FromRequire) { + auto ImportStringRef = [this](const StringRef& FromString) { + char* ToDiagMessage = new (Importer.getToContext()) char[FromString.size()]; + std::copy(FromString.begin(),FromString.end(),ToDiagMessage); + return StringRef(ToDiagMessage,FromString.size()); +}; + + auto ImportSubstitutionDiagnos = [this, &ImportStringRef] + (concepts::Requirement::SubstitutionDiagnostic* FromDiagnos, Error& Err)->concepts::Requirement::SubstitutionDiagnostic* { +const auto& ToEntity = ImportStringRef(FromDiagnos->SubstitutedEntity); +Expected ToLoc = import(FromDiagnos->DiagLoc); +if(!ToLoc) { + Err = ToLoc.takeError(); + return nullptr; +} +const auto& ToDiagMessage = ImportStringRef(FromDiagnos->DiagMessage); +return new (Importer.getToContext()) concepts::Requirement::SubstitutionDiagnostic{ + ToEntity, + ToLoc.get(), + ToDiagMessage}; + }; + switch (FromRequire->getKind()) { + case concepts::Requirement::RequirementKind::RK_Type: { +auto *From = cast(FromRequire); +if(From->isSubstitutionFailure()) +{ + // Should we return Error directly if TypeRequirement isSubstitutionFailure? + Error Err = Error::success(); + auto Diagnos = ImportSubstitutionDiagnos(From->getSubstitutionDiagnostic(),Err); + if (Err) +return std::move(Err); + return new (Importer.getToContext()) concepts::TypeRequirement(Diagnos); +} +else { + Expected ToType = import(From->getType()); + if(!ToType) +return ToType.takeError(); + return new (Importer.getToContext()) concepts::TypeRequirement(ToType.get()); +} +break; + } + case concepts::Requirement::RequirementKind::RK_Compound: + case concepts::Requirement::RequirementKind::RK_Simple: { +const auto *From = cast(FromRequire); + +auto Status = From->getSatisfactionStatus(); +llvm::PointerUnion E; +if (Status == concepts::ExprRequirement::SS_ExprSubstitutionFailure) { + Error Err = Error::success(); + E = ImportSubstitutionDiagnos(From->getExprSubstitutionDiagnostic(),Err); + if (Err) +return std::move(Err); +} else { + auto ExpectE = import(From->getExpr()); + if (!ExpectE) +return ExpectE.takeError(); + E = ExpectE.get(); +} + +std::optional Req; +ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr; +SourceLocation NoexceptLoc; +bool IsRKSimple = FromRequire->getKind() == concepts::Requirement::RK_Simple; +if (IsRKSimple) { + Req.emplace(); +} else { + auto NoexceptLoc = import(From->getNoexceptLoc()); + if(!NoexceptLoc) +return NoexceptLoc.takeError(); + auto& FromTypeRequirement = From->getReturnTypeRequirement(); + + if(FromTypeRequirement.isTypeConstraint()) { +auto ParamsOrErr = import(FromTypeRequirement.getTypeConstraintTemplateParameterList()); +if (!ParamsOrErr) + return ParamsOrErr.takeError(); +if (Status >= + conce
[clang] KISHAN KUMAR S D, HRUTHIK K K , KIRAN V-R V COLLEGE OF ENGINEERING(CSE 6TH SEM)-Implement Clang identifiers to retrieve the mangled name and the fully qualified name of functions #5 (PR #14504
llvmbot wrote: @llvm/pr-subscribers-clang Author: KISHAN KUMAR S D (kishan-kumar-s-d-444) Changes # Add `__fq_func__` and `__mangled_func__` predefined identifiers to Clang ## Summary This pull request introduces two new predefined identifiers to Clang: 1. `__fq_func__` - Returns the fully qualified name of the current function 2. `__mangled_func__` - Returns the mangled name of the current function ## Affected Files 1. `llvm-project/clang/include/clang/AST/Expr.h` 2. `llvm-project/clang/lib/AST/Expr.cpp` 3. `llvm-project/clang/include/clang/Basic/TokenKinds.def` 4. `llvm-project/clang/lib/Sema/SemaExpr.cpp` 5. `llvm-project/clang/lib/Parse/ParseExpr.cpp` ## Motivation The existing predefined identifiers have limitations: - `__func__`: Only unqualified name - `__PRETTY_FUNCTION__`: Detailed signature without full qualification - No built-in way to get mangled names New identifiers provide: - Complete namespace/class qualification (`__fq_func__`) - Exact linkage name (`__mangled_func__`) - Consistent with existing identifier patterns ## Implementation Details 1. New `PredefinedIdentKind` enum values: - `FQFunction` - `MangledFunction` 2. Core implementations: ## 1) `Expr.h` → `llvm-project/clang/include/clang/AST/Expr.h` ```cpp enum class PredefinedIdentKind { Func, Function, LFunction, // Same as Function, but as wide string. FuncDName, FuncSig, LFuncSig, // Same as FuncSig, but as wide string PrettyFunction, /// The same as PrettyFunction, except that the /// 'virtual' keyword is omitted for virtual member functions. PrettyFunctionNoVirtual, FQFunction, MangledFunction }; ``` ## `2)Expr.cpp` -->`llvm-project/clang/lib/AST` ``` StringRef PredefinedExpr::getIdentKindName(PredefinedIdentKind IK) { switch (IK) { case PredefinedIdentKind::Func: return "__func__"; case PredefinedIdentKind::Function: return "__FUNCTION__"; case PredefinedIdentKind::FuncDName: return "__FUNCDNAME__"; case PredefinedIdentKind::FQFunction: return "__fq_func__"; case PredefinedIdentKind::MangledFunction: return "__mangled_func__"; case PredefinedIdentKind::LFunction: return "L__FUNCTION__"; case PredefinedIdentKind::PrettyFunction: return "__PRETTY_FUNCTION__"; case PredefinedIdentKind::FuncSig: return "__FUNCSIG__"; case PredefinedIdentKind::LFuncSig: return "L__FUNCSIG__"; case PredefinedIdentKind::PrettyFunctionNoVirtual: break; } llvm_unreachable("Unknown ident kind for PredefinedExpr"); } ``` ``` std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK, const Decl *CurrentDecl, bool ForceElaboratedPrinting) { ASTContext &Context = CurrentDecl->getASTContext(); if (IK == PredefinedIdentKind::FQFunction) { if (const auto *ND = dyn_cast(CurrentDecl)) return ND->getQualifiedNameAsString(); return " "; } if (IK == PredefinedIdentKind::MangledFunction) { if (const auto *ND = dyn_cast (CurrentDecl)) { std::unique_ptr MC; MC.reset(Context.createMangleContext()); SmallString<256> Buffer; llvm::raw_svector_ostream Out(Buffer); GlobalDecl GD; if (const CXXConstructorDecl *CD = dyn_cast (ND)) GD = GlobalDecl(CD, Ctor_Base); else if (const CXXDestructorDecl *DD = dyn_cast (ND)) GD = GlobalDecl(DD, Dtor_Base); else if (auto FD = dyn_cast (ND)) { GD = FD->isReferenceableKernel() ? GlobalDecl(FD) : GlobalDecl(ND); } else GD = GlobalDecl(ND); MC->mangleName(GD, Out); return std::string(Buffer); } return " "; } // Remaining Code continues ``` ## `3)TokenKinds.def` -->`llvm-project/clang/include/clang/Basic/TokenKinds.def` ``` KEYWORD(__fq_func__, KEYALL) KEYWORD(__mangled_func__, KEYALL) ``` ## `4)SemaExpr.cpp` -->`llvm-project/clang/lib/Sema/SemaExpr.cpp` ``` static PredefinedIdentKind getPredefinedExprKind(tok::TokenKind Kind) { switch (Kind) { default: llvm_unreachable("unexpected TokenKind"); case tok::kw___func__: return PredefinedIdentKind::Func; case tok::kw___fq_func__: return PredefinedIdentKind::FQFunction; case tok::kw___mangled_func__: return PredefinedIdentKind::MangledFunction; // Code Continues ``` ## `5)ParseExpr.cpp` -->`llvm-project/clang/lib/Parse/ParseExpr.cpp` ``` case tok::kw_L__FUNCTION__: case tok::kw_L__FUNCSIG__: case tok::kw___PRETTY_FUNCTION__: //Add below lines case tok::kw___fq_func__: case tok::kw___mangled_func__: //end here ``` ## Example Usage   --- Full diff: https://github.com/llvm/llvm-project/pull/145042.diff 5 Files Affected: - (modified) clang/include/clang/AST/Expr.
[clang] KISHAN KUMAR S D, HRUTHIK K K , KIRAN V-R V COLLEGE OF ENGINEERING(CSE 6TH SEM)-Implement Clang identifiers to retrieve the mangled name and the fully qualified name of functions #5 (PR #14504
https://github.com/kishan-kumar-s-d-444 created https://github.com/llvm/llvm-project/pull/145042 # Add `__fq_func__` and `__mangled_func__` predefined identifiers to Clang ## Summary This pull request introduces two new predefined identifiers to Clang: 1. `__fq_func__` - Returns the fully qualified name of the current function 2. `__mangled_func__` - Returns the mangled name of the current function ## Affected Files 1. `llvm-project/clang/include/clang/AST/Expr.h` 2. `llvm-project/clang/lib/AST/Expr.cpp` 3. `llvm-project/clang/include/clang/Basic/TokenKinds.def` 4. `llvm-project/clang/lib/Sema/SemaExpr.cpp` 5. `llvm-project/clang/lib/Parse/ParseExpr.cpp` ## Motivation The existing predefined identifiers have limitations: - `__func__`: Only unqualified name - `__PRETTY_FUNCTION__`: Detailed signature without full qualification - No built-in way to get mangled names New identifiers provide: - Complete namespace/class qualification (`__fq_func__`) - Exact linkage name (`__mangled_func__`) - Consistent with existing identifier patterns ## Implementation Details 1. New `PredefinedIdentKind` enum values: - `FQFunction` - `MangledFunction` 2. Core implementations: ## 1) `Expr.h` → `llvm-project/clang/include/clang/AST/Expr.h` ```cpp enum class PredefinedIdentKind { Func, Function, LFunction, // Same as Function, but as wide string. FuncDName, FuncSig, LFuncSig, // Same as FuncSig, but as wide string PrettyFunction, /// The same as PrettyFunction, except that the /// 'virtual' keyword is omitted for virtual member functions. PrettyFunctionNoVirtual, FQFunction, MangledFunction }; ``` ## `2)Expr.cpp` -->`llvm-project/clang/lib/AST` ``` StringRef PredefinedExpr::getIdentKindName(PredefinedIdentKind IK) { switch (IK) { case PredefinedIdentKind::Func: return "__func__"; case PredefinedIdentKind::Function: return "__FUNCTION__"; case PredefinedIdentKind::FuncDName: return "__FUNCDNAME__"; case PredefinedIdentKind::FQFunction: return "__fq_func__"; case PredefinedIdentKind::MangledFunction: return "__mangled_func__"; case PredefinedIdentKind::LFunction: return "L__FUNCTION__"; case PredefinedIdentKind::PrettyFunction: return "__PRETTY_FUNCTION__"; case PredefinedIdentKind::FuncSig: return "__FUNCSIG__"; case PredefinedIdentKind::LFuncSig: return "L__FUNCSIG__"; case PredefinedIdentKind::PrettyFunctionNoVirtual: break; } llvm_unreachable("Unknown ident kind for PredefinedExpr"); } ``` ``` std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK, const Decl *CurrentDecl, bool ForceElaboratedPrinting) { ASTContext &Context = CurrentDecl->getASTContext(); if (IK == PredefinedIdentKind::FQFunction) { if (const auto *ND = dyn_cast(CurrentDecl)) return ND->getQualifiedNameAsString(); return ""; } if (IK == PredefinedIdentKind::MangledFunction) { if (const auto *ND = dyn_cast(CurrentDecl)) { std::unique_ptr MC; MC.reset(Context.createMangleContext()); SmallString<256> Buffer; llvm::raw_svector_ostream Out(Buffer); GlobalDecl GD; if (const CXXConstructorDecl *CD = dyn_cast(ND)) GD = GlobalDecl(CD, Ctor_Base); else if (const CXXDestructorDecl *DD = dyn_cast(ND)) GD = GlobalDecl(DD, Dtor_Base); else if (auto FD = dyn_cast(ND)) { GD = FD->isReferenceableKernel() ? GlobalDecl(FD) : GlobalDecl(ND); } else GD = GlobalDecl(ND); MC->mangleName(GD, Out); return std::string(Buffer); } return ""; } // Remaining Code continues ``` ## `3)TokenKinds.def` -->`llvm-project/clang/include/clang/Basic/TokenKinds.def` ``` KEYWORD(__fq_func__, KEYALL) KEYWORD(__mangled_func__, KEYALL) ``` ## `4)SemaExpr.cpp` -->`llvm-project/clang/lib/Sema/SemaExpr.cpp` ``` static PredefinedIdentKind getPredefinedExprKind(tok::TokenKind Kind) { switch (Kind) { default: llvm_unreachable("unexpected TokenKind"); case tok::kw___func__: return PredefinedIdentKind::Func; case tok::kw___fq_func__: return PredefinedIdentKind::FQFunction; case tok::kw___mangled_func__: return PredefinedIdentKind::MangledFunction; // Code Continues ``` ## `5)ParseExpr.cpp` -->`llvm-project/clang/lib/Parse/ParseExpr.cpp` ``` case tok::kw_L__FUNCTION__: case tok::kw_L__FUNCSIG__: case tok::kw___PRETTY_FUNCTION__: //Add below lines case tok::kw___fq_func__: case tok::kw___mangled_func__: //end here ``` ## Example Usage   >From fdf7f676690f7af5109970f239eba8f34850442f Mon Sep 17 00:00:00 2001 From: KISHAN KUMAR S D Date: Fri, 20 Jun 2025 19:35:57 +0530 Subject: [PATCH 1/5] Update Expr.h --- clang/include/clang/AST/Expr.h | 4 +++- 1 file changed, 3 insertions(+),
[clang] [Clang] Implement diagnostics for why is_empty is false (PR #145044)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Samarth Narang (snarang181) Changes Expands on https://github.com/llvm/llvm-project/issues/141911 --- Full diff: https://github.com/llvm/llvm-project/pull/145044.diff 4 Files Affected: - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+7-1) - (modified) clang/lib/Sema/SemaTypeTraits.cpp (+66) - (modified) clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp (+44) - (modified) clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp (+58) ``diff diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 34b798a09c216..ec1969a4fd10b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1767,7 +1767,8 @@ def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" "%Replaceable{replaceable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Empty{empty}" "}1">; def note_unsatisfied_trait_reason @@ -1787,6 +1788,11 @@ def note_unsatisfied_trait_reason "%NonReplaceableField{has a non-replaceable member %1 of type %2}|" "%NTCBase{has a non-trivially-copyable base %1}|" "%NTCField{has a non-trivially-copyable member %1 of type %2}|" + "%NonEmptyMember{has a non-static data member %1 of type %2}|" + "%VirtualFunction{has a virtual function %1}|" + "%VirtualBase{has a virtual base class %1}|" + "%NonEmptyBase{has a base class %1 that is not empty}|" + "%ZeroLengthField{field %1 is a non-zero-length bit-field}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 4dbb2450857e0..b387721f1a54a 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -1956,6 +1956,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_replaceable", TypeTrait::UTT_IsReplaceable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_empty", TypeTrait::UTT_IsEmpty) .Default(std::nullopt); } @@ -2285,6 +2286,68 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc, + const CXXRecordDecl *D) { + // Non-static data members (ignore zero-width bit‐fields). + for (auto *Field : D->fields()) { +if (Field->isBitField() && Field->getBitWidthValue() == 0) + continue; +S.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::NonEmptyMember << Field +<< Field->getType() << Field->getSourceRange(); + } + + // Virtual functions. + for (auto *M : D->methods()) { +if (M->isVirtual()) { + S.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VirtualFunction << M->getDeclName() + << M->getSourceRange(); + break; +} + } + + // Virtual bases and non-empty bases. + for (auto &B : D->bases()) { +auto *BR = B.getType()->getAsCXXRecordDecl(); +if (!BR || BR->isInvalidDecl()) + continue; +if (B.isVirtual()) { + S.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VirtualBase << B.getType() + << B.getSourceRange(); +} +if (!BR->isEmpty()) { + S.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NonEmptyBase << B.getType() + << B.getSourceRange(); +} + } +} + +static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc, QualType T) { + // Emit primary "not empty" diagnostic. + S.Diag(Loc, diag::note_unsatisfied_trait) << T << diag::TraitName::Empty; + + // While diagnosing is_empty, we want to look at the actual type, not a + // reference or an array of it. So we need to massage the QualType param to + // strip refs and arrays. + if (T->isReferenceType()) +S.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::Ref; + T = T.getNonReferenceType(); + + if (auto *AT = S.Context.getAsArrayType(T)) +T = AT->getElementType(); + + if (auto *D = T->getAsCXXRecordDecl()) { +if (D->hasDefinition()) { + DiagnoseIsEmptyReason(S, Loc, D); + S.Diag(D->getLocation(), diag::note_defined_here) << D; +} + } +} + void Sema::DiagnoseTypeTraitDetails(const Expr *E) { E = E->IgnoreParenImpCasts(); if (E->containsErrors()) @@ -2305,6 +2368,9
[clang] [Clang] Implement diagnostics for why is_empty is false (PR #145044)
https://github.com/snarang181 ready_for_review https://github.com/llvm/llvm-project/pull/145044 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
eZWALT wrote: > Thanks for the work and sorry I could not have a look into it earlier Nono, thank you for your time and guidance! Between today and tomorrow i'll upload the updated version, thanks for taking the time to improve it and the nitpicks! https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Add CodeGen support for scalar FEAT_CPA (PR #105669)
https://github.com/davemgreen edited https://github.com/llvm/llvm-project/pull/105669 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL][SPRIV] Handle signed RWBuffer correctly (PR #144774)
https://github.com/Keenuts approved this pull request. https://github.com/llvm/llvm-project/pull/144774 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Add CodeGen support for scalar FEAT_CPA (PR #105669)
@@ -0,0 +1,723 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=+cpa -aarch64-use-featcpa-codegen=true -O0 -global-isel=1 -global-isel-abort=1 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-CPA-O0 davemgreen wrote: Remove -global-isel-abort=1. https://github.com/llvm/llvm-project/pull/105669 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL][SPRIV] Handle signed RWBuffer correctly (PR #144774)
s-perron wrote: @michalpaszkowski Any problems with me creating the new parallel type `spirv.SignedImage`? https://github.com/llvm/llvm-project/pull/144774 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [flang][AArch64] Always link compiler-rt to flang after libgcc (PR #144710)
https://github.com/tarunprabhu approved this pull request. Other than the question about `Flang-RT` vs `compiler-rt` in the `llvm/CMakeLists`, this looks good to me. Thanks. https://github.com/llvm/llvm-project/pull/144710 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [flang][AArch64] Always link compiler-rt to flang after libgcc (PR #144710)
https://github.com/tarunprabhu edited https://github.com/llvm/llvm-project/pull/144710 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [flang][AArch64] Always link compiler-rt to flang after libgcc (PR #144710)
@@ -653,6 +653,13 @@ if(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD STREQUAL "all") set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD ${LLVM_ALL_EXPERIMENTAL_TARGETS}) endif() +if("flang" IN_LIST LLVM_ENABLE_PROJECTS AND + "AArch64" IN_LIST LLVM_TARGETS_TO_BUILD AND + NOT "compiler-rt" IN_LIST LLVM_ENABLE_RUNTIMES) + message(STATUS "Enabling Flang-RT as a dependency of Flang") tarunprabhu wrote: Should this say "Enabling compiler-rt" instead of `Flang_RT` if the next line enables compiler-rt? https://github.com/llvm/llvm-project/pull/144710 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -1143,6 +1143,97 @@ class OMPFullClause final : public OMPNoChildClause { static OMPFullClause *CreateEmpty(const ASTContext &C); }; +/// This class represents the 'looprange' clause in the +/// '#pragma omp fuse' directive +/// +/// \code {c} +/// #pragma omp fuse looprange(1,2) +/// { +/// for(int i = 0; i < 64; ++i) +/// for(int j = 0; j < 256; j+=2) +/// for(int k = 127; k >= 0; --k) +/// \endcode +class OMPLoopRangeClause final +: public OMPClause, + private llvm::TrailingObjects { + friend class OMPClauseReader; + friend class llvm::TrailingObjects; + + /// Location of '(' + SourceLocation LParenLoc; + + /// Location of first and count expressions + SourceLocation FirstLoc, CountLoc; + + /// Number of looprange arguments (always 2: first, count) + unsigned NumArgs = 2; + + /// Set the argument expressions. + void setArgs(ArrayRef Args) { +assert(Args.size() == NumArgs && "Expected exactly 2 looprange arguments"); +std::copy(Args.begin(), Args.end(), getTrailingObjects()); + } + + /// Build an empty clause for deserialization. + explicit OMPLoopRangeClause() + : OMPClause(llvm::omp::OMPC_looprange, {}, {}), NumArgs(2) {} + +public: + /// Build a 'looprange' clause AST node. + static OMPLoopRangeClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation FirstLoc, SourceLocation CountLoc, + SourceLocation EndLoc, ArrayRef Args); + + /// Build an empty 'looprange' clause node. + static OMPLoopRangeClause *CreateEmpty(const ASTContext &C); + + // Location getters/setters + SourceLocation getLParenLoc() const { return LParenLoc; } + SourceLocation getFirstLoc() const { return FirstLoc; } + SourceLocation getCountLoc() const { return CountLoc; } + + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + void setFirstLoc(SourceLocation Loc) { FirstLoc = Loc; } + void setCountLoc(SourceLocation Loc) { CountLoc = Loc; } + + /// Get looprange arguments: first and count + Expr *getFirst() const { return getArgs()[0]; } + Expr *getCount() const { return getArgs()[1]; } eZWALT wrote: I did not notice this, thank you! https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -508,6 +512,43 @@ OMPInterchangeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, SourceLocation(), SourceLocation(), NumLoops); } +OMPFuseDirective *OMPFuseDirective::Create( +const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, +ArrayRef Clauses, unsigned NumLoops, unsigned NumLoopNests, +Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits) { + + OMPFuseDirective *Dir = createDirective( + C, Clauses, AssociatedStmt, TransformedStmtOffset + 1, StartLoc, EndLoc, + NumLoops); + Dir->setTransformedStmt(TransformedStmt); + Dir->setPreInits(PreInits); + // The number of top level canonical nests could + // not match the total number of generated loops + // Example: + // Before fusion: + // for (int i = 0; i < N; ++i) + // for (int j = 0; j < M; ++j) + // A[i][j] = i + j; + // + // for (int k = 0; k < P; ++k) + // B[k] = k * 2; + // Here, NumLoopNests = 2, but NumLoops = 3. eZWALT wrote: Yes I guessed that probably this information would not be used... However i wanted to be consistent with other loop transformations and avoid changing the structure for loop nest only related transformations, so I did the visitor just for the sake of consistency. I know it might not be the best solution in terms of redundancy and extra lines of code, but i believe its more consistent with the rest of loop transformations. But again, you are 100% correct, the total number of loops does not really mater without the loop nest structure. https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -3256,9 +3256,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { var, ConvertTypeForMem(VD->getType()), getContext().getDeclAlign(VD)); // No other cases for now. -} else { +} else llvm_unreachable("DeclRefExpr for Decl not entered in LocalDeclMap?"); -} eZWALT wrote: This should not be in the pr thanks! https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
https://github.com/Meinersbur commented: Thanks for the work and sorry I could not have a look into it earlier https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -3256,9 +3256,8 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { var, ConvertTypeForMem(VD->getType()), getContext().getDeclAlign(VD)); // No other cases for now. -} else { +} else llvm_unreachable("DeclRefExpr for Decl not entered in LocalDeclMap?"); -} eZWALT wrote: > This shouldn't be inside the pr thanks! https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
https://github.com/eZWALT deleted https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
https://github.com/eZWALT edited https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -1479,7 +1492,109 @@ class SemaOpenMP : public SemaBase { bool checkTransformableLoopNest( OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops, SmallVectorImpl &LoopHelpers, - Stmt *&Body, SmallVectorImpl> &OriginalInits); + Stmt *&Body, SmallVectorImpl> &OriginalInits); + + /// @brief Categories of loops encountered during semantic OpenMP loop + /// analysis + /// + /// This enumeration identifies the structural category of a loop or sequence + /// of loops analyzed in the context of OpenMP transformations and directives. + /// This categorization helps differentiate between original source loops + /// and the structures resulting from applying OpenMP loop transformations. + enum class OMPLoopCategory { + +/// @var OMPLoopCategory::RegularLoop +/// Represents a standard canonical loop nest found in the +/// original source code or an intact loop after transformations +/// (i.e Post/Pre loops of a loopranged fusion) +RegularLoop, + +/// @var OMPLoopCategory::TransformSingleLoop +/// Represents the resulting loop structure when an OpenMP loop +// transformation, generates a single, top-level loop +TransformSingleLoop, + +/// @var OMPLoopCategory::TransformLoopSequence +/// Represents the resulting loop structure when an OpenMP loop +/// transformation +/// generates a sequence of two or more canonical loop nests +TransformLoopSequence + }; + + /// The main recursive process of `checkTransformableLoopSequence` that + /// performs grammatical parsing of a canonical loop sequence. It extracts + /// key information, such as the number of top-level loops, loop statements, + /// helper expressions, and other relevant loop-related data, all in a single + /// execution to avoid redundant traversals. This analysis flattens inner + /// Loop Sequences + /// + /// \param LoopSeqStmtThe AST of the original statement. + /// \param LoopSeqSize[out] Number of top level canonical loops. + /// \param NumLoops [out] Number of total canonical loops (nested too). + /// \param LoopHelpers[out] The multiple loop analyses results. + /// \param ForStmts [out] The multiple Stmt of each For loop. + /// \param OriginalInits [out] The raw original initialization statements + /// of each belonging to a loop of the loop sequence + /// \param TransformPreInits [out] The multiple collection of statements and + /// declarations that must have been executed/declared + /// before entering the loop (each belonging to a + /// particular loop transformation, nullptr otherwise) + /// \param LoopSequencePreInits [out] Additional general collection of loop + /// transformation related statements and declarations + /// not bounded to a particular loop that must be + /// executed before entering the loop transformation + /// \param LoopCategories [out] A sequence of OMPLoopCategory values, + /// one for each loop or loop transformation node + /// successfully analyzed. + /// \param Context + /// \param Kind The loop transformation directive kind. + /// \return Whether the original statement is both syntactically and + /// semantically correct according to OpenMP 6.0 canonical loop + /// sequence definition. + bool analyzeLoopSequence( + Stmt *LoopSeqStmt, unsigned &LoopSeqSize, unsigned &NumLoops, + SmallVectorImpl &LoopHelpers, + SmallVectorImpl &ForStmts, + SmallVectorImpl> &OriginalInits, + SmallVectorImpl> &TransformsPreInits, + SmallVectorImpl> &LoopSequencePreInits, alexey-bataev wrote: Better to use preallocated vectors in favor of compile time https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] bd36f73 - [CIR] Add initial support for bitfields in structs (#142041)
Author: Andres-Salamanca Date: 2025-06-20T09:03:02-05:00 New Revision: bd36f7331a9f575272aebb9e0163194541110912 URL: https://github.com/llvm/llvm-project/commit/bd36f7331a9f575272aebb9e0163194541110912 DIFF: https://github.com/llvm/llvm-project/commit/bd36f7331a9f575272aebb9e0163194541110912.diff LOG: [CIR] Add initial support for bitfields in structs (#142041) This change adds support for bitfields CIR records can now contain bit fields. I’ve updated the `CIRGenBitFieldInfo` comment, which originally came from the incubator and was identical to the one in OGCodeGen, to better reflect the current implementation. Support for bitfields in unions big-endian architectures and `get` and `set` operations remains unimplemented and will be addressed in a future patch. Added: clang/test/CIR/CodeGen/bitfields.c clang/test/CIR/CodeGen/bitfields.cpp Modified: clang/include/clang/CIR/MissingFeatures.h clang/lib/CIR/CodeGen/CIRGenRecordLayout.h clang/lib/CIR/CodeGen/CIRGenRecordLayoutBuilder.cpp clang/lib/CIR/CodeGen/TargetInfo.cpp clang/lib/CIR/CodeGen/TargetInfo.h Removed: diff --git a/clang/include/clang/CIR/MissingFeatures.h b/clang/include/clang/CIR/MissingFeatures.h index 45452c5929a3b..e0b2959f374f8 100644 --- a/clang/include/clang/CIR/MissingFeatures.h +++ b/clang/include/clang/CIR/MissingFeatures.h @@ -149,6 +149,8 @@ struct MissingFeatures { static bool cxxabiUseARMGuardVarABI() { return false; } static bool cxxabiAppleARM64CXXABI() { return false; } static bool cxxabiStructorImplicitParam() { return false; } + static bool isDiscreteBitFieldABI() { return false; } + static bool isBigEndian() { return false; } // Address class static bool addressOffset() { return false; } @@ -239,6 +241,7 @@ struct MissingFeatures { static bool builtinCall() { return false; } static bool builtinCallF128() { return false; } static bool builtinCallMathErrno() { return false; } + static bool nonFineGrainedBitfields() { return false; } // Missing types static bool dataMemberType() { return false; } diff --git a/clang/lib/CIR/CodeGen/CIRGenRecordLayout.h b/clang/lib/CIR/CodeGen/CIRGenRecordLayout.h index ac8832b8c9b24..3b51ab784d374 100644 --- a/clang/lib/CIR/CodeGen/CIRGenRecordLayout.h +++ b/clang/lib/CIR/CodeGen/CIRGenRecordLayout.h @@ -14,6 +14,106 @@ namespace clang::CIRGen { +/// Record with information about how a bitfield should be accessed. This is +/// very similar to what LLVM codegen does, once CIR evolves it's possible we +/// can use a more higher level representation. +/// +/// Often we lay out a sequence of bitfields as a contiguous sequence of bits. +/// When the AST record layout does this, we represent it in CIR as a +/// `!cir.record` type, which directly reflects the structure's layout, +/// including bitfield packing and padding, using CIR types such as +/// `!cir.bool`, `!s8i`, `!u16i`. +/// +/// To access a particular bitfield in CIR, we use the operations +/// `cir.get_bitfield` (`GetBitfieldOp`) or `cir.set_bitfield` +/// (`SetBitfieldOp`). These operations rely on the `bitfield_info` +/// attribute, which provides detailed metadata required for access, +/// such as the size and offset of the bitfield, the type and size of +/// the underlying storage, and whether the value is signed. +/// The CIRGenRecordLayout also has a bitFields map which encodes which +/// byte-sequence this bitfield falls within. Let's assume the following C +/// struct: +/// +/// struct S { +/// char a, b, c; +/// unsigned bits : 3; +/// unsigned more_bits : 4; +/// unsigned still_more_bits : 7; +/// }; +/// +/// This will end up as the following cir.record. The bitfield members are +/// represented by one !u16i value, and the array provides padding to align the +/// struct to a 4-byte alignment. +/// +/// !rec_S = !cir.record}> +/// +/// When generating code to access more_bits, we'll generate something +/// essentially like this: +/// +/// #bfi_more_bits = #cir.bitfield_info +/// +/// cir.func @store_field() { +/// %0 = cir.alloca !rec_S, !cir.ptr, ["s"] {alignment = 4 : i64} +/// %1 = cir.const #cir.int<2> : !s32i +/// %2 = cir.cast(integral, %1 : !s32i), !u32i +/// %3 = cir.get_member %0[3] {name = "more_bits"} : !cir.ptr -> +/// !cir.ptr +/// %4 = cir.set_bitfield(#bfi_more_bits, %3 : +/// !cir.ptr, %2 : !u32i) -> !u32i +/// cir.return +/// } +/// +struct CIRGenBitFieldInfo { + /// The offset within a contiguous run of bitfields that are represented as + /// a single "field" within the cir.record type. This offset is in bits. + unsigned offset : 16; + + /// The total size of the bit-field, in bits. + unsigned size : 15; + + /// Whether the bit-field is signed. + unsigned isSigned : 1; + + /// The storage size in bits which should be used when accessing this + /// bitfield. + unsigned sto
[clang] [ExtractAPI] Include +/- symbols for ObjC methods (PR #145035)
https://github.com/snprajwal created https://github.com/llvm/llvm-project/pull/145035 ObjC methods include a +/- prefix to indicate if they are a class or instance method. This information is valuable, and must be included in the navigator generated by ExtractAPI. rdar://150870936 >From 5937db0685ce9bc559a70c38fdbecef8e7e14591 Mon Sep 17 00:00:00 2001 From: Prajwal Nadig Date: Fri, 20 Jun 2025 13:13:17 +0100 Subject: [PATCH] [ExtractAPI] Include +/- symbols for ObjC methods ObjC methods include a +/- prefix to indicate if they are a class or instance method. This information is valuable, and must be included in the navigator generated by ExtractAPI. rdar://150870936 --- .../Serialization/SymbolGraphSerializer.cpp | 16 clang/test/ExtractAPI/objc_instancetype.m| 8 2 files changed, 24 insertions(+) diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 139023f32e8d3..d3df9eb604f27 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -341,6 +341,22 @@ Object serializeNames(const APIRecord *Record) { serializeArray(Names, "subHeading", serializeDeclarationFragments(Record->SubHeading)); DeclarationFragments NavigatorFragments; + // The +/- prefix for Objective-C methods is important information, and + // should be included in the navigator fragment. The entire subheading is + // not included as it can contain too much information for other records. + switch (Record->getKind()) { + case APIRecord::RK_ObjCClassMethod: +NavigatorFragments.append("+ ", DeclarationFragments::FragmentKind::Text, + /*PreciseIdentifier*/ ""); +break; + case APIRecord::RK_ObjCInstanceMethod: +NavigatorFragments.append("- ", DeclarationFragments::FragmentKind::Text, + /*PreciseIdentifier*/ ""); +break; + default: +break; + } + NavigatorFragments.append(Record->Name, DeclarationFragments::FragmentKind::Identifier, /*PreciseIdentifier*/ ""); diff --git a/clang/test/ExtractAPI/objc_instancetype.m b/clang/test/ExtractAPI/objc_instancetype.m index 071ebe440918a..dbd47a1f746ff 100644 --- a/clang/test/ExtractAPI/objc_instancetype.m +++ b/clang/test/ExtractAPI/objc_instancetype.m @@ -157,6 +157,10 @@ - (id) reset; }, "names": { "navigator": [ + { +"kind": "text", +"spelling": "- " + }, { "kind": "identifier", "spelling": "init" @@ -228,6 +232,10 @@ - (id) reset; }, "names": { "navigator": [ + { +"kind": "text", +"spelling": "- " + }, { "kind": "identifier", "spelling": "reset" ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Preprocessor] Do not expand macros if the input is already preprocessed (PR #137665)
https://github.com/jmmartinez updated https://github.com/llvm/llvm-project/pull/137665 From f0d1f76540ca2121a7b70c71c7403a7d45584482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Mon, 28 Apr 2025 17:05:46 +0200 Subject: [PATCH 1/8] Pre-commit test: [Preprocessor] Do not expand macros if the input is already preprocessed --- clang/test/Preprocessor/preprocess-cpp-output.c | 9 + 1 file changed, 9 insertions(+) create mode 100644 clang/test/Preprocessor/preprocess-cpp-output.c diff --git a/clang/test/Preprocessor/preprocess-cpp-output.c b/clang/test/Preprocessor/preprocess-cpp-output.c new file mode 100644 index 0..59ff057e9b871 --- /dev/null +++ b/clang/test/Preprocessor/preprocess-cpp-output.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -E -x c %s | FileCheck %s --check-prefixes=EXPANDED +// RUN: %clang_cc1 -E -x cpp-output %s | FileCheck %s --check-prefixes=EXPANDED + +// EXPANDED: void __attribute__((__attribute__((always_inline foo() + +#define always_inline __attribute__((always_inline)) +void __attribute__((always_inline)) foo() { +return 4; +} From 3bd55452d3528b76c5d27d6f6e2a021aff2b9aa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Tue, 13 May 2025 15:03:46 +0200 Subject: [PATCH 2/8] [Modules] initializers.cpp test fix The module contents should not contain preprocessor directives. The contents should be already preprocessed. Duplicate the modules instead to propose 2 versions: one with the namespace ns and one without. --- clang/test/Modules/initializers.cpp | 59 +++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/clang/test/Modules/initializers.cpp b/clang/test/Modules/initializers.cpp index dcd9b08ec6f7a..e1f826fbc09f3 100644 --- a/clang/test/Modules/initializers.cpp +++ b/clang/test/Modules/initializers.cpp @@ -48,6 +48,7 @@ // instantiation for v in one of the two headers, because we will only // parse one of the two get() functions. +#ifdef NS #pragma clang module build m module m { module a { @@ -60,9 +61,7 @@ module m { #pragma clang module begin m.a inline int non_trivial() { return 3; } -#ifdef NS namespace ns { -#endif int a = non_trivial(); inline int b = non_trivial(); @@ -102,12 +101,64 @@ inline void use(bool b, ...) { X::e, X::f, X::g, X::h); } -#ifdef NS } -#endif #pragma clang module end #pragma clang module endbuild +#else +#pragma clang module build m +module m { + module a { +header "foo.h" { size 123 mtime 456789 } + } + module b {} +} + +#pragma clang module contents +#pragma clang module begin m.a +inline int non_trivial() { return 3; } + +int a = non_trivial(); +inline int b = non_trivial(); +thread_local int c = non_trivial(); +inline thread_local int d = non_trivial(); + +template int e = non_trivial(); +template inline int f = non_trivial(); +template thread_local int g = non_trivial(); +template inline thread_local int h = non_trivial(); + +inline int unused = 123; // should not be emitted + +template struct X { + static int a; + static inline int b = non_trivial(); + static thread_local int c; + static inline thread_local int d = non_trivial(); + + template static int e; + template static inline int f = non_trivial(); + template static thread_local int g; + template static inline thread_local int h = non_trivial(); + + static inline int unused = 123; // should not be emitted +}; + +template int X::a = non_trivial(); +template thread_local int X::c = non_trivial(); +template template int X::e = non_trivial(); +template template thread_local int X::g = non_trivial(); + +inline void use(bool b, ...) { + if (b) return; + use(true, e, f, g, h, + X::a, X::b, X::c, X::d, + X::e, X::f, X::g, X::h); +} + +#pragma clang module end +#pragma clang module endbuild +#endif #if IMPORT == 1 // Import the module and the m.a submodule; runs the ordered initializers and From 75b7fd4a9e3fb556e53fbb858ea7890622ae64da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Tue, 22 Apr 2025 18:40:37 +0200 Subject: [PATCH 3/8] [Preprocessor] Do not expand macros if the input is already preprocessed --- clang/include/clang/Lex/Preprocessor.h | 5 + clang/lib/Frontend/InitPreprocessor.cpp | 7 +++ clang/test/Preprocessor/preprocess-cpp-output.c | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 78be2bd64d61c..40ccc4f4b0d40 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -1837,6 +1837,11 @@ class Preprocessor { MacroExpansionInDirectivesOverride = true; } + void SetDisableMacroExpansion() { +DisableMacroExpansion = true; +MacroExpansionInDirectivesOverride = false; + } + /// Peeks ahead N tokens and returns that token without co
[clang] [llvm] [AArch64] Add CodeGen support for scalar FEAT_CPA (PR #105669)
@@ -0,0 +1,723 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=+cpa -aarch64-use-featcpa-codegen=true -O0 -global-isel=1 -global-isel-abort=1 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-CPA-O0 +; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=+cpa -aarch64-use-featcpa-codegen=true -O3 -global-isel=1 -global-isel-abort=1 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-CPA-O3 +; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=-cpa -O0 -global-isel=1 -global-isel-abort=1 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-NOCPA-O0 +; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=-cpa -O3 -global-isel=1 -global-isel-abort=1 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-NOCPA-O3 + +%struct.my_type = type { i64, i64 } +%struct.my_type2 = type { i64, i64, i64, i64, i64, i64 } + +@array = external dso_local global [10 x %struct.my_type], align 8 +@array2 = external dso_local global [10 x %struct.my_type2], align 8 + +define void @addpt1(i64 %index, i64 %arg) { +; CHECK-CPA-O0-LABEL: addpt1: +; CHECK-CPA-O0: // %bb.0: // %entry +; CHECK-CPA-O0-NEXT:adrp x8, array +; CHECK-CPA-O0-NEXT:add x8, x8, :lo12:array +; CHECK-CPA-O0-NEXT:addpt x8, x8, x0, lsl #4 +; CHECK-CPA-O0-NEXT:str x1, [x8, #8] +; CHECK-CPA-O0-NEXT:ret +; +; CHECK-CPA-O3-LABEL: addpt1: +; CHECK-CPA-O3: // %bb.0: // %entry +; CHECK-CPA-O3-NEXT:adrp x8, array +; CHECK-CPA-O3-NEXT:add x8, x8, :lo12:array +; CHECK-CPA-O3-NEXT:addpt x8, x8, x0, lsl #4 +; CHECK-CPA-O3-NEXT:str x1, [x8, #8] +; CHECK-CPA-O3-NEXT:ret +; +; CHECK-NOCPA-O0-LABEL: addpt1: +; CHECK-NOCPA-O0: // %bb.0: // %entry +; CHECK-NOCPA-O0-NEXT:adrp x8, array +; CHECK-NOCPA-O0-NEXT:add x8, x8, :lo12:array +; CHECK-NOCPA-O0-NEXT:add x8, x8, x0, lsl #4 +; CHECK-NOCPA-O0-NEXT:str x1, [x8, #8] +; CHECK-NOCPA-O0-NEXT:ret +; +; CHECK-NOCPA-O3-LABEL: addpt1: +; CHECK-NOCPA-O3: // %bb.0: // %entry +; CHECK-NOCPA-O3-NEXT:adrp x8, array +; CHECK-NOCPA-O3-NEXT:add x8, x8, :lo12:array +; CHECK-NOCPA-O3-NEXT:add x8, x8, x0, lsl #4 +; CHECK-NOCPA-O3-NEXT:str x1, [x8, #8] +; CHECK-NOCPA-O3-NEXT:ret +entry: + %e2 = getelementptr inbounds %struct.my_type, ptr @array, i64 %index, i32 1 + store i64 %arg, ptr %e2, align 8 + ret void +} + +define void @maddpt1(i32 %pos, ptr %val) { +; CHECK-CPA-O0-LABEL: maddpt1: +; CHECK-CPA-O0: // %bb.0: // %entry +; CHECK-CPA-O0-NEXT:// implicit-def: $x8 +; CHECK-CPA-O0-NEXT:mov w8, w0 +; CHECK-CPA-O0-NEXT:sxtw x8, w8 +; CHECK-CPA-O0-NEXT:mov w9, #48 // =0x30 +; CHECK-CPA-O0-NEXT:// kill: def $x9 killed $w9 +; CHECK-CPA-O0-NEXT:adrp x10, array2 +; CHECK-CPA-O0-NEXT:add x10, x10, :lo12:array2 +; CHECK-CPA-O0-NEXT:maddpt x0, x8, x9, x10 +; CHECK-CPA-O0-NEXT:mov w8, #48 // =0x30 +; CHECK-CPA-O0-NEXT:mov w2, w8 +; CHECK-CPA-O0-NEXT:b memcpy +; +; CHECK-CPA-O3-LABEL: maddpt1: +; CHECK-CPA-O3: // %bb.0: // %entry +; CHECK-CPA-O3-NEXT:// kill: def $w0 killed $w0 def $x0 +; CHECK-CPA-O3-NEXT:sxtw x9, w0 +; CHECK-CPA-O3-NEXT:mov w8, #48 // =0x30 +; CHECK-CPA-O3-NEXT:ldr q0, [x1] +; CHECK-CPA-O3-NEXT:adrp x10, array2 +; CHECK-CPA-O3-NEXT:add x10, x10, :lo12:array2 +; CHECK-CPA-O3-NEXT:maddpt x8, x9, x8, x10 +; CHECK-CPA-O3-NEXT:str q0, [x8] +; CHECK-CPA-O3-NEXT:ldr q0, [x1, #16] +; CHECK-CPA-O3-NEXT:str q0, [x8, #16] +; CHECK-CPA-O3-NEXT:ldr q0, [x1, #32] +; CHECK-CPA-O3-NEXT:str q0, [x8, #32] +; CHECK-CPA-O3-NEXT:ret +; +; CHECK-NOCPA-O0-LABEL: maddpt1: +; CHECK-NOCPA-O0: // %bb.0: // %entry +; CHECK-NOCPA-O0-NEXT:adrp x9, array2 +; CHECK-NOCPA-O0-NEXT:add x9, x9, :lo12:array2 +; CHECK-NOCPA-O0-NEXT:mov w8, #48 // =0x30 +; CHECK-NOCPA-O0-NEXT:smaddl x0, w0, w8, x9 +; CHECK-NOCPA-O0-NEXT:mov w8, #48 // =0x30 +; CHECK-NOCPA-O0-NEXT:mov w2, w8 +; CHECK-NOCPA-O0-NEXT:b memcpy +; +; CHECK-NOCPA-O3-LABEL: maddpt1: +; CHECK-NOCPA-O3: // %bb.0: // %entry +; CHECK-NOCPA-O3-NEXT:mov w8, #48 // =0x30 +; CHECK-NOCPA-O3-NEXT:adrp x9, array2 +; CHECK-NOCPA-O3-NEXT:add x9, x9, :lo12:array2 +; CHECK-NOCPA-O3-NEXT:smaddl x8, w0, w8, x9 +; CHECK-NOCPA-O3-NEXT:ldr q0, [x1] +; CHECK-NOCPA-O3-NEXT:str q0, [x8] +; CHECK-NOCPA-O3-NEXT:ldr q0, [x1, #16] +; CHECK-NOCPA-O3-NEXT:str q0, [x8, #16] +; CHECK-NOCPA-O3-NEXT:ldr q0, [x1, #32] +; CHECK-NOCPA-O3-NEXT:str q0, [x8, #32] +; CHECK-NOCPA-O3-NEXT:ret +entry: + %idxprom = sext i32 %pos to i64 + %arrayidx = getelementptr inbounds [10 x %struct.my_type2], ptr @array2, i64 0, i64 %idxprom + tail call void @llvm.memcpy.p0.p0.i64(ptr align 8 dereferenceable(48) %arrayidx, ptr align 8 dereferenceable(48) %val, i64 48, i1 false) + ret void +} + +define void @msubpt1(i32 %index, i32 %elem)
[clang] Inject compilation command into __cli_ global variable (PR #144622)
https://github.com/Pavithra029 updated https://github.com/llvm/llvm-project/pull/144622 >From d41ac68039e6d654249fbeceb3b77c4b6780f9c0 Mon Sep 17 00:00:00 2001 From: pavithra Date: Wed, 18 Jun 2025 05:50:13 +0530 Subject: [PATCH 1/2] Inject compilation command into __cli_ global variable --- clang/lib/CodeGen/CodeGenModule.cpp | 100 1 file changed, 100 insertions(+) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index c005d3322ed7a..577cb6f0abd2c 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1472,6 +1472,106 @@ void CodeGenModule::Release() { } } } + + // 1. Get source file name + /* std::string FileName = getModule().getSourceFileName(); // like "foo.c" +llvm::StringRef BaseName = llvm::sys::path::filename(FileName); + +// 2. Create variable name like __cli_foo_c +std::string VarName = "__cli_" + BaseName.str(); +std::replace(VarName.begin(), VarName.end(), '.', '_'); + +// 3. Get the compilation command line from options +std::string CmdLineStr; +for (const std::string &Arg : CodeGenOpts.CommandLineArgs) { +CmdLineStr += Arg + " "; +} + +// 4. Create LLVM IR string global +llvm::Constant *CmdStr = llvm::ConstantDataArray::getString(getLLVMContext(), CmdLineStr, true); +// 1. Prepare internal string global variable +auto *GV = new llvm::GlobalVariable( +getModule(), +CmdStr->getType(), +true, +llvm::GlobalValue::InternalLinkage, +CmdStr, +VarName + ".data" +); +GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + +// 2. Create external pointer global pointing to internal string +llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 0); +llvm::Constant *Indices[] = {Zero, Zero}; +llvm::Constant *PtrToStr = llvm::ConstantExpr::getGetElementPtr(CmdStr->getType(), GV, Indices); + +auto *ExternGV = new llvm::GlobalVariable( +getModule(), +PtrToStr->getType(), +true, +llvm::GlobalValue::ExternalLinkage, +PtrToStr, +VarName +); +ExternGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); +(void)ExternGV; +llvm::errs() << "✅ Emitting __cli global variable!\n"; + + */ + + // === BEGIN: Emit global __cli_ variable === + +std::string FileName = getModule().getSourceFileName(); +llvm::StringRef BaseName = llvm::sys::path::filename(FileName); +std::string VarName = "__cli_" + BaseName.str(); +std::replace(VarName.begin(), VarName.end(), '.', '_'); + +// Join command line args into one string +std::string CmdLineStr; +for (const std::string &Arg : CodeGenOpts.CommandLineArgs) { +CmdLineStr += Arg + " "; +} + +// Step 1: Create string constant (char[] data) +llvm::Constant *CmdStr = llvm::ConstantDataArray::getString(getLLVMContext(), CmdLineStr, true); + +// Step 2: Emit internal variable: @__cli_foo_c.data +auto *DataGV = new llvm::GlobalVariable( +getModule(), +CmdStr->getType(), // [N x i8] +true, // constant +llvm::GlobalValue::InternalLinkage, +CmdStr, +VarName + ".data" +); +DataGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); + +// Step 3: Pointer to string +llvm::Constant *PtrToStr = llvm::ConstantExpr::getPointerCast( +DataGV, llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(getLLVMContext())) +); + + +// Step 4: Remove dummy external if exists +if (auto *Old = getModule().getNamedGlobal(VarName)) { +Old->eraseFromParent(); +} + +// ✅ Step 5: Emit the real global variable +auto *FinalGV = new llvm::GlobalVariable( +getModule(), +PtrToStr->getType(), // i8* +true, // constant +llvm::GlobalValue::ExternalLinkage, // important: this makes it visible! +PtrToStr, +VarName +); +//FinalGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); + +llvm::errs() << "✅ Emitting " << VarName << " global variable!\n"; + +// === END === + } void CodeGenModule::EmitOpenCLMetadata() { >From 666c6f4130b18aee0fc5cb79cc6678bcb5c72eed Mon Sep 17 00:00:00 2001 From: pavithra Date: Fri, 20 Jun 2025 19:24:00 +0530 Subject: [PATCH 2/2] Fix: Inject __cli_ global variable with command line --- clang/lib/CodeGen/CodeGenModule.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 577cb6f0abd2c..b996da98c5de0 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1515,7 +1515,7 @@ auto *ExternGV = new llvm::GlobalVariable( ); ExternGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); (void)ExternGV; -llvm::errs() << "✅ Emitting __cli global variable!\n"; +llvm::errs() << "Emitting __cli global variable!\n"; */ @@ -1557,7 +1557,7 @@ if (auto *Old = getModule().ge
[clang] [llvm] [AArch64] Add CodeGen support for scalar FEAT_CPA (PR #105669)
@@ -0,0 +1,723 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=aarch64 -verify-machineinstrs --mattr=+cpa -aarch64-use-featcpa-codegen=true -O0 -global-isel=1 -global-isel-abort=1 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK-CPA-O0 rgwott wrote: Done. https://github.com/llvm/llvm-project/pull/105669 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Add CodeGen support for scalar FEAT_CPA (PR #105669)
@@ -10716,6 +10716,21 @@ let Predicates = [HasCPA] in { // Scalar multiply-add/subtract def MADDPT : MulAccumCPA<0, "maddpt">; def MSUBPT : MulAccumCPA<1, "msubpt">; + + def : Pat<(ptradd GPR64sp:$Rn, GPR64sp:$Rm), +(ADDPT_shift GPR64sp:$Rn, GPR64sp:$Rm, (i32 0))>; + def : Pat<(ptradd GPR64sp:$Rn, (shl GPR64sp:$Rm, (i64 imm0_7:$imm))), +(ADDPT_shift GPR64sp:$Rn, GPR64sp:$Rm, + (i32 (trunc_imm imm0_7:$imm)))>; rgwott wrote: Done. https://github.com/llvm/llvm-project/pull/105669 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Add CodeGen support for scalar FEAT_CPA (PR #105669)
https://github.com/jthackray approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/105669 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [LLVM][Clang] Add and enable strict mode for `getTrailingObjects` (PR #144930)
https://github.com/jurahul updated https://github.com/llvm/llvm-project/pull/144930 >From e98584961d23ea73981fa17c644e5eec03e58e11 Mon Sep 17 00:00:00 2001 From: Rahul Joshi Date: Thu, 19 Jun 2025 10:25:12 -0700 Subject: [PATCH] [LLVM][Clang] Add and enable strict mode for `getTrailingObjects` Under strict mode, the templated `getTrailingObjects` can be called only when there is > 1 trailing types. The strict mode can be disabled on a per-call basis when its not possible to know statically if there will be a single or multiple trailing types (like in OpenMPClause.h). --- clang/include/clang/AST/OpenMPClause.h| 46 --- clang/lib/AST/Expr.cpp| 3 +- llvm/include/llvm/Support/TrailingObjects.h | 38 +-- .../unittests/Support/TrailingObjectsTest.cpp | 5 +- 4 files changed, 57 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 2fa8fa529741e..b62ebd614e4c7 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -295,7 +295,8 @@ template class OMPVarListClause : public OMPClause { /// Fetches list of variables associated with this clause. MutableArrayRef getVarRefs() { -return static_cast(this)->template getTrailingObjects(NumVars); +return static_cast(this) +->template getTrailingObjects(NumVars); } /// Sets the list of variables for this clause. @@ -334,8 +335,8 @@ template class OMPVarListClause : public OMPClause { /// Fetches list of all variables in the clause. ArrayRef getVarRefs() const { -return static_cast(this)->template getTrailingObjects( -NumVars); +return static_cast(this) +->template getTrailingObjects(NumVars); } }; @@ -380,7 +381,8 @@ template class OMPDirectiveListClause : public OMPClause { MutableArrayRef getDirectiveKinds() { return static_cast(this) -->template getTrailingObjects(NumKinds); +->template getTrailingObjects( +NumKinds); } void setDirectiveKinds(ArrayRef DK) { @@ -5901,15 +5903,17 @@ class OMPMappableExprListClause : public OMPVarListClause, /// Get the unique declarations that are in the trailing objects of the /// class. MutableArrayRef getUniqueDeclsRef() { -return static_cast(this)->template getTrailingObjects( -NumUniqueDeclarations); +return static_cast(this) +->template getTrailingObjects( +NumUniqueDeclarations); } /// Get the unique declarations that are in the trailing objects of the /// class. ArrayRef getUniqueDeclsRef() const { return static_cast(this) -->template getTrailingObjects(NumUniqueDeclarations); +->template getTrailingObjects( +NumUniqueDeclarations); } /// Set the unique declarations that are in the trailing objects of the @@ -5923,15 +5927,17 @@ class OMPMappableExprListClause : public OMPVarListClause, /// Get the number of lists per declaration that are in the trailing /// objects of the class. MutableArrayRef getDeclNumListsRef() { -return static_cast(this)->template getTrailingObjects( -NumUniqueDeclarations); +return static_cast(this) +->template getTrailingObjects( +NumUniqueDeclarations); } /// Get the number of lists per declaration that are in the trailing /// objects of the class. ArrayRef getDeclNumListsRef() const { -return static_cast(this)->template getTrailingObjects( -NumUniqueDeclarations); +return static_cast(this) +->template getTrailingObjects( +NumUniqueDeclarations); } /// Set the number of lists per declaration that are in the trailing @@ -5946,7 +5952,8 @@ class OMPMappableExprListClause : public OMPVarListClause, /// objects of the class. They are appended after the number of lists. MutableArrayRef getComponentListSizesRef() { return MutableArrayRef( -static_cast(this)->template getTrailingObjects() + +static_cast(this) +->template getTrailingObjects() + NumUniqueDeclarations, NumComponentLists); } @@ -5955,7 +5962,8 @@ class OMPMappableExprListClause : public OMPVarListClause, /// objects of the class. They are appended after the number of lists. ArrayRef getComponentListSizesRef() const { return ArrayRef( -static_cast(this)->template getTrailingObjects() + +static_cast(this) +->template getTrailingObjects() + NumUniqueDeclarations, NumComponentLists); } @@ -5971,13 +5979,15 @@ class OMPMappableExprListClause : public OMPVarListClause, /// Get the components that are in the trailing objects of the class. MutableArrayRef getComponentsRef() { return static_cast(this) -->template getTrailingObjects(NumComponents); +->template getTrailingObjects( +
[clang] [llvm] [AArch64] Add CodeGen support for scalar FEAT_CPA (PR #105669)
https://github.com/ostannard approved this pull request. LGTM https://github.com/llvm/llvm-project/pull/105669 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -1479,7 +1492,109 @@ class SemaOpenMP : public SemaBase { bool checkTransformableLoopNest( OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops, SmallVectorImpl &LoopHelpers, - Stmt *&Body, SmallVectorImpl> &OriginalInits); + Stmt *&Body, SmallVectorImpl> &OriginalInits); + + /// @brief Categories of loops encountered during semantic OpenMP loop + /// analysis + /// + /// This enumeration identifies the structural category of a loop or sequence + /// of loops analyzed in the context of OpenMP transformations and directives. + /// This categorization helps differentiate between original source loops + /// and the structures resulting from applying OpenMP loop transformations. + enum class OMPLoopCategory { + +/// @var OMPLoopCategory::RegularLoop +/// Represents a standard canonical loop nest found in the +/// original source code or an intact loop after transformations +/// (i.e Post/Pre loops of a loopranged fusion) +RegularLoop, + +/// @var OMPLoopCategory::TransformSingleLoop +/// Represents the resulting loop structure when an OpenMP loop +// transformation, generates a single, top-level loop +TransformSingleLoop, + +/// @var OMPLoopCategory::TransformLoopSequence +/// Represents the resulting loop structure when an OpenMP loop +/// transformation +/// generates a sequence of two or more canonical loop nests +TransformLoopSequence + }; + + /// The main recursive process of `checkTransformableLoopSequence` that + /// performs grammatical parsing of a canonical loop sequence. It extracts + /// key information, such as the number of top-level loops, loop statements, + /// helper expressions, and other relevant loop-related data, all in a single + /// execution to avoid redundant traversals. This analysis flattens inner + /// Loop Sequences + /// + /// \param LoopSeqStmtThe AST of the original statement. + /// \param LoopSeqSize[out] Number of top level canonical loops. + /// \param NumLoops [out] Number of total canonical loops (nested too). + /// \param LoopHelpers[out] The multiple loop analyses results. + /// \param ForStmts [out] The multiple Stmt of each For loop. + /// \param OriginalInits [out] The raw original initialization statements + /// of each belonging to a loop of the loop sequence + /// \param TransformPreInits [out] The multiple collection of statements and + /// declarations that must have been executed/declared + /// before entering the loop (each belonging to a + /// particular loop transformation, nullptr otherwise) + /// \param LoopSequencePreInits [out] Additional general collection of loop + /// transformation related statements and declarations + /// not bounded to a particular loop that must be + /// executed before entering the loop transformation + /// \param LoopCategories [out] A sequence of OMPLoopCategory values, + /// one for each loop or loop transformation node + /// successfully analyzed. + /// \param Context + /// \param Kind The loop transformation directive kind. + /// \return Whether the original statement is both syntactically and + /// semantically correct according to OpenMP 6.0 canonical loop + /// sequence definition. + bool analyzeLoopSequence( + Stmt *LoopSeqStmt, unsigned &LoopSeqSize, unsigned &NumLoops, + SmallVectorImpl &LoopHelpers, + SmallVectorImpl &ForStmts, + SmallVectorImpl> &OriginalInits, + SmallVectorImpl> &TransformsPreInits, + SmallVectorImpl> &LoopSequencePreInits, eZWALT wrote: It was originally implemented that way, but I changed it after @alexey-bataev’s suggestion. At the time, I didn’t fully understand the tradeoff and followed the recommendation a bit blindly. Could you clarify the reasoning behind the change? If it has a significant impact, I’ll be happy to revert or adjust accordingly. https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Ast importer visitors (PR #138838)
ganenkokb-yandex wrote: > Code looks almost acceptable. I could not verify if the tests are sufficient > (I am not familiar with this new syntax). Can you test this on large projects > that use these types of expressions? It is my approach. All fixes aside ASTImporter are came from real cases. I covered with tests all code paths for new decls and expressions for concepts, except ``` ImportExprRequirement ... if (FromTypeRequirement.isSubstitutionFailure()) --- how to get here? - it is compile time error? ``` Newly added VisitSubstNonTypeTemplateParmPackExpr, VisitPseudoObjectExpr, VisitCXXParenListInitExpr are also without tests. I've faced them on my project, and looks like it is not because of newly implemented concepts imports. But I'm not sure. Should I move 'em to separate pull request? https://github.com/llvm/llvm-project/pull/138838 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 96ab74b - [InstCombine] remove undef loads, such as memcpy from undef (#143958)
Author: Jameson Nash Date: 2025-06-20T10:32:31-04:00 New Revision: 96ab74bf175f46de4b6fbfc68deecd3567e42a52 URL: https://github.com/llvm/llvm-project/commit/96ab74bf175f46de4b6fbfc68deecd3567e42a52 DIFF: https://github.com/llvm/llvm-project/commit/96ab74bf175f46de4b6fbfc68deecd3567e42a52.diff LOG: [InstCombine] remove undef loads, such as memcpy from undef (#143958) Extend `isAllocSiteRemovable` to be able to check if the ModRef info indicates the alloca is only Ref or only Mod, and be able to remove it accordingly. It seemed that there were a surprising number of benchmarks with this pattern which weren't getting optimized previously (due to MemorySSA walk limits). There were somewhat more existing tests than I'd like to have modified which were simply doing exactly this pattern (and thus relying on undef memory). Claude code contributed the new tests (and found an important typo that I'd made). This implements the discussion in https://github.com/llvm/llvm-project/pull/143782#discussion_r2142720376. Added: llvm/test/Transforms/InstCombine/dead-alloc-elim.ll Modified: clang/test/Misc/loop-opt-setup.c llvm/lib/Transforms/InstCombine/InstructionCombining.cpp llvm/test/Transforms/InstCombine/and-or-icmps.ll llvm/test/Transforms/InstCombine/apint-shift.ll llvm/test/Transforms/InstCombine/call-cast-target.ll llvm/test/Transforms/InstCombine/fp-ret-bitcast.ll llvm/test/Transforms/InstCombine/getelementptr.ll llvm/test/Transforms/InstCombine/malloc-free.ll llvm/test/Transforms/InstCombine/multiple-uses-load-bitcast-select.ll llvm/test/Transforms/InstCombine/objsize.ll llvm/test/Transforms/InstCombine/select-load.ll llvm/test/Transforms/InstCombine/shift-amount-reassociation.ll llvm/test/Transforms/InstCombine/vscale_gep.ll Removed: diff --git a/clang/test/Misc/loop-opt-setup.c b/clang/test/Misc/loop-opt-setup.c index 01643e6073b56..c1c620e52200d 100644 --- a/clang/test/Misc/loop-opt-setup.c +++ b/clang/test/Misc/loop-opt-setup.c @@ -15,7 +15,7 @@ int foo(void) { // CHECK-NOT: br i1 void Helper(void) { - const int *nodes[5]; + const int *nodes[5] = {0}; int num_active = 5; while (num_active) diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp index afd3359e22ff3..bcc73090277aa 100644 --- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -3277,12 +3277,13 @@ static bool isRemovableWrite(CallBase &CB, Value *UsedV, return Dest && Dest->Ptr == UsedV; } -static bool isAllocSiteRemovable(Instruction *AI, - SmallVectorImpl &Users, - const TargetLibraryInfo &TLI) { +static std::optional +isAllocSiteRemovable(Instruction *AI, SmallVectorImpl &Users, + const TargetLibraryInfo &TLI, bool KnowInit) { SmallVector Worklist; const std::optional Family = getAllocationFamily(AI, &TLI); Worklist.push_back(AI); + ModRefInfo Access = KnowInit ? ModRefInfo::NoModRef : ModRefInfo::Mod; do { Instruction *PI = Worklist.pop_back_val(); @@ -3291,7 +3292,7 @@ static bool isAllocSiteRemovable(Instruction *AI, switch (I->getOpcode()) { default: // Give up the moment we see something we can't handle. -return false; +return std::nullopt; case Instruction::AddrSpaceCast: case Instruction::BitCast: @@ -3306,10 +3307,10 @@ static bool isAllocSiteRemovable(Instruction *AI, // We also fold comparisons in some conditions provided the alloc has // not escaped (see isNeverEqualToUnescapedAlloc). if (!ICI->isEquality()) - return false; + return std::nullopt; unsigned OtherIndex = (ICI->getOperand(0) == PI) ? 1 : 0; if (!isNeverEqualToUnescapedAlloc(ICI->getOperand(OtherIndex), TLI, AI)) - return false; + return std::nullopt; // Do not fold compares to aligned_alloc calls, as they may have to // return null in case the required alignment cannot be satisfied, @@ -3329,7 +3330,7 @@ static bool isAllocSiteRemovable(Instruction *AI, if (CB && TLI.getLibFunc(*CB->getCalledFunction(), TheLibFunc) && TLI.has(TheLibFunc) && TheLibFunc == LibFunc_aligned_alloc && !AlignmentAndSizeKnownValid(CB)) - return false; + return std::nullopt; Users.emplace_back(I); continue; } @@ -3339,14 +3340,21 @@ static bool isAllocSiteRemovable(Instruction *AI, if (IntrinsicInst *II = dyn_cast(I)) { switch (II->getIntrinsicID()) { default: -return false; +return std::nullopt; case Intrinsic::memmove: case Intrinsic::memcpy: case Intr
[clang] [llvm] [InstCombine] remove dead loads, such as memcpy from undef (PR #143958)
https://github.com/vtjnash closed https://github.com/llvm/llvm-project/pull/143958 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -14189,10 +14196,49 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective( getASTContext(), StartLoc, EndLoc, NestedLoopCount, Clauses, AStmt, B); } +/// Overloaded base case function +template static bool tryHandleAs(T *t, F &&) { + return false; +} + +/// +/// Tries to recursively cast `t` to one of the given types and invokes `f` if +/// successful. +/// +/// @tparam Class The first type to check. +/// @tparam Rest The remaining types to check. +/// @tparam T The base type of `t`. +/// @tparam F The callable type for the function to invoke upon a successful +/// cast. +/// @param t The object to be checked. +/// @param f The function to invoke if `t` matches `Class`. +/// @return `true` if `t` matched any type and `f` was called, otherwise +/// `false`. +template +static bool tryHandleAs(T *t, F &&f) { + if (Class *c = dyn_cast(t)) { +f(c); +return true; + } + return tryHandleAs(t, std::forward(f)); +} + +/// Updates OriginalInits by checking Transform against loop transformation +/// directives and appending their pre-inits if a match is found. +static void updatePreInits(OMPLoopBasedDirective *Transform, + SmallVectorImpl> &PreInits) { + if (!tryHandleAs( + Transform, [&PreInits](auto *Dir) { +appendFlattenedStmtList(PreInits.back(), Dir->getPreInits()); + })) +llvm_unreachable("Unhandled loop transformation"); +} + bool SemaOpenMP::checkTransformableLoopNest( OpenMPDirectiveKind Kind, Stmt *AStmt, int NumLoops, SmallVectorImpl &LoopHelpers, -Stmt *&Body, SmallVectorImpl> &OriginalInits) { eZWALT wrote: The same i told you before in the other comment, i refactored it to match the suggestion of alexey. https://github.com/llvm/llvm-project/pull/139293 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -15499,6 +15836,496 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective( buildPreInits(Context, PreInits)); } +StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef Clauses, +Stmt *AStmt, +SourceLocation StartLoc, +SourceLocation EndLoc) { + + ASTContext &Context = getASTContext(); + DeclContext *CurrContext = SemaRef.CurContext; + Scope *CurScope = SemaRef.getCurScope(); + CaptureVars CopyTransformer(SemaRef); + + // Ensure the structured block is not empty + if (!AStmt) +return StmtError(); + + unsigned NumLoops = 1; + unsigned LoopSeqSize = 1; + + // Defer transformation in dependent contexts + // The NumLoopNests argument is set to a placeholder 1 (even though + // using looprange fuse could yield up to 3 top level loop nests) + // because a dependent context could prevent determining its true value + if (CurrContext->isDependentContext()) { +return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses, +NumLoops, LoopSeqSize, AStmt, nullptr, +nullptr); + } + + // Validate that the potential loop sequence is transformable for fusion + // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops + SmallVector LoopHelpers; + SmallVector LoopStmts; + SmallVector> OriginalInits; + SmallVector> TransformsPreInits; + SmallVector> LoopSequencePreInits; + SmallVector LoopCategories; + if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, LoopSeqSize, NumLoops, + LoopHelpers, LoopStmts, OriginalInits, + TransformsPreInits, LoopSequencePreInits, + LoopCategories, Context)) +return StmtError(); + + // Handle clauses, which can be any of the following: [looprange, apply] + const OMPLoopRangeClause *LRC = + OMPExecutableDirective::getSingleClause(Clauses); + + // The clause arguments are invalidated if any error arises + // such as non-constant or non-positive arguments + if (LRC && (!LRC->getFirst() || !LRC->getCount())) +return StmtError(); + + // Delayed semantic check of LoopRange constraint + // Evaluates the loop range arguments and returns the first and count values + auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count, + uint64_t &FirstVal, + uint64_t &CountVal) { +llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context); +llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context); +FirstVal = FirstInt.getZExtValue(); +CountVal = CountInt.getZExtValue(); + }; + + // OpenMP [6.0, Restrictions] + // first + count - 1 must not evaluate to a value greater than the + // loop sequence length of the associated canonical loop sequence. + auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal, + unsigned NumLoops) -> bool { +return FirstVal + CountVal - 1 <= NumLoops; + }; + uint64_t FirstVal = 1, CountVal = 0, LastVal = LoopSeqSize; + + // Validates the loop range after evaluating the semantic information + // and ensures that the range is valid for the given loop sequence size. + // Expressions are evaluated at compile time to obtain constant values. + if (LRC) { +EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal, + CountVal); +if (CountVal == 1) + SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion) + << getOpenMPDirectiveName(OMPD_fuse); + +if (!ValidLoopRange(FirstVal, CountVal, LoopSeqSize)) { + SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange) + << getOpenMPDirectiveName(OMPD_fuse) << (FirstVal + CountVal - 1) + << LoopSeqSize; + return StmtError(); +} + +LastVal = FirstVal + CountVal - 1; + } + + // Complete fusion generates a single canonical loop nest + // However looprange clause generates several loop nests + unsigned NumLoopNests = LRC ? LoopSeqSize - CountVal + 1 : 1; + + // Emit a warning for redundant loop fusion when the sequence contains only + // one loop. + if (LoopSeqSize == 1) +SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion) +<< getOpenMPDirectiveName(OMPD_fuse); + + assert(LoopHelpers.size() == LoopSeqSize && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + assert(OriginalInits.size() == LoopSeqSize && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + + // Select the type with the largest bit width among all induction variables + QualType IVType = LoopHel
[clang] [flang] [llvm] [openmp] [Clang][OpenMP][LoopTransformations] Add support for "#pragma omp fuse" loop transformation directive and "looprange" clause (PR #139293)
@@ -15499,6 +15836,496 @@ StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective( buildPreInits(Context, PreInits)); } +StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef Clauses, +Stmt *AStmt, +SourceLocation StartLoc, +SourceLocation EndLoc) { + + ASTContext &Context = getASTContext(); + DeclContext *CurrContext = SemaRef.CurContext; + Scope *CurScope = SemaRef.getCurScope(); + CaptureVars CopyTransformer(SemaRef); + + // Ensure the structured block is not empty + if (!AStmt) +return StmtError(); + + unsigned NumLoops = 1; + unsigned LoopSeqSize = 1; + + // Defer transformation in dependent contexts + // The NumLoopNests argument is set to a placeholder 1 (even though + // using looprange fuse could yield up to 3 top level loop nests) + // because a dependent context could prevent determining its true value + if (CurrContext->isDependentContext()) { +return OMPFuseDirective::Create(Context, StartLoc, EndLoc, Clauses, +NumLoops, LoopSeqSize, AStmt, nullptr, +nullptr); + } + + // Validate that the potential loop sequence is transformable for fusion + // Also collect the HelperExprs, Loop Stmts, Inits, and Number of loops + SmallVector LoopHelpers; + SmallVector LoopStmts; + SmallVector> OriginalInits; + SmallVector> TransformsPreInits; + SmallVector> LoopSequencePreInits; + SmallVector LoopCategories; + if (!checkTransformableLoopSequence(OMPD_fuse, AStmt, LoopSeqSize, NumLoops, + LoopHelpers, LoopStmts, OriginalInits, + TransformsPreInits, LoopSequencePreInits, + LoopCategories, Context)) +return StmtError(); + + // Handle clauses, which can be any of the following: [looprange, apply] + const OMPLoopRangeClause *LRC = + OMPExecutableDirective::getSingleClause(Clauses); + + // The clause arguments are invalidated if any error arises + // such as non-constant or non-positive arguments + if (LRC && (!LRC->getFirst() || !LRC->getCount())) +return StmtError(); + + // Delayed semantic check of LoopRange constraint + // Evaluates the loop range arguments and returns the first and count values + auto EvaluateLoopRangeArguments = [&Context](Expr *First, Expr *Count, + uint64_t &FirstVal, + uint64_t &CountVal) { +llvm::APSInt FirstInt = First->EvaluateKnownConstInt(Context); +llvm::APSInt CountInt = Count->EvaluateKnownConstInt(Context); +FirstVal = FirstInt.getZExtValue(); +CountVal = CountInt.getZExtValue(); + }; + + // OpenMP [6.0, Restrictions] + // first + count - 1 must not evaluate to a value greater than the + // loop sequence length of the associated canonical loop sequence. + auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal, + unsigned NumLoops) -> bool { +return FirstVal + CountVal - 1 <= NumLoops; + }; + uint64_t FirstVal = 1, CountVal = 0, LastVal = LoopSeqSize; + + // Validates the loop range after evaluating the semantic information + // and ensures that the range is valid for the given loop sequence size. + // Expressions are evaluated at compile time to obtain constant values. + if (LRC) { +EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal, + CountVal); +if (CountVal == 1) + SemaRef.Diag(LRC->getCountLoc(), diag::warn_omp_redundant_fusion) + << getOpenMPDirectiveName(OMPD_fuse); + +if (!ValidLoopRange(FirstVal, CountVal, LoopSeqSize)) { + SemaRef.Diag(LRC->getFirstLoc(), diag::err_omp_invalid_looprange) + << getOpenMPDirectiveName(OMPD_fuse) << (FirstVal + CountVal - 1) + << LoopSeqSize; + return StmtError(); +} + +LastVal = FirstVal + CountVal - 1; + } + + // Complete fusion generates a single canonical loop nest + // However looprange clause generates several loop nests + unsigned NumLoopNests = LRC ? LoopSeqSize - CountVal + 1 : 1; + + // Emit a warning for redundant loop fusion when the sequence contains only + // one loop. + if (LoopSeqSize == 1) +SemaRef.Diag(AStmt->getBeginLoc(), diag::warn_omp_redundant_fusion) +<< getOpenMPDirectiveName(OMPD_fuse); + + assert(LoopHelpers.size() == LoopSeqSize && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + assert(OriginalInits.size() == LoopSeqSize && + "Expecting loop iteration space dimensionality to match number of " + "affected loops"); + + // Select the type with the largest bit width among all induction variables + QualType IVType = LoopHel
[clang] [ExtractAPI] Include +/- symbols for ObjC methods (PR #145035)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Prajwal Nadig (snprajwal) Changes ObjC methods include a +/- prefix to indicate if they are a class or instance method. This information is valuable, and must be included in the navigator generated by ExtractAPI. rdar://150870936 --- Full diff: https://github.com/llvm/llvm-project/pull/145035.diff 2 Files Affected: - (modified) clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp (+16) - (modified) clang/test/ExtractAPI/objc_instancetype.m (+8) ``diff diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp index 139023f32e8d3..d3df9eb604f27 100644 --- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp +++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp @@ -341,6 +341,22 @@ Object serializeNames(const APIRecord *Record) { serializeArray(Names, "subHeading", serializeDeclarationFragments(Record->SubHeading)); DeclarationFragments NavigatorFragments; + // The +/- prefix for Objective-C methods is important information, and + // should be included in the navigator fragment. The entire subheading is + // not included as it can contain too much information for other records. + switch (Record->getKind()) { + case APIRecord::RK_ObjCClassMethod: +NavigatorFragments.append("+ ", DeclarationFragments::FragmentKind::Text, + /*PreciseIdentifier*/ ""); +break; + case APIRecord::RK_ObjCInstanceMethod: +NavigatorFragments.append("- ", DeclarationFragments::FragmentKind::Text, + /*PreciseIdentifier*/ ""); +break; + default: +break; + } + NavigatorFragments.append(Record->Name, DeclarationFragments::FragmentKind::Identifier, /*PreciseIdentifier*/ ""); diff --git a/clang/test/ExtractAPI/objc_instancetype.m b/clang/test/ExtractAPI/objc_instancetype.m index 071ebe440918a..dbd47a1f746ff 100644 --- a/clang/test/ExtractAPI/objc_instancetype.m +++ b/clang/test/ExtractAPI/objc_instancetype.m @@ -157,6 +157,10 @@ - (id) reset; }, "names": { "navigator": [ + { +"kind": "text", +"spelling": "- " + }, { "kind": "identifier", "spelling": "init" @@ -228,6 +232,10 @@ - (id) reset; }, "names": { "navigator": [ + { +"kind": "text", +"spelling": "- " + }, { "kind": "identifier", "spelling": "reset" `` https://github.com/llvm/llvm-project/pull/145035 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Add CodeGen support for scalar FEAT_CPA (PR #105669)
@@ -10716,6 +10716,21 @@ let Predicates = [HasCPA] in { // Scalar multiply-add/subtract def MADDPT : MulAccumCPA<0, "maddpt">; def MSUBPT : MulAccumCPA<1, "msubpt">; + + def : Pat<(ptradd GPR64sp:$Rn, GPR64sp:$Rm), +(ADDPT_shift GPR64sp:$Rn, GPR64sp:$Rm, (i32 0))>; + def : Pat<(ptradd GPR64sp:$Rn, (shl GPR64sp:$Rm, (i64 imm0_7:$imm))), +(ADDPT_shift GPR64sp:$Rn, GPR64sp:$Rm, + (i32 (trunc_imm imm0_7:$imm)))>; davemgreen wrote: Do you mind making the shift operand (lsl_imm3_shift_operand) an i64 as opposed to i32, to avoid the trunc_imm? Representing it as an i64 seems like a more natural type for something based on pointers, even if the exact type does not matter due to the range. https://github.com/llvm/llvm-project/pull/105669 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Add CodeGen support for scalar FEAT_CPA (PR #105669)
https://github.com/davemgreen commented: Thanks for the updates, this is quite a bit simpler now. As far as I can tell this looks OK to me. https://github.com/llvm/llvm-project/pull/105669 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [AArch64] Add CodeGen support for scalar FEAT_CPA (PR #105669)
https://github.com/davemgreen edited https://github.com/llvm/llvm-project/pull/105669 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] Inject compilation command into __cli_ global variable (PR #144622)
https://github.com/Pavithra029 updated https://github.com/llvm/llvm-project/pull/144622 >From d41ac68039e6d654249fbeceb3b77c4b6780f9c0 Mon Sep 17 00:00:00 2001 From: pavithra Date: Wed, 18 Jun 2025 05:50:13 +0530 Subject: [PATCH 1/2] Inject compilation command into __cli_ global variable --- clang/lib/CodeGen/CodeGenModule.cpp | 100 1 file changed, 100 insertions(+) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index c005d3322ed7a..577cb6f0abd2c 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1472,6 +1472,106 @@ void CodeGenModule::Release() { } } } + + // 1. Get source file name + /* std::string FileName = getModule().getSourceFileName(); // like "foo.c" +llvm::StringRef BaseName = llvm::sys::path::filename(FileName); + +// 2. Create variable name like __cli_foo_c +std::string VarName = "__cli_" + BaseName.str(); +std::replace(VarName.begin(), VarName.end(), '.', '_'); + +// 3. Get the compilation command line from options +std::string CmdLineStr; +for (const std::string &Arg : CodeGenOpts.CommandLineArgs) { +CmdLineStr += Arg + " "; +} + +// 4. Create LLVM IR string global +llvm::Constant *CmdStr = llvm::ConstantDataArray::getString(getLLVMContext(), CmdLineStr, true); +// 1. Prepare internal string global variable +auto *GV = new llvm::GlobalVariable( +getModule(), +CmdStr->getType(), +true, +llvm::GlobalValue::InternalLinkage, +CmdStr, +VarName + ".data" +); +GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); + +// 2. Create external pointer global pointing to internal string +llvm::Constant *Zero = llvm::ConstantInt::get(llvm::Type::getInt32Ty(getLLVMContext()), 0); +llvm::Constant *Indices[] = {Zero, Zero}; +llvm::Constant *PtrToStr = llvm::ConstantExpr::getGetElementPtr(CmdStr->getType(), GV, Indices); + +auto *ExternGV = new llvm::GlobalVariable( +getModule(), +PtrToStr->getType(), +true, +llvm::GlobalValue::ExternalLinkage, +PtrToStr, +VarName +); +ExternGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); +(void)ExternGV; +llvm::errs() << "✅ Emitting __cli global variable!\n"; + + */ + + // === BEGIN: Emit global __cli_ variable === + +std::string FileName = getModule().getSourceFileName(); +llvm::StringRef BaseName = llvm::sys::path::filename(FileName); +std::string VarName = "__cli_" + BaseName.str(); +std::replace(VarName.begin(), VarName.end(), '.', '_'); + +// Join command line args into one string +std::string CmdLineStr; +for (const std::string &Arg : CodeGenOpts.CommandLineArgs) { +CmdLineStr += Arg + " "; +} + +// Step 1: Create string constant (char[] data) +llvm::Constant *CmdStr = llvm::ConstantDataArray::getString(getLLVMContext(), CmdLineStr, true); + +// Step 2: Emit internal variable: @__cli_foo_c.data +auto *DataGV = new llvm::GlobalVariable( +getModule(), +CmdStr->getType(), // [N x i8] +true, // constant +llvm::GlobalValue::InternalLinkage, +CmdStr, +VarName + ".data" +); +DataGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); + +// Step 3: Pointer to string +llvm::Constant *PtrToStr = llvm::ConstantExpr::getPointerCast( +DataGV, llvm::PointerType::getUnqual(llvm::Type::getInt8Ty(getLLVMContext())) +); + + +// Step 4: Remove dummy external if exists +if (auto *Old = getModule().getNamedGlobal(VarName)) { +Old->eraseFromParent(); +} + +// ✅ Step 5: Emit the real global variable +auto *FinalGV = new llvm::GlobalVariable( +getModule(), +PtrToStr->getType(), // i8* +true, // constant +llvm::GlobalValue::ExternalLinkage, // important: this makes it visible! +PtrToStr, +VarName +); +//FinalGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None); + +llvm::errs() << "✅ Emitting " << VarName << " global variable!\n"; + +// === END === + } void CodeGenModule::EmitOpenCLMetadata() { >From 666c6f4130b18aee0fc5cb79cc6678bcb5c72eed Mon Sep 17 00:00:00 2001 From: pavithra Date: Fri, 20 Jun 2025 19:24:00 +0530 Subject: [PATCH 2/2] Fix: Inject __cli_ global variable with command line --- clang/lib/CodeGen/CodeGenModule.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 577cb6f0abd2c..b996da98c5de0 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1515,7 +1515,7 @@ auto *ExternGV = new llvm::GlobalVariable( ); ExternGV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); (void)ExternGV; -llvm::errs() << "✅ Emitting __cli global variable!\n"; +llvm::errs() << "Emitting __cli global variable!\n"; */ @@ -1557,7 +1557,7 @@ if (auto *Old = getModule().ge
[clang] [HLSL][SPIRV] Allow large z value in numthreads (PR #144934)
@@ -1033,12 +1033,15 @@ void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) { void SemaHLSL::handleNumThreadsAttr(Decl *D, const ParsedAttr &AL) { llvm::VersionTuple SMVersion = getASTContext().getTargetInfo().getTriple().getOSVersion(); + bool IsDXIL = getASTContext().getTargetInfo().getTriple().getArch() == +llvm::Triple::dxil; + uint32_t ZMax = 1024; s-perron wrote: I don't think so. These are close to the limits on actual machines. For Android, the existing checks are way beyond the limit. See maxComputeWorkGroupInvocations and maxComputeWorkGroupSize in https://vulkan.lunarg.com/doc/sdk/1.4.313.2/windows/profiles_definitions.html. https://github.com/llvm/llvm-project/pull/144934 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [flang] [llvm] [flang][AArch64] Always link compiler-rt to flang after libgcc (PR #144710)
https://github.com/kiranchandramohan updated https://github.com/llvm/llvm-project/pull/144710 >From 2c278271277823b3544d991365e58f97dd4b7031 Mon Sep 17 00:00:00 2001 From: David Truby Date: Wed, 18 Jun 2025 10:17:05 +0100 Subject: [PATCH] [flang][AArch64] Always compiler-rt to flang linking after libgcc This patch fixes an issue where the __trampoline_setup symbol is missing with some programs compiled with flang. This symbol is present only in compiler-rt and not in libgcc. This patch adds compiler-rt to the link line after libgcc if libgcc is being used, so that only this symbol will be picked from compiler-rt. --- clang/lib/Driver/ToolChains/CommonArgs.cpp | 7 +++ flang/test/Driver/flang-ld-aarch64.f90 | 9 + llvm/CMakeLists.txt| 7 +++ 3 files changed, 23 insertions(+) create mode 100644 flang/test/Driver/flang-ld-aarch64.f90 diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index d5b2c5c1e199e..672b73432847d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -2252,6 +2252,13 @@ static void AddLibgcc(const ToolChain &TC, const Driver &D, if (LGT == LibGccType::SharedLibGcc || (LGT == LibGccType::UnspecifiedLibGcc && D.CCCIsCXX())) CmdArgs.push_back("-lgcc"); + // compiler-rt is needed after libgcc for flang on AArch64 for the + // __trampoline_setup symbol + if (D.IsFlangMode() && TC.getArch() == llvm::Triple::aarch64) { +CmdArgs.push_back("--as-needed"); +CmdArgs.push_back(TC.getCompilerRTArgString(Args, "builtins")); +CmdArgs.push_back("--no-as-needed"); + } } void tools::AddRunTimeLibs(const ToolChain &TC, const Driver &D, diff --git a/flang/test/Driver/flang-ld-aarch64.f90 b/flang/test/Driver/flang-ld-aarch64.f90 new file mode 100644 index 0..61cd46cea5cd1 --- /dev/null +++ b/flang/test/Driver/flang-ld-aarch64.f90 @@ -0,0 +1,9 @@ +! Check linker flags for AArch64 linux, since it needs both libgcc and +! compiler-rt, with compiler-rt second when -rtlib=libgcc. + +! RUN: %flang -### -rtlib=libgcc --target=aarch64-linux-gnu %S/Inputs/hello.f90 2>&1 | FileCheck %s + +! CHECK-LABEL: "{{.*}}ld{{(\.exe)?}}" +! CHECK-SAME: "-lflang_rt.runtime" "-lm" +! CHECK-SAME: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" +! CHECK-SAME: "--as-needed" "{{.*}}{{\\|/}}libclang_rt.builtins.a" "--no-as-needed" diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 0849bec26d56a..1b91e45c202e3 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -653,6 +653,13 @@ if(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD STREQUAL "all") set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD ${LLVM_ALL_EXPERIMENTAL_TARGETS}) endif() +if("flang" IN_LIST LLVM_ENABLE_PROJECTS AND + "AArch64" IN_LIST LLVM_TARGETS_TO_BUILD AND + NOT "compiler-rt" IN_LIST LLVM_ENABLE_RUNTIMES) + message(STATUS "Enabling Flang-RT as a dependency of Flang") + list(APPEND LLVM_ENABLE_RUNTIMES "compiler-rt") +endif() + set(LLVM_TARGETS_TO_BUILD ${LLVM_TARGETS_TO_BUILD} ${LLVM_EXPERIMENTAL_TARGETS_TO_BUILD}) ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 14e89b0 - [C++20] [Modules] Add exported modules as transitive imported modules
Author: Chuanqi Xu Date: 2025-06-20T17:03:29+08:00 New Revision: 14e89b061fdecedcec4bb035060a56588610cb5c URL: https://github.com/llvm/llvm-project/commit/14e89b061fdecedcec4bb035060a56588610cb5c DIFF: https://github.com/llvm/llvm-project/commit/14e89b061fdecedcec4bb035060a56588610cb5c.diff LOG: [C++20] [Modules] Add exported modules as transitive imported modules Close https://github.com/llvm/llvm-project/issues/144230 The root cause of the problem is, when we decide the transitive imports, we didn't deal with exported imports. Added: clang/test/Modules/pr144230.cppm Modified: clang/lib/Sema/SemaModule.cpp Removed: diff --git a/clang/lib/Sema/SemaModule.cpp b/clang/lib/Sema/SemaModule.cpp index 9fcaad48d3058..54ee0486763b1 100644 --- a/clang/lib/Sema/SemaModule.cpp +++ b/clang/lib/Sema/SemaModule.cpp @@ -136,6 +136,7 @@ makeTransitiveImportsVisible(ASTContext &Ctx, VisibleModuleSet &VisibleModules, "modules only."); llvm::SmallVector Worklist; + llvm::SmallSet Visited; Worklist.push_back(Imported); Module *FoundPrimaryModuleInterface = @@ -144,18 +145,22 @@ makeTransitiveImportsVisible(ASTContext &Ctx, VisibleModuleSet &VisibleModules, while (!Worklist.empty()) { Module *Importing = Worklist.pop_back_val(); -if (VisibleModules.isVisible(Importing)) +if (Visited.count(Importing)) continue; +Visited.insert(Importing); // FIXME: The ImportLoc here is not meaningful. It may be problematic if we // use the sourcelocation loaded from the visible modules. VisibleModules.setVisible(Importing, ImportLoc); if (isImportingModuleUnitFromSameModule(Ctx, Importing, CurrentModule, -FoundPrimaryModuleInterface)) +FoundPrimaryModuleInterface)) { for (Module *TransImported : Importing->Imports) -if (!VisibleModules.isVisible(TransImported)) - Worklist.push_back(TransImported); +Worklist.push_back(TransImported); + + for (auto [Exports, _] : Importing->Exports) +Worklist.push_back(Exports); +} } } diff --git a/clang/test/Modules/pr144230.cppm b/clang/test/Modules/pr144230.cppm new file mode 100644 index 0..7de9fc6461ab1 --- /dev/null +++ b/clang/test/Modules/pr144230.cppm @@ -0,0 +1,26 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t + +// RUN: %clang_cc1 -std=c++20 %t/A.cppm -emit-module-interface -o %t/A.pcm +// RUN: %clang_cc1 -std=c++20 %t/P.cppm -emit-module-interface -o %t/M-P.pcm -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/M.cppm -emit-module-interface -o %t/M.pcm -fprebuilt-module-path=%t +// RUN: %clang_cc1 -std=c++20 %t/M.cpp -fprebuilt-module-path=%t -fsyntax-only -verify + +//--- A.cppm +export module A; +export using T = int; + +//--- P.cppm +export module M:P; +import A; + +//--- M.cppm +export module M; +export import :P; + +//--- M.cpp +// expected-no-diagnostics +module M; + +T x; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [CIR] Add initial support for bitfields in structs (PR #142041)
https://github.com/Andres-Salamanca closed https://github.com/llvm/llvm-project/pull/142041 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [BUG] Fix : #139514 (PR #144956)
https://github.com/RahulXDTT closed https://github.com/llvm/llvm-project/pull/144956 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang][OpenCL] Declare cl_amd_media_ops/cl_amd_media_ops2 builtins with -fdeclare-opencl-builtins (PR #143507)
https://github.com/jmmartinez updated https://github.com/llvm/llvm-project/pull/143507 From 813e65b376216543f0250270f2b59ef888adf35d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?= Date: Tue, 10 Jun 2025 12:28:35 +0200 Subject: [PATCH 1/6] [Clang][OpenCL] Pre-commit tests: fdeclare-opencl-builtins does not declare cl_amd_media_ops builtins --- clang/test/SemaOpenCL/amd-media-ops.cl | 98 ++ 1 file changed, 98 insertions(+) create mode 100644 clang/test/SemaOpenCL/amd-media-ops.cl diff --git a/clang/test/SemaOpenCL/amd-media-ops.cl b/clang/test/SemaOpenCL/amd-media-ops.cl new file mode 100644 index 0..33e662004a0fe --- /dev/null +++ b/clang/test/SemaOpenCL/amd-media-ops.cl @@ -0,0 +1,98 @@ +// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -verify -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header %s +// expected-no-diagnostics +// RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -verify=fdecalre -pedantic -Wconversion -Werror -fsyntax-only -cl-std=CL -finclude-default-header -fdeclare-opencl-builtins %s + +#define TEST_1ARG_BUILTIN_WITH_TYPE(builtin, ret, type) \ +ret test_ ## builtin ## _ ## ret ## _## type (type a) { \ +return builtin(a); \ +} + +#define TEST_2ARG_BUILTIN_WITH_TYPE(builtin, ret, type) \ +ret test_ ## builtin ## _ ## ret ## _## type (type a, type b) { \ +return builtin(a, b); \ +} + +#define TEST_3ARG_BUILTIN_WITH_TYPE(builtin, ret, type) \ +ret test_ ## builtin ## _ ## ret ## _ ## type (type a, type b, type c) { \ +return builtin(a, b, c); \ +} + +#define TEST_1ARG_BUILTIN(builtin, ret, type) \ +TEST_1ARG_BUILTIN_WITH_TYPE(builtin, ret, type) \ +TEST_1ARG_BUILTIN_WITH_TYPE(builtin, ret ## 2, type ## 2) \ +TEST_1ARG_BUILTIN_WITH_TYPE(builtin, ret ## 3, type ## 3) \ +TEST_1ARG_BUILTIN_WITH_TYPE(builtin, ret ## 4, type ## 4) \ +TEST_1ARG_BUILTIN_WITH_TYPE(builtin, ret ## 8, type ## 8) \ +TEST_1ARG_BUILTIN_WITH_TYPE(builtin, ret ## 16, type ## 16) + +#define TEST_2ARG_BUILTIN(builtin, ret, type) \ +TEST_2ARG_BUILTIN_WITH_TYPE(builtin, ret, type) \ +TEST_2ARG_BUILTIN_WITH_TYPE(builtin, ret ## 2, type ## 2) \ +TEST_2ARG_BUILTIN_WITH_TYPE(builtin, ret ## 3, type ## 3) \ +TEST_2ARG_BUILTIN_WITH_TYPE(builtin, ret ## 4, type ## 4) \ +TEST_2ARG_BUILTIN_WITH_TYPE(builtin, ret ## 8, type ## 8) \ +TEST_2ARG_BUILTIN_WITH_TYPE(builtin, ret ## 16, type ## 16) + +#define TEST_3ARG_BUILTIN(builtin, ret, type) \ +TEST_3ARG_BUILTIN_WITH_TYPE(builtin, ret, type) \ +TEST_3ARG_BUILTIN_WITH_TYPE(builtin, ret ## 2, type ## 2) \ +TEST_3ARG_BUILTIN_WITH_TYPE(builtin, ret ## 3, type ## 3) \ +TEST_3ARG_BUILTIN_WITH_TYPE(builtin, ret ## 4, type ## 4) \ +TEST_3ARG_BUILTIN_WITH_TYPE(builtin, ret ## 8, type ## 8) \ +TEST_3ARG_BUILTIN_WITH_TYPE(builtin, ret ## 16, type ## 16) + +#define TEST_3ARG_BUILTIN_WITH_TYPES(builtin, ret, type_a, type_b, type_c) \ +ret test_ ## builtin ## _ ## ret ## _ ## type_a ## _ ## type_b ## _ ## type_c (type_a a, type_b b, type_c c) { \ +return builtin(a, b, c); \ +} + +#define TEST_3ARG_WITH_TYPES_BUILTIN(builtin, ret, type_a, type_b, type_c) \ +TEST_3ARG_BUILTIN_WITH_TYPES(builtin, ret, type_a, type_b, type_c) \ +TEST_3ARG_BUILTIN_WITH_TYPES(builtin, ret ## 2, type_a ## 2, type_b ## 2, type_c ## 2) \ +TEST_3ARG_BUILTIN_WITH_TYPES(builtin, ret ## 3, type_a ## 3, type_b ## 3, type_c ## 3) \ +TEST_3ARG_BUILTIN_WITH_TYPES(builtin, ret ## 4, type_a ## 4, type_b ## 4, type_c ## 4) \ +TEST_3ARG_BUILTIN_WITH_TYPES(builtin, ret ## 8, type_a ## 8, type_b ## 8, type_c ## 8) \ +TEST_3ARG_BUILTIN_WITH_TYPES(builtin, ret ## 16, type_a ## 16, type_b ## 16, type_c ## 16) + +TEST_3ARG_BUILTIN(amd_bitalign, uint, uint) // fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} +TEST_3ARG_BUILTIN(amd_bytealign, uint, uint) // fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} +TEST_3ARG_BUILTIN(amd_lerp, uint, uint) // fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} fdecalre-error{{use of undeclared identifier}} + +uint test_amd_pack(float4 a) { +return amd_pack(a); // fdecalre-error{{use of undeclared identifier}} +} + +uint test_amd_sad4(uint4 a, uint4 b, uint c) { +return amd_
[clang-tools-extra] Use spelling for clangd missing includes filtering (PR #143411)
kadircet wrote: sorry for silence here, i was mostly waiting for some replies to https://github.com/llvm/llvm-project/pull/140594#issuecomment-2958066558. as it stands, i feel like we'll likely limit users with a spelling based filter. unless people have concerns/disagreement, i'd suggest we resolve this by filtering on resolved paths. https://github.com/llvm/llvm-project/pull/143411 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Register all LLVM targets in AllClangUnitTest main (PR #144428)
@@ -117,6 +117,7 @@ get_property(LINK_LIBS GLOBAL PROPERTY CLANG_UNITTEST_LINK_LIBS) get_property(LLVM_COMPONENTS GLOBAL PROPERTY CLANG_UNITTEST_LLVM_COMPONENTS) add_distinct_clang_unittest(AllClangUnitTests ${SRCS} + AllClangUnitTests.cpp kadircet wrote: thanks a lot, this is really neat! and yeah i think initialization-order-fiasco should be less of a concern here. https://github.com/llvm/llvm-project/pull/144428 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang] Register all LLVM targets in AllClangUnitTest main (PR #144428)
https://github.com/kadircet approved this pull request. https://github.com/llvm/llvm-project/pull/144428 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [LLVM][Clang] Add and enable strict mode for `getTrailingObjects` (PR #144930)
https://github.com/jurahul updated https://github.com/llvm/llvm-project/pull/144930 >From f5216d4c55c4dffa8785ff2fa051492ed98f405a Mon Sep 17 00:00:00 2001 From: Rahul Joshi Date: Thu, 19 Jun 2025 10:25:12 -0700 Subject: [PATCH] [LLVM][Clang] Add and enable strict mode for `getTrailingObjects` Under strict mode, the templated `getTrailingObjects` can be called only when there is > 1 trailing types. The strict mode can be disabled on a per-call basis when its not possible to know statically if there will be a single or multiple trailing types (like in OpenMPClause.h). --- clang/include/clang/AST/OpenMPClause.h| 46 --- clang/lib/AST/Expr.cpp| 3 +- llvm/include/llvm/Support/TrailingObjects.h | 21 + .../unittests/Support/TrailingObjectsTest.cpp | 5 +- 4 files changed, 47 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h index 2fa8fa529741e..b62ebd614e4c7 100644 --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -295,7 +295,8 @@ template class OMPVarListClause : public OMPClause { /// Fetches list of variables associated with this clause. MutableArrayRef getVarRefs() { -return static_cast(this)->template getTrailingObjects(NumVars); +return static_cast(this) +->template getTrailingObjects(NumVars); } /// Sets the list of variables for this clause. @@ -334,8 +335,8 @@ template class OMPVarListClause : public OMPClause { /// Fetches list of all variables in the clause. ArrayRef getVarRefs() const { -return static_cast(this)->template getTrailingObjects( -NumVars); +return static_cast(this) +->template getTrailingObjects(NumVars); } }; @@ -380,7 +381,8 @@ template class OMPDirectiveListClause : public OMPClause { MutableArrayRef getDirectiveKinds() { return static_cast(this) -->template getTrailingObjects(NumKinds); +->template getTrailingObjects( +NumKinds); } void setDirectiveKinds(ArrayRef DK) { @@ -5901,15 +5903,17 @@ class OMPMappableExprListClause : public OMPVarListClause, /// Get the unique declarations that are in the trailing objects of the /// class. MutableArrayRef getUniqueDeclsRef() { -return static_cast(this)->template getTrailingObjects( -NumUniqueDeclarations); +return static_cast(this) +->template getTrailingObjects( +NumUniqueDeclarations); } /// Get the unique declarations that are in the trailing objects of the /// class. ArrayRef getUniqueDeclsRef() const { return static_cast(this) -->template getTrailingObjects(NumUniqueDeclarations); +->template getTrailingObjects( +NumUniqueDeclarations); } /// Set the unique declarations that are in the trailing objects of the @@ -5923,15 +5927,17 @@ class OMPMappableExprListClause : public OMPVarListClause, /// Get the number of lists per declaration that are in the trailing /// objects of the class. MutableArrayRef getDeclNumListsRef() { -return static_cast(this)->template getTrailingObjects( -NumUniqueDeclarations); +return static_cast(this) +->template getTrailingObjects( +NumUniqueDeclarations); } /// Get the number of lists per declaration that are in the trailing /// objects of the class. ArrayRef getDeclNumListsRef() const { -return static_cast(this)->template getTrailingObjects( -NumUniqueDeclarations); +return static_cast(this) +->template getTrailingObjects( +NumUniqueDeclarations); } /// Set the number of lists per declaration that are in the trailing @@ -5946,7 +5952,8 @@ class OMPMappableExprListClause : public OMPVarListClause, /// objects of the class. They are appended after the number of lists. MutableArrayRef getComponentListSizesRef() { return MutableArrayRef( -static_cast(this)->template getTrailingObjects() + +static_cast(this) +->template getTrailingObjects() + NumUniqueDeclarations, NumComponentLists); } @@ -5955,7 +5962,8 @@ class OMPMappableExprListClause : public OMPVarListClause, /// objects of the class. They are appended after the number of lists. ArrayRef getComponentListSizesRef() const { return ArrayRef( -static_cast(this)->template getTrailingObjects() + +static_cast(this) +->template getTrailingObjects() + NumUniqueDeclarations, NumComponentLists); } @@ -5971,13 +5979,15 @@ class OMPMappableExprListClause : public OMPVarListClause, /// Get the components that are in the trailing objects of the class. MutableArrayRef getComponentsRef() { return static_cast(this) -->template getTrailingObjects(NumComponents); +->template getTrailingObjects( +
[clang-tools-extra] [clang-tidy] Add `performance-explicit-move-constructor` check (PR #122599)
5chmidti wrote: > > but this check could check the signatures themselves to be in the expected > > form > > So warning for signatures like `foo(foo&) = default`? Looking at this again, maybe this shouldn't not that route. Other checks already capture some of those problems. What @PiotrZSL mentioned was more for changing the detection to happen when the performance issue occurs, not preemptively based on the ctor declarations themselves. So detecting construction expressions that call a copy ctor with an rvalue (and xvalue I think) while a ln explicit move ctor is available (that could produce many more matches (perfwise this should not be that expensive overall due to the low analysis cost, but diagnostics might). So that would be a trade off to consider https://github.com/llvm/llvm-project/pull/122599 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Ast importer visitors (PR #138838)
balazske wrote: If `FromTypeRequirement.isSubstitutionFailure()` can be true at compile error it can be still possible to call `testImport` or `getTuDecl` with the code. https://github.com/llvm/llvm-project/pull/138838 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [lldb] [Clang][PowerPC] Add __dmr1024 type and DMF integer calculation builtins (PR #142480)
https://github.com/maryammo closed https://github.com/llvm/llvm-project/pull/142480 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] Add function scope identifier (PR #145074)
llvmbot wrote: @llvm/pr-subscribers-clang Author: KUSHAL R U (KushalRU11) Changes This PR introduces a new Clang-based tool: FunctionScopeIdentifier. The tool identifies C/C++ functions that span specific line ranges in a source file. It extends Clang’s tooling interface by supporting a custom command-line option: -identify-scope-range=Example usage: ./bin/FunctionScopeIdentifier -identify-scope-range=5-10,12-15 test.cpp -- -std=c++17 The tool reports all functions that overlap with the specified line ranges, including the function name and its start/end lines. This can assist with code analysis, refactoring, and tooling automation. Key Features Accepts multiple line ranges via -identify-scope-range (e.g. 5-10,12-18) Uses Clang AST matchers to identify function declarations with bodies Outputs function names and their source line spans that intersect the given ranges Supports standard Clang compilation arguments (e.g. -I, -D) Files Added clang/tools/FunctionScopeIdentifier/FunctionScopeIdentifier.cpp clang/tools/FunctionScopeIdentifier/CMakeLists.txt test-files/test.cpp test-files/test1.cpp test-files/test.ll (IR generated for validation) --- Patch is 58.09 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/145074.diff 8 Files Affected: - (modified) clang/CMakeLists.txt (+4) - (modified) clang/tools/CMakeLists.txt (+2) - (added) clang/tools/FunctionScopeIdentifier/CMakeLists.txt (+10) - (added) clang/tools/FunctionScopeIdentifier/FunctionScopeIdentifier.cpp (+117) - (added) test-files/test.cpp (+11) - (added) test-files/test.ll (+1005) - (added) test-files/test1.cpp (+9) - (added) test-files/test1.ll (+54) ``diff diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index ab2ac9bc6b9ad..9471553f02286 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -879,6 +879,8 @@ if (LLVM_ADD_NATIVE_VISUALIZERS_TO_SOLUTION) endif() add_subdirectory(utils/hmaptool) + + if(CLANG_BUILT_STANDALONE) llvm_distribution_add_targets() process_llvm_pass_plugins() @@ -889,3 +891,5 @@ set(CLANG_INSTALL_LIBDIR_BASENAME "lib${CLANG_LIBDIR_SUFFIX}") configure_file( ${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake ${CLANG_BINARY_DIR}/include/clang/Config/config.h) + + diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt index 50e3d694236ac..bed19848c250e 100644 --- a/clang/tools/CMakeLists.txt +++ b/clang/tools/CMakeLists.txt @@ -52,3 +52,5 @@ add_llvm_external_project(clang-tools-extra extra) add_clang_subdirectory(libclang) add_clang_subdirectory(offload-arch) + +add_clang_subdirectory(FunctionScopeIdentifier) diff --git a/clang/tools/FunctionScopeIdentifier/CMakeLists.txt b/clang/tools/FunctionScopeIdentifier/CMakeLists.txt new file mode 100644 index 0..d8e3ff9967b43 --- /dev/null +++ b/clang/tools/FunctionScopeIdentifier/CMakeLists.txt @@ -0,0 +1,10 @@ +add_clang_executable(FunctionScopeIdentifier + FunctionScopeIdentifier.cpp +) + +target_link_libraries(FunctionScopeIdentifier + PRIVATE + clangTooling + clangBasic + clangASTMatchers +) diff --git a/clang/tools/FunctionScopeIdentifier/FunctionScopeIdentifier.cpp b/clang/tools/FunctionScopeIdentifier/FunctionScopeIdentifier.cpp new file mode 100644 index 0..56046b4be5ec2 --- /dev/null +++ b/clang/tools/FunctionScopeIdentifier/FunctionScopeIdentifier.cpp @@ -0,0 +1,117 @@ +#include "clang/Tooling/CommonOptionsParser.h" +#include "clang/Tooling/Tooling.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "llvm/Support/CommandLine.h" +#include +#include +#include + +using namespace clang; +using namespace clang::tooling; +using namespace llvm; +using namespace clang::ast_matchers; + +// Create an option category for the tool +static cl::OptionCategory MyToolCategory("function-scope-identifier options"); + +// Command-line option for line ranges +static cl::opt IdentifyRange( +"identify-scope-range", +cl::desc("Comma-separated list of line ranges (e.g., 5-10,15-20)"), +cl::value_desc("line-ranges"), +cl::Required, +cl::cat(MyToolCategory)); + +// Parse line range string like "5-10,15-20" into vector of pairs +std::vector> parseRanges(const std::string &rangeStr) { +std::vector> ranges; +std::stringstream ss(rangeStr); +std::string part; +while (std::getline(ss, part, ',')) { +auto dash = part.find('-'); +if (dash != std::string::npos) { +unsigned start = std::stoi(part.substr(0, dash)); +unsigned end = std::stoi(part.substr(dash + 1)); +ranges.emplace_back(start, end); +} +} +return ranges; +} + +// AST matcher callback +class FunctionVisitor : public MatchFinder::MatchCallback { +
[clang] 65cb3bc - [Clang][PowerPC] Add __dmr1024 type and DMF integer calculation builtins (#142480)
Author: Maryam Moghadas Date: 2025-06-20T13:03:14-04:00 New Revision: 65cb3bcf327da8f9740e56897bc9954364e59eb6 URL: https://github.com/llvm/llvm-project/commit/65cb3bcf327da8f9740e56897bc9954364e59eb6 DIFF: https://github.com/llvm/llvm-project/commit/65cb3bcf327da8f9740e56897bc9954364e59eb6.diff LOG: [Clang][PowerPC] Add __dmr1024 type and DMF integer calculation builtins (#142480) Define the __dmr1024 type used to manipulate the new DMR registers introduced by the Dense Math Facility (DMF) on PowerPC, and add six Clang builtins that correspond to the integer outer-product accumulate to ACC PowerPC instructions: * __builtin_mma_dmxvi8gerx4 * __builtin_mma_pmdmxvi8gerx4 * __builtin_mma_dmxvi8gerx4pp * __builtin_mma_pmdmxvi8gerx4pp * __builtin_mma_dmxvi8gerx4spp * __builtin_mma_pmdmxvi8gerx4spp. Added: clang/test/CodeGen/PowerPC/builtins-ppc-dmf.c clang/test/CodeGen/PowerPC/ppc-dmf-paired-vec-memops-builtin-err.c clang/test/CodeGen/PowerPC/ppc-dmf-types.c clang/test/CodeGen/PowerPC/ppc-future-mma-builtin-err.c clang/test/Sema/ppc-dmf-types.c Modified: clang/include/clang/Basic/BuiltinsPPC.def clang/include/clang/Basic/PPCTypes.def clang/lib/AST/ASTContext.cpp clang/test/AST/ast-dump-ppc-types.c clang/test/CodeGenCXX/ppc-mangle-mma-types.cpp lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp Removed: diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def index bb7d54bbb793e..099500754a0e0 100644 --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -1134,6 +1134,18 @@ UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2np, "vW512*VVi15i15i3", true, "mma,paired-vector-memops") UNALIASED_CUSTOM_BUILTIN(mma_pmxvbf16ger2nn, "vW512*VVi15i15i3", true, "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_dmxvi8gerx4, "vW1024*W256V", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmdmxvi8gerx4, "vW1024*W256Vi255i15i15", false, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_dmxvi8gerx4pp, "vW1024*W256V", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmdmxvi8gerx4pp, "vW1024*W256Vi255i15i15", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_dmxvi8gerx4spp, "vW1024*W256V", true, + "mma,paired-vector-memops") +UNALIASED_CUSTOM_BUILTIN(mma_pmdmxvi8gerx4spp, "vW1024*W256Vi255i15i15", true, + "mma,paired-vector-memops") // FIXME: Obviously incomplete. diff --git a/clang/include/clang/Basic/PPCTypes.def b/clang/include/clang/Basic/PPCTypes.def index 9e2cb2aedc9fc..fc4155ca98b2d 100644 --- a/clang/include/clang/Basic/PPCTypes.def +++ b/clang/include/clang/Basic/PPCTypes.def @@ -30,6 +30,7 @@ #endif +PPC_VECTOR_MMA_TYPE(__dmr1024, DMR1024, 1024) PPC_VECTOR_MMA_TYPE(__vector_quad, VectorQuad, 512) PPC_VECTOR_VSX_TYPE(__vector_pair, VectorPair, 256) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 74be2871f270c..02d6570d0ea0f 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3522,6 +3522,7 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, case BuiltinType::BFloat16: case BuiltinType::VectorQuad: case BuiltinType::VectorPair: +case BuiltinType::DMR1024: OS << "?"; return; diff --git a/clang/test/AST/ast-dump-ppc-types.c b/clang/test/AST/ast-dump-ppc-types.c index 26ae5441f20d7..1c860c268e0ec 100644 --- a/clang/test/AST/ast-dump-ppc-types.c +++ b/clang/test/AST/ast-dump-ppc-types.c @@ -1,9 +1,11 @@ +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu future \ +// RUN: -ast-dump %s | FileCheck %s // RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu pwr10 \ -// RUN: -ast-dump -ast-dump-filter __vector %s | FileCheck %s +// RUN: -ast-dump %s | FileCheck %s // RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu pwr9 \ -// RUN: -ast-dump -ast-dump-filter __vector %s | FileCheck %s +// RUN: -ast-dump %s | FileCheck %s // RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu pwr8 \ -// RUN: -ast-dump -ast-dump-filter __vector %s | FileCheck %s +// RUN: -ast-dump %s | FileCheck %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -ast-dump %s | FileCheck %s \ // RUN: --check-prefix=CHECK-X86_64 // RUN: %clang_cc1 -triple arm-unknown-unknown -ast-dump %s | FileCheck %s \ @@ -15,16 +17,21 @@ // are correctly defined. We also added checks on a couple of other targets to // ensure the types are target-dependent. +// CHECK: TypedefDecl {{.*}} implicit __dmr1024 '__dmr1024' +// CHECK: `-BuiltinType {{.*}} '__dmr1024' // CHECK:
[clang] [llvm] KISHAN KUMAR S D, HRUTHIK K K , KIRAN V-R V COLLEGE OF ENGINEERING(CSE 6TH SEM)-Implement Clang identifiers to retrieve the mangled name and the fully qualified name of functions #5 (PR
https://github.com/kishan-kumar-s-d-444 updated https://github.com/llvm/llvm-project/pull/145042 >From fdf7f676690f7af5109970f239eba8f34850442f Mon Sep 17 00:00:00 2001 From: KISHAN KUMAR S D Date: Fri, 20 Jun 2025 19:35:57 +0530 Subject: [PATCH 1/6] Update Expr.h --- clang/include/clang/AST/Expr.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 9fc23d30b733f..2da16d4dc069d 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -2003,7 +2003,9 @@ enum class PredefinedIdentKind { PrettyFunction, /// The same as PrettyFunction, except that the /// 'virtual' keyword is omitted for virtual member functions. - PrettyFunctionNoVirtual + PrettyFunctionNoVirtual, + FQFunction, + MangledFunction }; /// [C99 6.4.2.2] - A predefined identifier such as __func__. >From b814391bd581ab82acf30366ffd3952f3f72a490 Mon Sep 17 00:00:00 2001 From: KISHAN KUMAR S D Date: Fri, 20 Jun 2025 19:38:50 +0530 Subject: [PATCH 2/6] Update TokenKinds.def --- clang/include/clang/Basic/TokenKinds.def | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def index 94e72fea56a68..1f9f0d60e8b02 100644 --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -480,6 +480,9 @@ KEYWORD(__thread, KEYALL) KEYWORD(__FUNCTION__, KEYALL) KEYWORD(__PRETTY_FUNCTION__ , KEYALL) KEYWORD(__auto_type , KEYALL) +KEYWORD(__fq_func__, KEYALL) +KEYWORD(__mangled_func__, KEYALL) + // MS Extensions KEYWORD(__FUNCDNAME__ , KEYMS) >From fe6fc7ba8183b267ee00fdc66c3060f1449194b2 Mon Sep 17 00:00:00 2001 From: KISHAN KUMAR S D Date: Fri, 20 Jun 2025 19:39:32 +0530 Subject: [PATCH 3/6] Update Expr.cpp --- clang/lib/AST/Expr.cpp | 32 1 file changed, 32 insertions(+) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index c3722c65abf6e..12b6745536d53 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -653,6 +653,10 @@ StringRef PredefinedExpr::getIdentKindName(PredefinedIdentKind IK) { return "__FUNCTION__"; case PredefinedIdentKind::FuncDName: return "__FUNCDNAME__"; + case PredefinedIdentKind::FQFunction: +return "__fq_func__"; + case PredefinedIdentKind::MangledFunction: +return "__mangled_func__"; case PredefinedIdentKind::LFunction: return "L__FUNCTION__"; case PredefinedIdentKind::PrettyFunction: @@ -674,6 +678,34 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK, bool ForceElaboratedPrinting) { ASTContext &Context = CurrentDecl->getASTContext(); + if (IK == PredefinedIdentKind::FQFunction) { + if (const auto *ND = dyn_cast(CurrentDecl)) +return ND->getQualifiedNameAsString(); + return ""; +} + +if (IK == PredefinedIdentKind::MangledFunction) { + if (const auto *ND = dyn_cast(CurrentDecl)) { +std::unique_ptr MC; +MC.reset(Context.createMangleContext()); +SmallString<256> Buffer; +llvm::raw_svector_ostream Out(Buffer); +GlobalDecl GD; +if (const CXXConstructorDecl *CD = dyn_cast(ND)) + GD = GlobalDecl(CD, Ctor_Base); +else if (const CXXDestructorDecl *DD = dyn_cast(ND)) + GD = GlobalDecl(DD, Dtor_Base); +else if (auto FD = dyn_cast(ND)) { + GD = FD->isReferenceableKernel() ? GlobalDecl(FD) : GlobalDecl(ND); +} else + GD = GlobalDecl(ND); +MC->mangleName(GD, Out); +return std::string(Buffer); + } + return ""; +} + + if (IK == PredefinedIdentKind::FuncDName) { if (const NamedDecl *ND = dyn_cast(CurrentDecl)) { std::unique_ptr MC; >From add48ac76f28fa94ff4aed30116722a2b24799fb Mon Sep 17 00:00:00 2001 From: KISHAN KUMAR S D Date: Fri, 20 Jun 2025 19:40:35 +0530 Subject: [PATCH 4/6] Update SemaExpr.cpp --- clang/lib/Sema/SemaExpr.cpp | 4 1 file changed, 4 insertions(+) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 413eff4aa294a..2e5cd6a821c70 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1992,6 +1992,10 @@ static PredefinedIdentKind getPredefinedExprKind(tok::TokenKind Kind) { llvm_unreachable("unexpected TokenKind"); case tok::kw___func__: return PredefinedIdentKind::Func; // [C99 6.4.2.2] + case tok::kw___fq_func__: +return PredefinedIdentKind::FQFunction; + case tok::kw___mangled_func__: +return PredefinedIdentKind::MangledFunction; case tok::kw___FUNCTION__: return PredefinedIdentKind::Function; case tok::kw___FUNCDNAME__: >From f5847a1c5a93bb0e70eae2e211abe50a1cd3677d Mon Sep 17 00:00:00 2001 From: KISHAN KUMAR S D Date: Fri, 20 Jun 2025 19:41:40 +0530 Subject: [PATCH 5/6] Update ParseExpr.cpp --- clang/lib/Parse/Pars
[clang] __sys builtin support (PR #145079)
https://github.com/AdamGlass created https://github.com/llvm/llvm-project/pull/145079 Adds support for __sys Clang builtin for Aarch64 __sys is a long existing MSVC intrinsic used to manage caches, tlbs, etc by writing to system registers: • It takes a macro-generated constant and uses it to form the AArch64 SYS instruction which is MSR with op0=1. The macro drops op0 and expects the implementation to hardcode it to 1 in the encoding. • Volume use is in systems code (kernels, hypervisors, boot environments, firmware) • Has an unused return value due to MSVC cut/paste error Implementation: • Clang builtin, sharing code with Read/WriteStatusReg • Hardcodes the op0=1 • Explicitly returns 0 • Code-format change from clang-format • Unittests included • Not limited to MSVC-environment as its generally useful and neutral Adam Glass adamgl...@spottedfoobar.com adamgl...@microsoft.com @dpaoliello >From cd5afb986fbbc6ceb68e2b4c6afc48bd1c8bf02e Mon Sep 17 00:00:00 2001 From: Adam Glass Date: Fri, 13 Jun 2025 17:59:20 -0700 Subject: [PATCH] __sys builtin support --- clang/include/clang/Basic/BuiltinsAArch64.def | 1 + clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 25 --- clang/lib/Headers/intrin.h| 1 + clang/lib/Sema/SemaARM.cpp| 2 +- clang/test/CodeGen/arm64-microsoft-sys.c | 68 +++ clang/test/Sema/builtins-microsoft-arm64.c| 9 +++ 6 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 clang/test/CodeGen/arm64-microsoft-sys.c diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def index 8867a9fe09fb9..3bb329d210c07 100644 --- a/clang/include/clang/Basic/BuiltinsAArch64.def +++ b/clang/include/clang/Basic/BuiltinsAArch64.def @@ -267,6 +267,7 @@ TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", INTRIN_H, ALL_MS_LANGUAGES, TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_ReadStatusReg, "LLii", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_WriteStatusReg, "viLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__sys, "UiiLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__mulh, "SLLiSLLiSLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp index dab311903f6dd..d1c62c6b754a5 100644 --- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp @@ -5471,19 +5471,21 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, } if (BuiltinID == clang::AArch64::BI_ReadStatusReg || - BuiltinID == clang::AArch64::BI_WriteStatusReg) { + BuiltinID == clang::AArch64::BI_WriteStatusReg || + BuiltinID == clang::AArch64::BI__sys) { LLVMContext &Context = CGM.getLLVMContext(); unsigned SysReg = E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue(); std::string SysRegStr; -llvm::raw_string_ostream(SysRegStr) << - ((1 << 1) | ((SysReg >> 14) & 1)) << ":" << - ((SysReg >> 11) & 7) << ":" << - ((SysReg >> 7) & 15) << ":" << - ((SysReg >> 3) & 15) << ":" << - ( SysReg& 7); +unsigned SysRegOp0 = (BuiltinID != clang::AArch64::BI__sys) + ? ((1 << 1) | ((SysReg >> 14) & 1)) + : 1; +llvm::raw_string_ostream(SysRegStr) +<< SysRegOp0 << ":" << ((SysReg >> 11) & 7) << ":" +<< ((SysReg >> 7) & 15) << ":" << ((SysReg >> 3) & 15) << ":" +<< (SysReg & 7); llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysRegStr) }; llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops); @@ -5500,8 +5502,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, llvm::Function *F = CGM.getIntrinsic(Intrinsic::write_register, Types); llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1)); - -return Builder.CreateCall(F, { Metadata, ArgValue }); +llvm::Value *Result = Builder.CreateCall(F, {Metadata, ArgValue}); +if (BuiltinID == clang::AArch64::BI__sys) { + // Return 0 for convenience, even though MSVC returns some other undefined + // value. + Result = ConstantInt::get(Builder.getInt32Ty(), 0); +} +return Result; } if (BuiltinID == clang::AArch64::BI_AddressOfReturnAddress) { diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index 3dd1eb45817d4..0ab69fd403d2d 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -374,6 +374,7 @@ long _InterlockedAdd(long volatile *Addend, long Value); __int64 _InterlockedAdd64(__int64
[clang] __sys builtin support (PR #145079)
llvmbot wrote: @llvm/pr-subscribers-clang Author: Adam Glass (AdamGlass) Changes Adds support for __sys Clang builtin for Aarch64 __sys is a long existing MSVC intrinsic used to manage caches, tlbs, etc by writing to system registers: • It takes a macro-generated constant and uses it to form the AArch64 SYS instruction which is MSR with op0=1. The macro drops op0 and expects the implementation to hardcode it to 1 in the encoding. • Volume use is in systems code (kernels, hypervisors, boot environments, firmware) • Has an unused return value due to MSVC cut/paste error Implementation: • Clang builtin, sharing code with Read/WriteStatusReg • Hardcodes the op0=1 • Explicitly returns 0 • Code-format change from clang-format • Unittests included • Not limited to MSVC-environment as its generally useful and neutral Adam Glass adamglass@spottedfoobar.com adamglass@microsoft.com @dpaoliello --- Full diff: https://github.com/llvm/llvm-project/pull/145079.diff 6 Files Affected: - (modified) clang/include/clang/Basic/BuiltinsAArch64.def (+1) - (modified) clang/lib/CodeGen/TargetBuiltins/ARM.cpp (+16-9) - (modified) clang/lib/Headers/intrin.h (+1) - (modified) clang/lib/Sema/SemaARM.cpp (+1-1) - (added) clang/test/CodeGen/arm64-microsoft-sys.c (+68) - (modified) clang/test/Sema/builtins-microsoft-arm64.c (+9) ``diff diff --git a/clang/include/clang/Basic/BuiltinsAArch64.def b/clang/include/clang/Basic/BuiltinsAArch64.def index 8867a9fe09fb9..3bb329d210c07 100644 --- a/clang/include/clang/Basic/BuiltinsAArch64.def +++ b/clang/include/clang/Basic/BuiltinsAArch64.def @@ -267,6 +267,7 @@ TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", INTRIN_H, ALL_MS_LANGUAGES, TARGET_HEADER_BUILTIN(__getReg, "ULLii", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_ReadStatusReg, "LLii", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_WriteStatusReg, "viLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__sys, "UiiLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__mulh, "SLLiSLLiSLLi", "nh", INTRIN_H, ALL_MS_LANGUAGES, "") diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp index dab311903f6dd..d1c62c6b754a5 100644 --- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp @@ -5471,19 +5471,21 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, } if (BuiltinID == clang::AArch64::BI_ReadStatusReg || - BuiltinID == clang::AArch64::BI_WriteStatusReg) { + BuiltinID == clang::AArch64::BI_WriteStatusReg || + BuiltinID == clang::AArch64::BI__sys) { LLVMContext &Context = CGM.getLLVMContext(); unsigned SysReg = E->getArg(0)->EvaluateKnownConstInt(getContext()).getZExtValue(); std::string SysRegStr; -llvm::raw_string_ostream(SysRegStr) << - ((1 << 1) | ((SysReg >> 14) & 1)) << ":" << - ((SysReg >> 11) & 7) << ":" << - ((SysReg >> 7) & 15) << ":" << - ((SysReg >> 3) & 15) << ":" << - ( SysReg& 7); +unsigned SysRegOp0 = (BuiltinID != clang::AArch64::BI__sys) + ? ((1 << 1) | ((SysReg >> 14) & 1)) + : 1; +llvm::raw_string_ostream(SysRegStr) +<< SysRegOp0 << ":" << ((SysReg >> 11) & 7) << ":" +<< ((SysReg >> 7) & 15) << ":" << ((SysReg >> 3) & 15) << ":" +<< (SysReg & 7); llvm::Metadata *Ops[] = { llvm::MDString::get(Context, SysRegStr) }; llvm::MDNode *RegName = llvm::MDNode::get(Context, Ops); @@ -5500,8 +5502,13 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, llvm::Function *F = CGM.getIntrinsic(Intrinsic::write_register, Types); llvm::Value *ArgValue = EmitScalarExpr(E->getArg(1)); - -return Builder.CreateCall(F, { Metadata, ArgValue }); +llvm::Value *Result = Builder.CreateCall(F, {Metadata, ArgValue}); +if (BuiltinID == clang::AArch64::BI__sys) { + // Return 0 for convenience, even though MSVC returns some other undefined + // value. + Result = ConstantInt::get(Builder.getInt32Ty(), 0); +} +return Result; } if (BuiltinID == clang::AArch64::BI_AddressOfReturnAddress) { diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index 3dd1eb45817d4..0ab69fd403d2d 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -374,6 +374,7 @@ long _InterlockedAdd(long volatile *Addend, long Value); __int64 _InterlockedAdd64(__int64 volatile *Addend, __int64 Value); __int64 _ReadStatusReg(int); void _WriteStatusReg(int, __int64); +unsigned int __sys(int, __int64); unsigned short __cdecl _byteswap_ushort(unsigned
[clang] __sys builtin support (PR #145079)
github-actions[bot] wrote: Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using `@` followed by their GitHub username. If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the [LLVM GitHub User Guide](https://llvm.org/docs/GitHub.html). You can also ask questions in a comment on this PR, on the [LLVM Discord](https://discord.com/invite/xS7Z362) or on the [forums](https://discourse.llvm.org/). https://github.com/llvm/llvm-project/pull/145079 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang][ARM] Include arm_acle.h in intrin.h on supported platforms (PR #144172)
@@ -50,11 +50,11 @@ BUILTIN(__builtin_arm_wfi, "v", "") BUILTIN(__builtin_arm_sev, "v", "") BUILTIN(__builtin_arm_sevl, "v", "") BUILTIN(__builtin_arm_chkfeat, "WUiWUi", "") -TARGET_HEADER_BUILTIN(__yield, "v", "h", ARMACLE_H, ALL_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__wfe, "v", "h", ARMACLE_H, ALL_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__wfi, "v", "h", ARMACLE_H, ALL_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__sev, "v", "h", ARMACLE_H, ALL_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__sevl, "v", "h", ARMACLE_H, ALL_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__yield, "v", "h", INTRIN_H, ALL_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__wfe, "v", "h", INTRIN_H, ALL_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__wfi, "v", "h", INTRIN_H, ALL_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__sev, "v", "h", INTRIN_H, ALL_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__sevl, "v", "h", INTRIN_H, ALL_LANGUAGES, "") sarnex wrote: Good catch, I missed that. I guess the best solution is to have a different warning for Linux/Windows. @rnk Opinions? https://github.com/llvm/llvm-project/pull/144172 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits