[clang] [llvm] [ValueTracking] Return true for AddrSpaceCast in canCreateUndefOrPoison (PR #144686)

2025-06-20 Thread Wenju He via cfe-commits

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)

2025-06-20 Thread Nikita Popov via cfe-commits


@@ -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)

2025-06-20 Thread Nikita Popov via cfe-commits

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)

2025-06-20 Thread Wenju He via cfe-commits

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)

2025-06-20 Thread Henrich Lauko via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread Timm Baeder via cfe-commits

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)

2025-06-20 Thread Nikita Popov via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread David Spickett via cfe-commits
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)

2025-06-20 Thread Michael Kruse via cfe-commits

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)

2025-06-20 Thread Balázs Kéri via cfe-commits


@@ -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)

2025-06-20 Thread Balázs Kéri via cfe-commits

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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Balázs Kéri via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits

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)

2025-06-20 Thread Wenju He via cfe-commits

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)

2025-06-20 Thread Henrich Lauko via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread Henrich Lauko via cfe-commits

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)

2025-06-20 Thread Nikita Popov via cfe-commits

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)

2025-06-20 Thread Nikita Popov via cfe-commits


@@ -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)

2025-06-20 Thread Krzysztof Parzyszek via cfe-commits

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)

2025-06-20 Thread Tom Eccles via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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

2025-06-20 Thread via cfe-commits

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
![CODE 
SNIPPET](https://github.com/user-attachments/assets/44c87dce-1e1b-458e-bc63-e9d8432c649c)
![OUTPUT](https://github.com/user-attachments/assets/c7e4fe2d-98cb-4d3b-b3b1-9ff909d5a2ac)




---
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

2025-06-20 Thread KISHAN KUMAR S D via cfe-commits

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
![CODE 
SNIPPET](https://github.com/user-attachments/assets/44c87dce-1e1b-458e-bc63-e9d8432c649c)
![OUTPUT](https://github.com/user-attachments/assets/c7e4fe2d-98cb-4d3b-b3b1-9ff909d5a2ac)




>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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread Samarth Narang via cfe-commits

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)

2025-06-20 Thread Walter J.T.V via cfe-commits

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)

2025-06-20 Thread David Green via cfe-commits

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)

2025-06-20 Thread Nathan Gauër via cfe-commits

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)

2025-06-20 Thread David Green via cfe-commits


@@ -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)

2025-06-20 Thread Steven Perron via cfe-commits

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)

2025-06-20 Thread Tarun Prabhu via cfe-commits

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)

2025-06-20 Thread Tarun Prabhu via cfe-commits

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)

2025-06-20 Thread Tarun Prabhu via cfe-commits


@@ -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)

2025-06-20 Thread Walter J.T.V via cfe-commits


@@ -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)

2025-06-20 Thread Walter J.T.V via cfe-commits


@@ -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)

2025-06-20 Thread Walter J.T.V via cfe-commits


@@ -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)

2025-06-20 Thread Michael Kruse via cfe-commits

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)

2025-06-20 Thread Walter J.T.V via cfe-commits


@@ -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)

2025-06-20 Thread Walter J.T.V via cfe-commits

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)

2025-06-20 Thread Walter J.T.V via cfe-commits

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)

2025-06-20 Thread Alexey Bataev via cfe-commits


@@ -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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread Prajwal Nadig via cfe-commits

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)

2025-06-20 Thread Juan Manuel Martinez Caamaño via cfe-commits

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)

2025-06-20 Thread Rodolfo Wottrich via cfe-commits


@@ -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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread Rodolfo Wottrich via cfe-commits


@@ -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)

2025-06-20 Thread Rodolfo Wottrich via cfe-commits


@@ -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)

2025-06-20 Thread Jonathan Thackray via cfe-commits

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)

2025-06-20 Thread Rahul Joshi via cfe-commits

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)

2025-06-20 Thread Oliver Stannard via cfe-commits

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)

2025-06-20 Thread Walter J.T.V via cfe-commits


@@ -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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread Jameson Nash via cfe-commits

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)

2025-06-20 Thread Walter J.T.V via cfe-commits


@@ -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)

2025-06-20 Thread Walter J.T.V via cfe-commits


@@ -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)

2025-06-20 Thread Walter J.T.V via cfe-commits


@@ -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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread David Green via cfe-commits


@@ -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)

2025-06-20 Thread David Green via cfe-commits

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)

2025-06-20 Thread David Green via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread Steven Perron via cfe-commits


@@ -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)

2025-06-20 Thread Kiran Chandramohan via cfe-commits

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

2025-06-20 Thread Chuanqi Xu via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread Rahul Samajpati via cfe-commits

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)

2025-06-20 Thread Juan Manuel Martinez Caamaño via cfe-commits

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)

2025-06-20 Thread kadir çetinkaya via cfe-commits

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)

2025-06-20 Thread kadir çetinkaya via cfe-commits


@@ -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)

2025-06-20 Thread kadir çetinkaya via cfe-commits

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)

2025-06-20 Thread Rahul Joshi via cfe-commits

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)

2025-06-20 Thread Julian Schmidt via cfe-commits

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)

2025-06-20 Thread Balázs Kéri via cfe-commits

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)

2025-06-20 Thread Maryam Moghadas via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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

2025-06-20 Thread KISHAN KUMAR S D via cfe-commits

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)

2025-06-20 Thread Adam Glass via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread via cfe-commits

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)

2025-06-20 Thread Nick Sarnie via cfe-commits


@@ -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


  1   2   3   >