[llvm-branch-commits] [FlowSensitive] [StatusOr] [15/N] Support nested StatusOrs (PR #170950)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Florian Mayer (fmayer)


Changes



---
Full diff: https://github.com/llvm/llvm-project/pull/170950.diff


2 Files Affected:

- (modified) 
clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp (+24) 
- (modified) 
clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
 (+149) 


``diff
diff --git 
a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp 
b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
index 1b68d704239e8..c917c8e8c11ba 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
@@ -1037,6 +1037,26 @@ transferAssertionResultOperatorBoolCall(const 
CXXMemberCallExpr *Expr,
   State.Env.setValue(*Expr, Res);
 }
 
+static void transferDerefCall(const CallExpr *Expr,
+  const MatchFinder::MatchResult &,
+  LatticeTransferState &State) {
+  auto *StatusOrLoc = State.Env.get(*Expr->getArg(0));
+
+  if (StatusOrLoc && State.Env.getStorageLocation(*Expr) == nullptr)
+State.Env.setStorageLocation(*Expr,
+ StatusOrLoc->getSyntheticField("value"));
+}
+
+static void transferArrowCall(const CallExpr *Expr,
+  const MatchFinder::MatchResult &,
+  LatticeTransferState &State) {
+  auto *StatusOrLoc = State.Env.get(*Expr->getArg(0));
+  if (!StatusOrLoc)
+return;
+  State.Env.setValue(*Expr, State.Env.create(
+StatusOrLoc->getSyntheticField("value")));
+}
+
 static RecordStorageLocation *
 getSmartPtrLikeStorageLocation(const Expr &E, const Environment &Env) {
   if (!E.isPRValue())
@@ -1123,6 +1143,10 @@ buildTransferMatchSwitch(ASTContext &Ctx,
   transferValueAssignmentCall)
   .CaseOfCFGStmt(isStatusOrValueConstructor(),
transferValueConstructor)
+  .CaseOfCFGStmt(isStatusOrOperatorCallWithName("->"),
+   transferArrowCall)
+  .CaseOfCFGStmt(isStatusOrOperatorCallWithName("*"),
+   transferDerefCall)
   .CaseOfCFGStmt(isAsStatusCallWithStatus(),
transferAsStatusCallWithStatus)
   .CaseOfCFGStmt(isAsStatusCallWithStatusOr(),
diff --git 
a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
 
b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
index 48e61abf09f19..cd7353c62f537 100644
--- 
a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
+++ 
b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
@@ -3691,6 +3691,155 @@ TEST_P(UncheckedStatusOrAccessModelTest, 
UniquePtrReset) {
   )cc");
 }
 
+TEST_P(UncheckedStatusOrAccessModelTest, NestedStatusOrInStatusOrStruct) {
+  // Non-standard assignment with a nested StatusOr.
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Inner {
+  absl::StatusOr sor;
+};
+
+struct Outer {
+  absl::StatusOr inner;
+};
+
+void target() {
+  Outer foo = Make();
+  foo.inner->sor = "a";  // [[unsafe]]
+}
+  )cc");
+
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Foo {
+  absl::StatusOr sor;
+};
+
+void target(const absl::StatusOr& foo) {
+  if (foo.ok() && foo->sor.ok()) foo->sor.value();
+}
+  )cc");
+
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Foo {
+  absl::StatusOr sor;
+};
+
+void target(const absl::StatusOr& foo) {
+  if (foo.ok() && (*foo).sor.ok()) (*foo).sor.value();
+}
+  )cc");
+
+  // With assignment.
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Foo {
+  absl::StatusOr sor;
+};
+
+void target(absl::StatusOr& foo) {
+  if (foo.ok() && foo->sor.ok()) {
+foo->sor = Make>();
+foo->sor.value();  // [[unsafe]]
+  }
+}
+  )cc");
+
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Foo {
+  absl::StatusOr sor;
+};
+
+void target(absl::StatusOr& foo) {
+  if (foo.ok() && foo->sor.ok()) {
+auto n = Make>();
+if (n.ok()) foo->sor = n;
+foo->sor.value();
+  }
+}
+  )cc");
+
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Foo {
+  absl::StatusOr s

[llvm-branch-commits] [FlowSensitive] [StatusOr] [15/N] Support nested StatusOrs (PR #170950)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-analysis

Author: Florian Mayer (fmayer)


Changes



---
Full diff: https://github.com/llvm/llvm-project/pull/170950.diff


2 Files Affected:

- (modified) 
clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp (+24) 
- (modified) 
clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
 (+149) 


``diff
diff --git 
a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp 
b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
index 1b68d704239e8..c917c8e8c11ba 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
@@ -1037,6 +1037,26 @@ transferAssertionResultOperatorBoolCall(const 
CXXMemberCallExpr *Expr,
   State.Env.setValue(*Expr, Res);
 }
 
+static void transferDerefCall(const CallExpr *Expr,
+  const MatchFinder::MatchResult &,
+  LatticeTransferState &State) {
+  auto *StatusOrLoc = State.Env.get(*Expr->getArg(0));
+
+  if (StatusOrLoc && State.Env.getStorageLocation(*Expr) == nullptr)
+State.Env.setStorageLocation(*Expr,
+ StatusOrLoc->getSyntheticField("value"));
+}
+
+static void transferArrowCall(const CallExpr *Expr,
+  const MatchFinder::MatchResult &,
+  LatticeTransferState &State) {
+  auto *StatusOrLoc = State.Env.get(*Expr->getArg(0));
+  if (!StatusOrLoc)
+return;
+  State.Env.setValue(*Expr, State.Env.create(
+StatusOrLoc->getSyntheticField("value")));
+}
+
 static RecordStorageLocation *
 getSmartPtrLikeStorageLocation(const Expr &E, const Environment &Env) {
   if (!E.isPRValue())
@@ -1123,6 +1143,10 @@ buildTransferMatchSwitch(ASTContext &Ctx,
   transferValueAssignmentCall)
   .CaseOfCFGStmt(isStatusOrValueConstructor(),
transferValueConstructor)
+  .CaseOfCFGStmt(isStatusOrOperatorCallWithName("->"),
+   transferArrowCall)
+  .CaseOfCFGStmt(isStatusOrOperatorCallWithName("*"),
+   transferDerefCall)
   .CaseOfCFGStmt(isAsStatusCallWithStatus(),
transferAsStatusCallWithStatus)
   .CaseOfCFGStmt(isAsStatusCallWithStatusOr(),
diff --git 
a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
 
b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
index 48e61abf09f19..cd7353c62f537 100644
--- 
a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
+++ 
b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
@@ -3691,6 +3691,155 @@ TEST_P(UncheckedStatusOrAccessModelTest, 
UniquePtrReset) {
   )cc");
 }
 
+TEST_P(UncheckedStatusOrAccessModelTest, NestedStatusOrInStatusOrStruct) {
+  // Non-standard assignment with a nested StatusOr.
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Inner {
+  absl::StatusOr sor;
+};
+
+struct Outer {
+  absl::StatusOr inner;
+};
+
+void target() {
+  Outer foo = Make();
+  foo.inner->sor = "a";  // [[unsafe]]
+}
+  )cc");
+
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Foo {
+  absl::StatusOr sor;
+};
+
+void target(const absl::StatusOr& foo) {
+  if (foo.ok() && foo->sor.ok()) foo->sor.value();
+}
+  )cc");
+
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Foo {
+  absl::StatusOr sor;
+};
+
+void target(const absl::StatusOr& foo) {
+  if (foo.ok() && (*foo).sor.ok()) (*foo).sor.value();
+}
+  )cc");
+
+  // With assignment.
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Foo {
+  absl::StatusOr sor;
+};
+
+void target(absl::StatusOr& foo) {
+  if (foo.ok() && foo->sor.ok()) {
+foo->sor = Make>();
+foo->sor.value();  // [[unsafe]]
+  }
+}
+  )cc");
+
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Foo {
+  absl::StatusOr sor;
+};
+
+void target(absl::StatusOr& foo) {
+  if (foo.ok() && foo->sor.ok()) {
+auto n = Make>();
+if (n.ok()) foo->sor = n;
+foo->sor.value();
+  }
+}
+  )cc");
+
+  ExpectDiagnosticsFor(
+  R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+struct Foo {
+  absl::S

[llvm-branch-commits] [FlowSensitive] [StatusOr] [15/15] Support references to Status(Or)* (PR #170951)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Florian Mayer (fmayer)


Changes

That hopefully concludes the initial upstreaming.


---
Full diff: https://github.com/llvm/llvm-project/pull/170951.diff


2 Files Affected:

- (modified) 
clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp (+65) 
- (modified) 
clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
 (+50) 


``diff
diff --git 
a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp 
b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
index c917c8e8c11ba..f8439d875d8c7 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
@@ -351,6 +351,25 @@ static auto isAssertionResultConstructFromBoolCall() {
   hasArgument(0, hasType(booleanType(;
 }
 
+static auto isStatusOrReturningCall() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return callExpr(
+  callee(functionDecl(returns(possiblyReferencedStatusOrType();
+}
+
+static auto isStatusOrPtrReturningCall() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return callExpr(callee(functionDecl(returns(hasUnqualifiedDesugaredType(
+  pointerType(pointee(possiblyReferencedStatusOrType(;
+}
+
+static auto isStatusPtrReturningCall() {
+  using namespace ::clang::ast_matchers; // NOLINT: Too many names
+  return callExpr(callee(functionDecl(returns(hasUnqualifiedDesugaredType(
+  pointerType(pointee(hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(statusClass()));
+}
+
 static auto
 buildDiagnoseMatchSwitch(const UncheckedStatusOrAccessModelOptions &Options) {
   return CFGMatchSwitchBuildergetSyntheticField("value")));
 }
 
+static void transferStatusOrPtrReturningCall(const CallExpr *Expr,
+ const MatchFinder::MatchResult &,
+ LatticeTransferState &State) {
+  PointerValue *PointerVal =
+  dyn_cast_or_null(State.Env.getValue(*Expr));
+  if (!PointerVal) {
+PointerVal = cast(State.Env.createValue(Expr->getType()));
+State.Env.setValue(*Expr, *PointerVal);
+  }
+
+  auto *RecordLoc =
+  dyn_cast_or_null(&PointerVal->getPointeeLoc());
+  if (RecordLoc != nullptr &&
+  State.Env.getValue(locForOk(locForStatus(*RecordLoc))) == nullptr)
+initializeStatusOr(*RecordLoc, State.Env);
+}
+
+static void transferStatusPtrReturningCall(const CallExpr *Expr,
+   const MatchFinder::MatchResult &,
+   LatticeTransferState &State) {
+  PointerValue *PointerVal =
+  dyn_cast_or_null(State.Env.getValue(*Expr));
+  if (!PointerVal) {
+PointerVal = cast(State.Env.createValue(Expr->getType()));
+State.Env.setValue(*Expr, *PointerVal);
+  }
+
+  auto *RecordLoc =
+  dyn_cast_or_null(&PointerVal->getPointeeLoc());
+  if (RecordLoc != nullptr &&
+  State.Env.getValue(locForOk(*RecordLoc)) == nullptr)
+initializeStatus(*RecordLoc, State.Env);
+}
+
 static RecordStorageLocation *
 getSmartPtrLikeStorageLocation(const Expr &E, const Environment &Env) {
   if (!E.isPRValue())
@@ -1209,6 +1262,18 @@ buildTransferMatchSwitch(ASTContext &Ctx,
 transferNonConstMemberCall)
   .CaseOfCFGStmt(isNonConstMemberOperatorCall(),
   transferNonConstMemberOperatorCall)
+  // N.B. this has to be after transferConstMemberCall, otherwise we would
+  // always return a fresh RecordStorageLocation for the StatusOr.
+  .CaseOfCFGStmt(isStatusOrReturningCall(),
+   [](const CallExpr *Expr,
+  const MatchFinder::MatchResult &,
+  LatticeTransferState &State) {
+ transferStatusOrReturningCall(Expr, State);
+   })
+  .CaseOfCFGStmt(isStatusOrPtrReturningCall(),
+   transferStatusOrPtrReturningCall)
+  .CaseOfCFGStmt(isStatusPtrReturningCall(),
+   transferStatusPtrReturningCall)
   // N.B. These need to come after all other CXXConstructExpr.
   // These are there to make sure that every Status and StatusOr object
   // have their ok boolean initialized when constructed. If we were to
diff --git 
a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
 
b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
index cd7353c62f537..c012d0527870b 100644
--- 
a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
+++ 
b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
@@ -3840,6 +3840,56 @@ TEST

[llvm-branch-commits] [FlowSensitive] [StatusOr] [15/15] Support references to Status(Or)* (PR #170951)

2025-12-05 Thread Florian Mayer via llvm-branch-commits

https://github.com/fmayer created 
https://github.com/llvm/llvm-project/pull/170951

That hopefully concludes the initial upstreaming.



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [FlowSensitive] [StatusOr] [15/N] Support nested StatusOrs (PR #170950)

2025-12-05 Thread Florian Mayer via llvm-branch-commits

https://github.com/fmayer created 
https://github.com/llvm/llvm-project/pull/170950

None


___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [BPF] add allows-misaligned-mem-access target feature (PR #168314)

2025-12-05 Thread Claire Fan via llvm-branch-commits

https://github.com/clairechingching updated 
https://github.com/llvm/llvm-project/pull/168314

>From 812fb70d9be2962b002daaf319a08dc2231d155a Mon Sep 17 00:00:00 2001
From: Claire xyz 
Date: Fri, 7 Nov 2025 11:08:47 -0500
Subject: [PATCH] [BPF] add allows-misaligned-mem-access target feature

This enables misaligned memory access when the feature is enabled
---
 llvm/lib/Target/BPF/BPF.td|   4 +
 llvm/lib/Target/BPF/BPFISelLowering.cpp   |  20 ++
 llvm/lib/Target/BPF/BPFISelLowering.h |   7 +
 llvm/lib/Target/BPF/BPFSubtarget.cpp  |   2 +
 llvm/lib/Target/BPF/BPFSubtarget.h|   6 +
 llvm/test/CodeGen/BPF/unaligned_load_store.ll | 196 ++
 6 files changed, 235 insertions(+)
 create mode 100644 llvm/test/CodeGen/BPF/unaligned_load_store.ll

diff --git a/llvm/lib/Target/BPF/BPF.td b/llvm/lib/Target/BPF/BPF.td
index dff76ca07af51..a7aa6274f5ac1 100644
--- a/llvm/lib/Target/BPF/BPF.td
+++ b/llvm/lib/Target/BPF/BPF.td
@@ -27,6 +27,10 @@ def ALU32 : SubtargetFeature<"alu32", "HasAlu32", "true",
 def DwarfRIS: SubtargetFeature<"dwarfris", "UseDwarfRIS", "true",
"Disable MCAsmInfo 
DwarfUsesRelocationsAcrossSections">;
 
+def MisalignedMemAccess : SubtargetFeature<"allows-misaligned-mem-access",
+   "AllowsMisalignedMemAccess", "true",
+   "Allows misaligned memory access">;
+
 def : Proc<"generic", []>;
 def : Proc<"v1", []>;
 def : Proc<"v2", []>;
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp 
b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index f4f414d192df0..5ec7f5905fd22 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.cpp
+++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp
@@ -196,6 +196,26 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine 
&TM,
   HasJmp32 = STI.getHasJmp32();
   HasJmpExt = STI.getHasJmpExt();
   HasMovsx = STI.hasMovsx();
+
+  AllowsMisalignedMemAccess = STI.getAllowsMisalignedMemAccess();
+}
+
+bool BPFTargetLowering::allowsMisalignedMemoryAccesses(EVT VT, unsigned, Align,
+   
MachineMemOperand::Flags,
+   unsigned *Fast) const {
+  // allows-misaligned-mem-access is disabled
+  if (!AllowsMisalignedMemAccess)
+return false;
+
+  // only allow misalignment for simple value types
+  if (!VT.isSimple())
+return false;
+
+  // always assume fast mode when misalignment is allowed
+  if (Fast)
+*Fast = true;
+
+  return true;
 }
 
 bool BPFTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) 
const {
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.h 
b/llvm/lib/Target/BPF/BPFISelLowering.h
index 8f60261c10e9e..fe01bd5b8cf85 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.h
+++ b/llvm/lib/Target/BPF/BPFISelLowering.h
@@ -46,6 +46,10 @@ class BPFTargetLowering : public TargetLowering {
   // with the given GlobalAddress is legal.
   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
 
+  bool allowsMisalignedMemoryAccesses(EVT VT, unsigned, Align,
+  MachineMemOperand::Flags,
+  unsigned *) const override;
+
   BPFTargetLowering::ConstraintType
   getConstraintType(StringRef Constraint) const override;
 
@@ -73,6 +77,9 @@ class BPFTargetLowering : public TargetLowering {
   bool HasJmpExt;
   bool HasMovsx;
 
+  // Allows Misalignment
+  bool AllowsMisalignedMemAccess;
+
   SDValue LowerSDIVSREM(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.cpp 
b/llvm/lib/Target/BPF/BPFSubtarget.cpp
index 4167547680b12..bd2880d10340e 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.cpp
+++ b/llvm/lib/Target/BPF/BPFSubtarget.cpp
@@ -66,6 +66,8 @@ void BPFSubtarget::initializeEnvironment() {
   HasGotol = false;
   HasStoreImm = false;
   HasLoadAcqStoreRel = false;
+  HasGotox = false;
+  AllowsMisalignedMemAccess = false;
 }
 
 void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.h 
b/llvm/lib/Target/BPF/BPFSubtarget.h
index aed2211265e23..a9a20008733c9 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.h
+++ b/llvm/lib/Target/BPF/BPFSubtarget.h
@@ -63,6 +63,9 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
   // whether we should enable MCAsmInfo DwarfUsesRelocationsAcrossSections
   bool UseDwarfRIS;
 
+  // whether we allows misaligned memory access
+  bool AllowsMisalignedMemAccess;
+
   // whether cpu v4 insns are enabled.
   bool HasLdsx, HasMovsx, HasBswap, HasSdivSmod, HasGotol, HasStoreImm,
   HasLoadAcqStoreRel;
@@ -87,6 +90,9 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
   bool getHasJmp32() const { return HasJmp32; }
   bool getHasAlu32() const { return 

[llvm-branch-commits] [llvm] cff97ac - Merge branch 'main' into revert-141918-fix/indirect-call-instrumentation-snippet

2025-12-05 Thread via llvm-branch-commits

Author: Paschalis Mpeis
Date: 2025-12-05T15:52:34Z
New Revision: cff97ac142aaa6ee33e9e3e8dd1b824bb9880dee

URL: 
https://github.com/llvm/llvm-project/commit/cff97ac142aaa6ee33e9e3e8dd1b824bb9880dee
DIFF: 
https://github.com/llvm/llvm-project/commit/cff97ac142aaa6ee33e9e3e8dd1b824bb9880dee.diff

LOG: Merge branch 'main' into 
revert-141918-fix/indirect-call-instrumentation-snippet

Added: 


Modified: 
llvm/utils/gn/secondary/libcxx/include/BUILD.gn

Removed: 




diff  --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn 
b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
index f4405664d0dad..9755fe3a7ea50 100644
--- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
+++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
@@ -1182,6 +1182,7 @@ if (current_toolchain == default_toolchain) {
   "__locale_dir/support/fuchsia.h",
   "__locale_dir/support/linux.h",
   "__locale_dir/support/netbsd.h",
+  "__locale_dir/support/newlib.h",
   "__locale_dir/support/no_locale/characters.h",
   "__locale_dir/support/no_locale/strtonum.h",
   "__locale_dir/support/windows.h",



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] 58b7140 - [gn build] Port 72402e8b6709

2025-12-05 Thread LLVM GN Syncbot via llvm-branch-commits

Author: LLVM GN Syncbot
Date: 2025-12-05T15:42:33Z
New Revision: 58b71403868ca3dc20d01f0c7e66b8ec5b31a162

URL: 
https://github.com/llvm/llvm-project/commit/58b71403868ca3dc20d01f0c7e66b8ec5b31a162
DIFF: 
https://github.com/llvm/llvm-project/commit/58b71403868ca3dc20d01f0c7e66b8ec5b31a162.diff

LOG: [gn build] Port 72402e8b6709

Added: 


Modified: 
llvm/utils/gn/secondary/libcxx/include/BUILD.gn

Removed: 




diff  --git a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn 
b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
index f4405664d0dad..9755fe3a7ea50 100644
--- a/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
+++ b/llvm/utils/gn/secondary/libcxx/include/BUILD.gn
@@ -1182,6 +1182,7 @@ if (current_toolchain == default_toolchain) {
   "__locale_dir/support/fuchsia.h",
   "__locale_dir/support/linux.h",
   "__locale_dir/support/netbsd.h",
+  "__locale_dir/support/newlib.h",
   "__locale_dir/support/no_locale/characters.h",
   "__locale_dir/support/no_locale/strtonum.h",
   "__locale_dir/support/windows.h",



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [RFC][LLVM][Clang] Add LLVM plugin hook for back-ends (PR #170846)

2025-12-05 Thread Alexis Engelke via llvm-branch-commits

https://github.com/aengelke updated 
https://github.com/llvm/llvm-project/pull/170846

>From 89e9b4a5863e957971a3febc95862c1d5fe43f28 Mon Sep 17 00:00:00 2001
From: Alexis Engelke 
Date: Fri, 5 Dec 2025 12:33:55 +
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
 =?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Created using spr 1.3.5-bogner
---
 clang/lib/CodeGen/BackendUtil.cpp | 33 +++
 llvm/include/llvm/Passes/PassPlugin.h | 31 +
 llvm/lib/Passes/PassPlugin.cpp|  5 
 3 files changed, 49 insertions(+), 20 deletions(-)

diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index 97bc063ad34e5..188ea36d44523 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -144,6 +144,7 @@ class EmitAssemblyHelper {
   const LangOptions &LangOpts;
   llvm::Module *TheModule;
   IntrusiveRefCntPtr VFS;
+  llvm::SmallVector Plugins;
 
   std::unique_ptr OS;
 
@@ -973,16 +974,9 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
 }
 #endif
   }
-  // Attempt to load pass plugins and register their callbacks with PB.
-  for (auto &PluginFN : CodeGenOpts.PassPlugins) {
-auto PassPlugin = PassPlugin::Load(PluginFN);
-if (PassPlugin) {
-  PassPlugin->registerPassBuilderCallbacks(PB);
-} else {
-  Diags.Report(diag::err_fe_unable_to_load_plugin)
-  << PluginFN << toString(PassPlugin.takeError());
-}
-  }
+  // Register plugin callbacks with PB.
+  for (auto &Plugin : Plugins)
+Plugin.registerPassBuilderCallbacks(PB);
   for (const auto &PassCallback : CodeGenOpts.PassBuilderCallbacks)
 PassCallback(PB);
 #define HANDLE_EXTENSION(Ext)  
\
@@ -1211,6 +1205,14 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
 void EmitAssemblyHelper::RunCodegenPipeline(
 BackendAction Action, std::unique_ptr &OS,
 std::unique_ptr &DwoOS) {
+  // Invoke pre-codegen callback from plugin, which might want to take over the
+  // entire code generation itself.
+  for (auto &Plugin : Plugins) {
+CodeGenFileType CGFT = getCodeGenFileType(Action);
+if (Plugin.invokePreCodeGenCallback(*TheModule, *TM, CGFT, *OS))
+  return;
+  }
+
   // We still use the legacy PM to run the codegen pipeline since the new PM
   // does not work with the codegen pipeline.
   // FIXME: make the new PM work with the codegen pipeline.
@@ -1274,6 +1276,17 @@ void EmitAssemblyHelper::emitAssembly(BackendAction 
Action,
   // Before executing passes, print the final values of the LLVM options.
   cl::PrintOptionValues();
 
+  // Attempt to load pass plugins.
+  for (auto &PluginFN : CodeGenOpts.PassPlugins) {
+auto PassPlugin = PassPlugin::Load(PluginFN);
+if (PassPlugin) {
+  Plugins.push_back(std::move(*PassPlugin));
+} else {
+  Diags.Report(diag::err_fe_unable_to_load_plugin)
+  << PluginFN << toString(PassPlugin.takeError());
+}
+  }
+
   std::unique_ptr ThinLinkOS, DwoOS;
   RunOptimizationPipeline(Action, OS, ThinLinkOS, BC);
   RunCodegenPipeline(Action, OS, DwoOS);
diff --git a/llvm/include/llvm/Passes/PassPlugin.h 
b/llvm/include/llvm/Passes/PassPlugin.h
index 947504bc207a7..9ca0b4c29ed96 100644
--- a/llvm/include/llvm/Passes/PassPlugin.h
+++ b/llvm/include/llvm/Passes/PassPlugin.h
@@ -14,6 +14,7 @@
 #define LLVM_PASSES_PASSPLUGIN_H
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CodeGen.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DynamicLibrary.h"
 #include "llvm/Support/Error.h"
@@ -21,7 +22,9 @@
 #include 
 
 namespace llvm {
+class Module;
 class PassBuilder;
+class TargetMachine;
 
 /// \macro LLVM_PLUGIN_API_VERSION
 /// Identifies the API version understood by this plugin.
@@ -30,14 +33,15 @@ class PassBuilder;
 /// against that of the plugin. A mismatch is an error. The supported version
 /// will be incremented for ABI-breaking changes to the \c 
PassPluginLibraryInfo
 /// struct, i.e. when callbacks are added, removed, or reordered.
-#define LLVM_PLUGIN_API_VERSION 1
+#define LLVM_PLUGIN_API_VERSION 2
 
 extern "C" {
 /// Information about the plugin required to load its passes
 ///
 /// This struct defines the core interface for pass plugins and is supposed to
-/// be filled out by plugin implementors. LLVM-side users of a plugin are
-/// expected to use the \c PassPlugin class below to interface with it.
+/// be filled out by plugin implementors. Unused function pointers can be set 
to
+/// nullptr. LLVM-side users of a plugin are expected to use the \c PassPlugin
+/// class below to interface with it.
 struct PassPluginLibraryInfo {
   /// The API version understood by this plugin, usually \c
   /// LLVM_PLUGIN_API_VERSION
@@ -49,7 +53,14 @@ struct PassPluginLibraryInfo {
 
   /// The callback for registering plugin passes with a \c PassBuilder
   /// ins

[llvm-branch-commits] [clang] [llvm] [RFC][LLVM][Clang] Add LLVM plugin hook for back-ends (PR #170846)

2025-12-05 Thread via llvm-branch-commits

github-actions[bot] wrote:

This is a comment for testing the issue write workflow

https://github.com/llvm/llvm-project/pull/170846
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [RFC][LLVM][Clang] Add LLVM plugin hook for back-ends (PR #170846)

2025-12-05 Thread Alexis Engelke via llvm-branch-commits

https://github.com/aengelke edited 
https://github.com/llvm/llvm-project/pull/170846
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [RFC][LLVM][Clang] Add LLVM plugin hook for back-ends (PR #170846)

2025-12-05 Thread Alexis Engelke via llvm-branch-commits

https://github.com/aengelke edited 
https://github.com/llvm/llvm-project/pull/170846
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [RFC][LLVM][Clang] Add LLVM plugin hook for back-ends (PR #170846)

2025-12-05 Thread via llvm-branch-commits

github-actions[bot] wrote:

This is another comment for testing the issue write workflow that was placed in 
a separate file

https://github.com/llvm/llvm-project/pull/170846
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [RFC][LLVM][Clang] Add LLVM plugin hook for back-ends (PR #170846)

2025-12-05 Thread Alexis Engelke via llvm-branch-commits

aengelke wrote:

Added plugin support to llc and test the plugin behavior through that.

https://github.com/llvm/llvm-project/pull/170846
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [RFC][LLVM][Clang] Add LLVM plugin hook for back-ends (PR #170846)

2025-12-05 Thread Eli Friedman via llvm-branch-commits

https://github.com/efriedma-quic commented:

This looks like what I was expecting; the architecture seems fine.

https://github.com/llvm/llvm-project/pull/170846
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Make use of subsetOf and anyCommon methods of BitVector (NFC) (PR #170876)

2025-12-05 Thread Amir Ayupov via llvm-branch-commits

https://github.com/aaupov approved this pull request.


https://github.com/llvm/llvm-project/pull/170876
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [PowerPC] Add support for AMO store builtins (PR #170933)

2025-12-05 Thread Maryam Moghadas via llvm-branch-commits

https://github.com/maryammo created 
https://github.com/llvm/llvm-project/pull/170933

This commit adds 4 Clang builtins for PowerPC AMO store operations:

__builtin_amo_stwat for 32-bit unsigned operations
__builtin_amo_stdat for 64-bit unsigned operations
__builtin_amo_stwat_s for 32-bit signed operations
__builtin_amo_stdat_s for 64-bit signed operations

and maps GCC's AMO store functions to these Clang builtins for compatibility.

>From aa5e8c5224fdf8c42bccbe331e7dfcb096a67606 Mon Sep 17 00:00:00 2001
From: Maryam Moghadas 
Date: Wed, 3 Dec 2025 22:59:57 +
Subject: [PATCH] [PowerPC] Add support for AMO store builtins

---
 clang/include/clang/Basic/BuiltinsPPC.def |   5 +
 clang/lib/CodeGen/TargetBuiltins/PPC.cpp  |  14 +++
 clang/lib/Headers/amo.h   |  89 +++
 clang/lib/Sema/SemaPPC.cpp|  28 +
 clang/test/CodeGen/PowerPC/builtins-amo-err.c |  24 
 clang/test/CodeGen/PowerPC/builtins-ppc-amo.c |  63 ++
 clang/test/CodeGen/PowerPC/ppc-amo-header.c   | 108 ++
 llvm/include/llvm/IR/IntrinsicsPowerPC.td |   9 ++
 llvm/lib/Target/PowerPC/PPCISelLowering.cpp   |  24 
 llvm/lib/Target/PowerPC/PPCInstr64Bit.td  |   2 +-
 llvm/lib/Target/PowerPC/PPCInstrInfo.td   |   2 +-
 llvm/test/CodeGen/PowerPC/amo-enable.ll   |  32 ++
 12 files changed, 398 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/BuiltinsPPC.def 
b/clang/include/clang/Basic/BuiltinsPPC.def
index 7689daf00e6a7..f518429136e3c 100644
--- a/clang/include/clang/Basic/BuiltinsPPC.def
+++ b/clang/include/clang/Basic/BuiltinsPPC.def
@@ -1010,6 +1010,11 @@ TARGET_BUILTIN(__builtin_amo_lwat_cond, "UiUi*Ii", "", 
"isa-v30-instructions")
 TARGET_BUILTIN(__builtin_amo_ldat_cond, "ULiULi*Ii", "", 
"isa-v30-instructions")
 TARGET_BUILTIN(__builtin_amo_lwat_cond_s, "SiSi*Ii", "", 
"isa-v30-instructions")
 TARGET_BUILTIN(__builtin_amo_ldat_cond_s, "SLiSLi*Ii", "", 
"isa-v30-instructions")
+TARGET_BUILTIN(__builtin_amo_stwat, "vUi*UiIi", "", "isa-v30-instructions")
+TARGET_BUILTIN(__builtin_amo_stdat, "vULi*ULiIi", "", "isa-v30-instructions")
+TARGET_BUILTIN(__builtin_amo_stwat_s, "vSi*SiIi", "", "isa-v30-instructions")
+TARGET_BUILTIN(__builtin_amo_stdat_s, "vSLi*SLiIi", "", "isa-v30-instructions")
+
 
 // Set the floating point rounding mode
 BUILTIN(__builtin_setrnd, "di", "")
diff --git a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp 
b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
index bccb6acdb4e06..6568959351a5d 100644
--- a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
@@ -1386,5 +1386,19 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned 
BuiltinID,
 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_ldat_cond),
   {Op0, Op1});
   }
+  case PPC::BI__builtin_amo_stwat_s: {
+Value *Op0 = EmitScalarExpr(E->getArg(0));
+Value *Op1 = EmitScalarExpr(E->getArg(1));
+Value *Op2 = EmitScalarExpr(E->getArg(2));
+return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_stwat),
+  {Op0, Op1, Op2});
+  }
+  case PPC::BI__builtin_amo_stdat_s: {
+Value *Op0 = EmitScalarExpr(E->getArg(0));
+Value *Op1 = EmitScalarExpr(E->getArg(1));
+Value *Op2 = EmitScalarExpr(E->getArg(2));
+return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_stdat),
+  {Op0, Op1, Op2});
+  }
   }
 }
diff --git a/clang/lib/Headers/amo.h b/clang/lib/Headers/amo.h
index 97eff35e9c5dc..c7563f203d1f8 100644
--- a/clang/lib/Headers/amo.h
+++ b/clang/lib/Headers/amo.h
@@ -124,6 +124,95 @@ static inline int64_t amo_ldat_sswap(int64_t *ptr, int64_t 
val) {
   return __builtin_amo_ldat_s(ptr, val, _AMO_LD_SWAP);
 }
 
+/* AMO Store Operation Codes (FC values) */
+enum _AMO_ST {
+  _AMO_ST_ADD = 0x00,  /* Store Add */
+  _AMO_ST_XOR = 0x01,  /* Store Xor */
+  _AMO_ST_IOR = 0x02,  /* Store Ior */
+  _AMO_ST_AND = 0x03,  /* Store And */
+  _AMO_ST_UMAX = 0x04, /* Store Unsigned Maximum */
+  _AMO_ST_SMAX = 0x05, /* Store Signed Maximum */
+  _AMO_ST_UMIN = 0x06, /* Store Unsigned Minimum */
+  _AMO_ST_SMIN = 0x07, /* Store Signed Minimum */
+  _AMO_ST_TWIN = 0x18  /* Store Twin */
+};
+
+/* 32-bit unsigned AMO store operations */
+static inline void amo_stwat_add(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_ADD);
+}
+
+static inline void amo_stwat_xor(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_XOR);
+}
+
+static inline void amo_stwat_ior(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_IOR);
+}
+
+static inline void amo_stwat_and(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_AND);
+}
+
+static inline void amo_stwat_umax(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_UMAX);
+}
+
+static inline void amo_stwat_umin(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(pt

[llvm-branch-commits] [clang] [llvm] [PowerPC] Add support for AMO store builtins (PR #170933)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Maryam Moghadas (maryammo)


Changes

This commit adds 4 Clang builtins for PowerPC AMO store operations:

__builtin_amo_stwat for 32-bit unsigned operations
__builtin_amo_stdat for 64-bit unsigned operations
__builtin_amo_stwat_s for 32-bit signed operations
__builtin_amo_stdat_s for 64-bit signed operations

and maps GCC's AMO store functions to these Clang builtins for compatibility.

---

Patch is 21.21 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/170933.diff


12 Files Affected:

- (modified) clang/include/clang/Basic/BuiltinsPPC.def (+5) 
- (modified) clang/lib/CodeGen/TargetBuiltins/PPC.cpp (+14) 
- (modified) clang/lib/Headers/amo.h (+89) 
- (modified) clang/lib/Sema/SemaPPC.cpp (+28) 
- (modified) clang/test/CodeGen/PowerPC/builtins-amo-err.c (+24) 
- (modified) clang/test/CodeGen/PowerPC/builtins-ppc-amo.c (+63) 
- (modified) clang/test/CodeGen/PowerPC/ppc-amo-header.c (+108) 
- (modified) llvm/include/llvm/IR/IntrinsicsPowerPC.td (+9) 
- (modified) llvm/lib/Target/PowerPC/PPCISelLowering.cpp (+24) 
- (modified) llvm/lib/Target/PowerPC/PPCInstr64Bit.td (+1-1) 
- (modified) llvm/lib/Target/PowerPC/PPCInstrInfo.td (+1-1) 
- (modified) llvm/test/CodeGen/PowerPC/amo-enable.ll (+32) 


``diff
diff --git a/clang/include/clang/Basic/BuiltinsPPC.def 
b/clang/include/clang/Basic/BuiltinsPPC.def
index 7689daf00e6a7..f518429136e3c 100644
--- a/clang/include/clang/Basic/BuiltinsPPC.def
+++ b/clang/include/clang/Basic/BuiltinsPPC.def
@@ -1010,6 +1010,11 @@ TARGET_BUILTIN(__builtin_amo_lwat_cond, "UiUi*Ii", "", 
"isa-v30-instructions")
 TARGET_BUILTIN(__builtin_amo_ldat_cond, "ULiULi*Ii", "", 
"isa-v30-instructions")
 TARGET_BUILTIN(__builtin_amo_lwat_cond_s, "SiSi*Ii", "", 
"isa-v30-instructions")
 TARGET_BUILTIN(__builtin_amo_ldat_cond_s, "SLiSLi*Ii", "", 
"isa-v30-instructions")
+TARGET_BUILTIN(__builtin_amo_stwat, "vUi*UiIi", "", "isa-v30-instructions")
+TARGET_BUILTIN(__builtin_amo_stdat, "vULi*ULiIi", "", "isa-v30-instructions")
+TARGET_BUILTIN(__builtin_amo_stwat_s, "vSi*SiIi", "", "isa-v30-instructions")
+TARGET_BUILTIN(__builtin_amo_stdat_s, "vSLi*SLiIi", "", "isa-v30-instructions")
+
 
 // Set the floating point rounding mode
 BUILTIN(__builtin_setrnd, "di", "")
diff --git a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp 
b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
index bccb6acdb4e06..6568959351a5d 100644
--- a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
@@ -1386,5 +1386,19 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned 
BuiltinID,
 return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_ldat_cond),
   {Op0, Op1});
   }
+  case PPC::BI__builtin_amo_stwat_s: {
+Value *Op0 = EmitScalarExpr(E->getArg(0));
+Value *Op1 = EmitScalarExpr(E->getArg(1));
+Value *Op2 = EmitScalarExpr(E->getArg(2));
+return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_stwat),
+  {Op0, Op1, Op2});
+  }
+  case PPC::BI__builtin_amo_stdat_s: {
+Value *Op0 = EmitScalarExpr(E->getArg(0));
+Value *Op1 = EmitScalarExpr(E->getArg(1));
+Value *Op2 = EmitScalarExpr(E->getArg(2));
+return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_stdat),
+  {Op0, Op1, Op2});
+  }
   }
 }
diff --git a/clang/lib/Headers/amo.h b/clang/lib/Headers/amo.h
index 97eff35e9c5dc..c7563f203d1f8 100644
--- a/clang/lib/Headers/amo.h
+++ b/clang/lib/Headers/amo.h
@@ -124,6 +124,95 @@ static inline int64_t amo_ldat_sswap(int64_t *ptr, int64_t 
val) {
   return __builtin_amo_ldat_s(ptr, val, _AMO_LD_SWAP);
 }
 
+/* AMO Store Operation Codes (FC values) */
+enum _AMO_ST {
+  _AMO_ST_ADD = 0x00,  /* Store Add */
+  _AMO_ST_XOR = 0x01,  /* Store Xor */
+  _AMO_ST_IOR = 0x02,  /* Store Ior */
+  _AMO_ST_AND = 0x03,  /* Store And */
+  _AMO_ST_UMAX = 0x04, /* Store Unsigned Maximum */
+  _AMO_ST_SMAX = 0x05, /* Store Signed Maximum */
+  _AMO_ST_UMIN = 0x06, /* Store Unsigned Minimum */
+  _AMO_ST_SMIN = 0x07, /* Store Signed Minimum */
+  _AMO_ST_TWIN = 0x18  /* Store Twin */
+};
+
+/* 32-bit unsigned AMO store operations */
+static inline void amo_stwat_add(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_ADD);
+}
+
+static inline void amo_stwat_xor(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_XOR);
+}
+
+static inline void amo_stwat_ior(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_IOR);
+}
+
+static inline void amo_stwat_and(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_AND);
+}
+
+static inline void amo_stwat_umax(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_UMAX);
+}
+
+static inline void amo_stwat_umin(uint32_t *ptr, uint32_t val) {
+  __builtin_amo_stwat(ptr, val, _AMO_ST_UMIN);
+}
+
+/* 32-bit signed AMO store operations */
+static inline v

[llvm-branch-commits] [llvm] DAG: Use RuntimeLibcalls to legalize vector frem calls (PR #170719)

2025-12-05 Thread Matt Arsenault via llvm-branch-commits

https://github.com/arsenm updated 
https://github.com/llvm/llvm-project/pull/170719

>From fd85d171a5c7db883e848e001243d95f4192aca9 Mon Sep 17 00:00:00 2001
From: Matt Arsenault 
Date: Thu, 4 Dec 2025 14:28:55 +0100
Subject: [PATCH] DAG: Use RuntimeLibcalls to legalize vector frem calls

This continues the replacement of TargetLibraryInfo uses in codegen
with RuntimeLibcallsInfo started in 821d2825a4f782da3da3c03b8a002802bff4b95c.
The series there handled all of the multiple result calls. This
extends for the other handled case, which happened to be frem.

For some reason the Libcall for these are prefixed with "REM_", for
the instruction "frem", which maps to the libcall "fmod".
---
 .../include/llvm/CodeGen/RuntimeLibcallUtil.h |   4 +
 llvm/include/llvm/IR/RuntimeLibcalls.td   |  22 ++--
 .../SelectionDAG/LegalizeVectorOps.cpp| 114 ++
 llvm/lib/CodeGen/TargetLoweringBase.cpp   |  22 
 llvm/lib/IR/RuntimeLibcalls.cpp   |  53 +++-
 .../Util/DeclareRuntimeLibcalls/armpl.ll  |  35 --
 .../Util/DeclareRuntimeLibcalls/sleef.ll  |  36 --
 7 files changed, 166 insertions(+), 120 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h 
b/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h
index dda0899f11337..cc71c3206410a 100644
--- a/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h
+++ b/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h
@@ -132,6 +132,10 @@ LLVM_ABI Libcall getSINCOS_STRET(EVT RetVT);
 /// UNKNOWN_LIBCALL if there is none.
 LLVM_ABI Libcall getMODF(EVT VT);
 
+/// \return the REM_* value for the given types, or UNKNOWN_LIBCALL if there is
+/// none.
+LLVM_ABI Libcall getREM(EVT VT);
+
 /// \return the LROUND_* value for the given types, or UNKNOWN_LIBCALL if there
 /// is none.
 LLVM_ABI Libcall getLROUND(EVT VT);
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td 
b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 2d7ebc30e6097..2e6ef4abb3d01 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -227,7 +227,7 @@ foreach S = !listconcat(F32VectorSuffixes, 
F64VectorSuffixes) in {
   def FMA_#S : RuntimeLibcall;
   def FMAX_#S : RuntimeLibcall;
   def FMIN_#S : RuntimeLibcall;
-  def FMOD_#S : RuntimeLibcall;
+  def REM_#S : RuntimeLibcall; // "fmod"
   def HYPOT_#S : RuntimeLibcall;
   def ILOGB_#S : RuntimeLibcall;
   def LDEXP_#S : RuntimeLibcall;
@@ -3919,7 +3919,7 @@ defset list SLEEFGNUABI_VF2_VECFUNCS 
= {
   def _ZGVnN2vv_fdim : RuntimeLibcallImpl;
   def _ZGVnN2vv_fmax : RuntimeLibcallImpl;
   def _ZGVnN2vv_fmin : RuntimeLibcallImpl;
-  def _ZGVnN2vv_fmod : RuntimeLibcallImpl;
+  def _ZGVnN2vv_fmod : RuntimeLibcallImpl;
   def _ZGVnN2vv_hypot : RuntimeLibcallImpl;
   def _ZGVnN2vv_ldexp : RuntimeLibcallImpl;
   def _ZGVnN2vv_nextafter : RuntimeLibcallImpl;
@@ -3965,7 +3965,7 @@ defset list SLEEFGNUABI_VF4_VECFUNCS 
= {
   def _ZGVnN4vv_fdimf : RuntimeLibcallImpl;
   def _ZGVnN4vv_fmaxf : RuntimeLibcallImpl;
   def _ZGVnN4vv_fminf : RuntimeLibcallImpl;
-  def _ZGVnN4vv_fmodf : RuntimeLibcallImpl;
+  def _ZGVnN4vv_fmodf : RuntimeLibcallImpl;
   def _ZGVnN4vv_hypotf : RuntimeLibcallImpl;
   def _ZGVnN4vv_ldexpf : RuntimeLibcallImpl;
   def _ZGVnN4vv_nextafterf : RuntimeLibcallImpl;
@@ -4042,8 +4042,8 @@ defset list 
SLEEFGNUABI_SCALABLE_VECFUNCS = {
   def _ZGVsMxvv_fmaxf : RuntimeLibcallImpl;
   def _ZGVsMxvv_fmin : RuntimeLibcallImpl;
   def _ZGVsMxvv_fminf : RuntimeLibcallImpl;
-  def _ZGVsMxvv_fmod : RuntimeLibcallImpl;
-  def _ZGVsMxvv_fmodf : RuntimeLibcallImpl;
+  def _ZGVsMxvv_fmod : RuntimeLibcallImpl;
+  def _ZGVsMxvv_fmodf : RuntimeLibcallImpl;
   def _ZGVsMxvv_hypot : RuntimeLibcallImpl;
   def _ZGVsMxvv_hypotf : RuntimeLibcallImpl;
   def _ZGVsMxvv_ldexp : RuntimeLibcallImpl;
@@ -4107,8 +4107,8 @@ defset list 
SLEEFGNUABI_SCALABLE_VECFUNCS_RISCV = {
   def Sleef_fmaxfx_rvvm2 : RuntimeLibcallImpl;
   def Sleef_fmindx_u10rvvm2 : RuntimeLibcallImpl;
   def Sleef_fminfx_u10rvvm2 : RuntimeLibcallImpl;
-  def Sleef_fmoddx_rvvm2 : RuntimeLibcallImpl;
-  def Sleef_fmodfx_rvvm2 : RuntimeLibcallImpl;
+  def Sleef_fmoddx_rvvm2 : RuntimeLibcallImpl;
+  def Sleef_fmodfx_rvvm2 : RuntimeLibcallImpl;
   def Sleef_hypotdx_u05rvvm2 : RuntimeLibcallImpl;
   def Sleef_hypotfx_u05rvvm2 : RuntimeLibcallImpl;
   def Sleef_ilogbdx_rvvm2 : RuntimeLibcallImpl;
@@ -4200,8 +4200,8 @@ defset list ARMPL_VECFUNCS = {
   def armpl_svfmax_f64_x : RuntimeLibcallImpl;
   def armpl_svfmin_f32_x : RuntimeLibcallImpl;
   def armpl_svfmin_f64_x : RuntimeLibcallImpl;
-  def armpl_svfmod_f32_x : RuntimeLibcallImpl;
-  def armpl_svfmod_f64_x : RuntimeLibcallImpl;
+  def armpl_svfmod_f32_x : RuntimeLibcallImpl;
+  def armpl_svfmod_f64_x : RuntimeLibcallImpl;
   def armpl_svhypot_f32_x : RuntimeLibcallImpl;
   def armpl_svhypot_f64_x : RuntimeLibcallImpl;
   def armpl_svilogb_f32_x : RuntimeLibcallImpl;
@@ -4286,8 +4286,8 @@ defset list ARMPL_VECFUNCS = {
   def armpl_vfmaxq_f64 : RuntimeLibcallIm

[llvm-branch-commits] [llvm] DAG: Use RuntimeLibcalls to legalize vector frem calls (PR #170719)

2025-12-05 Thread Matt Arsenault via llvm-branch-commits

https://github.com/arsenm updated 
https://github.com/llvm/llvm-project/pull/170719

>From fd85d171a5c7db883e848e001243d95f4192aca9 Mon Sep 17 00:00:00 2001
From: Matt Arsenault 
Date: Thu, 4 Dec 2025 14:28:55 +0100
Subject: [PATCH] DAG: Use RuntimeLibcalls to legalize vector frem calls

This continues the replacement of TargetLibraryInfo uses in codegen
with RuntimeLibcallsInfo started in 821d2825a4f782da3da3c03b8a002802bff4b95c.
The series there handled all of the multiple result calls. This
extends for the other handled case, which happened to be frem.

For some reason the Libcall for these are prefixed with "REM_", for
the instruction "frem", which maps to the libcall "fmod".
---
 .../include/llvm/CodeGen/RuntimeLibcallUtil.h |   4 +
 llvm/include/llvm/IR/RuntimeLibcalls.td   |  22 ++--
 .../SelectionDAG/LegalizeVectorOps.cpp| 114 ++
 llvm/lib/CodeGen/TargetLoweringBase.cpp   |  22 
 llvm/lib/IR/RuntimeLibcalls.cpp   |  53 +++-
 .../Util/DeclareRuntimeLibcalls/armpl.ll  |  35 --
 .../Util/DeclareRuntimeLibcalls/sleef.ll  |  36 --
 7 files changed, 166 insertions(+), 120 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h 
b/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h
index dda0899f11337..cc71c3206410a 100644
--- a/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h
+++ b/llvm/include/llvm/CodeGen/RuntimeLibcallUtil.h
@@ -132,6 +132,10 @@ LLVM_ABI Libcall getSINCOS_STRET(EVT RetVT);
 /// UNKNOWN_LIBCALL if there is none.
 LLVM_ABI Libcall getMODF(EVT VT);
 
+/// \return the REM_* value for the given types, or UNKNOWN_LIBCALL if there is
+/// none.
+LLVM_ABI Libcall getREM(EVT VT);
+
 /// \return the LROUND_* value for the given types, or UNKNOWN_LIBCALL if there
 /// is none.
 LLVM_ABI Libcall getLROUND(EVT VT);
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td 
b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 2d7ebc30e6097..2e6ef4abb3d01 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -227,7 +227,7 @@ foreach S = !listconcat(F32VectorSuffixes, 
F64VectorSuffixes) in {
   def FMA_#S : RuntimeLibcall;
   def FMAX_#S : RuntimeLibcall;
   def FMIN_#S : RuntimeLibcall;
-  def FMOD_#S : RuntimeLibcall;
+  def REM_#S : RuntimeLibcall; // "fmod"
   def HYPOT_#S : RuntimeLibcall;
   def ILOGB_#S : RuntimeLibcall;
   def LDEXP_#S : RuntimeLibcall;
@@ -3919,7 +3919,7 @@ defset list SLEEFGNUABI_VF2_VECFUNCS 
= {
   def _ZGVnN2vv_fdim : RuntimeLibcallImpl;
   def _ZGVnN2vv_fmax : RuntimeLibcallImpl;
   def _ZGVnN2vv_fmin : RuntimeLibcallImpl;
-  def _ZGVnN2vv_fmod : RuntimeLibcallImpl;
+  def _ZGVnN2vv_fmod : RuntimeLibcallImpl;
   def _ZGVnN2vv_hypot : RuntimeLibcallImpl;
   def _ZGVnN2vv_ldexp : RuntimeLibcallImpl;
   def _ZGVnN2vv_nextafter : RuntimeLibcallImpl;
@@ -3965,7 +3965,7 @@ defset list SLEEFGNUABI_VF4_VECFUNCS 
= {
   def _ZGVnN4vv_fdimf : RuntimeLibcallImpl;
   def _ZGVnN4vv_fmaxf : RuntimeLibcallImpl;
   def _ZGVnN4vv_fminf : RuntimeLibcallImpl;
-  def _ZGVnN4vv_fmodf : RuntimeLibcallImpl;
+  def _ZGVnN4vv_fmodf : RuntimeLibcallImpl;
   def _ZGVnN4vv_hypotf : RuntimeLibcallImpl;
   def _ZGVnN4vv_ldexpf : RuntimeLibcallImpl;
   def _ZGVnN4vv_nextafterf : RuntimeLibcallImpl;
@@ -4042,8 +4042,8 @@ defset list 
SLEEFGNUABI_SCALABLE_VECFUNCS = {
   def _ZGVsMxvv_fmaxf : RuntimeLibcallImpl;
   def _ZGVsMxvv_fmin : RuntimeLibcallImpl;
   def _ZGVsMxvv_fminf : RuntimeLibcallImpl;
-  def _ZGVsMxvv_fmod : RuntimeLibcallImpl;
-  def _ZGVsMxvv_fmodf : RuntimeLibcallImpl;
+  def _ZGVsMxvv_fmod : RuntimeLibcallImpl;
+  def _ZGVsMxvv_fmodf : RuntimeLibcallImpl;
   def _ZGVsMxvv_hypot : RuntimeLibcallImpl;
   def _ZGVsMxvv_hypotf : RuntimeLibcallImpl;
   def _ZGVsMxvv_ldexp : RuntimeLibcallImpl;
@@ -4107,8 +4107,8 @@ defset list 
SLEEFGNUABI_SCALABLE_VECFUNCS_RISCV = {
   def Sleef_fmaxfx_rvvm2 : RuntimeLibcallImpl;
   def Sleef_fmindx_u10rvvm2 : RuntimeLibcallImpl;
   def Sleef_fminfx_u10rvvm2 : RuntimeLibcallImpl;
-  def Sleef_fmoddx_rvvm2 : RuntimeLibcallImpl;
-  def Sleef_fmodfx_rvvm2 : RuntimeLibcallImpl;
+  def Sleef_fmoddx_rvvm2 : RuntimeLibcallImpl;
+  def Sleef_fmodfx_rvvm2 : RuntimeLibcallImpl;
   def Sleef_hypotdx_u05rvvm2 : RuntimeLibcallImpl;
   def Sleef_hypotfx_u05rvvm2 : RuntimeLibcallImpl;
   def Sleef_ilogbdx_rvvm2 : RuntimeLibcallImpl;
@@ -4200,8 +4200,8 @@ defset list ARMPL_VECFUNCS = {
   def armpl_svfmax_f64_x : RuntimeLibcallImpl;
   def armpl_svfmin_f32_x : RuntimeLibcallImpl;
   def armpl_svfmin_f64_x : RuntimeLibcallImpl;
-  def armpl_svfmod_f32_x : RuntimeLibcallImpl;
-  def armpl_svfmod_f64_x : RuntimeLibcallImpl;
+  def armpl_svfmod_f32_x : RuntimeLibcallImpl;
+  def armpl_svfmod_f64_x : RuntimeLibcallImpl;
   def armpl_svhypot_f32_x : RuntimeLibcallImpl;
   def armpl_svhypot_f64_x : RuntimeLibcallImpl;
   def armpl_svilogb_f32_x : RuntimeLibcallImpl;
@@ -4286,8 +4286,8 @@ defset list ARMPL_VECFUNCS = {
   def armpl_vfmaxq_f64 : RuntimeLibcallIm

[llvm-branch-commits] [libcxx] Prepare libcxx and libcxxabi for pointer field protection. (PR #151651)

2025-12-05 Thread Peter Collingbourne via llvm-branch-commits


@@ -300,7 +300,7 @@ class _LIBCPP_EXPORTED_FROM_ABI 
_LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info
 protected:
   typedef __type_info_implementations::__impl __impl;
 
-  __impl::__type_name_t __type_name;
+  _LIBCPP_NO_PFP __impl::__type_name_t __type_name;

pcc wrote:

> Whether there is a "real benefit" is subjective, though. Not having to think 
> about PFP in libc++abi is a very real (and valuable) benefit from my 
> perspective (but perhaps not from someone else's perspective).

Sure, but it seems like a relatively small benefit. It lets us save changing 4 
lines of code in libc++ and libc++abi which seem to need very little 
maintenance (because they reflect ABI). According to `git blame` these lines 
were last changed in libc++abi 10 years ago, and in libc++ 6 years ago ignoring 
a formatting change. Whereas on the Clang side I think we would need somewhere 
around 100 lines of code to generate initializers for these fields, which will 
need to be maintained as Clang's API develops (and will need to be 
reimplemented in CIR, etc). Generating these initializers will need a separate 
code path because these RTTI types are not defined in the Clang AST like other 
types are.

> Can you explain why that's the case? Where/why is the name of the field 
> relevant when PFP is enabled? That's probably obvious when you know PFP but 
> I'm not seeing it.

That's because the field names are encoded into names of deactivation symbols 
(https://discourse.llvm.org/t/rfc-deactivation-symbols/85556) as well as being 
hashed into the discriminator used to sign pointers. In principle, we could 
encode field offsets instead of names, but I've frequently found the explicit 
names useful for debugging.

> IIUC, you are implying that right now, we could link both a PFP libc++ and a 
> non-PFP libc++ into the same program without issues because they use a 
> different inline namespace, and libc++abi.dylib doesn't have an inline 
> namespace. So IIUC what you're saying is that you could use pfp-libc++.dylib, 
> nonpfp-libc++.dylib and libc++abi.dylib (which would be PFP-agnostic) into 
> the same program. Is that the idea? My first reaction to this is that it 
> seems like a very fragile setup.

Yes, that's pretty much it (except that PFP doesn't support dynamic linking, so 
it would be .a instead of .dylib). As I mentioned earlier, we have no need for 
this. But maybe if we can avoid obvious breakage to this setup, that may be 
worthwhile in case someone needs it in the future (at which point it may be too 
late to fix it because the ABI will be set in stone).

https://github.com/llvm/llvm-project/pull/151651
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [libcxx] Prepare libcxx and libcxxabi for pointer field protection. (PR #151651)

2025-12-05 Thread Peter Collingbourne via llvm-branch-commits


@@ -34,10 +34,13 @@ template 
 struct __libcpp_is_trivially_relocatable : is_trivially_copyable<_Tp> {};
 #endif
 
+// __trivially_relocatable on libc++'s builtin types does not currently return 
the right answer with PFP.

pcc wrote:

The property is that the type must satisfy both of the following:
- contains a field of pointer type, either in the type itself or in one of its 
fields or bases
- the type containing the pointer field is not trivially copyable

Given that many of the affected types are containers, the trivial 
relocatability property will in some cases depend on a template argument. In 
other cases, the type is unconditionally non-trivially relocatable due to a 
pointer field.

In principle, we would be able to robustly detect this property via a type 
trait, and in an earlier version of the Clang patch I introduced such a trait: 
https://github.com/pcc/llvm-project/commit/ad5ee79d12f775c8d2478349ce4ae593d9f687be

But in #133538 @ojhunt reasonably asked for this to be removed for the initial 
version of the patch. We can revisit this as an optimization once trivial 
relocatability is added to the standard. Given that trivial relocatability will 
not be making it into C++26, I think this should not be a priority for now.

https://github.com/llvm/llvm-project/pull/151651
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [NFC] [FlowSensitive] Fix missing namespace in MockHeaders (PR #170954)

2025-12-05 Thread Florian Mayer via llvm-branch-commits

https://github.com/fmayer created 
https://github.com/llvm/llvm-project/pull/170954

This happened to work because we were missing both a namespace close and
open and things happened to be included in the correct order.



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [NFC] [FlowSensitive] Fix missing namespace in MockHeaders (PR #170954)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Florian Mayer (fmayer)


Changes

This happened to work because we were missing both a namespace close and
open and things happened to be included in the correct order.


---
Full diff: https://github.com/llvm/llvm-project/pull/170954.diff


1 Files Affected:

- (modified) clang/unittests/Analysis/FlowSensitive/MockHeaders.cpp (+4) 


``diff
diff --git a/clang/unittests/Analysis/FlowSensitive/MockHeaders.cpp 
b/clang/unittests/Analysis/FlowSensitive/MockHeaders.cpp
index 76c7310e16a4f..8ea2015da08df 100644
--- a/clang/unittests/Analysis/FlowSensitive/MockHeaders.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/MockHeaders.cpp
@@ -1358,6 +1358,8 @@ bool operator!=(const Status &lhs, const Status &rhs);
 Status OkStatus();
 Status InvalidArgumentError(const char *);
 
+}  // namespace absl
+
 #endif // STATUS_H
 )cc";
 
@@ -1370,6 +1372,8 @@ constexpr const char StatusOrDefsHeader[] = R"cc(
 #include "std_type_traits.h"
 #include "std_utility.h"
 
+namespace absl {
+
 template  struct StatusOr;
 
 namespace internal_statusor {

``




https://github.com/llvm/llvm-project/pull/170954
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] Reland "AMDGPU/PromoteAlloca: Always use i32 for indexing (#170511)" (PR #170956)

2025-12-05 Thread Nicolai Hähnle via llvm-branch-commits

https://github.com/nhaehnle created 
https://github.com/llvm/llvm-project/pull/170956

Create more canonical code that may even lead to slightly better
codegen.

---

**Stack**:
- [2/2] #170956 ⬅
- [1/2] #170955


⚠️ *Part of a stack created by [spr](https://github.com/nhaehnle/spr). Merging 
this PR using the GitHub UI may have unexpected results.*

From 06702f06ad96dca8e129574e0bb148dd7238c1b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolai=20H=C3=A4hnle?= 
Date: Fri, 5 Dec 2025 12:54:57 -0800
Subject: [PATCH] Reland "AMDGPU/PromoteAlloca: Always use i32 for indexing
 (#170511)"

Create more canonical code that may even lead to slightly better
codegen.

commit-id:a3832fee
---
 .../lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp | 13 +
 .../CodeGen/AMDGPU/promote-alloca-multidim.ll | 28 ++-
 .../AMDGPU/promote-alloca-negative-index.ll   | 12 +---
 .../AMDGPU/promote-alloca-vector-to-vector.ll |  2 +-
 4 files changed, 31 insertions(+), 24 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp 
b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
index d8e8c8f024518..b79689c39ef84 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -461,13 +461,15 @@ static Value *GEPToVectorIndex(GetElementPtrInst *GEP, 
AllocaInst *Alloca,
 return nullptr;
 
   Value *Offset = VarOffset.first;
-  auto *OffsetType = dyn_cast(Offset->getType());
-  if (!OffsetType)
+  if (!isa(Offset->getType()))
 return nullptr;
 
+  Offset = Builder.CreateSExtOrTrunc(Offset, Builder.getIntNTy(BW));
+  if (Offset != VarOffset.first)
+NewInsts.push_back(cast(Offset));
+
   if (!OffsetQuot.isOne()) {
-ConstantInt *ConstMul =
-ConstantInt::get(Ctx, OffsetQuot.sext(OffsetType->getBitWidth()));
+ConstantInt *ConstMul = ConstantInt::get(Ctx, OffsetQuot.sextOrTrunc(BW));
 Offset = Builder.CreateMul(Offset, ConstMul);
 if (Instruction *NewInst = dyn_cast(Offset))
   NewInsts.push_back(NewInst);
@@ -475,8 +477,7 @@ static Value *GEPToVectorIndex(GetElementPtrInst *GEP, 
AllocaInst *Alloca,
   if (ConstOffset.isZero())
 return Offset;
 
-  ConstantInt *ConstIndex =
-  ConstantInt::get(Ctx, IndexQuot.sext(OffsetType->getBitWidth()));
+  ConstantInt *ConstIndex = ConstantInt::get(Ctx, IndexQuot.sextOrTrunc(BW));
   Value *IndexAdd = Builder.CreateAdd(Offset, ConstIndex);
   if (Instruction *NewInst = dyn_cast(IndexAdd))
 NewInsts.push_back(NewInst);
diff --git a/llvm/test/CodeGen/AMDGPU/promote-alloca-multidim.ll 
b/llvm/test/CodeGen/AMDGPU/promote-alloca-multidim.ll
index 63622e67e7d0b..7b64d8728cc24 100644
--- a/llvm/test/CodeGen/AMDGPU/promote-alloca-multidim.ll
+++ b/llvm/test/CodeGen/AMDGPU/promote-alloca-multidim.ll
@@ -262,14 +262,15 @@ define amdgpu_kernel void 
@i64_2d_load_store_subvec_3_i64_offset(ptr %out) {
 ; CHECK-NEXT:[[TMP13:%.*]] = insertelement <6 x i64> [[TMP12]], i64 3, i32 
3
 ; CHECK-NEXT:[[TMP14:%.*]] = insertelement <6 x i64> [[TMP13]], i64 4, i32 
4
 ; CHECK-NEXT:[[TMP15:%.*]] = insertelement <6 x i64> [[TMP14]], i64 5, i32 
5
-; CHECK-NEXT:[[TMP1:%.*]] = mul i64 [[SEL3]], 3
-; CHECK-NEXT:[[TMP2:%.*]] = extractelement <6 x i64> [[TMP15]], i64 
[[TMP1]]
+; CHECK-NEXT:[[TMP7:%.*]] = trunc i64 [[SEL3]] to i32
+; CHECK-NEXT:[[TMP16:%.*]] = mul i32 [[TMP7]], 3
+; CHECK-NEXT:[[TMP2:%.*]] = extractelement <6 x i64> [[TMP15]], i32 
[[TMP16]]
 ; CHECK-NEXT:[[TMP3:%.*]] = insertelement <3 x i64> poison, i64 [[TMP2]], 
i64 0
-; CHECK-NEXT:[[TMP4:%.*]] = add i64 [[TMP1]], 1
-; CHECK-NEXT:[[TMP5:%.*]] = extractelement <6 x i64> [[TMP15]], i64 
[[TMP4]]
+; CHECK-NEXT:[[TMP17:%.*]] = add i32 [[TMP16]], 1
+; CHECK-NEXT:[[TMP5:%.*]] = extractelement <6 x i64> [[TMP15]], i32 
[[TMP17]]
 ; CHECK-NEXT:[[TMP6:%.*]] = insertelement <3 x i64> [[TMP3]], i64 
[[TMP5]], i64 1
-; CHECK-NEXT:[[TMP7:%.*]] = add i64 [[TMP1]], 2
-; CHECK-NEXT:[[TMP8:%.*]] = extractelement <6 x i64> [[TMP15]], i64 
[[TMP7]]
+; CHECK-NEXT:[[TMP18:%.*]] = add i32 [[TMP16]], 2
+; CHECK-NEXT:[[TMP8:%.*]] = extractelement <6 x i64> [[TMP15]], i32 
[[TMP18]]
 ; CHECK-NEXT:[[TMP9:%.*]] = insertelement <3 x i64> [[TMP6]], i64 
[[TMP8]], i64 2
 ; CHECK-NEXT:[[ELEM:%.*]] = extractelement <3 x i64> [[TMP9]], i32 2
 ; CHECK-NEXT:store i64 [[ELEM]], ptr [[OUT]], align 8
@@ -311,15 +312,16 @@ define amdgpu_kernel void 
@i64_2d_load_store_subvec_3_i64_offset_index(ptr %out)
 ; CHECK-NEXT:[[TMP14:%.*]] = insertelement <6 x i64> [[TMP13]], i64 3, i32 
3
 ; CHECK-NEXT:[[TMP15:%.*]] = insertelement <6 x i64> [[TMP14]], i64 4, i32 
4
 ; CHECK-NEXT:[[TMP16:%.*]] = insertelement <6 x i64> [[TMP15]], i64 5, i32 
5
-; CHECK-NEXT:[[TMP1:%.*]] = mul i64 [[SEL3]], 3
-; CHECK-NEXT:[[TMP2:%.*]] = add i64 [[TMP1]], 6
-; CHECK-NEXT:[[TMP3:%.*]] = extractelement <6 x i64> [[TMP16]], i64 
[[TMP2]]
+; CHECK-NEXT:[[TMP17:%.*]] = trunc i64 [[SEL3

[llvm-branch-commits] [llvm] Reland "AMDGPU/PromoteAlloca: Always use i32 for indexing (#170511)" (PR #170956)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-backend-amdgpu

Author: Nicolai Hähnle (nhaehnle)


Changes

Create more canonical code that may even lead to slightly better
codegen.

---

**Stack**:
- [2/2] #170956 ⬅
- [1/2] #170955


⚠️ *Part of a stack created by [spr](https://github.com/nhaehnle/spr). Merging 
this PR using the GitHub UI may have unexpected results.*

---
Full diff: https://github.com/llvm/llvm-project/pull/170956.diff


4 Files Affected:

- (modified) llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp (+7-6) 
- (modified) llvm/test/CodeGen/AMDGPU/promote-alloca-multidim.ll (+15-13) 
- (modified) llvm/test/CodeGen/AMDGPU/promote-alloca-negative-index.ll (+8-4) 
- (modified) llvm/test/CodeGen/AMDGPU/promote-alloca-vector-to-vector.ll (+1-1) 


``diff
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp 
b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
index d8e8c8f024518..b79689c39ef84 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp
@@ -461,13 +461,15 @@ static Value *GEPToVectorIndex(GetElementPtrInst *GEP, 
AllocaInst *Alloca,
 return nullptr;
 
   Value *Offset = VarOffset.first;
-  auto *OffsetType = dyn_cast(Offset->getType());
-  if (!OffsetType)
+  if (!isa(Offset->getType()))
 return nullptr;
 
+  Offset = Builder.CreateSExtOrTrunc(Offset, Builder.getIntNTy(BW));
+  if (Offset != VarOffset.first)
+NewInsts.push_back(cast(Offset));
+
   if (!OffsetQuot.isOne()) {
-ConstantInt *ConstMul =
-ConstantInt::get(Ctx, OffsetQuot.sext(OffsetType->getBitWidth()));
+ConstantInt *ConstMul = ConstantInt::get(Ctx, OffsetQuot.sextOrTrunc(BW));
 Offset = Builder.CreateMul(Offset, ConstMul);
 if (Instruction *NewInst = dyn_cast(Offset))
   NewInsts.push_back(NewInst);
@@ -475,8 +477,7 @@ static Value *GEPToVectorIndex(GetElementPtrInst *GEP, 
AllocaInst *Alloca,
   if (ConstOffset.isZero())
 return Offset;
 
-  ConstantInt *ConstIndex =
-  ConstantInt::get(Ctx, IndexQuot.sext(OffsetType->getBitWidth()));
+  ConstantInt *ConstIndex = ConstantInt::get(Ctx, IndexQuot.sextOrTrunc(BW));
   Value *IndexAdd = Builder.CreateAdd(Offset, ConstIndex);
   if (Instruction *NewInst = dyn_cast(IndexAdd))
 NewInsts.push_back(NewInst);
diff --git a/llvm/test/CodeGen/AMDGPU/promote-alloca-multidim.ll 
b/llvm/test/CodeGen/AMDGPU/promote-alloca-multidim.ll
index 63622e67e7d0b..7b64d8728cc24 100644
--- a/llvm/test/CodeGen/AMDGPU/promote-alloca-multidim.ll
+++ b/llvm/test/CodeGen/AMDGPU/promote-alloca-multidim.ll
@@ -262,14 +262,15 @@ define amdgpu_kernel void 
@i64_2d_load_store_subvec_3_i64_offset(ptr %out) {
 ; CHECK-NEXT:[[TMP13:%.*]] = insertelement <6 x i64> [[TMP12]], i64 3, i32 
3
 ; CHECK-NEXT:[[TMP14:%.*]] = insertelement <6 x i64> [[TMP13]], i64 4, i32 
4
 ; CHECK-NEXT:[[TMP15:%.*]] = insertelement <6 x i64> [[TMP14]], i64 5, i32 
5
-; CHECK-NEXT:[[TMP1:%.*]] = mul i64 [[SEL3]], 3
-; CHECK-NEXT:[[TMP2:%.*]] = extractelement <6 x i64> [[TMP15]], i64 
[[TMP1]]
+; CHECK-NEXT:[[TMP7:%.*]] = trunc i64 [[SEL3]] to i32
+; CHECK-NEXT:[[TMP16:%.*]] = mul i32 [[TMP7]], 3
+; CHECK-NEXT:[[TMP2:%.*]] = extractelement <6 x i64> [[TMP15]], i32 
[[TMP16]]
 ; CHECK-NEXT:[[TMP3:%.*]] = insertelement <3 x i64> poison, i64 [[TMP2]], 
i64 0
-; CHECK-NEXT:[[TMP4:%.*]] = add i64 [[TMP1]], 1
-; CHECK-NEXT:[[TMP5:%.*]] = extractelement <6 x i64> [[TMP15]], i64 
[[TMP4]]
+; CHECK-NEXT:[[TMP17:%.*]] = add i32 [[TMP16]], 1
+; CHECK-NEXT:[[TMP5:%.*]] = extractelement <6 x i64> [[TMP15]], i32 
[[TMP17]]
 ; CHECK-NEXT:[[TMP6:%.*]] = insertelement <3 x i64> [[TMP3]], i64 
[[TMP5]], i64 1
-; CHECK-NEXT:[[TMP7:%.*]] = add i64 [[TMP1]], 2
-; CHECK-NEXT:[[TMP8:%.*]] = extractelement <6 x i64> [[TMP15]], i64 
[[TMP7]]
+; CHECK-NEXT:[[TMP18:%.*]] = add i32 [[TMP16]], 2
+; CHECK-NEXT:[[TMP8:%.*]] = extractelement <6 x i64> [[TMP15]], i32 
[[TMP18]]
 ; CHECK-NEXT:[[TMP9:%.*]] = insertelement <3 x i64> [[TMP6]], i64 
[[TMP8]], i64 2
 ; CHECK-NEXT:[[ELEM:%.*]] = extractelement <3 x i64> [[TMP9]], i32 2
 ; CHECK-NEXT:store i64 [[ELEM]], ptr [[OUT]], align 8
@@ -311,15 +312,16 @@ define amdgpu_kernel void 
@i64_2d_load_store_subvec_3_i64_offset_index(ptr %out)
 ; CHECK-NEXT:[[TMP14:%.*]] = insertelement <6 x i64> [[TMP13]], i64 3, i32 
3
 ; CHECK-NEXT:[[TMP15:%.*]] = insertelement <6 x i64> [[TMP14]], i64 4, i32 
4
 ; CHECK-NEXT:[[TMP16:%.*]] = insertelement <6 x i64> [[TMP15]], i64 5, i32 
5
-; CHECK-NEXT:[[TMP1:%.*]] = mul i64 [[SEL3]], 3
-; CHECK-NEXT:[[TMP2:%.*]] = add i64 [[TMP1]], 6
-; CHECK-NEXT:[[TMP3:%.*]] = extractelement <6 x i64> [[TMP16]], i64 
[[TMP2]]
+; CHECK-NEXT:[[TMP17:%.*]] = trunc i64 [[SEL3]] to i32
+; CHECK-NEXT:[[TMP8:%.*]] = mul i32 [[TMP17]], 3
+; CHECK-NEXT:[[TMP18:%.*]] = add i32 [[TMP8]], 6
+; CHECK-NEXT:[[TMP3:%.*]] = extractelement <6 x i64> [[TMP16]], i32 
[[TMP18]]
 ; CHECK-NEX

[llvm-branch-commits] [llvm] [ADT] Make use of subsetOf and anyCommon methods of BitVector (NFC) (PR #170876)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-bolt

Author: Anatoly Trosinenko (atrosinenko)


Changes

Replace the code along these lines

BitVector Tmp = LHS;
Tmp &= RHS;
return Tmp.any();

and

BitVector Tmp = LHS;
Tmp.reset(RHS);
return Tmp.none();

with `LHS.anyCommon(RHS)` and `LHS.subsetOf(RHS)`, correspondingly, which
do not require creating temporary BitVector and can return early.

---
Full diff: https://github.com/llvm/llvm-project/pull/170876.diff


8 Files Affected:

- (modified) bolt/include/bolt/Passes/LivenessAnalysis.h (+2-3) 
- (modified) bolt/include/bolt/Passes/ReachingDefOrUse.h (+1-2) 
- (modified) bolt/lib/Passes/RegReAssign.cpp (+2-6) 
- (modified) bolt/lib/Passes/ShrinkWrapping.cpp (+4-6) 
- (modified) bolt/lib/Passes/StackAvailableExpressions.cpp (+1-2) 
- (modified) bolt/lib/Passes/TailDuplication.cpp (+4-4) 
- (modified) llvm/lib/CodeGen/RDFRegisters.cpp (+2-4) 
- (modified) llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp (+2-4) 


``diff
diff --git a/bolt/include/bolt/Passes/LivenessAnalysis.h 
b/bolt/include/bolt/Passes/LivenessAnalysis.h
index 1df1113318d0b..f4faa1dc34ecd 100644
--- a/bolt/include/bolt/Passes/LivenessAnalysis.h
+++ b/bolt/include/bolt/Passes/LivenessAnalysis.h
@@ -37,10 +37,9 @@ class LivenessAnalysis : public 
DataflowAnalysisgetStateAt(PP));
+const BitVector &BV = *this->getStateAt(PP);
 const BitVector &RegAliases = BC.MIB->getAliases(Reg);
-BV &= RegAliases;
-return BV.any();
+return BV.anyCommon(RegAliases);
   }
 
   void run() { Parent::run(); }
diff --git a/bolt/include/bolt/Passes/ReachingDefOrUse.h 
b/bolt/include/bolt/Passes/ReachingDefOrUse.h
index 585d673e3b84e..41a6091aad4cb 100644
--- a/bolt/include/bolt/Passes/ReachingDefOrUse.h
+++ b/bolt/include/bolt/Passes/ReachingDefOrUse.h
@@ -133,8 +133,7 @@ class ReachingDefOrUse
   RA.getInstClobberList(Point, Regs);
 else
   RA.getInstUsedRegsList(Point, Regs, false);
-Regs &= this->BC.MIB->getAliases(*TrackingReg);
-if (Regs.any())
+if (Regs.anyCommon(this->BC.MIB->getAliases(*TrackingReg)))
   Next.set(this->ExprToIdx[&Point]);
   }
 }
diff --git a/bolt/lib/Passes/RegReAssign.cpp b/bolt/lib/Passes/RegReAssign.cpp
index 0859cd244ce40..54eff51bfee68 100644
--- a/bolt/lib/Passes/RegReAssign.cpp
+++ b/bolt/lib/Passes/RegReAssign.cpp
@@ -316,18 +316,14 @@ void 
RegReAssign::aggressivePassOverFunction(BinaryFunction &Function) {
   break;
 }
 
-BitVector AnyAliasAlive = AliveAtStart;
-AnyAliasAlive &= BC.MIB->getAliases(ClassicReg);
-if (AnyAliasAlive.any()) {
+if (AliveAtStart.anyCommon(BC.MIB->getAliases(ClassicReg))) {
   LLVM_DEBUG(dbgs() << " Bailed on " << BC.MRI->getName(ClassicReg)
 << " with " << BC.MRI->getName(ExtReg)
 << " because classic reg is alive\n");
   --End;
   continue;
 }
-AnyAliasAlive = AliveAtStart;
-AnyAliasAlive &= BC.MIB->getAliases(ExtReg);
-if (AnyAliasAlive.any()) {
+if (AliveAtStart.anyCommon(BC.MIB->getAliases(ExtReg))) {
   LLVM_DEBUG(dbgs() << " Bailed on " << BC.MRI->getName(ClassicReg)
 << " with " << BC.MRI->getName(ExtReg)
 << " because extended reg is alive\n");
diff --git a/bolt/lib/Passes/ShrinkWrapping.cpp 
b/bolt/lib/Passes/ShrinkWrapping.cpp
index fe342ccd38a67..b882e2512866d 100644
--- a/bolt/lib/Passes/ShrinkWrapping.cpp
+++ b/bolt/lib/Passes/ShrinkWrapping.cpp
@@ -1100,9 +1100,8 @@ SmallVector 
ShrinkWrapping::fixPopsPlacements(
 bool Found = false;
 if (SPT.getStateAt(ProgramPoint::getLastPointAt(*BB))->first ==
 SaveOffset) {
-  BitVector BV = *RI.getStateAt(ProgramPoint::getLastPointAt(*BB));
-  BV &= UsesByReg[CSR];
-  if (!BV.any()) {
+  const BitVector &BV = *RI.getStateAt(ProgramPoint::getLastPointAt(*BB));
+  if (!BV.anyCommon(UsesByReg[CSR])) {
 Found = true;
 PP = BB;
 continue;
@@ -1110,9 +1109,8 @@ SmallVector 
ShrinkWrapping::fixPopsPlacements(
 }
 for (MCInst &Inst : llvm::reverse(*BB)) {
   if (SPT.getStateBefore(Inst)->first == SaveOffset) {
-BitVector BV = *RI.getStateAt(Inst);
-BV &= UsesByReg[CSR];
-if (!BV.any()) {
+const BitVector &BV = *RI.getStateAt(Inst);
+if (!BV.anyCommon(UsesByReg[CSR])) {
   Found = true;
   PP = &Inst;
   break;
diff --git a/bolt/lib/Passes/StackAvailableExpressions.cpp 
b/bolt/lib/Passes/StackAvailableExpressions.cpp
index a0d361f273de2..c685cc19badc3 100644
--- a/bolt/lib/Passes/StackAvailableExpressions.cpp
+++ b/bolt/lib/Passes/StackAvailableExpressions.cpp
@@ -103,8 +103,7 @@ bool StackAvailableExpressions::doesXKillsY(const MCInst 
*X, const MCInst *Y) {
   else
 RA.getInstClobberList(*Y, YClobbers);
 
-  XClobbers &= YClobbers;
-  return XClobbers.any();
+  return XClobbers.anyCommon(YClobbers);
 }
 
 Bit

[llvm-branch-commits] [llvm] [ADT] Make use of subsetOf and anyCommon methods of BitVector (NFC) (PR #170876)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-tools-llvm-exegesis

Author: Anatoly Trosinenko (atrosinenko)


Changes

Replace the code along these lines

BitVector Tmp = LHS;
Tmp &= RHS;
return Tmp.any();

and

BitVector Tmp = LHS;
Tmp.reset(RHS);
return Tmp.none();

with `LHS.anyCommon(RHS)` and `LHS.subsetOf(RHS)`, correspondingly, which
do not require creating temporary BitVector and can return early.

---
Full diff: https://github.com/llvm/llvm-project/pull/170876.diff


8 Files Affected:

- (modified) bolt/include/bolt/Passes/LivenessAnalysis.h (+2-3) 
- (modified) bolt/include/bolt/Passes/ReachingDefOrUse.h (+1-2) 
- (modified) bolt/lib/Passes/RegReAssign.cpp (+2-6) 
- (modified) bolt/lib/Passes/ShrinkWrapping.cpp (+4-6) 
- (modified) bolt/lib/Passes/StackAvailableExpressions.cpp (+1-2) 
- (modified) bolt/lib/Passes/TailDuplication.cpp (+4-4) 
- (modified) llvm/lib/CodeGen/RDFRegisters.cpp (+2-4) 
- (modified) llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp (+2-4) 


``diff
diff --git a/bolt/include/bolt/Passes/LivenessAnalysis.h 
b/bolt/include/bolt/Passes/LivenessAnalysis.h
index 1df1113318d0b..f4faa1dc34ecd 100644
--- a/bolt/include/bolt/Passes/LivenessAnalysis.h
+++ b/bolt/include/bolt/Passes/LivenessAnalysis.h
@@ -37,10 +37,9 @@ class LivenessAnalysis : public 
DataflowAnalysisgetStateAt(PP));
+const BitVector &BV = *this->getStateAt(PP);
 const BitVector &RegAliases = BC.MIB->getAliases(Reg);
-BV &= RegAliases;
-return BV.any();
+return BV.anyCommon(RegAliases);
   }
 
   void run() { Parent::run(); }
diff --git a/bolt/include/bolt/Passes/ReachingDefOrUse.h 
b/bolt/include/bolt/Passes/ReachingDefOrUse.h
index 585d673e3b84e..41a6091aad4cb 100644
--- a/bolt/include/bolt/Passes/ReachingDefOrUse.h
+++ b/bolt/include/bolt/Passes/ReachingDefOrUse.h
@@ -133,8 +133,7 @@ class ReachingDefOrUse
   RA.getInstClobberList(Point, Regs);
 else
   RA.getInstUsedRegsList(Point, Regs, false);
-Regs &= this->BC.MIB->getAliases(*TrackingReg);
-if (Regs.any())
+if (Regs.anyCommon(this->BC.MIB->getAliases(*TrackingReg)))
   Next.set(this->ExprToIdx[&Point]);
   }
 }
diff --git a/bolt/lib/Passes/RegReAssign.cpp b/bolt/lib/Passes/RegReAssign.cpp
index 0859cd244ce40..54eff51bfee68 100644
--- a/bolt/lib/Passes/RegReAssign.cpp
+++ b/bolt/lib/Passes/RegReAssign.cpp
@@ -316,18 +316,14 @@ void 
RegReAssign::aggressivePassOverFunction(BinaryFunction &Function) {
   break;
 }
 
-BitVector AnyAliasAlive = AliveAtStart;
-AnyAliasAlive &= BC.MIB->getAliases(ClassicReg);
-if (AnyAliasAlive.any()) {
+if (AliveAtStart.anyCommon(BC.MIB->getAliases(ClassicReg))) {
   LLVM_DEBUG(dbgs() << " Bailed on " << BC.MRI->getName(ClassicReg)
 << " with " << BC.MRI->getName(ExtReg)
 << " because classic reg is alive\n");
   --End;
   continue;
 }
-AnyAliasAlive = AliveAtStart;
-AnyAliasAlive &= BC.MIB->getAliases(ExtReg);
-if (AnyAliasAlive.any()) {
+if (AliveAtStart.anyCommon(BC.MIB->getAliases(ExtReg))) {
   LLVM_DEBUG(dbgs() << " Bailed on " << BC.MRI->getName(ClassicReg)
 << " with " << BC.MRI->getName(ExtReg)
 << " because extended reg is alive\n");
diff --git a/bolt/lib/Passes/ShrinkWrapping.cpp 
b/bolt/lib/Passes/ShrinkWrapping.cpp
index fe342ccd38a67..b882e2512866d 100644
--- a/bolt/lib/Passes/ShrinkWrapping.cpp
+++ b/bolt/lib/Passes/ShrinkWrapping.cpp
@@ -1100,9 +1100,8 @@ SmallVector 
ShrinkWrapping::fixPopsPlacements(
 bool Found = false;
 if (SPT.getStateAt(ProgramPoint::getLastPointAt(*BB))->first ==
 SaveOffset) {
-  BitVector BV = *RI.getStateAt(ProgramPoint::getLastPointAt(*BB));
-  BV &= UsesByReg[CSR];
-  if (!BV.any()) {
+  const BitVector &BV = *RI.getStateAt(ProgramPoint::getLastPointAt(*BB));
+  if (!BV.anyCommon(UsesByReg[CSR])) {
 Found = true;
 PP = BB;
 continue;
@@ -1110,9 +1109,8 @@ SmallVector 
ShrinkWrapping::fixPopsPlacements(
 }
 for (MCInst &Inst : llvm::reverse(*BB)) {
   if (SPT.getStateBefore(Inst)->first == SaveOffset) {
-BitVector BV = *RI.getStateAt(Inst);
-BV &= UsesByReg[CSR];
-if (!BV.any()) {
+const BitVector &BV = *RI.getStateAt(Inst);
+if (!BV.anyCommon(UsesByReg[CSR])) {
   Found = true;
   PP = &Inst;
   break;
diff --git a/bolt/lib/Passes/StackAvailableExpressions.cpp 
b/bolt/lib/Passes/StackAvailableExpressions.cpp
index a0d361f273de2..c685cc19badc3 100644
--- a/bolt/lib/Passes/StackAvailableExpressions.cpp
+++ b/bolt/lib/Passes/StackAvailableExpressions.cpp
@@ -103,8 +103,7 @@ bool StackAvailableExpressions::doesXKillsY(const MCInst 
*X, const MCInst *Y) {
   else
 RA.getInstClobberList(*Y, YClobbers);
 
-  XClobbers &= YClobbers;
-  return XClobbers.any();
+  return XClobbers.anyCommon(YClobb

[llvm-branch-commits] [llvm] [ADT] Make use of subsetOf and anyCommon methods of BitVector (NFC) (PR #170876)

2025-12-05 Thread Anatoly Trosinenko via llvm-branch-commits

https://github.com/atrosinenko ready_for_review 
https://github.com/llvm/llvm-project/pull/170876
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From 4fa5064b267bca9100fe2ab9678df253cdfcdf4f Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH 1/2] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6994cd88fba21..71e4a178fe21d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index c6841937c8d39..8af98ec6afb50 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2064,6 +2064,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 0380568412e62..331a388eac573 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6369,6 +6369,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.AddLastArg(CmdArgs, options::OPT_foperator_arrow_depth_EQ);
   Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_depth_EQ);
   Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_steps_EQ);
+  Args.AddLastArg(CmdArgs, options::OPT_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 6fa1ad9856783..8ca2b074acbea 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -44,6 +44,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -245,6 +257,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductTyp

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 6: Destructuring Expansion Statements) (PR #169685)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169685

>From 07d55ff90ee97ed9393f5b2d0aeadc43f0fc196f Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:00:57 +0100
Subject: [PATCH 1/6] [Clang] [C++26] Expansion Statements (Part 6)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   2 +
 clang/include/clang/Sema/Sema.h   |   3 +
 clang/lib/Sema/SemaExpand.cpp | 100 +-
 clang/lib/Sema/TreeTransform.h|  81 ++
 4 files changed, 162 insertions(+), 24 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a92a3a6a7c331..208c885909b00 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3712,6 +3712,8 @@ def err_conflicting_codeseg_attribute : Error<
 def warn_duplicate_codeseg_attribute : Warning<
   "duplicate code segment specifiers">, InGroup;
 
+def err_expansion_stmt_invalid_init : Error<
+  "cannot expand expression of type %0">;
 def err_expansion_stmt_vla : Error<
   "cannot expand variable length array type %0">;
 def err_expansion_stmt_incomplete : Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0adc570c73011..409e1d4e1b8ae 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -15713,6 +15713,9 @@ class Sema final : public SemaBase {
 
   ExprResult BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx);
 
+  ExprResult BuildCXXDestructuringExpansionSelectExpr(DecompositionDecl *DD,
+  Expr *Idx);
+
   std::optional
   ComputeExpansionSize(CXXExpansionStmtPattern *Expansion);
   ///@}
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 40891e96e97de..315a4bdfd3a6c 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -220,6 +220,52 @@ TryBuildIterableExpansionStmtInitializer(Sema &S, Expr 
*ExpansionInitializer,
   return Data;
 }
 
+static StmtResult BuildDestructuringCXXExpansionStmt(
+Sema &S, Expr *ExpansionInitializer, SourceLocation ColonLoc,
+bool VarIsConstexpr,
+ArrayRef LifetimeExtendTemps) {
+  auto Ctx = Sema::ExpressionEvaluationContext::PotentiallyEvaluated;
+  if (VarIsConstexpr)
+Ctx = Sema::ExpressionEvaluationContext::ImmediateFunctionContext;
+  EnterExpressionEvaluationContext ExprEvalCtx(S, Ctx);
+
+  // The declarations should be attached to the parent decl context.
+  Sema::ContextRAII CtxGuard(
+  S, S.CurContext->getEnclosingNonExpansionStatementContext(),
+  /*NewThis=*/false);
+
+  UnsignedOrNone Arity =
+  S.GetDecompositionElementCount(ExpansionInitializer->getType(), 
ColonLoc);
+
+  if (!Arity) {
+S.Diag(ExpansionInitializer->getBeginLoc(),
+   diag::err_expansion_stmt_invalid_init)
+<< ExpansionInitializer->getType()
+<< ExpansionInitializer->getSourceRange();
+return StmtError();
+  }
+
+  QualType AutoRRef = S.Context.getAutoRRefDeductType();
+  SmallVector Bindings;
+  for (unsigned I = 0; I < *Arity; ++I)
+Bindings.push_back(BindingDecl::Create(
+S.Context, S.CurContext, ColonLoc,
+S.getPreprocessor().getIdentifierInfo("__u" + std::to_string(I)),
+AutoRRef));
+
+  TypeSourceInfo *TSI = S.Context.getTrivialTypeSourceInfo(AutoRRef);
+  auto *DD =
+  DecompositionDecl::Create(S.Context, S.CurContext, ColonLoc, ColonLoc,
+AutoRRef, TSI, SC_Auto, Bindings);
+
+  if (VarIsConstexpr)
+DD->setConstexpr(true);
+
+  S.ApplyForRangeOrExpansionStatementLifetimeExtension(DD, 
LifetimeExtendTemps);
+  S.AddInitializerToDecl(DD, ExpansionInitializer, false);
+  return S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(DD), ColonLoc, ColonLoc);
+}
+
 CXXExpansionStmtDecl *
 Sema::ActOnCXXExpansionStmtDecl(unsigned TemplateDepth,
 SourceLocation TemplateKWLoc) {
@@ -368,8 +414,31 @@ StmtResult 
Sema::BuildNonEnumeratingCXXExpansionStmtPattern(
 Data.EndDecl, LParenLoc, ColonLoc, RParenLoc);
   }
 
-  Diag(ESD->getLocation(), diag::err_expansion_statements_todo);
-  return StmtError();
+  // If not, try destructuring.
+  StmtResult DecompDeclStmt = BuildDestructuringCXXExpansionStmt(
+  *this, ExpansionInitializer, ColonLoc, ExpansionVar->isConstexpr(),
+  LifetimeExtendTemps);
+  if (DecompDeclStmt.isInvalid()) {
+ActOnInitializerError(ExpansionVar);
+return StmtError();
+  }
+
+  auto *DS = DecompDeclStmt.getAs();
+  auto *DD = cast(DS->getSingleDecl());
+  if (DD->isInvalidDecl())
+return StmtError();
+
+  ExprResult Select = BuildCXXDestructuringExpansionSelectExpr(DD, Index);
+  if (Select.isInvalid()) {
+ActOnInitializerError(ExpansionVar);
+return StmtError();
+  }
+
+  if (FinaliseExpansionVar(*this, ExpansionVar, Select))
+return StmtE

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 5: Iterating Expansion Statements) (PR #169684)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169684

>From 778c6a7efd7a4f330ab81d8aae7cddebe516c8ec Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 16:18:02 +0100
Subject: [PATCH 1/9] [Clang] [C++26] Expansion Statements (Part 5)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   7 +
 clang/include/clang/Sema/Sema.h   |   6 +
 clang/lib/Sema/SemaExpand.cpp | 257 +-
 clang/lib/Sema/SemaStmt.cpp   |  13 +-
 clang/lib/Sema/TreeTransform.h|  14 +
 5 files changed, 291 insertions(+), 6 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fea25ef6a0734..0ce3d8164d955 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -165,6 +165,10 @@ def err_ice_too_large : Error<
 def err_expr_not_string_literal : Error<"expression is not a string literal">;
 def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
+def err_expansion_size_expr_not_ice : Error<
+  "expansion size is not a constant expression">;
+def err_expansion_size_negative : Error<
+  "expansion size must not be negative (was %0)">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
@@ -3710,6 +3714,9 @@ def err_conflicting_codeseg_attribute : Error<
 def warn_duplicate_codeseg_attribute : Warning<
   "duplicate code segment specifiers">, InGroup;
 
+def err_expansion_stmt_lambda : Error<
+  "cannot expand lambda closure type">;
+
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
 "valid for this target: %0">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5dee71b23422e..0adc570c73011 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -15705,6 +15705,12 @@ class Sema final : public SemaBase {
  SourceLocation ColonLoc,
  SourceLocation RParenLoc);
 
+  StmtResult BuildNonEnumeratingCXXExpansionStmtPattern(
+  CXXExpansionStmtDecl *ESD, Stmt *Init, DeclStmt *ExpansionVarStmt,
+  Expr *ExpansionInitializer, SourceLocation LParenLoc,
+  SourceLocation ColonLoc, SourceLocation RParenLoc,
+  ArrayRef LifetimeExtendTemps = {});
+
   ExprResult BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx);
 
   std::optional
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index a0f5e852ebdb1..4e392e33578e2 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -24,6 +24,25 @@
 using namespace clang;
 using namespace sema;
 
+namespace {
+struct IterableExpansionStmtData {
+  enum class State {
+NotIterable,
+Error,
+Ok,
+  };
+
+  DeclStmt *RangeDecl = nullptr;
+  DeclStmt *BeginDecl = nullptr;
+  DeclStmt *EndDecl = nullptr;
+  Expr *Initializer = nullptr;
+  State TheState = State::NotIterable;
+
+  bool isIterable() const { return TheState == State::Ok; }
+  bool hasError() { return TheState == State::Error; }
+};
+} // namespace
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -55,15 +74,134 @@ static bool HasDependentSize(const CXXExpansionStmtPattern 
*Pattern) {
 return InitListContainsPack(SelectExpr->getRangeExpr());
   }
 
-  case CXXExpansionStmtPattern::ExpansionStmtKind::Iterating:
-  case CXXExpansionStmtPattern::ExpansionStmtKind::Destructuring:
+  case CXXExpansionStmtPattern::ExpansionStmtKind::Iterating: {
+const Expr *Begin = Pattern->getBeginVar()->getInit();
+const Expr *End = Pattern->getEndVar()->getInit();
+return Begin->isInstantiationDependent() || 
End->isInstantiationDependent();
+  }
+
   case CXXExpansionStmtPattern::ExpansionStmtKind::Dependent:
+return true;
+
+  case CXXExpansionStmtPattern::ExpansionStmtKind::Destructuring:
 llvm_unreachable("TODO");
   }
 
   llvm_unreachable("invalid pattern kind");
 }
 
+static IterableExpansionStmtData
+TryBuildIterableExpansionStmtInitializer(Sema &S, Expr *ExpansionInitializer,
+ Expr *Index, SourceLocation ColonLoc,
+ bool VarIsConstexpr) {
+  IterableExpansionStmtData Data;
+
+  // C++26 [stmt.expand]p3: An expression is expansion-iterable if it does not
+  // have array type [...]
+  QualType Ty = ExpansionInitializer->getType().getNonReferenceType();
+  if (Ty->isArrayType())
+return Data;
+
+  // Lookup member and ADL 'begin()'/'end()'. Only check if they exist; even if
+  // they're deleted, inaccessible, etc., t

[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169683

>From 26f413ff4d537911520369e1f1833cf940dd2ab8 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 4)

---
 clang/include/clang/Sema/Sema.h |  34 +++
 clang/lib/Sema/SemaStmt.cpp | 503 ++--
 2 files changed, 313 insertions(+), 224 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 707f9eefccf36..7e23bb486bdda 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11067,6 +11067,37 @@ class Sema final : public SemaBase {
   BuildForRangeKind Kind,
   ArrayRef LifetimeExtendTemps = {});
 
+  /// Set the type of a for-range declaration whose for-range or expansion
+  /// initialiser is dependent.
+  void ActOnDependentForRangeInitializer(VarDecl *LoopVar,
+ BuildForRangeKind BFRK);
+
+  /// Holds the 'begin' and 'end' variables of a range-based for loop or
+  /// expansion statement; begin-expr and end-expr are also provided; the
+  /// latter are used in some diagnostics.
+  struct ForRangeBeginEndInfo {
+VarDecl *BeginVar = nullptr;
+VarDecl *EndVar = nullptr;
+Expr *BeginExpr = nullptr;
+Expr *EndExpr = nullptr;
+bool isValid() const { return BeginVar != nullptr && EndVar != nullptr; }
+  };
+
+  /// Determine begin-expr and end-expr and build variable declarations for
+  /// them as per [stmt.ranged].
+  ForRangeBeginEndInfo BuildCXXForRangeBeginEndVars(
+  Scope *S, VarDecl *RangeVar, SourceLocation ColonLoc,
+  SourceLocation CoawaitLoc,
+  ArrayRef LifetimeExtendTemps,
+  BuildForRangeKind Kind, bool ForExpansionStmt,
+  StmtResult *RebuildResult = nullptr,
+  llvm::function_ref RebuildWithDereference = {});
+
+  /// Build the range variable of a range-based for loop or iterating
+  /// expansion statement and return its DeclStmt.
+  StmtResult BuildCXXForRangeRangeVar(Scope *S, Expr *Range,
+  bool ForExpansionStmt);
+
   /// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement.
   /// This is a separate step from ActOnCXXForRangeStmt because analysis of the
   /// body cannot be performed until after the type of the range variable is
@@ -11208,6 +11239,9 @@ class Sema final : public SemaBase {
SourceLocation Loc,
unsigned NumParams);
 
+  void ApplyForRangeOrExpansionStatementLifetimeExtension(
+  VarDecl *RangeVar, ArrayRef Temporaries);
+
 private:
   /// Check whether the given statement can have musttail applied to it,
   /// issuing a diagnostic and returning false if not.
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 6bb1a27d1800c..3a1d73fdacf09 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2409,8 +2409,13 @@ void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,
 }
 
 /// Build a variable declaration for a for-range statement.
-VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
-  QualType Type, StringRef Name) {
+VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
+  StringRef Name, bool ForExpansionStmt) {
+  // Making the variable constexpr doesn't automatically add 'const' to the
+  // type, so do that now.
+  if (ForExpansionStmt && !Type->isReferenceType())
+Type = Type.withConst();
+
   DeclContext *DC = SemaRef.CurContext;
   IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
   TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
@@ -2418,9 +2423,11 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef, 
SourceLocation Loc,
   TInfo, SC_None);
   Decl->setImplicit();
   Decl->setCXXForRangeImplicitVar(true);
+  if (ForExpansionStmt)
+// CWG 3044: Do not make the variable 'static'.
+Decl->setConstexpr(true);
   return Decl;
 }
-
 }
 
 static bool ObjCEnumerationCollection(Expr *Collection) {
@@ -2428,6 +2435,25 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
   && Collection->getType()->getAs() != nullptr;
 }
 
+StmtResult Sema::BuildCXXForRangeRangeVar(Scope *S, Expr *Range,
+  bool ForExpansionStmt) {
+  // Divide by 2, since the variables are in the inner scope (loop body).
+  const auto DepthStr = std::to_string(S->getDepth() / 2);
+  SourceLocation RangeLoc = Range->getBeginLoc();
+  VarDecl *RangeVar =
+  BuildForRangeVarDecl(*this, RangeLoc, Context.getAutoRRefDeductType(),
+   std::string("__range") + DepthStr, 
ForExpansionStmt);
+  if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
+diag::err_for_r

[llvm-branch-commits] [clang] [Clang] [NFC] Expansion Statements (Part 4: for-range and `ParseScope` refactor) (PR #169683)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169683

>From 26f413ff4d537911520369e1f1833cf940dd2ab8 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 16:11:59 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 4)

---
 clang/include/clang/Sema/Sema.h |  34 +++
 clang/lib/Sema/SemaStmt.cpp | 503 ++--
 2 files changed, 313 insertions(+), 224 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 707f9eefccf36..7e23bb486bdda 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11067,6 +11067,37 @@ class Sema final : public SemaBase {
   BuildForRangeKind Kind,
   ArrayRef LifetimeExtendTemps = {});
 
+  /// Set the type of a for-range declaration whose for-range or expansion
+  /// initialiser is dependent.
+  void ActOnDependentForRangeInitializer(VarDecl *LoopVar,
+ BuildForRangeKind BFRK);
+
+  /// Holds the 'begin' and 'end' variables of a range-based for loop or
+  /// expansion statement; begin-expr and end-expr are also provided; the
+  /// latter are used in some diagnostics.
+  struct ForRangeBeginEndInfo {
+VarDecl *BeginVar = nullptr;
+VarDecl *EndVar = nullptr;
+Expr *BeginExpr = nullptr;
+Expr *EndExpr = nullptr;
+bool isValid() const { return BeginVar != nullptr && EndVar != nullptr; }
+  };
+
+  /// Determine begin-expr and end-expr and build variable declarations for
+  /// them as per [stmt.ranged].
+  ForRangeBeginEndInfo BuildCXXForRangeBeginEndVars(
+  Scope *S, VarDecl *RangeVar, SourceLocation ColonLoc,
+  SourceLocation CoawaitLoc,
+  ArrayRef LifetimeExtendTemps,
+  BuildForRangeKind Kind, bool ForExpansionStmt,
+  StmtResult *RebuildResult = nullptr,
+  llvm::function_ref RebuildWithDereference = {});
+
+  /// Build the range variable of a range-based for loop or iterating
+  /// expansion statement and return its DeclStmt.
+  StmtResult BuildCXXForRangeRangeVar(Scope *S, Expr *Range,
+  bool ForExpansionStmt);
+
   /// FinishCXXForRangeStmt - Attach the body to a C++0x for-range statement.
   /// This is a separate step from ActOnCXXForRangeStmt because analysis of the
   /// body cannot be performed until after the type of the range variable is
@@ -11208,6 +11239,9 @@ class Sema final : public SemaBase {
SourceLocation Loc,
unsigned NumParams);
 
+  void ApplyForRangeOrExpansionStatementLifetimeExtension(
+  VarDecl *RangeVar, ArrayRef Temporaries);
+
 private:
   /// Check whether the given statement can have musttail applied to it,
   /// issuing a diagnostic and returning false if not.
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 6bb1a27d1800c..3a1d73fdacf09 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -2409,8 +2409,13 @@ void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,
 }
 
 /// Build a variable declaration for a for-range statement.
-VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc,
-  QualType Type, StringRef Name) {
+VarDecl *BuildForRangeVarDecl(Sema &SemaRef, SourceLocation Loc, QualType Type,
+  StringRef Name, bool ForExpansionStmt) {
+  // Making the variable constexpr doesn't automatically add 'const' to the
+  // type, so do that now.
+  if (ForExpansionStmt && !Type->isReferenceType())
+Type = Type.withConst();
+
   DeclContext *DC = SemaRef.CurContext;
   IdentifierInfo *II = &SemaRef.PP.getIdentifierTable().get(Name);
   TypeSourceInfo *TInfo = SemaRef.Context.getTrivialTypeSourceInfo(Type, Loc);
@@ -2418,9 +2423,11 @@ VarDecl *BuildForRangeVarDecl(Sema &SemaRef, 
SourceLocation Loc,
   TInfo, SC_None);
   Decl->setImplicit();
   Decl->setCXXForRangeImplicitVar(true);
+  if (ForExpansionStmt)
+// CWG 3044: Do not make the variable 'static'.
+Decl->setConstexpr(true);
   return Decl;
 }
-
 }
 
 static bool ObjCEnumerationCollection(Expr *Collection) {
@@ -2428,6 +2435,25 @@ static bool ObjCEnumerationCollection(Expr *Collection) {
   && Collection->getType()->getAs() != nullptr;
 }
 
+StmtResult Sema::BuildCXXForRangeRangeVar(Scope *S, Expr *Range,
+  bool ForExpansionStmt) {
+  // Divide by 2, since the variables are in the inner scope (loop body).
+  const auto DepthStr = std::to_string(S->getDepth() / 2);
+  SourceLocation RangeLoc = Range->getBeginLoc();
+  VarDecl *RangeVar =
+  BuildForRangeVarDecl(*this, RangeLoc, Context.getAutoRRefDeductType(),
+   std::string("__range") + DepthStr, 
ForExpansionStmt);
+  if (FinishForRangeVarDecl(*this, RangeVar, Range, RangeLoc,
+diag::err_for_r

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 3: Enumerating Expansion Statements) (PR #169682)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169682

>From 1861f5a04b849455139583c37dce3dfa3a0f445b Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Tue, 25 Nov 2025 20:47:23 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 3)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   2 +
 clang/include/clang/Sema/Sema.h   |  22 +++
 clang/lib/Frontend/FrontendActions.cpp|   2 +
 clang/lib/Sema/SemaExpand.cpp | 151 ++
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  29 +++-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |  38 -
 clang/lib/Sema/SemaTemplateVariadic.cpp   |   8 +-
 clang/lib/Sema/TreeTransform.h|  83 +-
 .../Parser/cxx2c-expansion-statements.cpp |  80 +-
 9 files changed, 365 insertions(+), 50 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d97bc41302c26..fea25ef6a0734 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5842,6 +5842,8 @@ def note_template_nsdmi_here : Note<
   "in instantiation of default member initializer %q0 requested here">;
 def note_template_type_alias_instantiation_here : Note<
   "in instantiation of template type alias %0 requested here">;
+def note_expansion_stmt_instantiation_here : Note<
+  "in instantiation of expansion statement requested here">;
 def note_template_exception_spec_instantiation_here : Note<
   "in instantiation of exception specification for %0 requested here">;
 def note_template_requirement_instantiation_here : Note<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b40c96fd48851..3b14f4d605b61 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13177,6 +13177,9 @@ class Sema final : public SemaBase {
 
   /// We are performing partial ordering for template template parameters.
   PartialOrderingTTP,
+
+  /// We are instantiating an expansion statement.
+  ExpansionStmtInstantiation,
 } Kind;
 
 /// Whether we're substituting into constraints.
@@ -13372,6 +13375,12 @@ class Sema final : public SemaBase {
   concepts::Requirement *Req,
   SourceRange InstantiationRange = SourceRange());
 
+/// \brief Note that we are substituting the body of an expansion 
statement.
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+  CXXExpansionStmtPattern *ExpansionStmt,
+  ArrayRef TArgs,
+  SourceRange InstantiationRange);
+
 /// \brief Note that we are checking the satisfaction of the constraint
 /// expression inside of a nested requirement.
 InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -15644,6 +15653,19 @@ class Sema final : public SemaBase {
   ArrayRef LifetimeExtendTemps);
 
   StmtResult FinishCXXExpansionStmt(Stmt *Expansion, Stmt *Body);
+
+  StmtResult BuildCXXEnumeratingExpansionStmtPattern(Decl *ESD, Stmt *Init,
+ Stmt *ExpansionVar,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation RParenLoc);
+
+  ExprResult
+  BuildCXXExpansionInitListSelectExpr(CXXExpansionInitListExpr *Range,
+  Expr *Idx);
+
+  std::optional
+  ComputeExpansionSize(CXXExpansionStmtPattern *Expansion);
   ///@}
 };
 
diff --git a/clang/lib/Frontend/FrontendActions.cpp 
b/clang/lib/Frontend/FrontendActions.cpp
index e0c1d304e8290..75d5a76c04a32 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -476,6 +476,8 @@ class DefaultTemplateInstCallback : public 
TemplateInstantiationCallback {
   return "TypeAliasTemplateInstantiation";
 case CodeSynthesisContext::PartialOrderingTTP:
   return "PartialOrderingTTP";
+case CodeSynthesisContext::ExpansionStmtInstantiation:
+  return "ExpansionStmtInstantiation";
 }
 return "";
   }
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 96c0d9be9451c..f1cd2baa9ae39 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -24,6 +24,23 @@
 using namespace clang;
 using namespace sema;
 
+// Build a 'DeclRefExpr' designating the template parameter '__N'.
+static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
+  return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
+S.Context.getPointerDiffType(), VK_PRValue,
+ESD->getBeginLoc());
+}
+
+static bool FinaliseExpansionVar(Sema &S, VarDecl *Expan

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 6: Destructuring Expansion Statements) (PR #169685)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169685

>From 07d55ff90ee97ed9393f5b2d0aeadc43f0fc196f Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:00:57 +0100
Subject: [PATCH 1/6] [Clang] [C++26] Expansion Statements (Part 6)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   2 +
 clang/include/clang/Sema/Sema.h   |   3 +
 clang/lib/Sema/SemaExpand.cpp | 100 +-
 clang/lib/Sema/TreeTransform.h|  81 ++
 4 files changed, 162 insertions(+), 24 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a92a3a6a7c331..208c885909b00 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3712,6 +3712,8 @@ def err_conflicting_codeseg_attribute : Error<
 def warn_duplicate_codeseg_attribute : Warning<
   "duplicate code segment specifiers">, InGroup;
 
+def err_expansion_stmt_invalid_init : Error<
+  "cannot expand expression of type %0">;
 def err_expansion_stmt_vla : Error<
   "cannot expand variable length array type %0">;
 def err_expansion_stmt_incomplete : Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0adc570c73011..409e1d4e1b8ae 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -15713,6 +15713,9 @@ class Sema final : public SemaBase {
 
   ExprResult BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx);
 
+  ExprResult BuildCXXDestructuringExpansionSelectExpr(DecompositionDecl *DD,
+  Expr *Idx);
+
   std::optional
   ComputeExpansionSize(CXXExpansionStmtPattern *Expansion);
   ///@}
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 40891e96e97de..315a4bdfd3a6c 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -220,6 +220,52 @@ TryBuildIterableExpansionStmtInitializer(Sema &S, Expr 
*ExpansionInitializer,
   return Data;
 }
 
+static StmtResult BuildDestructuringCXXExpansionStmt(
+Sema &S, Expr *ExpansionInitializer, SourceLocation ColonLoc,
+bool VarIsConstexpr,
+ArrayRef LifetimeExtendTemps) {
+  auto Ctx = Sema::ExpressionEvaluationContext::PotentiallyEvaluated;
+  if (VarIsConstexpr)
+Ctx = Sema::ExpressionEvaluationContext::ImmediateFunctionContext;
+  EnterExpressionEvaluationContext ExprEvalCtx(S, Ctx);
+
+  // The declarations should be attached to the parent decl context.
+  Sema::ContextRAII CtxGuard(
+  S, S.CurContext->getEnclosingNonExpansionStatementContext(),
+  /*NewThis=*/false);
+
+  UnsignedOrNone Arity =
+  S.GetDecompositionElementCount(ExpansionInitializer->getType(), 
ColonLoc);
+
+  if (!Arity) {
+S.Diag(ExpansionInitializer->getBeginLoc(),
+   diag::err_expansion_stmt_invalid_init)
+<< ExpansionInitializer->getType()
+<< ExpansionInitializer->getSourceRange();
+return StmtError();
+  }
+
+  QualType AutoRRef = S.Context.getAutoRRefDeductType();
+  SmallVector Bindings;
+  for (unsigned I = 0; I < *Arity; ++I)
+Bindings.push_back(BindingDecl::Create(
+S.Context, S.CurContext, ColonLoc,
+S.getPreprocessor().getIdentifierInfo("__u" + std::to_string(I)),
+AutoRRef));
+
+  TypeSourceInfo *TSI = S.Context.getTrivialTypeSourceInfo(AutoRRef);
+  auto *DD =
+  DecompositionDecl::Create(S.Context, S.CurContext, ColonLoc, ColonLoc,
+AutoRRef, TSI, SC_Auto, Bindings);
+
+  if (VarIsConstexpr)
+DD->setConstexpr(true);
+
+  S.ApplyForRangeOrExpansionStatementLifetimeExtension(DD, 
LifetimeExtendTemps);
+  S.AddInitializerToDecl(DD, ExpansionInitializer, false);
+  return S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(DD), ColonLoc, ColonLoc);
+}
+
 CXXExpansionStmtDecl *
 Sema::ActOnCXXExpansionStmtDecl(unsigned TemplateDepth,
 SourceLocation TemplateKWLoc) {
@@ -368,8 +414,31 @@ StmtResult 
Sema::BuildNonEnumeratingCXXExpansionStmtPattern(
 Data.EndDecl, LParenLoc, ColonLoc, RParenLoc);
   }
 
-  Diag(ESD->getLocation(), diag::err_expansion_statements_todo);
-  return StmtError();
+  // If not, try destructuring.
+  StmtResult DecompDeclStmt = BuildDestructuringCXXExpansionStmt(
+  *this, ExpansionInitializer, ColonLoc, ExpansionVar->isConstexpr(),
+  LifetimeExtendTemps);
+  if (DecompDeclStmt.isInvalid()) {
+ActOnInitializerError(ExpansionVar);
+return StmtError();
+  }
+
+  auto *DS = DecompDeclStmt.getAs();
+  auto *DD = cast(DS->getSingleDecl());
+  if (DD->isInvalidDecl())
+return StmtError();
+
+  ExprResult Select = BuildCXXDestructuringExpansionSelectExpr(DD, Index);
+  if (Select.isInvalid()) {
+ActOnInitializerError(ExpansionVar);
+return StmtError();
+  }
+
+  if (FinaliseExpansionVar(*this, ExpansionVar, Select))
+return StmtE

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 7: Constexpr support and tests) (PR #169686)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169686

>From 08eaa56a2b0328744f89f45d4aa56aefff476868 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:09:56 +0100
Subject: [PATCH 1/6] [Clang] [C++26] Expansion Statements (Part 7)

---
 clang/lib/AST/ExprConstant.cpp   |   40 +
 clang/lib/Sema/SemaDeclCXX.cpp   |3 +
 clang/test/SemaCXX/cxx2c-expansion-stmts.cpp | 1042 ++
 3 files changed, 1085 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts.cpp

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d09eff7b54b65..07e70b8a21b40 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6036,6 +6036,12 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, 
EvalInfo &Info,
   const VarDecl *VD = dyn_cast_or_null(D);
   if (VD && !CheckLocalVariableDeclaration(Info, VD))
 return ESR_Failed;
+
+  if (const auto *ESD = dyn_cast(D)) {
+assert(ESD->getInstantiations() && "not expanded?");
+return EvaluateStmt(Result, Info, ESD->getInstantiations(), Case);
+  }
+
   // Each declaration initialization is its own full-expression.
   FullExpressionRAII Scope(Info);
   if (!EvaluateDecl(Info, D, /*EvaluateConditionDecl=*/true) &&
@@ -6308,6 +6314,40 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, 
EvalInfo &Info,
 return Scope.destroy() ? ESR_Succeeded : ESR_Failed;
   }
 
+  case Stmt::CXXExpansionStmtInstantiationClass: {
+BlockScopeRAII Scope(Info);
+const auto *Expansion = cast(S);
+for (const Stmt *Shared : Expansion->getSharedStmts()) {
+  EvalStmtResult ESR = EvaluateStmt(Result, Info, Shared);
+  if (ESR != ESR_Succeeded) {
+if (ESR != ESR_Failed && !Scope.destroy())
+  return ESR_Failed;
+return ESR;
+  }
+}
+
+// No need to push an extra scope for these since they're already
+// CompoundStmts.
+EvalStmtResult ESR = ESR_Succeeded;
+for (const Stmt *Instantiation : Expansion->getInstantiations()) {
+  ESR = EvaluateStmt(Result, Info, Instantiation);
+  if (ESR == ESR_Failed ||
+  ShouldPropagateBreakContinue(Info, Expansion, &Scope, ESR))
+return ESR;
+  if (ESR != ESR_Continue) {
+// Succeeded here actually means we encountered a 'break'.
+assert(ESR == ESR_Succeeded || ESR == ESR_Returned);
+break;
+  }
+}
+
+// Map Continue back to Succeeded if we fell off the end of the loop.
+if (ESR == ESR_Continue)
+  ESR = ESR_Succeeded;
+
+return Scope.destroy() ? ESR : ESR_Failed;
+  }
+
   case Stmt::SwitchStmtClass:
 return EvaluateSwitch(Result, Info, cast(S));
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 3bc748969065a..c6541e453cfff 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -2027,6 +2027,9 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const 
FunctionDecl *Dcl,
   //   - using-enum-declaration
   continue;
 
+case Decl::CXXExpansionStmt:
+  continue;
+
 case Decl::Typedef:
 case Decl::TypeAlias: {
   //   - typedef declarations and alias-declarations that do not define
diff --git a/clang/test/SemaCXX/cxx2c-expansion-stmts.cpp 
b/clang/test/SemaCXX/cxx2c-expansion-stmts.cpp
new file mode 100644
index 0..71ce71c4f69fe
--- /dev/null
+++ b/clang/test/SemaCXX/cxx2c-expansion-stmts.cpp
@@ -0,0 +1,1042 @@
+// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -fdeclspec -fblocks -verify
+namespace std {
+template 
+struct initializer_list {
+  const T* a;
+  const T* b;
+  initializer_list(T* a, T* b): a{a}, b{b} {}
+};
+}
+
+struct S {
+  int x;
+  constexpr S(int x) : x{x} {}
+};
+
+void g(int); // #g
+template  constexpr int tg() { return n; }
+
+void f1() {
+  template for (auto x : {}) static_assert(false, "discarded");
+  template for (constexpr auto x : {}) static_assert(false, "discarded");
+  template for (auto x : {1}) g(x);
+  template for (auto x : {1, 2, 3}) g(x);
+  template for (constexpr auto x : {1}) g(x);
+  template for (constexpr auto x : {1, 2, 3}) g(x);
+  template for (constexpr auto x : {1}) tg();
+  template for (constexpr auto x : {1, 2, 3})
+static_assert(tg());
+
+  template for (int x : {1, 2, 3}) g(x);
+  template for (S x : {1, 2, 3}) g(x.x);
+  template for (constexpr S x : {1, 2, 3}) tg();
+
+  template for (int x : {"1", S(1), {1, 2}}) { // expected-error {{cannot 
initialize a variable of type 'int' with an lvalue of type 'const char[2]'}} \
+  expected-error {{no viable 
conversion from 'S' to 'int'}} \
+  expected-error {{excess 
elements in scalar initializer}} \
+  expected-note 3 {{in 
instantiation of expansion statement requested

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 2: Parsing and Parser Tests) (PR #169681)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169681

>From f1dc87b93103ce2cca18815d76116e3b207d9f90 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Tue, 25 Nov 2025 17:56:59 +0100
Subject: [PATCH 1/5] [Clang] [C++26] Expansion Statements (Part 2)

---
 .../clang/Basic/DiagnosticParseKinds.td   |  13 +-
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +-
 clang/include/clang/Parse/Parser.h|  41 -
 clang/include/clang/Sema/Sema.h   |  33 +++-
 clang/lib/Parse/ParseDecl.cpp |  37 +
 clang/lib/Parse/ParseExpr.cpp |  13 +-
 clang/lib/Parse/ParseInit.cpp |  20 +++
 clang/lib/Parse/ParseStmt.cpp | 143 --
 clang/lib/Sema/CMakeLists.txt |   1 +
 clang/lib/Sema/SemaDecl.cpp   |   7 +-
 clang/lib/Sema/SemaExpand.cpp |  57 +++
 11 files changed, 310 insertions(+), 61 deletions(-)
 create mode 100644 clang/lib/Sema/SemaExpand.cpp

diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 9401377002223..75566ab7f6675 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -16,6 +16,10 @@ let CategoryName = "Parse Issue" in {
 defm enum_fixed_underlying_type : CXX11Compat<
   "enumeration types with a fixed underlying type are",
   /*ext_warn=*/false>;
+
+// C++26 compatibility with C++23.
+defm expansion_statements : CXX26Compat<
+  "expansion statements are">;
 }
 
 def err_asm_qualifier_ignored : Error<
@@ -419,9 +423,10 @@ def warn_cxx98_compat_for_range : Warning<
   "range-based for loop is incompatible with C++98">,
   InGroup, DefaultIgnore;
 def err_for_range_identifier : Error<
-  "range-based for loop requires type for loop variable">;
+  "%select{range-based for loop|expansion statement}0 requires "
+  "type for %select{loop|expansion}0 variable">;
 def err_for_range_expected_decl : Error<
-  "for range declaration must declare a variable">;
+  "%select{for range|expansion statement}0 declaration must declare a 
variable">;
 def err_argument_required_after_attribute : Error<
   "argument required after attribute">;
 def err_missing_param : Error<"expected parameter declarator">;
@@ -448,6 +453,10 @@ def err_unspecified_size_with_static : Error<
   "'static' may not be used without an array size">;
 def err_expected_parentheses_around_typename : Error<
   "expected parentheses around type name in %0 expression">;
+def err_expansion_stmt_requires_range : Error<
+  "expansion statement must be a range-based for loop">;
+def err_expansion_stmt_requires_cxx2c : Error<
+  "expansion statements are only supported in C++2c">;
 
 def err_expected_case_before_expression: Error<
   "expected 'case' keyword before expression">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9147b6a041c70..d97bc41302c26 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2908,10 +2908,10 @@ def note_which_delegates_to : Note<"which delegates 
to">;
 
 // C++11 range-based for loop
 def err_for_range_decl_must_be_var : Error<
-  "for range declaration must declare a variable">;
+  "%select{for range|expansion statement}0 declaration must declare a 
variable">;
 def err_for_range_storage_class : Error<
-  "loop variable %0 may not be declared %select{'extern'|'static'|"
-  "'__private_extern__'|'auto'|'register'|'constexpr'|'thread_local'}1">;
+  "%select{loop|expansion}0 variable %1 may not be declared 
%select{'extern'|'static'|"
+  "'__private_extern__'|'auto'|'register'|'constexpr'|'thread_local'}2">;
 def err_type_defined_in_for_range : Error<
   "types may not be defined in a for range declaration">;
 def err_for_range_deduction_failure : Error<
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index 58eb1c0a7c114..ff4f7b4e1dd2d 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1700,11 +1700,13 @@ class Parser : public CodeCompletionHandler {
   }
 
   /// Information on a C++0x for-range-initializer found while parsing a
-  /// declaration which turns out to be a for-range-declaration.
+  /// declaration which turns out to be a for-range-declaration. Also used
+  /// for C++26's expansion statements.
   struct ForRangeInit {
 SourceLocation ColonLoc;
 ExprResult RangeExpr;
 SmallVector LifetimeExtendTemps;
+bool ExpansionStmt = false;
 bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); }
   };
   struct ForRangeInfo : ForRangeInit {
@@ -4186,7 +4188,8 @@ class Parser : public CodeCompletionHandler {
   bool ParseExpressionList(SmallVectorImpl &Exprs,
llvm::function_ref ExpressionStarts =
llvm::function

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 2: Parsing and Parser Tests) (PR #169681)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169681

>From f1dc87b93103ce2cca18815d76116e3b207d9f90 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Tue, 25 Nov 2025 17:56:59 +0100
Subject: [PATCH 1/5] [Clang] [C++26] Expansion Statements (Part 2)

---
 .../clang/Basic/DiagnosticParseKinds.td   |  13 +-
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +-
 clang/include/clang/Parse/Parser.h|  41 -
 clang/include/clang/Sema/Sema.h   |  33 +++-
 clang/lib/Parse/ParseDecl.cpp |  37 +
 clang/lib/Parse/ParseExpr.cpp |  13 +-
 clang/lib/Parse/ParseInit.cpp |  20 +++
 clang/lib/Parse/ParseStmt.cpp | 143 --
 clang/lib/Sema/CMakeLists.txt |   1 +
 clang/lib/Sema/SemaDecl.cpp   |   7 +-
 clang/lib/Sema/SemaExpand.cpp |  57 +++
 11 files changed, 310 insertions(+), 61 deletions(-)
 create mode 100644 clang/lib/Sema/SemaExpand.cpp

diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 9401377002223..75566ab7f6675 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -16,6 +16,10 @@ let CategoryName = "Parse Issue" in {
 defm enum_fixed_underlying_type : CXX11Compat<
   "enumeration types with a fixed underlying type are",
   /*ext_warn=*/false>;
+
+// C++26 compatibility with C++23.
+defm expansion_statements : CXX26Compat<
+  "expansion statements are">;
 }
 
 def err_asm_qualifier_ignored : Error<
@@ -419,9 +423,10 @@ def warn_cxx98_compat_for_range : Warning<
   "range-based for loop is incompatible with C++98">,
   InGroup, DefaultIgnore;
 def err_for_range_identifier : Error<
-  "range-based for loop requires type for loop variable">;
+  "%select{range-based for loop|expansion statement}0 requires "
+  "type for %select{loop|expansion}0 variable">;
 def err_for_range_expected_decl : Error<
-  "for range declaration must declare a variable">;
+  "%select{for range|expansion statement}0 declaration must declare a 
variable">;
 def err_argument_required_after_attribute : Error<
   "argument required after attribute">;
 def err_missing_param : Error<"expected parameter declarator">;
@@ -448,6 +453,10 @@ def err_unspecified_size_with_static : Error<
   "'static' may not be used without an array size">;
 def err_expected_parentheses_around_typename : Error<
   "expected parentheses around type name in %0 expression">;
+def err_expansion_stmt_requires_range : Error<
+  "expansion statement must be a range-based for loop">;
+def err_expansion_stmt_requires_cxx2c : Error<
+  "expansion statements are only supported in C++2c">;
 
 def err_expected_case_before_expression: Error<
   "expected 'case' keyword before expression">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9147b6a041c70..d97bc41302c26 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2908,10 +2908,10 @@ def note_which_delegates_to : Note<"which delegates 
to">;
 
 // C++11 range-based for loop
 def err_for_range_decl_must_be_var : Error<
-  "for range declaration must declare a variable">;
+  "%select{for range|expansion statement}0 declaration must declare a 
variable">;
 def err_for_range_storage_class : Error<
-  "loop variable %0 may not be declared %select{'extern'|'static'|"
-  "'__private_extern__'|'auto'|'register'|'constexpr'|'thread_local'}1">;
+  "%select{loop|expansion}0 variable %1 may not be declared 
%select{'extern'|'static'|"
+  "'__private_extern__'|'auto'|'register'|'constexpr'|'thread_local'}2">;
 def err_type_defined_in_for_range : Error<
   "types may not be defined in a for range declaration">;
 def err_for_range_deduction_failure : Error<
diff --git a/clang/include/clang/Parse/Parser.h 
b/clang/include/clang/Parse/Parser.h
index 58eb1c0a7c114..ff4f7b4e1dd2d 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1700,11 +1700,13 @@ class Parser : public CodeCompletionHandler {
   }
 
   /// Information on a C++0x for-range-initializer found while parsing a
-  /// declaration which turns out to be a for-range-declaration.
+  /// declaration which turns out to be a for-range-declaration. Also used
+  /// for C++26's expansion statements.
   struct ForRangeInit {
 SourceLocation ColonLoc;
 ExprResult RangeExpr;
 SmallVector LifetimeExtendTemps;
+bool ExpansionStmt = false;
 bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); }
   };
   struct ForRangeInfo : ForRangeInit {
@@ -4186,7 +4188,8 @@ class Parser : public CodeCompletionHandler {
   bool ParseExpressionList(SmallVectorImpl &Exprs,
llvm::function_ref ExpressionStarts =
llvm::function

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 7: Constexpr support and tests) (PR #169686)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169686

>From 08eaa56a2b0328744f89f45d4aa56aefff476868 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:09:56 +0100
Subject: [PATCH 1/6] [Clang] [C++26] Expansion Statements (Part 7)

---
 clang/lib/AST/ExprConstant.cpp   |   40 +
 clang/lib/Sema/SemaDeclCXX.cpp   |3 +
 clang/test/SemaCXX/cxx2c-expansion-stmts.cpp | 1042 ++
 3 files changed, 1085 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts.cpp

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d09eff7b54b65..07e70b8a21b40 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6036,6 +6036,12 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, 
EvalInfo &Info,
   const VarDecl *VD = dyn_cast_or_null(D);
   if (VD && !CheckLocalVariableDeclaration(Info, VD))
 return ESR_Failed;
+
+  if (const auto *ESD = dyn_cast(D)) {
+assert(ESD->getInstantiations() && "not expanded?");
+return EvaluateStmt(Result, Info, ESD->getInstantiations(), Case);
+  }
+
   // Each declaration initialization is its own full-expression.
   FullExpressionRAII Scope(Info);
   if (!EvaluateDecl(Info, D, /*EvaluateConditionDecl=*/true) &&
@@ -6308,6 +6314,40 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, 
EvalInfo &Info,
 return Scope.destroy() ? ESR_Succeeded : ESR_Failed;
   }
 
+  case Stmt::CXXExpansionStmtInstantiationClass: {
+BlockScopeRAII Scope(Info);
+const auto *Expansion = cast(S);
+for (const Stmt *Shared : Expansion->getSharedStmts()) {
+  EvalStmtResult ESR = EvaluateStmt(Result, Info, Shared);
+  if (ESR != ESR_Succeeded) {
+if (ESR != ESR_Failed && !Scope.destroy())
+  return ESR_Failed;
+return ESR;
+  }
+}
+
+// No need to push an extra scope for these since they're already
+// CompoundStmts.
+EvalStmtResult ESR = ESR_Succeeded;
+for (const Stmt *Instantiation : Expansion->getInstantiations()) {
+  ESR = EvaluateStmt(Result, Info, Instantiation);
+  if (ESR == ESR_Failed ||
+  ShouldPropagateBreakContinue(Info, Expansion, &Scope, ESR))
+return ESR;
+  if (ESR != ESR_Continue) {
+// Succeeded here actually means we encountered a 'break'.
+assert(ESR == ESR_Succeeded || ESR == ESR_Returned);
+break;
+  }
+}
+
+// Map Continue back to Succeeded if we fell off the end of the loop.
+if (ESR == ESR_Continue)
+  ESR = ESR_Succeeded;
+
+return Scope.destroy() ? ESR : ESR_Failed;
+  }
+
   case Stmt::SwitchStmtClass:
 return EvaluateSwitch(Result, Info, cast(S));
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 3bc748969065a..c6541e453cfff 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -2027,6 +2027,9 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const 
FunctionDecl *Dcl,
   //   - using-enum-declaration
   continue;
 
+case Decl::CXXExpansionStmt:
+  continue;
+
 case Decl::Typedef:
 case Decl::TypeAlias: {
   //   - typedef declarations and alias-declarations that do not define
diff --git a/clang/test/SemaCXX/cxx2c-expansion-stmts.cpp 
b/clang/test/SemaCXX/cxx2c-expansion-stmts.cpp
new file mode 100644
index 0..71ce71c4f69fe
--- /dev/null
+++ b/clang/test/SemaCXX/cxx2c-expansion-stmts.cpp
@@ -0,0 +1,1042 @@
+// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -fdeclspec -fblocks -verify
+namespace std {
+template 
+struct initializer_list {
+  const T* a;
+  const T* b;
+  initializer_list(T* a, T* b): a{a}, b{b} {}
+};
+}
+
+struct S {
+  int x;
+  constexpr S(int x) : x{x} {}
+};
+
+void g(int); // #g
+template  constexpr int tg() { return n; }
+
+void f1() {
+  template for (auto x : {}) static_assert(false, "discarded");
+  template for (constexpr auto x : {}) static_assert(false, "discarded");
+  template for (auto x : {1}) g(x);
+  template for (auto x : {1, 2, 3}) g(x);
+  template for (constexpr auto x : {1}) g(x);
+  template for (constexpr auto x : {1, 2, 3}) g(x);
+  template for (constexpr auto x : {1}) tg();
+  template for (constexpr auto x : {1, 2, 3})
+static_assert(tg());
+
+  template for (int x : {1, 2, 3}) g(x);
+  template for (S x : {1, 2, 3}) g(x.x);
+  template for (constexpr S x : {1, 2, 3}) tg();
+
+  template for (int x : {"1", S(1), {1, 2}}) { // expected-error {{cannot 
initialize a variable of type 'int' with an lvalue of type 'const char[2]'}} \
+  expected-error {{no viable 
conversion from 'S' to 'int'}} \
+  expected-error {{excess 
elements in scalar initializer}} \
+  expected-note 3 {{in 
instantiation of expansion statement requested

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 11: Final Touches and Tests) (PR #169690)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169690

>From c8f44c08afd8fa2c818bcf563b8182c904790ad6 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 18:03:57 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 11)

---
 clang/docs/ReleaseNotes.rst   |   2 +
 .../clang/Basic/DiagnosticCommonKinds.td  |   4 -
 clang/test/AST/ast-dump-expansion-stmt.cpp|  49 +
 clang/test/AST/ast-print-expansion-stmts.cpp  | 104 ++
 clang/www/cxx_status.html |   2 +-
 5 files changed, 156 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/AST/ast-dump-expansion-stmt.cpp
 create mode 100644 clang/test/AST/ast-print-expansion-stmts.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f31e1c343e8aa..918515dbf127c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -189,6 +189,8 @@ C++2c Feature Support
   At this timem, references to constexpr and decomposition of *tuple-like* 
types are not supported
   (only arrays and aggregates are).
 
+- Implemented `P1306R5 `_ Expansion Statements.
+
 C++23 Feature Support
 ^
 
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td 
b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 0b9225980e826..6e50e225a8cc1 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -22,10 +22,6 @@ def select_constexpr_spec_kind : TextSubstitution<
 def fatal_too_many_errors
   : Error<"too many errors emitted, stopping now">, DefaultFatal;
 
-// TODO: Remove this.
-def err_expansion_statements_todo : Error<
-  "TODO (expansion statements)">;
-
 def warn_stack_exhausted : Warning<
   "stack nearly exhausted; compilation time may suffer, and "
   "crashes due to stack overflow are likely">,
diff --git a/clang/test/AST/ast-dump-expansion-stmt.cpp 
b/clang/test/AST/ast-dump-expansion-stmt.cpp
new file mode 100644
index 0..146157e2c13e6
--- /dev/null
+++ b/clang/test/AST/ast-dump-expansion-stmt.cpp
@@ -0,0 +1,49 @@
+// Test without serialization:
+// RUN: %clang_cc1 -std=c++26 -triple x86_64-unknown-unknown -ast-dump %s
+//
+// Test with serialization:
+// RUN: %clang_cc1 -std=c++26 -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -x c++ -std=c++26 -triple x86_64-unknown-unknown 
-include-pch %t -ast-dump-all /dev/null \
+// RUN: | sed -e "s/ //" -e "s/ imported//"
+
+template 
+struct Array {
+  T data[size]{};
+  constexpr const T* begin() const { return data; }
+  constexpr const T* end() const { return data + size; }
+};
+
+void foo(int);
+
+template 
+void test(T t) {
+  // CHECK:  CXXExpansionStmtDecl
+  // CHECK-NEXT:   CXXEnumeratingExpansionStmtPattern
+  // CHECK:CXXExpansionStmtInstantiation
+  template for (auto x : {1, 2, 3}) {
+foo(x);
+  }
+
+  // CHECK:  CXXExpansionStmtDecl
+  // CHECK-NEXT:   CXXIteratingExpansionStmtPattern
+  // CHECK:CXXExpansionStmtInstantiation
+  static constexpr Array a;
+  template for (auto x : a) {
+foo(x);
+  }
+
+  // CHECK:  CXXExpansionStmtDecl
+  // CHECK-NEXT:   CXXDestructuringExpansionStmtPattern
+  // CHECK:CXXExpansionStmtInstantiation
+  int arr[3]{1, 2, 3};
+  template for (auto x : arr) {
+foo(x);
+  }
+
+  // CHECK:  CXXExpansionStmtDecl
+  // CHECK-NEXT:   CXXDependentExpansionStmtPattern
+  // CHECK-NOT:CXXExpansionStmtInstantiation
+  template for (auto x : t) {
+foo(x);
+  }
+}
diff --git a/clang/test/AST/ast-print-expansion-stmts.cpp 
b/clang/test/AST/ast-print-expansion-stmts.cpp
new file mode 100644
index 0..bb9f79c6644c0
--- /dev/null
+++ b/clang/test/AST/ast-print-expansion-stmts.cpp
@@ -0,0 +1,104 @@
+// Without serialization:
+// RUN: %clang_cc1 -std=c++26 -ast-print %s | FileCheck %s
+//
+// With serialization:
+// RUN: %clang_cc1 -std=c++26 -emit-pch -o %t %s
+// RUN: %clang_cc1 -x c++ -std=c++26 -include-pch %t -ast-print  /dev/null | 
FileCheck %s
+
+template 
+struct Array {
+  T data[size]{};
+  constexpr const T* begin() const { return data; }
+  constexpr const T* end() const { return data + size; }
+};
+
+// CHECK: void foo(int);
+void foo(int);
+
+// CHECK: template  void test(T t) {
+template 
+void test(T t) {
+  // Enumerating expansion statement.
+  //
+  // CHECK:  template for (auto x : { 1, 2, 3 }) {
+  // CHECK-NEXT: foo(x);
+  // CHECK-NEXT: }
+  template for (auto x : {1, 2, 3}) {
+foo(x);
+  }
+
+  // Iterating expansion statement.
+  //
+  // CHECK:  static constexpr Array a;
+  // CHECK-NEXT: template for (auto x : a) {
+  // CHECK-NEXT:   foo(x);
+  // CHECK-NEXT: }
+  static constexpr Array a;
+  template for (auto x : a) {
+foo(x);
+  }
+
+  // Destructuring expansion statement.
+  //
+  // CHECK:  int arr[3]{1, 2, 3};
+  // CHECK-NEXT: template for (auto x : arr

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 10: Expansion Limit) (PR #169689)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169689

>From 4fa5064b267bca9100fe2ab9678df253cdfcdf4f Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:41:45 +0100
Subject: [PATCH 1/2] [Clang] [C++26] Expansion Statements (Part 10)

---
 .../clang/Basic/DiagnosticSemaKinds.td|  4 ++
 clang/include/clang/Basic/LangOptions.def |  1 +
 clang/include/clang/Options/Options.td|  4 ++
 clang/lib/Driver/ToolChains/Clang.cpp |  1 +
 clang/lib/Sema/SemaExpand.cpp | 18 +
 .../SemaCXX/cxx2c-expansion-stmts-limit.cpp   | 68 +++
 .../SemaCXX/cxx2c-fexpansion-statements.cpp   |  9 +++
 7 files changed, 105 insertions(+)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-limit.cpp
 create mode 100644 clang/test/SemaCXX/cxx2c-fexpansion-statements.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6994cd88fba21..71e4a178fe21d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -167,6 +167,10 @@ def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
 def err_expansion_size_expr_not_ice : Error<
   "expansion size is not a constant expression">;
+def err_expansion_too_big : Error<
+  "expansion size %0 exceeds maximum configured size %1">;
+def note_use_fexpansion_limit : Note<
+  "use -fexpansion-limit=N to adjust this limit">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
diff --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 40fc66ea12e34..315cb4dc5e1cf 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -377,6 +377,7 @@ LANGOPT(ConstexprCallDepth, 32, 512, Benign,
 "maximum constexpr call depth")
 LANGOPT(ConstexprStepLimit, 32, 1048576, Benign,
 "maximum constexpr evaluation steps")
+LANGOPT(MaxTemplateForExpansions, 32, 256, Benign, "maximum template for 
expansions")
 LANGOPT(EnableNewConstInterp, 1, 0, Benign,
 "enable the experimental new constant interpreter")
 LANGOPT(BracketDepth, 32, 256, Benign,
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index c6841937c8d39..8af98ec6afb50 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2064,6 +2064,10 @@ def fconstexpr_steps_EQ : Joined<["-"], 
"fconstexpr-steps=">, Group,
   Visibility<[ClangOption, CC1Option]>,
   HelpText<"Set the maximum number of steps in constexpr function evaluation 
(0 = no limit)">,
   MarshallingInfoInt, "1048576">;
+def fexpansion_limit_EQ : Joined<["-"], "fexpansion-limit=">, Group,
+  Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Set the maximum number of times a single expansion statement may 
be expanded (0 = no limit)">,
+  MarshallingInfoInt, "256">;
 def fexperimental_new_constant_interpreter : Flag<["-"], 
"fexperimental-new-constant-interpreter">, Group,
   HelpText<"Enable the experimental new constant interpreter">,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 0380568412e62..331a388eac573 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6369,6 +6369,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   Args.AddLastArg(CmdArgs, options::OPT_foperator_arrow_depth_EQ);
   Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_depth_EQ);
   Args.AddLastArg(CmdArgs, options::OPT_fconstexpr_steps_EQ);
+  Args.AddLastArg(CmdArgs, options::OPT_fexpansion_limit_EQ);
 
   Args.AddLastArg(CmdArgs, options::OPT_fexperimental_library);
 
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 6fa1ad9856783..8ca2b074acbea 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -44,6 +44,18 @@ struct IterableExpansionStmtData {
 };
 } // namespace
 
+static bool CheckExpansionSize(Sema &S, uint64_t NumInstantiations,
+   SourceLocation Loc) {
+  unsigned Max = S.LangOpts.MaxTemplateForExpansions;
+  if (Max != 0 && NumInstantiations > Max) {
+S.Diag(Loc, diag::err_expansion_too_big) << NumInstantiations << Max;
+S.Diag(Loc, diag::note_use_fexpansion_limit);
+return true;
+  }
+
+  return false;
+}
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -245,6 +257,9 @@ static StmtResult BuildDestructuringDecompositionDecl(
 return StmtError();
   }
 
+  if (CheckExpansionSize(S, *Arity, ColonLoc))
+return StmtError();
+
   QualType AutoRRef = S.Context.getAutoRRefDeductTyp

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 11: Final Touches and Tests) (PR #169690)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169690

>From c8f44c08afd8fa2c818bcf563b8182c904790ad6 Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 18:03:57 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 11)

---
 clang/docs/ReleaseNotes.rst   |   2 +
 .../clang/Basic/DiagnosticCommonKinds.td  |   4 -
 clang/test/AST/ast-dump-expansion-stmt.cpp|  49 +
 clang/test/AST/ast-print-expansion-stmts.cpp  | 104 ++
 clang/www/cxx_status.html |   2 +-
 5 files changed, 156 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/AST/ast-dump-expansion-stmt.cpp
 create mode 100644 clang/test/AST/ast-print-expansion-stmts.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f31e1c343e8aa..918515dbf127c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -189,6 +189,8 @@ C++2c Feature Support
   At this timem, references to constexpr and decomposition of *tuple-like* 
types are not supported
   (only arrays and aggregates are).
 
+- Implemented `P1306R5 `_ Expansion Statements.
+
 C++23 Feature Support
 ^
 
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td 
b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 0b9225980e826..6e50e225a8cc1 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -22,10 +22,6 @@ def select_constexpr_spec_kind : TextSubstitution<
 def fatal_too_many_errors
   : Error<"too many errors emitted, stopping now">, DefaultFatal;
 
-// TODO: Remove this.
-def err_expansion_statements_todo : Error<
-  "TODO (expansion statements)">;
-
 def warn_stack_exhausted : Warning<
   "stack nearly exhausted; compilation time may suffer, and "
   "crashes due to stack overflow are likely">,
diff --git a/clang/test/AST/ast-dump-expansion-stmt.cpp 
b/clang/test/AST/ast-dump-expansion-stmt.cpp
new file mode 100644
index 0..146157e2c13e6
--- /dev/null
+++ b/clang/test/AST/ast-dump-expansion-stmt.cpp
@@ -0,0 +1,49 @@
+// Test without serialization:
+// RUN: %clang_cc1 -std=c++26 -triple x86_64-unknown-unknown -ast-dump %s
+//
+// Test with serialization:
+// RUN: %clang_cc1 -std=c++26 -triple x86_64-unknown-unknown -emit-pch -o %t %s
+// RUN: %clang_cc1 -x c++ -std=c++26 -triple x86_64-unknown-unknown 
-include-pch %t -ast-dump-all /dev/null \
+// RUN: | sed -e "s/ //" -e "s/ imported//"
+
+template 
+struct Array {
+  T data[size]{};
+  constexpr const T* begin() const { return data; }
+  constexpr const T* end() const { return data + size; }
+};
+
+void foo(int);
+
+template 
+void test(T t) {
+  // CHECK:  CXXExpansionStmtDecl
+  // CHECK-NEXT:   CXXEnumeratingExpansionStmtPattern
+  // CHECK:CXXExpansionStmtInstantiation
+  template for (auto x : {1, 2, 3}) {
+foo(x);
+  }
+
+  // CHECK:  CXXExpansionStmtDecl
+  // CHECK-NEXT:   CXXIteratingExpansionStmtPattern
+  // CHECK:CXXExpansionStmtInstantiation
+  static constexpr Array a;
+  template for (auto x : a) {
+foo(x);
+  }
+
+  // CHECK:  CXXExpansionStmtDecl
+  // CHECK-NEXT:   CXXDestructuringExpansionStmtPattern
+  // CHECK:CXXExpansionStmtInstantiation
+  int arr[3]{1, 2, 3};
+  template for (auto x : arr) {
+foo(x);
+  }
+
+  // CHECK:  CXXExpansionStmtDecl
+  // CHECK-NEXT:   CXXDependentExpansionStmtPattern
+  // CHECK-NOT:CXXExpansionStmtInstantiation
+  template for (auto x : t) {
+foo(x);
+  }
+}
diff --git a/clang/test/AST/ast-print-expansion-stmts.cpp 
b/clang/test/AST/ast-print-expansion-stmts.cpp
new file mode 100644
index 0..bb9f79c6644c0
--- /dev/null
+++ b/clang/test/AST/ast-print-expansion-stmts.cpp
@@ -0,0 +1,104 @@
+// Without serialization:
+// RUN: %clang_cc1 -std=c++26 -ast-print %s | FileCheck %s
+//
+// With serialization:
+// RUN: %clang_cc1 -std=c++26 -emit-pch -o %t %s
+// RUN: %clang_cc1 -x c++ -std=c++26 -include-pch %t -ast-print  /dev/null | 
FileCheck %s
+
+template 
+struct Array {
+  T data[size]{};
+  constexpr const T* begin() const { return data; }
+  constexpr const T* end() const { return data + size; }
+};
+
+// CHECK: void foo(int);
+void foo(int);
+
+// CHECK: template  void test(T t) {
+template 
+void test(T t) {
+  // Enumerating expansion statement.
+  //
+  // CHECK:  template for (auto x : { 1, 2, 3 }) {
+  // CHECK-NEXT: foo(x);
+  // CHECK-NEXT: }
+  template for (auto x : {1, 2, 3}) {
+foo(x);
+  }
+
+  // Iterating expansion statement.
+  //
+  // CHECK:  static constexpr Array a;
+  // CHECK-NEXT: template for (auto x : a) {
+  // CHECK-NEXT:   foo(x);
+  // CHECK-NEXT: }
+  static constexpr Array a;
+  template for (auto x : a) {
+foo(x);
+  }
+
+  // Destructuring expansion statement.
+  //
+  // CHECK:  int arr[3]{1, 2, 3};
+  // CHECK-NEXT: template for (auto x : arr

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 3: Enumerating Expansion Statements) (PR #169682)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169682

>From 1861f5a04b849455139583c37dce3dfa3a0f445b Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Tue, 25 Nov 2025 20:47:23 +0100
Subject: [PATCH 1/4] [Clang] [C++26] Expansion Statements (Part 3)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   2 +
 clang/include/clang/Sema/Sema.h   |  22 +++
 clang/lib/Frontend/FrontendActions.cpp|   2 +
 clang/lib/Sema/SemaExpand.cpp | 151 ++
 clang/lib/Sema/SemaTemplateInstantiate.cpp|  29 +++-
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |  38 -
 clang/lib/Sema/SemaTemplateVariadic.cpp   |   8 +-
 clang/lib/Sema/TreeTransform.h|  83 +-
 .../Parser/cxx2c-expansion-statements.cpp |  80 +-
 9 files changed, 365 insertions(+), 50 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d97bc41302c26..fea25ef6a0734 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5842,6 +5842,8 @@ def note_template_nsdmi_here : Note<
   "in instantiation of default member initializer %q0 requested here">;
 def note_template_type_alias_instantiation_here : Note<
   "in instantiation of template type alias %0 requested here">;
+def note_expansion_stmt_instantiation_here : Note<
+  "in instantiation of expansion statement requested here">;
 def note_template_exception_spec_instantiation_here : Note<
   "in instantiation of exception specification for %0 requested here">;
 def note_template_requirement_instantiation_here : Note<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b40c96fd48851..3b14f4d605b61 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -13177,6 +13177,9 @@ class Sema final : public SemaBase {
 
   /// We are performing partial ordering for template template parameters.
   PartialOrderingTTP,
+
+  /// We are instantiating an expansion statement.
+  ExpansionStmtInstantiation,
 } Kind;
 
 /// Whether we're substituting into constraints.
@@ -13372,6 +13375,12 @@ class Sema final : public SemaBase {
   concepts::Requirement *Req,
   SourceRange InstantiationRange = SourceRange());
 
+/// \brief Note that we are substituting the body of an expansion 
statement.
+InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
+  CXXExpansionStmtPattern *ExpansionStmt,
+  ArrayRef TArgs,
+  SourceRange InstantiationRange);
+
 /// \brief Note that we are checking the satisfaction of the constraint
 /// expression inside of a nested requirement.
 InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
@@ -15644,6 +15653,19 @@ class Sema final : public SemaBase {
   ArrayRef LifetimeExtendTemps);
 
   StmtResult FinishCXXExpansionStmt(Stmt *Expansion, Stmt *Body);
+
+  StmtResult BuildCXXEnumeratingExpansionStmtPattern(Decl *ESD, Stmt *Init,
+ Stmt *ExpansionVar,
+ SourceLocation LParenLoc,
+ SourceLocation ColonLoc,
+ SourceLocation RParenLoc);
+
+  ExprResult
+  BuildCXXExpansionInitListSelectExpr(CXXExpansionInitListExpr *Range,
+  Expr *Idx);
+
+  std::optional
+  ComputeExpansionSize(CXXExpansionStmtPattern *Expansion);
   ///@}
 };
 
diff --git a/clang/lib/Frontend/FrontendActions.cpp 
b/clang/lib/Frontend/FrontendActions.cpp
index e0c1d304e8290..75d5a76c04a32 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -476,6 +476,8 @@ class DefaultTemplateInstCallback : public 
TemplateInstantiationCallback {
   return "TypeAliasTemplateInstantiation";
 case CodeSynthesisContext::PartialOrderingTTP:
   return "PartialOrderingTTP";
+case CodeSynthesisContext::ExpansionStmtInstantiation:
+  return "ExpansionStmtInstantiation";
 }
 return "";
   }
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index 96c0d9be9451c..f1cd2baa9ae39 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -24,6 +24,23 @@
 using namespace clang;
 using namespace sema;
 
+// Build a 'DeclRefExpr' designating the template parameter '__N'.
+static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
+  return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
+S.Context.getPointerDiffType(), VK_PRValue,
+ESD->getBeginLoc());
+}
+
+static bool FinaliseExpansionVar(Sema &S, VarDecl *Expan

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 31dfa44cec804e7f9850524ef0b60f8ccfcedc3b Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 208c885909b00..6994cd88fba21 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3720,6 +3720,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0adc570c73011..5a3603c284cd1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9531,7 +9531,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 59eac05e8f39e..73f1d1a7b46fd 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -744,8 +744,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -789,6 +790,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 90eee36d7dbe6..169e1d1cf1cb5 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4466,7 +4466,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 5: Iterating Expansion Statements) (PR #169684)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169684

>From 778c6a7efd7a4f330ab81d8aae7cddebe516c8ec Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 16:18:02 +0100
Subject: [PATCH 1/9] [Clang] [C++26] Expansion Statements (Part 5)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   7 +
 clang/include/clang/Sema/Sema.h   |   6 +
 clang/lib/Sema/SemaExpand.cpp | 257 +-
 clang/lib/Sema/SemaStmt.cpp   |  13 +-
 clang/lib/Sema/TreeTransform.h|  14 +
 5 files changed, 291 insertions(+), 6 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index fea25ef6a0734..0ce3d8164d955 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -165,6 +165,10 @@ def err_ice_too_large : Error<
 def err_expr_not_string_literal : Error<"expression is not a string literal">;
 def note_constexpr_assert_failed : Note<
   "assertion failed during evaluation of constant expression">;
+def err_expansion_size_expr_not_ice : Error<
+  "expansion size is not a constant expression">;
+def err_expansion_size_negative : Error<
+  "expansion size must not be negative (was %0)">;
 
 // Semantic analysis of constant literals.
 def ext_predef_outside_function : Warning<
@@ -3710,6 +3714,9 @@ def err_conflicting_codeseg_attribute : Error<
 def warn_duplicate_codeseg_attribute : Warning<
   "duplicate code segment specifiers">, InGroup;
 
+def err_expansion_stmt_lambda : Error<
+  "cannot expand lambda closure type">;
+
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
 "valid for this target: %0">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 5dee71b23422e..0adc570c73011 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -15705,6 +15705,12 @@ class Sema final : public SemaBase {
  SourceLocation ColonLoc,
  SourceLocation RParenLoc);
 
+  StmtResult BuildNonEnumeratingCXXExpansionStmtPattern(
+  CXXExpansionStmtDecl *ESD, Stmt *Init, DeclStmt *ExpansionVarStmt,
+  Expr *ExpansionInitializer, SourceLocation LParenLoc,
+  SourceLocation ColonLoc, SourceLocation RParenLoc,
+  ArrayRef LifetimeExtendTemps = {});
+
   ExprResult BuildCXXExpansionSelectExpr(InitListExpr *Range, Expr *Idx);
 
   std::optional
diff --git a/clang/lib/Sema/SemaExpand.cpp b/clang/lib/Sema/SemaExpand.cpp
index a0f5e852ebdb1..4e392e33578e2 100644
--- a/clang/lib/Sema/SemaExpand.cpp
+++ b/clang/lib/Sema/SemaExpand.cpp
@@ -24,6 +24,25 @@
 using namespace clang;
 using namespace sema;
 
+namespace {
+struct IterableExpansionStmtData {
+  enum class State {
+NotIterable,
+Error,
+Ok,
+  };
+
+  DeclStmt *RangeDecl = nullptr;
+  DeclStmt *BeginDecl = nullptr;
+  DeclStmt *EndDecl = nullptr;
+  Expr *Initializer = nullptr;
+  State TheState = State::NotIterable;
+
+  bool isIterable() const { return TheState == State::Ok; }
+  bool hasError() { return TheState == State::Error; }
+};
+} // namespace
+
 // Build a 'DeclRefExpr' designating the template parameter '__N'.
 static DeclRefExpr *BuildIndexDRE(Sema &S, CXXExpansionStmtDecl *ESD) {
   return S.BuildDeclRefExpr(ESD->getIndexTemplateParm(),
@@ -55,15 +74,134 @@ static bool HasDependentSize(const CXXExpansionStmtPattern 
*Pattern) {
 return InitListContainsPack(SelectExpr->getRangeExpr());
   }
 
-  case CXXExpansionStmtPattern::ExpansionStmtKind::Iterating:
-  case CXXExpansionStmtPattern::ExpansionStmtKind::Destructuring:
+  case CXXExpansionStmtPattern::ExpansionStmtKind::Iterating: {
+const Expr *Begin = Pattern->getBeginVar()->getInit();
+const Expr *End = Pattern->getEndVar()->getInit();
+return Begin->isInstantiationDependent() || 
End->isInstantiationDependent();
+  }
+
   case CXXExpansionStmtPattern::ExpansionStmtKind::Dependent:
+return true;
+
+  case CXXExpansionStmtPattern::ExpansionStmtKind::Destructuring:
 llvm_unreachable("TODO");
   }
 
   llvm_unreachable("invalid pattern kind");
 }
 
+static IterableExpansionStmtData
+TryBuildIterableExpansionStmtInitializer(Sema &S, Expr *ExpansionInitializer,
+ Expr *Index, SourceLocation ColonLoc,
+ bool VarIsConstexpr) {
+  IterableExpansionStmtData Data;
+
+  // C++26 [stmt.expand]p3: An expression is expansion-iterable if it does not
+  // have array type [...]
+  QualType Ty = ExpansionInitializer->getType().getNonReferenceType();
+  if (Ty->isArrayType())
+return Data;
+
+  // Lookup member and ADL 'begin()'/'end()'. Only check if they exist; even if
+  // they're deleted, inaccessible, etc., t

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 9: Control Flow) (PR #169688)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide updated 
https://github.com/llvm/llvm-project/pull/169688

>From 31dfa44cec804e7f9850524ef0b60f8ccfcedc3b Mon Sep 17 00:00:00 2001
From: Sirraide 
Date: Wed, 26 Nov 2025 17:21:39 +0100
Subject: [PATCH] [Clang] [C++26] Expansion Statements (Part 9)

---
 .../clang/Basic/DiagnosticSemaKinds.td|   6 +
 clang/include/clang/Sema/ScopeInfo.h  |   6 +-
 clang/include/clang/Sema/Sema.h   |   3 +-
 clang/lib/Parse/ParseStmt.cpp |  11 +-
 clang/lib/Sema/SemaLookup.cpp |  47 +--
 clang/lib/Sema/SemaStmt.cpp   |  30 -
 .../cxx2c-expansion-stmts-control-flow.cpp| 117 ++
 7 files changed, 205 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/SemaCXX/cxx2c-expansion-stmts-control-flow.cpp

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 208c885909b00..6994cd88fba21 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3720,6 +3720,12 @@ def err_expansion_stmt_incomplete : Error<
   "cannot expand expression of incomplete type %0">;
 def err_expansion_stmt_lambda : Error<
   "cannot expand lambda closure type">;
+def err_expansion_stmt_case : Error<
+  "%select{'case'|'default'}0 belongs to 'switch' outside enclosing expansion 
statement">;
+def note_enclosing_switch_statement_here : Note<
+  "switch statement is here">;
+def err_expansion_stmt_label : Error<
+  "labels are not allowed in expansion statements">;
 
 def err_attribute_patchable_function_entry_invalid_section
 : Error<"section argument to 'patchable_function_entry' attribute is not "
diff --git a/clang/include/clang/Sema/ScopeInfo.h 
b/clang/include/clang/Sema/ScopeInfo.h
index 4f4d38c961140..2a410bd2eab91 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -202,7 +202,11 @@ class FunctionScopeInfo {
 public:
   /// A SwitchStmt, along with a flag indicating if its list of case statements
   /// is incomplete (because we dropped an invalid one while parsing).
-  using SwitchInfo = llvm::PointerIntPair;
+  struct SwitchInfo : llvm::PointerIntPair {
+DeclContext *EnclosingDC;
+SwitchInfo(SwitchStmt *Switch, DeclContext *DC)
+: PointerIntPair(Switch, false), EnclosingDC(DC) {}
+  };
 
   /// SwitchStack - This is the current set of active switch statements in the
   /// block.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0adc570c73011..5a3603c284cd1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -9531,7 +9531,8 @@ class Sema final : public SemaBase {
   /// of an __label__ label name, otherwise it is a normal label definition
   /// or use.
   LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc,
- SourceLocation GnuLabelLoc = 
SourceLocation());
+ SourceLocation GnuLabelLoc = SourceLocation(),
+ bool ForLabelStmt = false);
 
   /// Perform a name lookup for a label with the specified name; this does not
   /// create a new label if the lookup fails.
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 59eac05e8f39e..73f1d1a7b46fd 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -744,8 +744,9 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
   // identifier ':' statement
   SourceLocation ColonLoc = ConsumeToken();
 
-  LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
-  IdentTok.getLocation());
+  LabelDecl *LD = Actions.LookupOrCreateLabel(
+  IdentTok.getIdentifierInfo(), IdentTok.getLocation(), /*GnuLabelLoc=*/{},
+  /*ForLabelStmt=*/true);
 
   // Read label attributes, if present.
   StmtResult SubStmt;
@@ -789,6 +790,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes 
&Attrs,
 
   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
 
+  // If a label cannot appear here, just return the underlying statement.
+  if (!LD) {
+Attrs.clear();
+return SubStmt.get();
+  }
+
   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
   Attrs.clear();
 
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 90eee36d7dbe6..169e1d1cf1cb5 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -4466,7 +4466,8 @@ LabelDecl *Sema::LookupExistingLabel(IdentifierInfo *II, 
SourceLocation Loc) {
 }
 
 LabelDecl *Sema::LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc,
- SourceLocation GnuLabelLoc) {
+ SourceLocation GnuLabelLoc,
+ bool ForLabelStmt) {
   if (GnuLabelLoc.isValid()) {
 /

[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 7: Constexpr support and tests) (PR #169686)

2025-12-05 Thread via llvm-branch-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 origin/main HEAD --extensions h,cpp -- 
clang/test/SemaCXX/cxx2c-expansion-stmts.cpp 
clang/lib/AST/ByteCode/Compiler.cpp clang/lib/AST/ByteCode/Compiler.h 
clang/lib/AST/ExprConstant.cpp clang/lib/Sema/SemaDeclCXX.cpp 
--diff_from_common_commit
``

:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:





View the diff from clang-format here.


``diff
diff --git a/clang/lib/AST/ByteCode/Compiler.h 
b/clang/lib/AST/ByteCode/Compiler.h
index 2585b60df..70d5f6197 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -249,6 +249,7 @@ public:
   bool visitCXXTryStmt(const CXXTryStmt *S);
   bool
   visitCXXExpansionStmtInstantiation(const CXXExpansionStmtInstantiation *S);
+
 protected:
   bool visitStmt(const Stmt *S);
   bool visitExpr(const Expr *E, bool DestroyToplevelScope) override;

``




https://github.com/llvm/llvm-project/pull/169686
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Clang] [C++26] Expansion Statements (Part 7: Constexpr support and tests) (PR #169686)

2025-12-05 Thread via llvm-branch-commits

https://github.com/Sirraide edited 
https://github.com/llvm/llvm-project/pull/169686
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] SROA: Recognize llvm.protected.field.ptr intrinsics. (PR #151650)

2025-12-05 Thread Nikita Popov via llvm-branch-commits


@@ -5875,6 +5895,32 @@ SROA::runOnAlloca(AllocaInst &AI) {
 return {Changed, CFGChanged};
   }
 
+  for (auto &P : AS.partitions()) {
+std::optional ProtectedFieldDisc;
+// For now, we can't split if a field is accessed both via protected
+// field and not.
+for (Slice &S : P) {
+  if (auto *II = dyn_cast(S.getUse()->getUser()))
+if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
+II->getIntrinsicID() == Intrinsic::lifetime_end)
+  continue;
+  if (!ProtectedFieldDisc)
+ProtectedFieldDisc = S.ProtectedFieldDisc;
+  if (*ProtectedFieldDisc != S.ProtectedFieldDisc)

nikic wrote:

Is there test coverage for this?

https://github.com/llvm/llvm-project/pull/151650
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [AMDGPU] Add builtins for wave reduction intrinsics (PR #170813)

2025-12-05 Thread via llvm-branch-commits

https://github.com/easyonaadit created 
https://github.com/llvm/llvm-project/pull/170813

None

>From c266d8cd285436f91dbbd13255a9fca52b65f232 Mon Sep 17 00:00:00 2001
From: Aaditya 
Date: Fri, 5 Dec 2025 14:03:36 +0530
Subject: [PATCH] [AMDGPU] Add builtins for wave reduction intrinsics

---
 clang/include/clang/Basic/BuiltinsAMDGPU.def |  4 +
 clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp  |  8 ++
 clang/test/CodeGenOpenCL/builtins-amdgcn.cl  | 84 
 3 files changed, 96 insertions(+)

diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def 
b/clang/include/clang/Basic/BuiltinsAMDGPU.def
index 8af6ce1528a45..c6a275d5db9f2 100644
--- a/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -406,6 +406,10 @@ BUILTIN(__builtin_amdgcn_wave_reduce_fadd_f32, "ffZi", 
"nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fsub_f32, "ffZi", "nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fmin_f32, "ffZi", "nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fmax_f32, "ffZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fadd_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fsub_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fmin_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fmax_f64, "ddZi", "nc")
 
 
//===--===//
 // R600-NI only builtins.
diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp 
b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
index eabdc370da6b4..673d2752ee3e1 100644
--- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
@@ -374,16 +374,19 @@ static Intrinsic::ID 
getIntrinsicIDforWaveReduction(unsigned BuiltinID) {
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_add_u64:
 return Intrinsic::amdgcn_wave_reduce_add;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f64:
 return Intrinsic::amdgcn_wave_reduce_fadd;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u64:
 return Intrinsic::amdgcn_wave_reduce_sub;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f64:
 return Intrinsic::amdgcn_wave_reduce_fsub;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i64:
 return Intrinsic::amdgcn_wave_reduce_min;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f64:
 return Intrinsic::amdgcn_wave_reduce_fmin;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u64:
@@ -392,6 +395,7 @@ static Intrinsic::ID 
getIntrinsicIDforWaveReduction(unsigned BuiltinID) {
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_i64:
 return Intrinsic::amdgcn_wave_reduce_max;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f64:
 return Intrinsic::amdgcn_wave_reduce_fmax;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u64:
@@ -415,14 +419,18 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned 
BuiltinID,
   switch (BuiltinID) {
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_add_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_max_i32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_and_b32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_or_b32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_xor_b32:
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl 
b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
index a5132c9114673..39f140ababab2 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
@@ -412,6 +412,13 @@ void test_wave_reduce_fadd_f32_default(global float* out, 
float in)
   *out = __builtin_amdgcn_wave_reduce_fadd_f32(in, 0);
 }
 
+// CHECK-LABEL: @test_wave_reduce_fadd_f64_default
+// CHECK: {{.*}}call{{.*}} double @llvm.amdgcn.wave.reduce.fadd.f64(
+void test_wave_reduce_fadd_f64_default(global double* out,

[llvm-branch-commits] [llvm] [AMDGPU] Add wave reduce intrinsics for double types - 2 (PR #170812)

2025-12-05 Thread via llvm-branch-commits

easyonaadit wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/170812?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#170813** https://app.graphite.com/github/pr/llvm/llvm-project/170813?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* **#170812** https://app.graphite.com/github/pr/llvm/llvm-project/170812?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/170812?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#170811** https://app.graphite.com/github/pr/llvm/llvm-project/170811?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `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/170812
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [AMDGPU] Add builtins for wave reduction intrinsics (PR #170813)

2025-12-05 Thread via llvm-branch-commits

easyonaadit wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/170813?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#170813** https://app.graphite.com/github/pr/llvm/llvm-project/170813?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/170813?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#170812** https://app.graphite.com/github/pr/llvm/llvm-project/170812?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* **#170811** https://app.graphite.com/github/pr/llvm/llvm-project/170811?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `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/170813
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [AMDGPU] Add builtins for wave reduction intrinsics (PR #170813)

2025-12-05 Thread via llvm-branch-commits

https://github.com/easyonaadit updated 
https://github.com/llvm/llvm-project/pull/170813

>From 96454902e2f60703e70a58248c4a928d9b40c014 Mon Sep 17 00:00:00 2001
From: Aaditya 
Date: Fri, 5 Dec 2025 14:03:36 +0530
Subject: [PATCH] [AMDGPU] Add builtins for wave reduction intrinsics

---
 clang/include/clang/Basic/BuiltinsAMDGPU.def |  4 +
 clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp  |  8 ++
 clang/test/CodeGenOpenCL/builtins-amdgcn.cl  | 84 
 3 files changed, 96 insertions(+)

diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def 
b/clang/include/clang/Basic/BuiltinsAMDGPU.def
index 8af6ce1528a45..c6a275d5db9f2 100644
--- a/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -406,6 +406,10 @@ BUILTIN(__builtin_amdgcn_wave_reduce_fadd_f32, "ffZi", 
"nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fsub_f32, "ffZi", "nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fmin_f32, "ffZi", "nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fmax_f32, "ffZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fadd_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fsub_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fmin_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fmax_f64, "ddZi", "nc")
 
 
//===--===//
 // R600-NI only builtins.
diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp 
b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
index eabdc370da6b4..673d2752ee3e1 100644
--- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
@@ -374,16 +374,19 @@ static Intrinsic::ID 
getIntrinsicIDforWaveReduction(unsigned BuiltinID) {
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_add_u64:
 return Intrinsic::amdgcn_wave_reduce_add;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f64:
 return Intrinsic::amdgcn_wave_reduce_fadd;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u64:
 return Intrinsic::amdgcn_wave_reduce_sub;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f64:
 return Intrinsic::amdgcn_wave_reduce_fsub;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i64:
 return Intrinsic::amdgcn_wave_reduce_min;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f64:
 return Intrinsic::amdgcn_wave_reduce_fmin;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u64:
@@ -392,6 +395,7 @@ static Intrinsic::ID 
getIntrinsicIDforWaveReduction(unsigned BuiltinID) {
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_i64:
 return Intrinsic::amdgcn_wave_reduce_max;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f64:
 return Intrinsic::amdgcn_wave_reduce_fmax;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u64:
@@ -415,14 +419,18 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned 
BuiltinID,
   switch (BuiltinID) {
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_add_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_max_i32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_and_b32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_or_b32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_xor_b32:
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl 
b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
index a5132c9114673..39f140ababab2 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
@@ -412,6 +412,13 @@ void test_wave_reduce_fadd_f32_default(global float* out, 
float in)
   *out = __builtin_amdgcn_wave_reduce_fadd_f32(in, 0);
 }
 
+// CHECK-LABEL: @test_wave_reduce_fadd_f64_default
+// CHECK: {{.*}}call{{.*}} double @llvm.amdgcn.wave.reduce.fadd.f64(
+void test_wave_reduce_fadd_f64_default(global double* out, doubl

[llvm-branch-commits] [clang] [AMDGPU] Add builtins for wave reduction intrinsics (PR #170813)

2025-12-05 Thread via llvm-branch-commits

https://github.com/easyonaadit updated 
https://github.com/llvm/llvm-project/pull/170813

>From 96454902e2f60703e70a58248c4a928d9b40c014 Mon Sep 17 00:00:00 2001
From: Aaditya 
Date: Fri, 5 Dec 2025 14:03:36 +0530
Subject: [PATCH] [AMDGPU] Add builtins for wave reduction intrinsics

---
 clang/include/clang/Basic/BuiltinsAMDGPU.def |  4 +
 clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp  |  8 ++
 clang/test/CodeGenOpenCL/builtins-amdgcn.cl  | 84 
 3 files changed, 96 insertions(+)

diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def 
b/clang/include/clang/Basic/BuiltinsAMDGPU.def
index 8af6ce1528a45..c6a275d5db9f2 100644
--- a/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -406,6 +406,10 @@ BUILTIN(__builtin_amdgcn_wave_reduce_fadd_f32, "ffZi", 
"nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fsub_f32, "ffZi", "nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fmin_f32, "ffZi", "nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fmax_f32, "ffZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fadd_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fsub_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fmin_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fmax_f64, "ddZi", "nc")
 
 
//===--===//
 // R600-NI only builtins.
diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp 
b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
index eabdc370da6b4..673d2752ee3e1 100644
--- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
@@ -374,16 +374,19 @@ static Intrinsic::ID 
getIntrinsicIDforWaveReduction(unsigned BuiltinID) {
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_add_u64:
 return Intrinsic::amdgcn_wave_reduce_add;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f64:
 return Intrinsic::amdgcn_wave_reduce_fadd;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u64:
 return Intrinsic::amdgcn_wave_reduce_sub;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f64:
 return Intrinsic::amdgcn_wave_reduce_fsub;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i64:
 return Intrinsic::amdgcn_wave_reduce_min;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f64:
 return Intrinsic::amdgcn_wave_reduce_fmin;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u64:
@@ -392,6 +395,7 @@ static Intrinsic::ID 
getIntrinsicIDforWaveReduction(unsigned BuiltinID) {
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_i64:
 return Intrinsic::amdgcn_wave_reduce_max;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f64:
 return Intrinsic::amdgcn_wave_reduce_fmax;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u64:
@@ -415,14 +419,18 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned 
BuiltinID,
   switch (BuiltinID) {
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_add_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_max_i32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_and_b32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_or_b32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_xor_b32:
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl 
b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
index a5132c9114673..39f140ababab2 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
@@ -412,6 +412,13 @@ void test_wave_reduce_fadd_f32_default(global float* out, 
float in)
   *out = __builtin_amdgcn_wave_reduce_fadd_f32(in, 0);
 }
 
+// CHECK-LABEL: @test_wave_reduce_fadd_f64_default
+// CHECK: {{.*}}call{{.*}} double @llvm.amdgcn.wave.reduce.fadd.f64(
+void test_wave_reduce_fadd_f64_default(global double* out, doubl

[llvm-branch-commits] SROA: Recognize llvm.protected.field.ptr intrinsics. (PR #151650)

2025-12-05 Thread Nikita Popov via llvm-branch-commits


@@ -158,6 +159,10 @@ class PtrUseVisitorBase {
   /// The constant offset of the use if that is known.
   APInt Offset;
 
+  // When this access is via an llvm.protected.field.ptr intrinsic, contains
+  // the second argument to the intrinsic, the discriminator.
+  Value *ProtectedFieldDisc;

nikic wrote:

Hm, it would be really good to implement this in a way that does not require 
hardcoding knowledge about pointer field protection into the generic 
PtrUseVisitor. Can the matching discriminants be verified in some other way 
(based on PFPUsers or so)?

https://github.com/llvm/llvm-project/pull/151650
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [TableGen] Slightly improve error location for a fatal error (PR #170790)

2025-12-05 Thread Matt Arsenault via llvm-branch-commits

https://github.com/arsenm approved this pull request.


https://github.com/llvm/llvm-project/pull/170790
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [AMDGPU] Simplify dpp builtin handling (PR #115090)

2025-12-05 Thread Stanislav Mekhanoshin via llvm-branch-commits

https://github.com/rampitec closed 
https://github.com/llvm/llvm-project/pull/115090
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [AMDGPU] Simplify dpp builtin handling (PR #115090)

2025-12-05 Thread Stanislav Mekhanoshin via llvm-branch-commits

rampitec wrote:

Closing this because of no interest, and because I no longer trust Graphite 
after the latest npm security issue.

https://github.com/llvm/llvm-project/pull/115090
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [AMDGPU] Add builtins for wave reduction intrinsics (PR #170813)

2025-12-05 Thread via llvm-branch-commits

https://github.com/easyonaadit updated 
https://github.com/llvm/llvm-project/pull/170813

>From 2a3eeae12e684c995d98c6ac5783de8d120be0ad Mon Sep 17 00:00:00 2001
From: Aaditya 
Date: Fri, 5 Dec 2025 14:03:36 +0530
Subject: [PATCH] [AMDGPU] Add builtins for wave reduction intrinsics

---
 clang/include/clang/Basic/BuiltinsAMDGPU.def |  4 +
 clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp  |  8 ++
 clang/test/CodeGenOpenCL/builtins-amdgcn.cl  | 84 
 3 files changed, 96 insertions(+)

diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def 
b/clang/include/clang/Basic/BuiltinsAMDGPU.def
index 8af6ce1528a45..c6a275d5db9f2 100644
--- a/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -406,6 +406,10 @@ BUILTIN(__builtin_amdgcn_wave_reduce_fadd_f32, "ffZi", 
"nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fsub_f32, "ffZi", "nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fmin_f32, "ffZi", "nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fmax_f32, "ffZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fadd_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fsub_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fmin_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fmax_f64, "ddZi", "nc")
 
 
//===--===//
 // R600-NI only builtins.
diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp 
b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
index eabdc370da6b4..673d2752ee3e1 100644
--- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
@@ -374,16 +374,19 @@ static Intrinsic::ID 
getIntrinsicIDforWaveReduction(unsigned BuiltinID) {
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_add_u64:
 return Intrinsic::amdgcn_wave_reduce_add;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f64:
 return Intrinsic::amdgcn_wave_reduce_fadd;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u64:
 return Intrinsic::amdgcn_wave_reduce_sub;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f64:
 return Intrinsic::amdgcn_wave_reduce_fsub;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i64:
 return Intrinsic::amdgcn_wave_reduce_min;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f64:
 return Intrinsic::amdgcn_wave_reduce_fmin;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u64:
@@ -392,6 +395,7 @@ static Intrinsic::ID 
getIntrinsicIDforWaveReduction(unsigned BuiltinID) {
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_i64:
 return Intrinsic::amdgcn_wave_reduce_max;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f64:
 return Intrinsic::amdgcn_wave_reduce_fmax;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u64:
@@ -415,14 +419,18 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned 
BuiltinID,
   switch (BuiltinID) {
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_add_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_max_i32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_and_b32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_or_b32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_xor_b32:
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl 
b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
index a5132c9114673..39f140ababab2 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
@@ -412,6 +412,13 @@ void test_wave_reduce_fadd_f32_default(global float* out, 
float in)
   *out = __builtin_amdgcn_wave_reduce_fadd_f32(in, 0);
 }
 
+// CHECK-LABEL: @test_wave_reduce_fadd_f64_default
+// CHECK: {{.*}}call{{.*}} double @llvm.amdgcn.wave.reduce.fadd.f64(
+void test_wave_reduce_fadd_f64_default(global double* out, doubl

[llvm-branch-commits] [clang] [AMDGPU] Add builtins for wave reduction intrinsics (PR #170813)

2025-12-05 Thread via llvm-branch-commits

https://github.com/easyonaadit updated 
https://github.com/llvm/llvm-project/pull/170813

>From 2a3eeae12e684c995d98c6ac5783de8d120be0ad Mon Sep 17 00:00:00 2001
From: Aaditya 
Date: Fri, 5 Dec 2025 14:03:36 +0530
Subject: [PATCH] [AMDGPU] Add builtins for wave reduction intrinsics

---
 clang/include/clang/Basic/BuiltinsAMDGPU.def |  4 +
 clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp  |  8 ++
 clang/test/CodeGenOpenCL/builtins-amdgcn.cl  | 84 
 3 files changed, 96 insertions(+)

diff --git a/clang/include/clang/Basic/BuiltinsAMDGPU.def 
b/clang/include/clang/Basic/BuiltinsAMDGPU.def
index 8af6ce1528a45..c6a275d5db9f2 100644
--- a/clang/include/clang/Basic/BuiltinsAMDGPU.def
+++ b/clang/include/clang/Basic/BuiltinsAMDGPU.def
@@ -406,6 +406,10 @@ BUILTIN(__builtin_amdgcn_wave_reduce_fadd_f32, "ffZi", 
"nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fsub_f32, "ffZi", "nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fmin_f32, "ffZi", "nc")
 BUILTIN(__builtin_amdgcn_wave_reduce_fmax_f32, "ffZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fadd_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fsub_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fmin_f64, "ddZi", "nc")
+BUILTIN(__builtin_amdgcn_wave_reduce_fmax_f64, "ddZi", "nc")
 
 
//===--===//
 // R600-NI only builtins.
diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp 
b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
index eabdc370da6b4..673d2752ee3e1 100644
--- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
@@ -374,16 +374,19 @@ static Intrinsic::ID 
getIntrinsicIDforWaveReduction(unsigned BuiltinID) {
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_add_u64:
 return Intrinsic::amdgcn_wave_reduce_add;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f64:
 return Intrinsic::amdgcn_wave_reduce_fadd;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u64:
 return Intrinsic::amdgcn_wave_reduce_sub;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f64:
 return Intrinsic::amdgcn_wave_reduce_fsub;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i64:
 return Intrinsic::amdgcn_wave_reduce_min;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f64:
 return Intrinsic::amdgcn_wave_reduce_fmin;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u64:
@@ -392,6 +395,7 @@ static Intrinsic::ID 
getIntrinsicIDforWaveReduction(unsigned BuiltinID) {
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_i64:
 return Intrinsic::amdgcn_wave_reduce_max;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f32:
+  case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f64:
 return Intrinsic::amdgcn_wave_reduce_fmax;
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u32:
   case clang::AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u64:
@@ -415,14 +419,18 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned 
BuiltinID,
   switch (BuiltinID) {
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_add_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fadd_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_sub_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fsub_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_min_i32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_min_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmin_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_max_i32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_max_u32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f32:
+  case AMDGPU::BI__builtin_amdgcn_wave_reduce_fmax_f64:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_and_b32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_or_b32:
   case AMDGPU::BI__builtin_amdgcn_wave_reduce_xor_b32:
diff --git a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl 
b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
index a5132c9114673..39f140ababab2 100644
--- a/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
+++ b/clang/test/CodeGenOpenCL/builtins-amdgcn.cl
@@ -412,6 +412,13 @@ void test_wave_reduce_fadd_f32_default(global float* out, 
float in)
   *out = __builtin_amdgcn_wave_reduce_fadd_f32(in, 0);
 }
 
+// CHECK-LABEL: @test_wave_reduce_fadd_f64_default
+// CHECK: {{.*}}call{{.*}} double @llvm.amdgcn.wave.reduce.fadd.f64(
+void test_wave_reduce_fadd_f64_default(global double* out, doubl

[llvm-branch-commits] [llvm] [AArch64][GlobalISel] Added support for neon right shifts (PR #170832)

2025-12-05 Thread Joshua Rodriguez via llvm-branch-commits

https://github.com/JoshdRod updated 
https://github.com/llvm/llvm-project/pull/170832

>From 7e897eac1eee87148b1f3529a42e4b927b556d44 Mon Sep 17 00:00:00 2001
From: Josh Rodriguez 
Date: Thu, 27 Nov 2025 15:34:40 +
Subject: [PATCH 1/9] [AArch64][GlobalISel] Removed fallback for sqshlu
 intrinsic

Added G_SQSHLU node, which lowers the llvm ir intrinsic aarch64_neon_sqshlu to 
the machine intrinsic sqshlu. Generated code is slightly less efficient compare 
to SDAG.
---
 llvm/lib/Target/AArch64/AArch64InstrGISel.td  |  8 +++
 .../AArch64/GISel/AArch64LegalizerInfo.cpp| 12 +
 .../AArch64/GISel/AArch64RegisterBankInfo.cpp |  9 
 llvm/test/CodeGen/AArch64/arm64-vshift.ll | 49 ++-
 4 files changed, 56 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrGISel.td 
b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
index 7d99786830e3d..7469a081d9787 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrGISel.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
@@ -252,6 +252,12 @@ def G_USDOT : AArch64GenericInstruction {
   let hasSideEffects = 0;
 }
 
+def G_SQSHLU : AArch64GenericInstruction {
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins type0:$src1, type0:$src2);
+  let hasSideEffects = 0;
+}
+
 // Generic instruction for the BSP pseudo. It is expanded into BSP, which
 // expands into BSL/BIT/BIF after register allocation.
 def G_BSP : AArch64GenericInstruction {
@@ -300,6 +306,8 @@ def : GINodeEquiv;
 def : GINodeEquiv;
 def : GINodeEquiv;
 
+def : GINodeEquiv;
+
 def : GINodeEquiv;
 
 def : GINodeEquiv;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp 
b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 1025b2502211a..0010834e01894 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -1857,6 +1857,18 @@ bool 
AArch64LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
 return LowerBinOp(TargetOpcode::G_SAVGFLOOR);
   case Intrinsic::aarch64_neon_srhadd:
 return LowerBinOp(TargetOpcode::G_SAVGCEIL);
+  case Intrinsic::aarch64_neon_sqshlu: {
+// Check if last operand is constant vector dup
+auto shiftAmount = 
isConstantOrConstantSplatVector(*MRI.getVRegDef(MI.getOperand(3).getReg()), 
MRI);
+if (shiftAmount) {
+   // If so, create a new intrinsic with the correct shift amount
+   MIB.buildInstr(AArch64::G_SQSHLU, {MI.getOperand(0)}, 
{MI.getOperand(2)}).addImm(shiftAmount->getSExtValue());
+   MI.eraseFromParent();
+   return true;
+} else {
+   return false;
+}
+  }
   case Intrinsic::aarch64_neon_abs: {
 // Lower the intrinsic to G_ABS.
 MIB.buildInstr(TargetOpcode::G_ABS, {MI.getOperand(0)}, 
{MI.getOperand(2)});
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp 
b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index 652a31f4e65f2..aa1517533b753 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -1072,6 +1072,15 @@ AArch64RegisterBankInfo::getInstrMapping(const 
MachineInstr &MI) const {
 // Index needs to be a GPR.
 OpRegBankIdx[2] = PMI_FirstGPR;
 break;
+  case AArch64::G_SQSHLU:
+// Destination and source need to be FPRs.
+OpRegBankIdx[0] = PMI_FirstFPR;
+OpRegBankIdx[1] = PMI_FirstFPR;
+
+// Shift Index needs to be a GPR.
+OpRegBankIdx[2] = PMI_FirstGPR;
+break;
+
   case TargetOpcode::G_INSERT_VECTOR_ELT:
 OpRegBankIdx[0] = PMI_FirstFPR;
 OpRegBankIdx[1] = PMI_FirstFPR;
diff --git a/llvm/test/CodeGen/AArch64/arm64-vshift.ll 
b/llvm/test/CodeGen/AArch64/arm64-vshift.ll
index 34843835d284a..961788f311041 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vshift.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vshift.ll
@@ -2,17 +2,7 @@
 ; RUN: llc < %s -mtriple=arm64-eabi -global-isel=0 | FileCheck %s 
--check-prefixes=CHECK,CHECK-SD
 ; RUN: llc < %s -mtriple=arm64-eabi -global-isel=1 -global-isel-abort=2 2>&1 | 
FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
-; CHECK-GI:warning: Instruction selection used fallback path for sqshlu8b
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu4h
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu2s
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu16b
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu8h
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu4s
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu2d
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu1d_constant
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu_i64_constant
-; CHECK-GI NEXT:warning: Instruction selection used fallback 

[llvm-branch-commits] [llvm] [ValueTracking] Make isBytewiseValue byte width agnostic (PR #106538)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits

https://github.com/s-barannikov updated 
https://github.com/llvm/llvm-project/pull/106538

>From 57d1ffe76c30630863eee2537ba4e140df5a1391 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov 
Date: Fri, 2 Aug 2024 13:14:49 +0300
Subject: [PATCH] [ValueTracking] Make isBytewiseValue byte width agnostic

This is a simple change to show how easy it can be to support unusual
byte widths in the middle end.
---
 llvm/lib/Analysis/ValueTracking.cpp | 30 +++--
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp 
b/llvm/lib/Analysis/ValueTracking.cpp
index 9cb6f19b9340c..b6cce9d372a47 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -6290,21 +6290,22 @@ bool llvm::canIgnoreSignBitOfNaN(const Use &U) {
 }
 
 Value *llvm::isBytewiseValue(Value *V, const DataLayout &DL) {
+  unsigned ByteWidth = DL.getByteWidth();
 
   // All byte-wide stores are splatable, even of arbitrary variables.
-  if (V->getType()->isIntegerTy(8))
+  if (V->getType()->isIntegerTy(ByteWidth))
 return V;
 
   LLVMContext &Ctx = V->getContext();
 
   // Undef don't care.
-  auto *UndefInt8 = UndefValue::get(Type::getInt8Ty(Ctx));
+  auto *UndefByte = UndefValue::get(Type::getIntNTy(Ctx, ByteWidth));
   if (isa(V))
-return UndefInt8;
+return UndefByte;
 
   // Return poison for zero-sized type.
   if (DL.getTypeStoreSize(V->getType()).isZero())
-return PoisonValue::get(Type::getInt8Ty(Ctx));
+return PoisonValue::get(Type::getIntNTy(Ctx, ByteWidth));
 
   Constant *C = dyn_cast(V);
   if (!C) {
@@ -6319,7 +6320,7 @@ Value *llvm::isBytewiseValue(Value *V, const DataLayout 
&DL) {
 
   // Handle 'null' ConstantArrayZero etc.
   if (C->isNullValue())
-return Constant::getNullValue(Type::getInt8Ty(Ctx));
+return Constant::getNullValue(Type::getIntNTy(Ctx, ByteWidth));
 
   // Constant floating-point values can be handled as integer values if the
   // corresponding integer value is "byteable".  An important case is 0.0.
@@ -6336,13 +6337,14 @@ Value *llvm::isBytewiseValue(Value *V, const DataLayout 
&DL) {
   : nullptr;
   }
 
-  // We can handle constant integers that are multiple of 8 bits.
+  // We can handle constant integers that are multiple of the byte width.
   if (ConstantInt *CI = dyn_cast(C)) {
-if (CI->getBitWidth() % 8 == 0) {
-  assert(CI->getBitWidth() > 8 && "8 bits should be handled above!");
-  if (!CI->getValue().isSplat(8))
+if (CI->getBitWidth() % ByteWidth == 0) {
+  assert(CI->getBitWidth() > ByteWidth &&
+ "single byte should be handled above!");
+  if (!CI->getValue().isSplat(ByteWidth))
 return nullptr;
-  return ConstantInt::get(Ctx, CI->getValue().trunc(8));
+  return ConstantInt::get(Ctx, CI->getValue().trunc(ByteWidth));
 }
   }
 
@@ -6362,15 +6364,15 @@ Value *llvm::isBytewiseValue(Value *V, const DataLayout 
&DL) {
   return LHS;
 if (!LHS || !RHS)
   return nullptr;
-if (LHS == UndefInt8)
+if (LHS == UndefByte)
   return RHS;
-if (RHS == UndefInt8)
+if (RHS == UndefByte)
   return LHS;
 return nullptr;
   };
 
   if (ConstantDataSequential *CA = dyn_cast(C)) {
-Value *Val = UndefInt8;
+Value *Val = UndefByte;
 for (uint64_t I = 0, E = CA->getNumElements(); I != E; ++I)
   if (!(Val = Merge(Val, isBytewiseValue(CA->getElementAsConstant(I), 
DL
 return nullptr;
@@ -6378,7 +6380,7 @@ Value *llvm::isBytewiseValue(Value *V, const DataLayout 
&DL) {
   }
 
   if (isa(C)) {
-Value *Val = UndefInt8;
+Value *Val = UndefByte;
 for (Value *Op : C->operands())
   if (!(Val = Merge(Val, isBytewiseValue(Op, DL
 return nullptr;

___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [ValueTracking] Add CharWidth argument to getConstantStringInfo (NFC) (PR #106541)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits

https://github.com/s-barannikov updated 
https://github.com/llvm/llvm-project/pull/106541

>From 92762688c98156ef73fc426f33eb22e0b6de68ab Mon Sep 17 00:00:00 2001
From: Sergei Barannikov 
Date: Wed, 28 Aug 2024 23:51:13 +0300
Subject: [PATCH] [ValueTracking] Add CharWidth argument to
 getConstantStringInfo (NFC)

The method assumes that host chars and target chars have the same width.
Add a CharWidth argument so that it can bail out if the requested char
width differs from the host char width.

Alternatively, the check could be done at call sites, but this is more
error-prone.

In the future, this method will be replaced with a different one that
allows host/target chars to have different widths. The prototype will
be the same except that StringRef is replaced with something that is
byte width agnostic. Adding CharWidth argument now reduces the future
diff.
---
 clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp   |   4 +-
 llvm/include/llvm/Analysis/ValueTracking.h|   2 +-
 llvm/lib/Analysis/ValueTracking.cpp   |   7 +-
 .../AMDGPU/AMDGPUPrintfRuntimeBinding.cpp |   4 +-
 llvm/lib/Target/SPIRV/SPIRVAsmPrinter.cpp |   2 +-
 .../Target/SPIRV/SPIRVPrepareFunctions.cpp|   2 +-
 .../WebAssembly/WebAssemblyAsmPrinter.cpp |   2 +-
 .../AggressiveInstCombine.cpp |  12 +-
 .../lib/Transforms/Utils/AMDGPUEmitPrintf.cpp |   4 +-
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 103 --
 10 files changed, 96 insertions(+), 46 deletions(-)

diff --git a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp 
b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
index eabdc370da6b4..7fabc659bbaef 100644
--- a/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/AMDGPU.cpp
@@ -306,7 +306,7 @@ void CodeGenFunction::ProcessOrderScopeAMDGCN(Value *Order, 
Value *Scope,
 
   // Some of the atomic builtins take the scope as a string name.
   StringRef scp;
-  if (llvm::getConstantStringInfo(Scope, scp)) {
+  if (llvm::getConstantStringInfo(Scope, scp, /*CharWidth=*/8)) {
 if (getTarget().getTriple().isSPIRV())
   scp = mapScopeToSPIRV(scp);
 SSID = getLLVMContext().getOrInsertSyncScopeID(scp);
@@ -352,7 +352,7 @@ void 
CodeGenFunction::AddAMDGPUFenceAddressSpaceMMRA(llvm::Instruction *Inst,
   for (unsigned K = 2; K < E->getNumArgs(); ++K) {
 llvm::Value *V = EmitScalarExpr(E->getArg(K));
 StringRef AS;
-if (llvm::getConstantStringInfo(V, AS)) {
+if (llvm::getConstantStringInfo(V, AS, /*CharWidth=*/8)) {
   MMRAs.push_back({Tag, AS});
   // TODO: Delete the resulting unused constant?
   continue;
diff --git a/llvm/include/llvm/Analysis/ValueTracking.h 
b/llvm/include/llvm/Analysis/ValueTracking.h
index b730a36488780..c1a613ae5336a 100644
--- a/llvm/include/llvm/Analysis/ValueTracking.h
+++ b/llvm/include/llvm/Analysis/ValueTracking.h
@@ -399,7 +399,7 @@ LLVM_ABI bool getConstantDataArrayInfo(const Value *V,
 /// trailing null characters as well as any other characters that come after
 /// it.
 LLVM_ABI bool getConstantStringInfo(const Value *V, StringRef &Str,
-bool TrimAtNul = true);
+unsigned CharWidth, bool TrimAtNul = true);
 
 /// If we can compute the length of the string pointed to by the specified
 /// pointer, return 'len+1'.  If we can't, return 0.
diff --git a/llvm/lib/Analysis/ValueTracking.cpp 
b/llvm/lib/Analysis/ValueTracking.cpp
index b6cce9d372a47..9845c9d59659e 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -6658,9 +6658,12 @@ bool llvm::getConstantDataArrayInfo(const Value *V,
 /// return true.  When TrimAtNul is set, Str will contain only the bytes up
 /// to but not including the first nul.  Return false on failure.
 bool llvm::getConstantStringInfo(const Value *V, StringRef &Str,
- bool TrimAtNul) {
+ unsigned CharWidth, bool TrimAtNul) {
+  if (CharWidth != CHAR_BIT)
+return false;
+
   ConstantDataArraySlice Slice;
-  if (!getConstantDataArrayInfo(V, Slice, 8))
+  if (!getConstantDataArrayInfo(V, Slice, CharWidth))
 return false;
 
   if (Slice.Array == nullptr) {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp 
b/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp
index 416de901ef19b..62a96859c3b9d 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUPrintfRuntimeBinding.cpp
@@ -121,7 +121,7 @@ static_assert(NonLiteralStr.size() == 3);
 
 static StringRef getAsConstantStr(Value *V) {
   StringRef S;
-  if (!getConstantStringInfo(V, S))
+  if (!getConstantStringInfo(V, S, /*CharWidth=*/8))
 S = NonLiteralStr;
 
   return S;
@@ -154,7 +154,7 @@ bool 
AMDGPUPrintfRuntimeBindingImpl::lowerPrintfForGpu(Module &M) {
 Value *Op = CI->getArgOperand(0);
 
 StringRef FormatStr;
-if (!getConstantStringInfo(Op, FormatStr)) {
+if (!getC

[llvm-branch-commits] [llvm] [IRBuilder] Add getByteTy and use it in CreatePtrAdd (PR #106539)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits

https://github.com/s-barannikov updated 
https://github.com/llvm/llvm-project/pull/106539

>From f46794af374e47905b8a608e9ab73500895d535e Mon Sep 17 00:00:00 2001
From: Sergei Barannikov 
Date: Thu, 22 Aug 2024 15:10:58 +0300
Subject: [PATCH] [IRBuilder] Add getByteTy and use it in CreatePtrAdd

The change requires DataLayout instance to be available, which, in turn,
requires insertion point to be set. In-tree tests detected only one case
when the function was called without setting an insertion point, it was
changed to create a constant expression directly.
---
 llvm/include/llvm/IR/IRBuilder.h  | 10 +++--
 .../Instrumentation/SanitizerCoverage.cpp |  5 ++---
 llvm/unittests/IR/IRBuilderTest.cpp   | 22 +++
 3 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 972a253344ddf..3bc1b85506fda 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -543,6 +543,12 @@ class IRBuilderBase {
   // Type creation methods
   
//======//
 
+  /// Fetch the type representing a byte.
+  IntegerType *getByteTy() {
+const DataLayout &DL = BB->getDataLayout();
+return Type::getIntNTy(Context, DL.getByteWidth());
+  }
+
   /// Fetch the type representing a single bit
   IntegerType *getInt1Ty() {
 return Type::getInt1Ty(Context);
@@ -2038,12 +2044,12 @@ class IRBuilderBase {
 
   Value *CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name = "",
   GEPNoWrapFlags NW = GEPNoWrapFlags::none()) {
-return CreateGEP(getInt8Ty(), Ptr, Offset, Name, NW);
+return CreateGEP(getByteTy(), Ptr, Offset, Name, NW);
   }
 
   Value *CreateInBoundsPtrAdd(Value *Ptr, Value *Offset,
   const Twine &Name = "") {
-return CreateGEP(getInt8Ty(), Ptr, Offset, Name,
+return CreateGEP(getByteTy(), Ptr, Offset, Name,
  GEPNoWrapFlags::inBounds());
   }
 
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp 
b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 09abf6a33648c..6a8887a95726c 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -369,14 +369,13 @@ ModuleSanitizerCoverage::CreateSecStartEnd(Module &M, 
const char *Section,
   GlobalVariable *SecEnd = new GlobalVariable(M, Ty, false, Linkage, nullptr,
   getSectionEnd(Section));
   SecEnd->setVisibility(GlobalValue::HiddenVisibility);
-  IRBuilder<> IRB(M.getContext());
   if (!TargetTriple.isOSBinFormatCOFF())
 return std::make_pair(SecStart, SecEnd);
 
   // Account for the fact that on windows-msvc __start_* symbols actually
   // point to a uint64_t before the start of the array.
-  auto GEP =
-  IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
+  Constant *GEP = ConstantExpr::getGetElementPtr(
+  Int8Ty, SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
   return std::make_pair(GEP, SecEnd);
 }
 
diff --git a/llvm/unittests/IR/IRBuilderTest.cpp 
b/llvm/unittests/IR/IRBuilderTest.cpp
index 4d5bbe971a060..cba3fb8250f3d 100644
--- a/llvm/unittests/IR/IRBuilderTest.cpp
+++ b/llvm/unittests/IR/IRBuilderTest.cpp
@@ -521,6 +521,14 @@ TEST_F(IRBuilderTest, DataLayout) {
   EXPECT_FALSE(M->getDataLayout().isLegalInteger(32));
 }
 
+TEST_F(IRBuilderTest, GetByteTy) {
+  IRBuilder<> Builder(BB);
+
+  EXPECT_TRUE(Builder.getByteTy()->isIntegerTy(8));
+  M->setDataLayout("b:32");
+  EXPECT_TRUE(Builder.getByteTy()->isIntegerTy(32));
+}
+
 TEST_F(IRBuilderTest, GetIntTy) {
   IRBuilder<> Builder(BB);
   IntegerType *Ty1 = Builder.getInt1Ty();
@@ -532,6 +540,20 @@ TEST_F(IRBuilderTest, GetIntTy) {
   EXPECT_EQ(IntPtrTy, IntegerType::get(Ctx, IntPtrBitSize));
 }
 
+TEST_F(IRBuilderTest, CreatePtrAdd) {
+  IRBuilder<> Builder(BB);
+
+  M->setDataLayout("b:16-p:32:32");
+  Value *V = Builder.CreatePtrAdd(GV, ConstantInt::get(Ctx, APInt(32, 42)));
+  ASSERT_TRUE(isa(V));
+  EXPECT_TRUE(cast(V)->getResultElementType()->isIntegerTy(16));
+
+  M->setDataLayout("b:32-p:64:32");
+  V = Builder.CreateInBoundsPtrAdd(GV, ConstantInt::get(Ctx, APInt(64, 42)));
+  ASSERT_TRUE(isa(V));
+  EXPECT_TRUE(cast(V)->getResultElementType()->isIntegerTy(32));
+}
+
 TEST_F(IRBuilderTest, UnaryOperators) {
   IRBuilder Builder(BB);
   Value *V = Builder.CreateLoad(GV->getValueType(), GV);

___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IRBuilder] Add getByteTy and use it in CreatePtrAdd (PR #106539)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits

https://github.com/s-barannikov updated 
https://github.com/llvm/llvm-project/pull/106539

>From f46794af374e47905b8a608e9ab73500895d535e Mon Sep 17 00:00:00 2001
From: Sergei Barannikov 
Date: Thu, 22 Aug 2024 15:10:58 +0300
Subject: [PATCH] [IRBuilder] Add getByteTy and use it in CreatePtrAdd

The change requires DataLayout instance to be available, which, in turn,
requires insertion point to be set. In-tree tests detected only one case
when the function was called without setting an insertion point, it was
changed to create a constant expression directly.
---
 llvm/include/llvm/IR/IRBuilder.h  | 10 +++--
 .../Instrumentation/SanitizerCoverage.cpp |  5 ++---
 llvm/unittests/IR/IRBuilderTest.cpp   | 22 +++
 3 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h
index 972a253344ddf..3bc1b85506fda 100644
--- a/llvm/include/llvm/IR/IRBuilder.h
+++ b/llvm/include/llvm/IR/IRBuilder.h
@@ -543,6 +543,12 @@ class IRBuilderBase {
   // Type creation methods
   
//======//
 
+  /// Fetch the type representing a byte.
+  IntegerType *getByteTy() {
+const DataLayout &DL = BB->getDataLayout();
+return Type::getIntNTy(Context, DL.getByteWidth());
+  }
+
   /// Fetch the type representing a single bit
   IntegerType *getInt1Ty() {
 return Type::getInt1Ty(Context);
@@ -2038,12 +2044,12 @@ class IRBuilderBase {
 
   Value *CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name = "",
   GEPNoWrapFlags NW = GEPNoWrapFlags::none()) {
-return CreateGEP(getInt8Ty(), Ptr, Offset, Name, NW);
+return CreateGEP(getByteTy(), Ptr, Offset, Name, NW);
   }
 
   Value *CreateInBoundsPtrAdd(Value *Ptr, Value *Offset,
   const Twine &Name = "") {
-return CreateGEP(getInt8Ty(), Ptr, Offset, Name,
+return CreateGEP(getByteTy(), Ptr, Offset, Name,
  GEPNoWrapFlags::inBounds());
   }
 
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp 
b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index 09abf6a33648c..6a8887a95726c 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -369,14 +369,13 @@ ModuleSanitizerCoverage::CreateSecStartEnd(Module &M, 
const char *Section,
   GlobalVariable *SecEnd = new GlobalVariable(M, Ty, false, Linkage, nullptr,
   getSectionEnd(Section));
   SecEnd->setVisibility(GlobalValue::HiddenVisibility);
-  IRBuilder<> IRB(M.getContext());
   if (!TargetTriple.isOSBinFormatCOFF())
 return std::make_pair(SecStart, SecEnd);
 
   // Account for the fact that on windows-msvc __start_* symbols actually
   // point to a uint64_t before the start of the array.
-  auto GEP =
-  IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
+  Constant *GEP = ConstantExpr::getGetElementPtr(
+  Int8Ty, SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
   return std::make_pair(GEP, SecEnd);
 }
 
diff --git a/llvm/unittests/IR/IRBuilderTest.cpp 
b/llvm/unittests/IR/IRBuilderTest.cpp
index 4d5bbe971a060..cba3fb8250f3d 100644
--- a/llvm/unittests/IR/IRBuilderTest.cpp
+++ b/llvm/unittests/IR/IRBuilderTest.cpp
@@ -521,6 +521,14 @@ TEST_F(IRBuilderTest, DataLayout) {
   EXPECT_FALSE(M->getDataLayout().isLegalInteger(32));
 }
 
+TEST_F(IRBuilderTest, GetByteTy) {
+  IRBuilder<> Builder(BB);
+
+  EXPECT_TRUE(Builder.getByteTy()->isIntegerTy(8));
+  M->setDataLayout("b:32");
+  EXPECT_TRUE(Builder.getByteTy()->isIntegerTy(32));
+}
+
 TEST_F(IRBuilderTest, GetIntTy) {
   IRBuilder<> Builder(BB);
   IntegerType *Ty1 = Builder.getInt1Ty();
@@ -532,6 +540,20 @@ TEST_F(IRBuilderTest, GetIntTy) {
   EXPECT_EQ(IntPtrTy, IntegerType::get(Ctx, IntPtrBitSize));
 }
 
+TEST_F(IRBuilderTest, CreatePtrAdd) {
+  IRBuilder<> Builder(BB);
+
+  M->setDataLayout("b:16-p:32:32");
+  Value *V = Builder.CreatePtrAdd(GV, ConstantInt::get(Ctx, APInt(32, 42)));
+  ASSERT_TRUE(isa(V));
+  EXPECT_TRUE(cast(V)->getResultElementType()->isIntegerTy(16));
+
+  M->setDataLayout("b:32-p:64:32");
+  V = Builder.CreateInBoundsPtrAdd(GV, ConstantInt::get(Ctx, APInt(64, 42)));
+  ASSERT_TRUE(isa(V));
+  EXPECT_TRUE(cast(V)->getResultElementType()->isIntegerTy(32));
+}
+
 TEST_F(IRBuilderTest, UnaryOperators) {
   IRBuilder Builder(BB);
   Value *V = Builder.CreateLoad(GV->getValueType(), GV);

___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [SimplifyLibCalls] Add initial support for non-8-bit bytes (PR #106542)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits

https://github.com/s-barannikov updated 
https://github.com/llvm/llvm-project/pull/106542

>From 7e6e862f6848a0ca209ed7dbf44e767e5ac7df0b Mon Sep 17 00:00:00 2001
From: Sergei Barannikov 
Date: Wed, 28 Aug 2024 16:09:44 +0300
Subject: [PATCH] [SimplifyLibCalls] Add initial support for non-8-bit bytes

The patch makes CharWidth argument of `getStringLength` mandatory
and ensures the correct values are passed in most cases.
This is *not* a complete support for unusual byte widths in
SimplifyLibCalls since `getConstantStringInfo` returns false for those.
The code guarded by `getConstantStringInfo` returning true is unchanged
because the changes are currently not testable.
---
 llvm/include/llvm/Analysis/ValueTracking.h|   4 +-
 .../llvm/Transforms/Utils/SimplifyLibCalls.h  |   4 +-
 llvm/lib/Analysis/MemoryBuiltins.cpp  |   3 +-
 llvm/lib/Analysis/ValueTracking.cpp   |  40 ++--
 .../InstCombine/InstCombineCalls.cpp  |  12 +-
 .../InstCombine/InstructionCombining.cpp  |   5 +-
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 193 --
 .../InstCombine/SimplifyLibCalls/fputs-b16.ll |  19 ++
 .../SimplifyLibCalls/fwrite-b16.ll|  19 ++
 .../SimplifyLibCalls/memchr-b16.ll|  34 +++
 .../SimplifyLibCalls/memcmp-b32.ll|  32 +++
 .../SimplifyLibCalls/memcpy-b16.ll|  69 +++
 .../SimplifyLibCalls/memcpy_chk-b16.ll|  17 ++
 .../SimplifyLibCalls/mempcpy-b16.ll   |  17 ++
 .../SimplifyLibCalls/memrchr-b16.ll   |  20 ++
 .../SimplifyLibCalls/memset-b16.ll|  66 ++
 .../SimplifyLibCalls/stpcpy-b16.ll|  31 +++
 .../SimplifyLibCalls/stpcpy_chk-b16.ll|  44 
 .../SimplifyLibCalls/stpncpy-b16.ll   |  47 +
 .../SimplifyLibCalls/strcat-b16.ll|  20 ++
 .../SimplifyLibCalls/strchr-b16.ll|  45 
 .../SimplifyLibCalls/strcmp-b32.ll|  50 +
 .../SimplifyLibCalls/strcpy-b16.ll|  18 ++
 .../SimplifyLibCalls/strcpy_chk-b16.ll|  30 +++
 .../SimplifyLibCalls/strlcpy-b16.ll   |  18 ++
 .../SimplifyLibCalls/strlen-b16.ll|  16 ++
 .../SimplifyLibCalls/strncat-b16.ll   |  20 ++
 .../SimplifyLibCalls/strncmp-b32.ll   |  34 +++
 .../SimplifyLibCalls/strncpy-b16.ll   |  43 
 .../SimplifyLibCalls/strndup-b16.ll   |  17 ++
 .../SimplifyLibCalls/strnlen-b16.ll   |  18 ++
 .../SimplifyLibCalls/wcslen-b16.ll|  19 ++
 llvm/test/Transforms/InstCombine/bcmp-1.ll|   2 +-
 llvm/test/Transforms/InstCombine/memcmp-1.ll  |   2 +-
 llvm/test/Transforms/InstCombine/strncmp-1.ll |   2 +-
 35 files changed, 929 insertions(+), 101 deletions(-)
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/fputs-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/fwrite-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/memchr-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/memcmp-b32.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/memcpy-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/memcpy_chk-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/mempcpy-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/memrchr-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/memset-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/stpcpy-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/stpcpy_chk-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/stpncpy-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strcat-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strchr-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strcmp-b32.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strcpy-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strcpy_chk-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strlcpy-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strlen-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strncat-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strncmp-b32.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strncpy-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strndup-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/strnlen-b16.ll
 create mode 100644 
llvm/test/Transforms/InstCombine/SimplifyLibCalls/wcslen-b16.ll

diff --git a/llvm/include/llvm/Analysis/ValueTracking.h 
b/llvm/include/llvm/Analysis/ValueTracking.h
index c1a

[llvm-branch-commits] [llvm] [mlir] [IR] Make @llvm.memset prototype byte width dependent (PR #106537)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits

https://github.com/s-barannikov updated 
https://github.com/llvm/llvm-project/pull/106537

>From c17c9fe15839fe7ff39303b266227cb336a0b971 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov 
Date: Thu, 1 Aug 2024 23:47:25 +0300
Subject: [PATCH] [IR] Make @llvm.memset prototype byte width dependent

This patch changes the type of the value argument of @llvm.memset and
similar intrinsics from i8 to iN, where N is the byte width specified
in data layout string.
Note that the argument still has fixed type (not overloaded), but type
checker will complain if the type does not match the byte width.

Ideally, the type of the argument would be dependent on the address
space of the pointer argument. It is easy to do this (and I did it
downstream as a PoC), but since data layout string doesn't currently
allow different byte widths for different address spaces, I refrained
from doing it now.
---
 llvm/include/llvm-c/Core.h|  2 +-
 llvm/include/llvm/IR/Intrinsics.h | 13 ++--
 llvm/include/llvm/IR/Intrinsics.td| 13 ++--
 llvm/lib/AsmParser/LLParser.cpp   |  4 +-
 llvm/lib/IR/AutoUpgrade.cpp   |  4 +-
 llvm/lib/IR/Core.cpp  |  4 +-
 llvm/lib/IR/Function.cpp  |  4 +-
 llvm/lib/IR/Intrinsics.cpp| 63 +++
 llvm/lib/IR/Verifier.cpp  |  2 +-
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp |  3 +-
 .../NumericalStabilitySanitizer.cpp   |  2 +-
 .../LLVMIR/LLVMToLLVMIRTranslation.cpp|  4 +-
 12 files changed, 71 insertions(+), 47 deletions(-)

diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index fc41b5835d6eb..63b6e3fec45c3 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2978,7 +2978,7 @@ LLVM_C_ABI LLVMValueRef 
LLVMGetIntrinsicDeclaration(LLVMModuleRef Mod,
  *
  * @see llvm::Intrinsic::getType()
  */
-LLVM_C_ABI LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID,
+LLVM_C_ABI LLVMTypeRef LLVMIntrinsicGetType(LLVMModuleRef Mod, unsigned ID,
 LLVMTypeRef *ParamTypes,
 size_t ParamCount);
 
diff --git a/llvm/include/llvm/IR/Intrinsics.h 
b/llvm/include/llvm/IR/Intrinsics.h
index 2c86a43e114ea..d6d6e5cb6bc6e 100644
--- a/llvm/include/llvm/IR/Intrinsics.h
+++ b/llvm/include/llvm/IR/Intrinsics.h
@@ -23,6 +23,7 @@
 
 namespace llvm {
 
+class DataLayout;
 class Type;
 class FunctionType;
 class Function;
@@ -77,7 +78,7 @@ namespace Intrinsic {
   LLVM_ABI std::string getNameNoUnnamedTypes(ID Id, ArrayRef Tys);
 
   /// Return the function type for an intrinsic.
-  LLVM_ABI FunctionType *getType(LLVMContext &Context, ID id,
+  LLVM_ABI FunctionType *getType(const Module *M, ID id,
  ArrayRef Tys = {});
 
   /// Returns true if the intrinsic can be overloaded.
@@ -155,6 +156,7 @@ namespace Intrinsic {
   struct IITDescriptor {
 enum IITDescriptorKind {
   Void,
+  Byte,
   VarArg,
   MMX,
   Token,
@@ -267,9 +269,9 @@ namespace Intrinsic {
   ///
   /// Returns false if the given type matches with the constraints, true
   /// otherwise.
-  LLVM_ABI MatchIntrinsicTypesResult
-  matchIntrinsicSignature(FunctionType *FTy, ArrayRef &Infos,
-  SmallVectorImpl &ArgTys);
+  LLVM_ABI MatchIntrinsicTypesResult matchIntrinsicSignature(
+  const DataLayout &DL, FunctionType *FTy, ArrayRef &Infos,
+  SmallVectorImpl &ArgTys);
 
   /// Verify if the intrinsic has variable arguments. This method is intended 
to
   /// be called after all the fixed arguments have been matched first.
@@ -284,7 +286,8 @@ namespace Intrinsic {
   ///
   /// Returns false if the given ID and function type combination is not a
   /// valid intrinsic call.
-  LLVM_ABI bool getIntrinsicSignature(Intrinsic::ID, FunctionType *FT,
+  LLVM_ABI bool getIntrinsicSignature(const DataLayout &DL, Intrinsic::ID,
+  FunctionType *FT,
   SmallVectorImpl &ArgTys);
 
   /// Same as previous, but accepts a Function instead of ID and FunctionType.
diff --git a/llvm/include/llvm/IR/Intrinsics.td 
b/llvm/include/llvm/IR/Intrinsics.td
index c3c4718c3548f..d3ede37c51b63 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -372,6 +372,7 @@ def IIT_V6 : IIT_Vec<6, 50>;
 def IIT_V10 : IIT_Vec<10, 51>;
 def IIT_V2048 : IIT_Vec<2048, 52>;
 def IIT_V4096 : IIT_Vec<4096, 53>;
+def IIT_BYTE : IIT_Base<54>;
 }
 
 defvar IIT_all_FixedTypes = !filter(iit, IIT_all,
@@ -414,6 +415,10 @@ class LLVMType {
 !foreach(iit, IITs, iit.Number));
 }
 
+class LLVMByteType : LLVMType {
+  let Sig = [IIT_BYTE.Number];
+}
+
 class LLVMAnyType : LLVMType {
   let ArgCode = !cond(
 !eq(vt, Any) : ArgKind.Any,
@@ -519,7 +524,7 @@ class LLVMVectorOfBitcastsToInt
   : LLVMMatchType

[llvm-branch-commits] [llvm] [IR] Account for byte width in m_PtrAdd (PR #106540)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits

https://github.com/s-barannikov updated 
https://github.com/llvm/llvm-project/pull/106540

>From 144961ba3708d8d6e1f3d3f25acf1a91bb1ee587 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov 
Date: Thu, 29 Aug 2024 00:54:20 +0300
Subject: [PATCH] [IR] Account for byte width in m_PtrAdd

The method has few uses yet, so just pass DL argument to it. The change
follows m_PtrToIntSameSize, and I don't see a better way of delivering
the byte width to the method.
---
 llvm/include/llvm/IR/PatternMatch.h   | 13 ++
 llvm/lib/Analysis/InstructionSimplify.cpp |  2 +-
 .../InstCombineSimplifyDemanded.cpp   |  7 ++---
 .../InstCombine/InstructionCombining.cpp  |  2 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp |  2 +-
 llvm/unittests/IR/PatternMatch.cpp| 26 ++-
 6 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/llvm/include/llvm/IR/PatternMatch.h 
b/llvm/include/llvm/IR/PatternMatch.h
index 88aef4a368f29..39a65d8b7db99 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -2046,15 +2046,17 @@ struct m_SplatOrPoisonMask {
 };
 
 template  struct PtrAdd_match {
+  const DataLayout &DL;
   PointerOpTy PointerOp;
   OffsetOpTy OffsetOp;
 
-  PtrAdd_match(const PointerOpTy &PointerOp, const OffsetOpTy &OffsetOp)
-  : PointerOp(PointerOp), OffsetOp(OffsetOp) {}
+  PtrAdd_match(const DataLayout &DL, const PointerOpTy &PointerOp,
+   const OffsetOpTy &OffsetOp)
+  : DL(DL), PointerOp(PointerOp), OffsetOp(OffsetOp) {}
 
   template  bool match(OpTy *V) const {
 auto *GEP = dyn_cast(V);
-return GEP && GEP->getSourceElementType()->isIntegerTy(8) &&
+return GEP && GEP->getSourceElementType()->isIntegerTy(DL.getByteWidth()) 
&&
PointerOp.match(GEP->getPointerOperand()) &&
OffsetOp.match(GEP->idx_begin()->get());
   }
@@ -2096,8 +2098,9 @@ inline auto m_GEP(const OperandTypes &...Ops) {
 /// Matches GEP with i8 source element type
 template 
 inline PtrAdd_match
-m_PtrAdd(const PointerOpTy &PointerOp, const OffsetOpTy &OffsetOp) {
-  return PtrAdd_match(PointerOp, OffsetOp);
+m_PtrAdd(const DataLayout &DL, const PointerOpTy &PointerOp,
+ const OffsetOpTy &OffsetOp) {
+  return PtrAdd_match(DL, PointerOp, OffsetOp);
 }
 
 
//===--===//
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp 
b/llvm/lib/Analysis/InstructionSimplify.cpp
index bd85444d7d2b0..cbe9b0d07efce 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -5534,7 +5534,7 @@ static Value *simplifyCastInst(unsigned CastOpc, Value 
*Op, Type *Ty,
   Value *Ptr, *X;
   if ((CastOpc == Instruction::PtrToInt || CastOpc == Instruction::PtrToAddr) 
&&
   match(Op,
-m_PtrAdd(m_Value(Ptr),
+m_PtrAdd(Q.DL, m_Value(Ptr),
  m_Sub(m_Value(X), m_PtrToIntOrAddr(m_Deferred(Ptr) &&
   X->getType() == Ty && Ty == Q.DL.getIndexType(Ptr->getType()))
 return X;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 550dfc57a348b..0728063385bc3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1052,9 +1052,10 @@ Value 
*InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
 Value *InnerPtr;
 uint64_t GEPIndex;
 uint64_t PtrMaskImmediate;
-if (match(I, m_Intrinsic(
- m_PtrAdd(m_Value(InnerPtr), m_ConstantInt(GEPIndex)),
- m_ConstantInt(PtrMaskImmediate {
+if (match(I,
+  m_Intrinsic(
+  m_PtrAdd(DL, m_Value(InnerPtr), m_ConstantInt(GEPIndex)),
+  m_ConstantInt(PtrMaskImmediate {
 
   LHSKnown = computeKnownBits(InnerPtr, I, Depth + 1);
   if (!LHSKnown.isZero()) {
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp 
b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index c6de57cb34c69..d935915374018 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2695,7 +2695,7 @@ static Instruction 
*canonicalizeGEPOfConstGEPI8(GetElementPtrInst &GEP,
   auto &DL = IC.getDataLayout();
   Value *Base;
   const APInt *C1;
-  if (!match(Src, m_PtrAdd(m_Value(Base), m_APInt(C1
+  if (!match(Src, m_PtrAdd(DL, m_Value(Base), m_APInt(C1
 return nullptr;
   Value *VarIndex;
   const APInt *C2;
diff --git a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp 
b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
index 333cbb6ed1384..8362412b742f6 100644
--- a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
+++ b/llvm/lib/Transforms/Scalar/SeparateConstOff

[llvm-branch-commits] [llvm] [IR] Account for byte width in m_PtrAdd (PR #106540)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits

https://github.com/s-barannikov updated 
https://github.com/llvm/llvm-project/pull/106540

>From 144961ba3708d8d6e1f3d3f25acf1a91bb1ee587 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov 
Date: Thu, 29 Aug 2024 00:54:20 +0300
Subject: [PATCH] [IR] Account for byte width in m_PtrAdd

The method has few uses yet, so just pass DL argument to it. The change
follows m_PtrToIntSameSize, and I don't see a better way of delivering
the byte width to the method.
---
 llvm/include/llvm/IR/PatternMatch.h   | 13 ++
 llvm/lib/Analysis/InstructionSimplify.cpp |  2 +-
 .../InstCombineSimplifyDemanded.cpp   |  7 ++---
 .../InstCombine/InstructionCombining.cpp  |  2 +-
 .../Scalar/SeparateConstOffsetFromGEP.cpp |  2 +-
 llvm/unittests/IR/PatternMatch.cpp| 26 ++-
 6 files changed, 35 insertions(+), 17 deletions(-)

diff --git a/llvm/include/llvm/IR/PatternMatch.h 
b/llvm/include/llvm/IR/PatternMatch.h
index 88aef4a368f29..39a65d8b7db99 100644
--- a/llvm/include/llvm/IR/PatternMatch.h
+++ b/llvm/include/llvm/IR/PatternMatch.h
@@ -2046,15 +2046,17 @@ struct m_SplatOrPoisonMask {
 };
 
 template  struct PtrAdd_match {
+  const DataLayout &DL;
   PointerOpTy PointerOp;
   OffsetOpTy OffsetOp;
 
-  PtrAdd_match(const PointerOpTy &PointerOp, const OffsetOpTy &OffsetOp)
-  : PointerOp(PointerOp), OffsetOp(OffsetOp) {}
+  PtrAdd_match(const DataLayout &DL, const PointerOpTy &PointerOp,
+   const OffsetOpTy &OffsetOp)
+  : DL(DL), PointerOp(PointerOp), OffsetOp(OffsetOp) {}
 
   template  bool match(OpTy *V) const {
 auto *GEP = dyn_cast(V);
-return GEP && GEP->getSourceElementType()->isIntegerTy(8) &&
+return GEP && GEP->getSourceElementType()->isIntegerTy(DL.getByteWidth()) 
&&
PointerOp.match(GEP->getPointerOperand()) &&
OffsetOp.match(GEP->idx_begin()->get());
   }
@@ -2096,8 +2098,9 @@ inline auto m_GEP(const OperandTypes &...Ops) {
 /// Matches GEP with i8 source element type
 template 
 inline PtrAdd_match
-m_PtrAdd(const PointerOpTy &PointerOp, const OffsetOpTy &OffsetOp) {
-  return PtrAdd_match(PointerOp, OffsetOp);
+m_PtrAdd(const DataLayout &DL, const PointerOpTy &PointerOp,
+ const OffsetOpTy &OffsetOp) {
+  return PtrAdd_match(DL, PointerOp, OffsetOp);
 }
 
 
//===--===//
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp 
b/llvm/lib/Analysis/InstructionSimplify.cpp
index bd85444d7d2b0..cbe9b0d07efce 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -5534,7 +5534,7 @@ static Value *simplifyCastInst(unsigned CastOpc, Value 
*Op, Type *Ty,
   Value *Ptr, *X;
   if ((CastOpc == Instruction::PtrToInt || CastOpc == Instruction::PtrToAddr) 
&&
   match(Op,
-m_PtrAdd(m_Value(Ptr),
+m_PtrAdd(Q.DL, m_Value(Ptr),
  m_Sub(m_Value(X), m_PtrToIntOrAddr(m_Deferred(Ptr) &&
   X->getType() == Ty && Ty == Q.DL.getIndexType(Ptr->getType()))
 return X;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp 
b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 550dfc57a348b..0728063385bc3 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1052,9 +1052,10 @@ Value 
*InstCombinerImpl::SimplifyDemandedUseBits(Instruction *I,
 Value *InnerPtr;
 uint64_t GEPIndex;
 uint64_t PtrMaskImmediate;
-if (match(I, m_Intrinsic(
- m_PtrAdd(m_Value(InnerPtr), m_ConstantInt(GEPIndex)),
- m_ConstantInt(PtrMaskImmediate {
+if (match(I,
+  m_Intrinsic(
+  m_PtrAdd(DL, m_Value(InnerPtr), m_ConstantInt(GEPIndex)),
+  m_ConstantInt(PtrMaskImmediate {
 
   LHSKnown = computeKnownBits(InnerPtr, I, Depth + 1);
   if (!LHSKnown.isZero()) {
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp 
b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index c6de57cb34c69..d935915374018 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2695,7 +2695,7 @@ static Instruction 
*canonicalizeGEPOfConstGEPI8(GetElementPtrInst &GEP,
   auto &DL = IC.getDataLayout();
   Value *Base;
   const APInt *C1;
-  if (!match(Src, m_PtrAdd(m_Value(Base), m_APInt(C1
+  if (!match(Src, m_PtrAdd(DL, m_Value(Base), m_APInt(C1
 return nullptr;
   Value *VarIndex;
   const APInt *C2;
diff --git a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp 
b/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
index 333cbb6ed1384..8362412b742f6 100644
--- a/llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp
+++ b/llvm/lib/Transforms/Scalar/SeparateConstOff

[llvm-branch-commits] [llvm] [mlir] [IR] Make @llvm.memset prototype byte width dependent (PR #106537)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits

https://github.com/s-barannikov updated 
https://github.com/llvm/llvm-project/pull/106537

>From c17c9fe15839fe7ff39303b266227cb336a0b971 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov 
Date: Thu, 1 Aug 2024 23:47:25 +0300
Subject: [PATCH] [IR] Make @llvm.memset prototype byte width dependent

This patch changes the type of the value argument of @llvm.memset and
similar intrinsics from i8 to iN, where N is the byte width specified
in data layout string.
Note that the argument still has fixed type (not overloaded), but type
checker will complain if the type does not match the byte width.

Ideally, the type of the argument would be dependent on the address
space of the pointer argument. It is easy to do this (and I did it
downstream as a PoC), but since data layout string doesn't currently
allow different byte widths for different address spaces, I refrained
from doing it now.
---
 llvm/include/llvm-c/Core.h|  2 +-
 llvm/include/llvm/IR/Intrinsics.h | 13 ++--
 llvm/include/llvm/IR/Intrinsics.td| 13 ++--
 llvm/lib/AsmParser/LLParser.cpp   |  4 +-
 llvm/lib/IR/AutoUpgrade.cpp   |  4 +-
 llvm/lib/IR/Core.cpp  |  4 +-
 llvm/lib/IR/Function.cpp  |  4 +-
 llvm/lib/IR/Intrinsics.cpp| 63 +++
 llvm/lib/IR/Verifier.cpp  |  2 +-
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp |  3 +-
 .../NumericalStabilitySanitizer.cpp   |  2 +-
 .../LLVMIR/LLVMToLLVMIRTranslation.cpp|  4 +-
 12 files changed, 71 insertions(+), 47 deletions(-)

diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index fc41b5835d6eb..63b6e3fec45c3 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -2978,7 +2978,7 @@ LLVM_C_ABI LLVMValueRef 
LLVMGetIntrinsicDeclaration(LLVMModuleRef Mod,
  *
  * @see llvm::Intrinsic::getType()
  */
-LLVM_C_ABI LLVMTypeRef LLVMIntrinsicGetType(LLVMContextRef Ctx, unsigned ID,
+LLVM_C_ABI LLVMTypeRef LLVMIntrinsicGetType(LLVMModuleRef Mod, unsigned ID,
 LLVMTypeRef *ParamTypes,
 size_t ParamCount);
 
diff --git a/llvm/include/llvm/IR/Intrinsics.h 
b/llvm/include/llvm/IR/Intrinsics.h
index 2c86a43e114ea..d6d6e5cb6bc6e 100644
--- a/llvm/include/llvm/IR/Intrinsics.h
+++ b/llvm/include/llvm/IR/Intrinsics.h
@@ -23,6 +23,7 @@
 
 namespace llvm {
 
+class DataLayout;
 class Type;
 class FunctionType;
 class Function;
@@ -77,7 +78,7 @@ namespace Intrinsic {
   LLVM_ABI std::string getNameNoUnnamedTypes(ID Id, ArrayRef Tys);
 
   /// Return the function type for an intrinsic.
-  LLVM_ABI FunctionType *getType(LLVMContext &Context, ID id,
+  LLVM_ABI FunctionType *getType(const Module *M, ID id,
  ArrayRef Tys = {});
 
   /// Returns true if the intrinsic can be overloaded.
@@ -155,6 +156,7 @@ namespace Intrinsic {
   struct IITDescriptor {
 enum IITDescriptorKind {
   Void,
+  Byte,
   VarArg,
   MMX,
   Token,
@@ -267,9 +269,9 @@ namespace Intrinsic {
   ///
   /// Returns false if the given type matches with the constraints, true
   /// otherwise.
-  LLVM_ABI MatchIntrinsicTypesResult
-  matchIntrinsicSignature(FunctionType *FTy, ArrayRef &Infos,
-  SmallVectorImpl &ArgTys);
+  LLVM_ABI MatchIntrinsicTypesResult matchIntrinsicSignature(
+  const DataLayout &DL, FunctionType *FTy, ArrayRef &Infos,
+  SmallVectorImpl &ArgTys);
 
   /// Verify if the intrinsic has variable arguments. This method is intended 
to
   /// be called after all the fixed arguments have been matched first.
@@ -284,7 +286,8 @@ namespace Intrinsic {
   ///
   /// Returns false if the given ID and function type combination is not a
   /// valid intrinsic call.
-  LLVM_ABI bool getIntrinsicSignature(Intrinsic::ID, FunctionType *FT,
+  LLVM_ABI bool getIntrinsicSignature(const DataLayout &DL, Intrinsic::ID,
+  FunctionType *FT,
   SmallVectorImpl &ArgTys);
 
   /// Same as previous, but accepts a Function instead of ID and FunctionType.
diff --git a/llvm/include/llvm/IR/Intrinsics.td 
b/llvm/include/llvm/IR/Intrinsics.td
index c3c4718c3548f..d3ede37c51b63 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -372,6 +372,7 @@ def IIT_V6 : IIT_Vec<6, 50>;
 def IIT_V10 : IIT_Vec<10, 51>;
 def IIT_V2048 : IIT_Vec<2048, 52>;
 def IIT_V4096 : IIT_Vec<4096, 53>;
+def IIT_BYTE : IIT_Base<54>;
 }
 
 defvar IIT_all_FixedTypes = !filter(iit, IIT_all,
@@ -414,6 +415,10 @@ class LLVMType {
 !foreach(iit, IITs, iit.Number));
 }
 
+class LLVMByteType : LLVMType {
+  let Sig = [IIT_BYTE.Number];
+}
+
 class LLVMAnyType : LLVMType {
   let ArgCode = !cond(
 !eq(vt, Any) : ArgKind.Any,
@@ -519,7 +524,7 @@ class LLVMVectorOfBitcastsToInt
   : LLVMMatchType

[llvm-branch-commits] [llvm] [AArch64][GlobalISel] Added support for neon right shifts (PR #170832)

2025-12-05 Thread via llvm-branch-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 origin/main HEAD --extensions cpp -- 
llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp 
llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp 
--diff_from_common_commit
``

:warning:
The reproduction instructions above might return results for more than one PR
in a stack if you are using a stacked PR workflow. You can limit the results by
changing `origin/main` to the base branch/commit you want to compare against.
:warning:





View the diff from clang-format here.


``diff
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp 
b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 0c8472b75..8951ccfbd 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -1858,20 +1858,25 @@ bool 
AArch64LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
   case Intrinsic::aarch64_neon_srhadd:
 return LowerBinOp(TargetOpcode::G_SAVGCEIL);
   case Intrinsic::aarch64_neon_sqshrn: {
-if (MRI.getType(MI.getOperand(0).getReg()).isVector())
-{
-  // Create right shift instruction. Get v. register the output is written 
to
-  auto Shr = MIB.buildInstr(AArch64::G_VASHR, 
{MRI.getType(MI.getOperand(2).getReg())}, {MI.getOperand(2), 
MI.getOperand(3).getImm()});
+if (MRI.getType(MI.getOperand(0).getReg()).isVector()) {
+  // Create right shift instruction. Get v. register the output is written
+  // to
+  auto Shr = MIB.buildInstr(AArch64::G_VASHR,
+{MRI.getType(MI.getOperand(2).getReg())},
+{MI.getOperand(2), MI.getOperand(3).getImm()});
   // Build the narrow intrinsic, taking in the v. register of the shift
-  MIB.buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {MI.getOperand(0)}, {Shr}); 
MI.eraseFromParent();
+  MIB.buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {MI.getOperand(0)}, {Shr});
+  MI.eraseFromParent();
 }
 break;
   }
   case Intrinsic::aarch64_neon_sqshrun: {
-if (MRI.getType(MI.getOperand(0).getReg()).isVector())
-{
-  // Create right shift instruction. Get v. register the output is written 
to
-  auto Shr = MIB.buildInstr(AArch64::G_VASHR, 
{MRI.getType(MI.getOperand(2).getReg())}, {MI.getOperand(2), 
MI.getOperand(3).getImm()});
+if (MRI.getType(MI.getOperand(0).getReg()).isVector()) {
+  // Create right shift instruction. Get v. register the output is written
+  // to
+  auto Shr = MIB.buildInstr(AArch64::G_VASHR,
+{MRI.getType(MI.getOperand(2).getReg())},
+{MI.getOperand(2), MI.getOperand(3).getImm()});
   // Build the narrow intrinsic, taking in the v. register of the shift
   MIB.buildInstr(TargetOpcode::G_TRUNC_SSAT_U, {MI.getOperand(0)}, {Shr});
   MI.eraseFromParent();
@@ -1879,10 +1884,12 @@ bool 
AArch64LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
 break;
   }
   case Intrinsic::aarch64_neon_sqrshrn: {
-if (MRI.getType(MI.getOperand(0).getReg()).isVector())
-{
-  // Create right shift instruction. Get v. register the output is written 
to
-  auto Shr = MIB.buildInstr(AArch64::G_SRSHR, 
{MRI.getType(MI.getOperand(2).getReg())}, {MI.getOperand(2), 
MI.getOperand(3).getImm()});
+if (MRI.getType(MI.getOperand(0).getReg()).isVector()) {
+  // Create right shift instruction. Get v. register the output is written
+  // to
+  auto Shr = MIB.buildInstr(AArch64::G_SRSHR,
+{MRI.getType(MI.getOperand(2).getReg())},
+{MI.getOperand(2), MI.getOperand(3).getImm()});
   // Build the narrow intrinsic, taking in the v. register of the shift
   MIB.buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {MI.getOperand(0)}, {Shr});
   MI.eraseFromParent();
@@ -1890,10 +1897,12 @@ bool 
AArch64LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
 break;
   }
   case Intrinsic::aarch64_neon_sqrshrun: {
-if (MRI.getType(MI.getOperand(0).getReg()).isVector())
-{
-  // Create right shift instruction. Get v. register the output is written 
to
-  auto Shr = MIB.buildInstr(AArch64::G_SRSHR, 
{MRI.getType(MI.getOperand(2).getReg())}, {MI.getOperand(2), 
MI.getOperand(3).getImm()});
+if (MRI.getType(MI.getOperand(0).getReg()).isVector()) {
+  // Create right shift instruction. Get v. register the output is written
+  // to
+  auto Shr = MIB.buildInstr(AArch64::G_SRSHR,
+{MRI.getType(MI.getOperand(2).getReg())},
+{MI.getOperand(2), MI.getOperand(3).getImm()});
   // Build the narrow intrinsic, taking in the v. register of the shift
   MIB.buildInstr(TargetOp

[llvm-branch-commits] [TableGen] Slightly improve error location for a fatal error (PR #170790)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits


@@ -1316,11 +1316,18 @@ CodeGenRegBank::getOrCreateSubClass(const 
CodeGenRegisterClass *RC,
   return {&RegClasses.back(), true};
 }
 
-CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def) const {
+CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def,
+  ArrayRef Loc) const {
   if (CodeGenRegisterClass *RC = Def2RC.lookup(Def))
 return RC;
 
-  PrintFatalError(Def->getLoc(), "Not a known RegisterClass!");
+  ArrayRef DiagLoc = Loc.empty() ? Def->getLoc() : Loc;
+  // TODO: Ideally we should update the API to allow resolving HwMode.

s-barannikov wrote:

Is that even possible? HwModes are resolved at runtime

https://github.com/llvm/llvm-project/pull/170790
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [TableGen] Slightly improve error location for a fatal error (PR #170790)

2025-12-05 Thread Sergei Barannikov via llvm-branch-commits


@@ -1316,11 +1316,18 @@ CodeGenRegBank::getOrCreateSubClass(const 
CodeGenRegisterClass *RC,
   return {&RegClasses.back(), true};
 }
 
-CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def) const {
+CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def,

s-barannikov wrote:

I would prefer that the caller ensure that it is passing an instance of 
RegisterClass.

https://github.com/llvm/llvm-project/pull/170790
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [AArch64][GlobalISel] Added support for neon right shifts (PR #170832)

2025-12-05 Thread Joshua Rodriguez via llvm-branch-commits

https://github.com/JoshdRod created 
https://github.com/llvm/llvm-project/pull/170832

Many neon right shift intrinsics were not supported by GlobalISel, mainly due 
to a lack of legalisation logic. This logic has now been implemented.

>From 7e897eac1eee87148b1f3529a42e4b927b556d44 Mon Sep 17 00:00:00 2001
From: Josh Rodriguez 
Date: Thu, 27 Nov 2025 15:34:40 +
Subject: [PATCH 1/8] [AArch64][GlobalISel] Removed fallback for sqshlu
 intrinsic

Added G_SQSHLU node, which lowers the llvm ir intrinsic aarch64_neon_sqshlu to 
the machine intrinsic sqshlu. Generated code is slightly less efficient compare 
to SDAG.
---
 llvm/lib/Target/AArch64/AArch64InstrGISel.td  |  8 +++
 .../AArch64/GISel/AArch64LegalizerInfo.cpp| 12 +
 .../AArch64/GISel/AArch64RegisterBankInfo.cpp |  9 
 llvm/test/CodeGen/AArch64/arm64-vshift.ll | 49 ++-
 4 files changed, 56 insertions(+), 22 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrGISel.td 
b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
index 7d99786830e3d..7469a081d9787 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrGISel.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
@@ -252,6 +252,12 @@ def G_USDOT : AArch64GenericInstruction {
   let hasSideEffects = 0;
 }
 
+def G_SQSHLU : AArch64GenericInstruction {
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins type0:$src1, type0:$src2);
+  let hasSideEffects = 0;
+}
+
 // Generic instruction for the BSP pseudo. It is expanded into BSP, which
 // expands into BSL/BIT/BIF after register allocation.
 def G_BSP : AArch64GenericInstruction {
@@ -300,6 +306,8 @@ def : GINodeEquiv;
 def : GINodeEquiv;
 def : GINodeEquiv;
 
+def : GINodeEquiv;
+
 def : GINodeEquiv;
 
 def : GINodeEquiv;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp 
b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 1025b2502211a..0010834e01894 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -1857,6 +1857,18 @@ bool 
AArch64LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
 return LowerBinOp(TargetOpcode::G_SAVGFLOOR);
   case Intrinsic::aarch64_neon_srhadd:
 return LowerBinOp(TargetOpcode::G_SAVGCEIL);
+  case Intrinsic::aarch64_neon_sqshlu: {
+// Check if last operand is constant vector dup
+auto shiftAmount = 
isConstantOrConstantSplatVector(*MRI.getVRegDef(MI.getOperand(3).getReg()), 
MRI);
+if (shiftAmount) {
+   // If so, create a new intrinsic with the correct shift amount
+   MIB.buildInstr(AArch64::G_SQSHLU, {MI.getOperand(0)}, 
{MI.getOperand(2)}).addImm(shiftAmount->getSExtValue());
+   MI.eraseFromParent();
+   return true;
+} else {
+   return false;
+}
+  }
   case Intrinsic::aarch64_neon_abs: {
 // Lower the intrinsic to G_ABS.
 MIB.buildInstr(TargetOpcode::G_ABS, {MI.getOperand(0)}, 
{MI.getOperand(2)});
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp 
b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
index 652a31f4e65f2..aa1517533b753 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp
@@ -1072,6 +1072,15 @@ AArch64RegisterBankInfo::getInstrMapping(const 
MachineInstr &MI) const {
 // Index needs to be a GPR.
 OpRegBankIdx[2] = PMI_FirstGPR;
 break;
+  case AArch64::G_SQSHLU:
+// Destination and source need to be FPRs.
+OpRegBankIdx[0] = PMI_FirstFPR;
+OpRegBankIdx[1] = PMI_FirstFPR;
+
+// Shift Index needs to be a GPR.
+OpRegBankIdx[2] = PMI_FirstGPR;
+break;
+
   case TargetOpcode::G_INSERT_VECTOR_ELT:
 OpRegBankIdx[0] = PMI_FirstFPR;
 OpRegBankIdx[1] = PMI_FirstFPR;
diff --git a/llvm/test/CodeGen/AArch64/arm64-vshift.ll 
b/llvm/test/CodeGen/AArch64/arm64-vshift.ll
index 34843835d284a..961788f311041 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vshift.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vshift.ll
@@ -2,17 +2,7 @@
 ; RUN: llc < %s -mtriple=arm64-eabi -global-isel=0 | FileCheck %s 
--check-prefixes=CHECK,CHECK-SD
 ; RUN: llc < %s -mtriple=arm64-eabi -global-isel=1 -global-isel-abort=2 2>&1 | 
FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
-; CHECK-GI:warning: Instruction selection used fallback path for sqshlu8b
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu4h
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu2s
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu16b
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu8h
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu4s
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu2d
-; CHECK-GI NEXT:warning: Instruction selection used fallback path for 
sqshlu1d_constant
-; CHECK-GI 

[llvm-branch-commits] [llvm] [AArch64][GlobalISel] Added support for neon right shifts (PR #170832)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-backend-aarch64

Author: Joshua Rodriguez (JoshdRod)


Changes

Many neon right shift intrinsics were not supported by GlobalISel, mainly due 
to a lack of legalisation logic. This logic has now been implemented.

---

Patch is 23.34 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/170832.diff


5 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64InstrGISel.td (+22) 
- (modified) llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp (+76) 
- (modified) llvm/lib/Target/AArch64/GISel/AArch64RegisterBankInfo.cpp (+15) 
- (modified) llvm/test/CodeGen/AArch64/arm64-int-neon.ll (+3-10) 
- (modified) llvm/test/CodeGen/AArch64/arm64-vshift.ll (+73-152) 


``diff
diff --git a/llvm/lib/Target/AArch64/AArch64InstrGISel.td 
b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
index 7d99786830e3d..75354e4098fb4 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrGISel.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrGISel.td
@@ -252,6 +252,24 @@ def G_USDOT : AArch64GenericInstruction {
   let hasSideEffects = 0;
 }
 
+def G_SQSHLU : AArch64GenericInstruction {
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins type0:$src1, type0:$src2);
+  let hasSideEffects = 0;
+}
+
+def G_SRSHR: AArch64GenericInstruction {
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins type0:$src1, type0:$src2);
+  let hasSideEffects = 0;
+}
+
+def G_URSHR: AArch64GenericInstruction {
+  let OutOperandList = (outs type0:$dst);
+  let InOperandList = (ins type0:$src1, type0:$src2);
+  let hasSideEffects = 0;
+}
+
 // Generic instruction for the BSP pseudo. It is expanded into BSP, which
 // expands into BSL/BIT/BIF after register allocation.
 def G_BSP : AArch64GenericInstruction {
@@ -300,6 +318,10 @@ def : GINodeEquiv;
 def : GINodeEquiv;
 def : GINodeEquiv;
 
+def : GINodeEquiv;
+def : GINodeEquiv;
+def : GINodeEquiv;
+
 def : GINodeEquiv;
 
 def : GINodeEquiv;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp 
b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 1025b2502211a..0c8472b759132 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -1857,6 +1857,82 @@ bool 
AArch64LegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
 return LowerBinOp(TargetOpcode::G_SAVGFLOOR);
   case Intrinsic::aarch64_neon_srhadd:
 return LowerBinOp(TargetOpcode::G_SAVGCEIL);
+  case Intrinsic::aarch64_neon_sqshrn: {
+if (MRI.getType(MI.getOperand(0).getReg()).isVector())
+{
+  // Create right shift instruction. Get v. register the output is written 
to
+  auto Shr = MIB.buildInstr(AArch64::G_VASHR, 
{MRI.getType(MI.getOperand(2).getReg())}, {MI.getOperand(2), 
MI.getOperand(3).getImm()});
+  // Build the narrow intrinsic, taking in the v. register of the shift
+  MIB.buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {MI.getOperand(0)}, {Shr}); 
MI.eraseFromParent();
+}
+break;
+  }
+  case Intrinsic::aarch64_neon_sqshrun: {
+if (MRI.getType(MI.getOperand(0).getReg()).isVector())
+{
+  // Create right shift instruction. Get v. register the output is written 
to
+  auto Shr = MIB.buildInstr(AArch64::G_VASHR, 
{MRI.getType(MI.getOperand(2).getReg())}, {MI.getOperand(2), 
MI.getOperand(3).getImm()});
+  // Build the narrow intrinsic, taking in the v. register of the shift
+  MIB.buildInstr(TargetOpcode::G_TRUNC_SSAT_U, {MI.getOperand(0)}, {Shr});
+  MI.eraseFromParent();
+}
+break;
+  }
+  case Intrinsic::aarch64_neon_sqrshrn: {
+if (MRI.getType(MI.getOperand(0).getReg()).isVector())
+{
+  // Create right shift instruction. Get v. register the output is written 
to
+  auto Shr = MIB.buildInstr(AArch64::G_SRSHR, 
{MRI.getType(MI.getOperand(2).getReg())}, {MI.getOperand(2), 
MI.getOperand(3).getImm()});
+  // Build the narrow intrinsic, taking in the v. register of the shift
+  MIB.buildInstr(TargetOpcode::G_TRUNC_SSAT_S, {MI.getOperand(0)}, {Shr});
+  MI.eraseFromParent();
+}
+break;
+  }
+  case Intrinsic::aarch64_neon_sqrshrun: {
+if (MRI.getType(MI.getOperand(0).getReg()).isVector())
+{
+  // Create right shift instruction. Get v. register the output is written 
to
+  auto Shr = MIB.buildInstr(AArch64::G_SRSHR, 
{MRI.getType(MI.getOperand(2).getReg())}, {MI.getOperand(2), 
MI.getOperand(3).getImm()});
+  // Build the narrow intrinsic, taking in the v. register of the shift
+  MIB.buildInstr(TargetOpcode::G_TRUNC_SSAT_U, {MI.getOperand(0)}, {Shr});
+  MI.eraseFromParent();
+}
+break;
+  }
+  case Intrinsic::aarch64_neon_uqrshrn: {
+if (MRI.getType(MI.getOperand(0).getReg()).isVector())
+{
+  // Create right shift instruction. Get v. register the output is written 
to
+  auto Shr = MIB.buildInstr(AArch64::G_URSHR, 
{MRI.getType(MI.getOperand(2).getReg())}, {MI.getOperand(2

[llvm-branch-commits] [llvm] [ADT] Make use of subsetOf and anyCommon methods of BitVector (NFC) (PR #170876)

2025-12-05 Thread Anatoly Trosinenko via llvm-branch-commits

https://github.com/atrosinenko created 
https://github.com/llvm/llvm-project/pull/170876

Replace the code along these lines

BitVector Tmp = LHS;
Tmp &= RHS;
return Tmp.any();

and

BitVector Tmp = LHS;
Tmp.reset(RHS);
return Tmp.none();

with `LHS.anyCommon(RHS)` and `LHS.subsetOf(RHS)`, correspondingly, which
do not require creating temporary BitVector and can return early.

>From 73766497cd71e96377c0cab2ef13a1a3566fe4cd Mon Sep 17 00:00:00 2001
From: Anatoly Trosinenko 
Date: Fri, 5 Dec 2025 16:08:28 +0300
Subject: [PATCH] [ADT] Make use of subsetOf and anyCommon methods of BitVector
 (NFC)

Replace the code along these lines

BitVector Tmp = LHS;
Tmp &= RHS;
return Tmp.any();

and

BitVector Tmp = LHS;
Tmp.reset(RHS);
return Tmp.none();

with `LHS.anyCommon(RHS)` and `LHS.subsetOf(RHS)`, correspondingly, which
do not require creating temporary BitVector and can return early.
---
 bolt/include/bolt/Passes/LivenessAnalysis.h   |  5 ++---
 bolt/include/bolt/Passes/ReachingDefOrUse.h   |  3 +--
 bolt/lib/Passes/RegReAssign.cpp   |  8 ++--
 bolt/lib/Passes/ShrinkWrapping.cpp| 10 --
 bolt/lib/Passes/StackAvailableExpressions.cpp |  3 +--
 bolt/lib/Passes/TailDuplication.cpp   |  8 
 llvm/lib/CodeGen/RDFRegisters.cpp |  6 ++
 llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp |  6 ++
 8 files changed, 18 insertions(+), 31 deletions(-)

diff --git a/bolt/include/bolt/Passes/LivenessAnalysis.h 
b/bolt/include/bolt/Passes/LivenessAnalysis.h
index 1df1113318d0b..f4faa1dc34ecd 100644
--- a/bolt/include/bolt/Passes/LivenessAnalysis.h
+++ b/bolt/include/bolt/Passes/LivenessAnalysis.h
@@ -37,10 +37,9 @@ class LivenessAnalysis : public 
DataflowAnalysisgetStateAt(PP));
+const BitVector &BV = *this->getStateAt(PP);
 const BitVector &RegAliases = BC.MIB->getAliases(Reg);
-BV &= RegAliases;
-return BV.any();
+return BV.anyCommon(RegAliases);
   }
 
   void run() { Parent::run(); }
diff --git a/bolt/include/bolt/Passes/ReachingDefOrUse.h 
b/bolt/include/bolt/Passes/ReachingDefOrUse.h
index 585d673e3b84e..41a6091aad4cb 100644
--- a/bolt/include/bolt/Passes/ReachingDefOrUse.h
+++ b/bolt/include/bolt/Passes/ReachingDefOrUse.h
@@ -133,8 +133,7 @@ class ReachingDefOrUse
   RA.getInstClobberList(Point, Regs);
 else
   RA.getInstUsedRegsList(Point, Regs, false);
-Regs &= this->BC.MIB->getAliases(*TrackingReg);
-if (Regs.any())
+if (Regs.anyCommon(this->BC.MIB->getAliases(*TrackingReg)))
   Next.set(this->ExprToIdx[&Point]);
   }
 }
diff --git a/bolt/lib/Passes/RegReAssign.cpp b/bolt/lib/Passes/RegReAssign.cpp
index 0859cd244ce40..54eff51bfee68 100644
--- a/bolt/lib/Passes/RegReAssign.cpp
+++ b/bolt/lib/Passes/RegReAssign.cpp
@@ -316,18 +316,14 @@ void 
RegReAssign::aggressivePassOverFunction(BinaryFunction &Function) {
   break;
 }
 
-BitVector AnyAliasAlive = AliveAtStart;
-AnyAliasAlive &= BC.MIB->getAliases(ClassicReg);
-if (AnyAliasAlive.any()) {
+if (AliveAtStart.anyCommon(BC.MIB->getAliases(ClassicReg))) {
   LLVM_DEBUG(dbgs() << " Bailed on " << BC.MRI->getName(ClassicReg)
 << " with " << BC.MRI->getName(ExtReg)
 << " because classic reg is alive\n");
   --End;
   continue;
 }
-AnyAliasAlive = AliveAtStart;
-AnyAliasAlive &= BC.MIB->getAliases(ExtReg);
-if (AnyAliasAlive.any()) {
+if (AliveAtStart.anyCommon(BC.MIB->getAliases(ExtReg))) {
   LLVM_DEBUG(dbgs() << " Bailed on " << BC.MRI->getName(ClassicReg)
 << " with " << BC.MRI->getName(ExtReg)
 << " because extended reg is alive\n");
diff --git a/bolt/lib/Passes/ShrinkWrapping.cpp 
b/bolt/lib/Passes/ShrinkWrapping.cpp
index fe342ccd38a67..b882e2512866d 100644
--- a/bolt/lib/Passes/ShrinkWrapping.cpp
+++ b/bolt/lib/Passes/ShrinkWrapping.cpp
@@ -1100,9 +1100,8 @@ SmallVector 
ShrinkWrapping::fixPopsPlacements(
 bool Found = false;
 if (SPT.getStateAt(ProgramPoint::getLastPointAt(*BB))->first ==
 SaveOffset) {
-  BitVector BV = *RI.getStateAt(ProgramPoint::getLastPointAt(*BB));
-  BV &= UsesByReg[CSR];
-  if (!BV.any()) {
+  const BitVector &BV = *RI.getStateAt(ProgramPoint::getLastPointAt(*BB));
+  if (!BV.anyCommon(UsesByReg[CSR])) {
 Found = true;
 PP = BB;
 continue;
@@ -1110,9 +1109,8 @@ SmallVector 
ShrinkWrapping::fixPopsPlacements(
 }
 for (MCInst &Inst : llvm::reverse(*BB)) {
   if (SPT.getStateBefore(Inst)->first == SaveOffset) {
-BitVector BV = *RI.getStateAt(Inst);
-BV &= UsesByReg[CSR];
-if (!BV.any()) {
+const BitVector &BV = *RI.getStateAt(Inst);
+if (!BV.anyCommon(UsesByReg[CSR])) {
   Found = true;
   PP = &Inst;
   break;
diff --git a/bolt/l

[llvm-branch-commits] [llvm] [ADT] Make use of subsetOf and anyCommon methods of BitVector (NFC) (PR #170876)

2025-12-05 Thread Anatoly Trosinenko via llvm-branch-commits

atrosinenko wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.com/github/pr/llvm/llvm-project/170876?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#170876** https://app.graphite.com/github/pr/llvm/llvm-project/170876?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.com/github/pr/llvm/llvm-project/170876?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#170875** https://app.graphite.com/github/pr/llvm/llvm-project/170875?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `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/170876
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [TableGen] Slightly improve error location for a fatal error (PR #170790)

2025-12-05 Thread Alexander Richardson via llvm-branch-commits


@@ -1316,11 +1316,18 @@ CodeGenRegBank::getOrCreateSubClass(const 
CodeGenRegisterClass *RC,
   return {&RegClasses.back(), true};
 }
 
-CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def) const {
+CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def,
+  ArrayRef Loc) const {
   if (CodeGenRegisterClass *RC = Def2RC.lookup(Def))
 return RC;
 
-  PrintFatalError(Def->getLoc(), "Not a known RegisterClass!");
+  ArrayRef DiagLoc = Loc.empty() ? Def->getLoc() : Loc;
+  // TODO: Ideally we should update the API to allow resolving HwMode.

arichardson wrote:

In some cases (e.g. inside a `let Predicates = [...]` block), we may be able to 
know exactly what it resolves to but that will require a lot more refactoring. 
I can drop the comment if you prefer.

https://github.com/llvm/llvm-project/pull/170790
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [TableGen] Slightly improve error location for a fatal error (PR #170790)

2025-12-05 Thread Alexander Richardson via llvm-branch-commits


@@ -1316,11 +1316,18 @@ CodeGenRegBank::getOrCreateSubClass(const 
CodeGenRegisterClass *RC,
   return {&RegClasses.back(), true};
 }
 
-CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def) const {
+CodeGenRegisterClass *CodeGenRegBank::getRegClass(const Record *Def,

arichardson wrote:

Do you mean add an `assert(Def->isSubclassOf("RegisterClassLike"))` inside this 
function? It can't be RegisterClass yet since there are too many callers that 
don't correctly check yet. In the future that could be "RegisterClass" once all 
callers have been updated to avoid assertions.

https://github.com/llvm/llvm-project/pull/170790
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Make use of subsetOf and anyCommon methods of BitVector (NFC) (PR #170876)

2025-12-05 Thread Jakub Kuderski via llvm-branch-commits

https://github.com/kuhar commented:

Can you add unit tests?

https://github.com/llvm/llvm-project/pull/170876
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Make use of subsetOf and anyCommon methods of BitVector (NFC) (PR #170876)

2025-12-05 Thread Jakub Kuderski via llvm-branch-commits

https://github.com/kuhar edited https://github.com/llvm/llvm-project/pull/170876
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [compiler-rt] 12a532c - Revert "[clang][Darwin] Prefer the toolchain-provided libc++.dylib if there i…"

2025-12-05 Thread via llvm-branch-commits

Author: Kewen Meng
Date: 2025-12-05T12:01:47-08:00
New Revision: 12a532cc430c3b89483ce9cc89bbfc7bea8541e5

URL: 
https://github.com/llvm/llvm-project/commit/12a532cc430c3b89483ce9cc89bbfc7bea8541e5
DIFF: 
https://github.com/llvm/llvm-project/commit/12a532cc430c3b89483ce9cc89bbfc7bea8541e5.diff

LOG: Revert "[clang][Darwin] Prefer the toolchain-provided libc++.dylib if 
there i…"

This reverts commit 190b8d0b4f19e1c3d68c5d153ec7be71a9969192.

Added: 


Modified: 
clang/lib/Driver/ToolChains/Darwin.cpp
clang/test/Driver/darwin-header-search-libcxx.cpp
clang/test/Driver/experimental-library-flag.cpp
compiler-rt/cmake/config-ix.cmake

Removed: 
clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++.dylib
clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++experimental.a
clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/bin/.keep

clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/include/c++/v1/.keep
clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++.a

clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++experimental.a
clang/test/Driver/darwin-link-libcxx.cpp



diff  --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index 30c53389dc22f..fc3cd9030f71d 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -2846,49 +2846,11 @@ void AppleMachO::AddCXXStdlibLibArgs(const ArgList 
&Args,
   CXXStdlibType Type = GetCXXStdlibType(Args);
 
   switch (Type) {
-  case ToolChain::CST_Libcxx: {
-// On Darwin, we prioritize a libc++ located in the toolchain to a libc++
-// located in the sysroot. Unlike the driver for most other platforms, on
-// Darwin we do that by explicitly passing the library path to the linker
-// to avoid having to add the toolchain's `lib/` directory to the linker
-// search path, which would make other libraries findable as well.
-//
-// Prefering the toolchain library over the sysroot library matches the
-// behavior we have for headers, where we prefer headers in the toolchain
-// over headers in the sysroot if there are any. Note that it's important
-// for the header search path behavior to match the link-time search path
-// behavior to ensure that we link the program against a library that
-// matches the headers that were used to compile it.
-//
-// Otherwise, we end up compiling against some set of headers and then
-// linking against a 
diff erent library (which, confusingly, shares the same
-// name) which may have been configured with 
diff erent options, be at a
-// 
diff erent version, etc.
-SmallString<128> InstallLib = 
llvm::sys::path::parent_path(getDriver().Dir);
-llvm::sys::path::append(InstallLib, "lib"); // /lib
-auto Link = [&](StringRef Library) {
-  SmallString<128> Shared(InstallLib);
-  llvm::sys::path::append(Shared,
-  SmallString<4>("lib") + Library + ".dylib");
-  SmallString<128> Static(InstallLib);
-  llvm::sys::path::append(Static, SmallString<4>("lib") + Library + ".a");
-  SmallString<32> Relative("-l");
-  Relative += Library;
-
-  if (getVFS().exists(Shared)) {
-CmdArgs.push_back(Args.MakeArgString(Shared));
-  } else if (getVFS().exists(Static)) {
-CmdArgs.push_back(Args.MakeArgString(Static));
-  } else {
-CmdArgs.push_back(Args.MakeArgString(Relative));
-  }
-};
-
-Link("c++");
+  case ToolChain::CST_Libcxx:
+CmdArgs.push_back("-lc++");
 if (Args.hasArg(options::OPT_fexperimental_library))
-  Link("c++experimental");
+  CmdArgs.push_back("-lc++experimental");
 break;
-  }
 
   case ToolChain::CST_Libstdcxx:
 // Unfortunately, -lstdc++ doesn't always exist in the standard search 
path;

diff  --git 
a/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++.dylib 
b/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++.dylib
deleted file mode 100644
index e69de29bb2d1d..0

diff  --git 
a/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++experimental.a 
b/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++experimental.a
deleted file mode 100644
index e69de29bb2d1d..0

diff  --git 
a/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/bin/.keep 
b/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/bin/.keep
deleted file mode 100644
index e69de29bb2d1d..0

diff  --git 
a/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/include/c++/v1/.keep
 
b/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/include/c++/v1/.keep
deleted file mode 100644
index e69de29bb2d1d..0

diff  --git 
a/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++.a 
b/clang/test/Driv

[llvm-branch-commits] [clang] 3ac8417 - Reapply "[clang][Darwin] Prefer the toolchain-provided libc++.dylib if there i…"

2025-12-05 Thread Louis Dionne via llvm-branch-commits

Author: Louis Dionne
Date: 2025-12-05T15:19:05-05:00
New Revision: 3ac8417fb4d6d0916cf5082d76d9794420a9cd8e

URL: 
https://github.com/llvm/llvm-project/commit/3ac8417fb4d6d0916cf5082d76d9794420a9cd8e
DIFF: 
https://github.com/llvm/llvm-project/commit/3ac8417fb4d6d0916cf5082d76d9794420a9cd8e.diff

LOG: Reapply "[clang][Darwin] Prefer the toolchain-provided libc++.dylib if 
there i…"

This reverts commit 12a532cc430c3b89483ce9cc89bbfc7bea8541e5.

Added: 
clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++.dylib
clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++experimental.a
clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/bin/.keep

clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/include/c++/v1/.keep
clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++.a

clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++experimental.a
clang/test/Driver/darwin-link-libcxx.cpp

Modified: 
clang/lib/Driver/ToolChains/Darwin.cpp
clang/test/Driver/darwin-header-search-libcxx.cpp
clang/test/Driver/experimental-library-flag.cpp
compiler-rt/cmake/config-ix.cmake

Removed: 




diff  --git a/clang/lib/Driver/ToolChains/Darwin.cpp 
b/clang/lib/Driver/ToolChains/Darwin.cpp
index fc3cd9030f71d..30c53389dc22f 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -2846,11 +2846,49 @@ void AppleMachO::AddCXXStdlibLibArgs(const ArgList 
&Args,
   CXXStdlibType Type = GetCXXStdlibType(Args);
 
   switch (Type) {
-  case ToolChain::CST_Libcxx:
-CmdArgs.push_back("-lc++");
+  case ToolChain::CST_Libcxx: {
+// On Darwin, we prioritize a libc++ located in the toolchain to a libc++
+// located in the sysroot. Unlike the driver for most other platforms, on
+// Darwin we do that by explicitly passing the library path to the linker
+// to avoid having to add the toolchain's `lib/` directory to the linker
+// search path, which would make other libraries findable as well.
+//
+// Prefering the toolchain library over the sysroot library matches the
+// behavior we have for headers, where we prefer headers in the toolchain
+// over headers in the sysroot if there are any. Note that it's important
+// for the header search path behavior to match the link-time search path
+// behavior to ensure that we link the program against a library that
+// matches the headers that were used to compile it.
+//
+// Otherwise, we end up compiling against some set of headers and then
+// linking against a 
diff erent library (which, confusingly, shares the same
+// name) which may have been configured with 
diff erent options, be at a
+// 
diff erent version, etc.
+SmallString<128> InstallLib = 
llvm::sys::path::parent_path(getDriver().Dir);
+llvm::sys::path::append(InstallLib, "lib"); // /lib
+auto Link = [&](StringRef Library) {
+  SmallString<128> Shared(InstallLib);
+  llvm::sys::path::append(Shared,
+  SmallString<4>("lib") + Library + ".dylib");
+  SmallString<128> Static(InstallLib);
+  llvm::sys::path::append(Static, SmallString<4>("lib") + Library + ".a");
+  SmallString<32> Relative("-l");
+  Relative += Library;
+
+  if (getVFS().exists(Shared)) {
+CmdArgs.push_back(Args.MakeArgString(Shared));
+  } else if (getVFS().exists(Static)) {
+CmdArgs.push_back(Args.MakeArgString(Static));
+  } else {
+CmdArgs.push_back(Args.MakeArgString(Relative));
+  }
+};
+
+Link("c++");
 if (Args.hasArg(options::OPT_fexperimental_library))
-  CmdArgs.push_back("-lc++experimental");
+  Link("c++experimental");
 break;
+  }
 
   case ToolChain::CST_Libstdcxx:
 // Unfortunately, -lstdc++ doesn't always exist in the standard search 
path;

diff  --git 
a/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++.dylib 
b/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++.dylib
new file mode 100644
index 0..e69de29bb2d1d

diff  --git 
a/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++experimental.a 
b/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++experimental.a
new file mode 100644
index 0..e69de29bb2d1d

diff  --git 
a/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/bin/.keep 
b/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/bin/.keep
new file mode 100644
index 0..e69de29bb2d1d

diff  --git 
a/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/include/c++/v1/.keep
 
b/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/include/c++/v1/.keep
new file mode 100644
index 0..e69de29bb2d1d

diff  --git 
a/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++.a 
b/clang/test/Driver/Inputs/bas

[llvm-branch-commits] [clang] 4c50d83 - Require darwin

2025-12-05 Thread Louis Dionne via llvm-branch-commits

Author: Louis Dionne
Date: 2025-12-05T15:23:05-05:00
New Revision: 4c50d83e8ddecf0cf6f642671523e14770d1c3e7

URL: 
https://github.com/llvm/llvm-project/commit/4c50d83e8ddecf0cf6f642671523e14770d1c3e7
DIFF: 
https://github.com/llvm/llvm-project/commit/4c50d83e8ddecf0cf6f642671523e14770d1c3e7.diff

LOG: Require darwin

Added: 


Modified: 
clang/test/Driver/darwin-link-libcxx.cpp

Removed: 




diff  --git a/clang/test/Driver/darwin-link-libcxx.cpp 
b/clang/test/Driver/darwin-link-libcxx.cpp
index 1c4f31b257512..fca1e3c6f3d6f 100644
--- a/clang/test/Driver/darwin-link-libcxx.cpp
+++ b/clang/test/Driver/darwin-link-libcxx.cpp
@@ -1,5 +1,8 @@
 // UNSUPPORTED: system-windows
 
+// TODO: Make this test portable across platforms
+// REQUIRES: system-darwin
+
 // Tests to check that we link against the toolchain-provided libc++ built 
library when it is provided.
 // This is required to prefer the toolchain's libc++ over the system's libc++, 
which matches the behavior
 // we have for header search paths.



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [ADT] Make use of subsetOf and anyCommon methods of BitVector (NFC) (PR #170876)

2025-12-05 Thread Jakub Kuderski via llvm-branch-commits

https://github.com/kuhar approved this pull request.


https://github.com/llvm/llvm-project/pull/170876
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [libc] [libc][printf] De-string-viewify writer internals. (PR #170959)

2025-12-05 Thread Alexey Samsonov via llvm-branch-commits

https://github.com/vonosmas ready_for_review 
https://github.com/llvm/llvm-project/pull/170959
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [BPF] add allows-misaligned-mem-access target feature (PR #168314)

2025-12-05 Thread Claire Fan via llvm-branch-commits

https://github.com/clairechingching updated 
https://github.com/llvm/llvm-project/pull/168314

>From 93282b2f8a2249bce33c7c87aa4d8704674f6c46 Mon Sep 17 00:00:00 2001
From: Claire xyz 
Date: Fri, 7 Nov 2025 11:08:47 -0500
Subject: [PATCH] [BPF] add allows-misaligned-mem-access target feature

This enables misaligned memory access when the feature is enabled
---
 llvm/lib/Target/BPF/BPF.td|   4 +
 llvm/lib/Target/BPF/BPFISelLowering.cpp   |  20 ++
 llvm/lib/Target/BPF/BPFISelLowering.h |   7 +
 llvm/lib/Target/BPF/BPFSubtarget.cpp  |   1 +
 llvm/lib/Target/BPF/BPFSubtarget.h|   6 +
 llvm/test/CodeGen/BPF/unaligned_load_store.ll | 196 ++
 6 files changed, 234 insertions(+)
 create mode 100644 llvm/test/CodeGen/BPF/unaligned_load_store.ll

diff --git a/llvm/lib/Target/BPF/BPF.td b/llvm/lib/Target/BPF/BPF.td
index dff76ca07af51..a7aa6274f5ac1 100644
--- a/llvm/lib/Target/BPF/BPF.td
+++ b/llvm/lib/Target/BPF/BPF.td
@@ -27,6 +27,10 @@ def ALU32 : SubtargetFeature<"alu32", "HasAlu32", "true",
 def DwarfRIS: SubtargetFeature<"dwarfris", "UseDwarfRIS", "true",
"Disable MCAsmInfo 
DwarfUsesRelocationsAcrossSections">;
 
+def MisalignedMemAccess : SubtargetFeature<"allows-misaligned-mem-access",
+   "AllowsMisalignedMemAccess", "true",
+   "Allows misaligned memory access">;
+
 def : Proc<"generic", []>;
 def : Proc<"v1", []>;
 def : Proc<"v2", []>;
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp 
b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index f4f414d192df0..5ec7f5905fd22 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.cpp
+++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp
@@ -196,6 +196,26 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine 
&TM,
   HasJmp32 = STI.getHasJmp32();
   HasJmpExt = STI.getHasJmpExt();
   HasMovsx = STI.hasMovsx();
+
+  AllowsMisalignedMemAccess = STI.getAllowsMisalignedMemAccess();
+}
+
+bool BPFTargetLowering::allowsMisalignedMemoryAccesses(EVT VT, unsigned, Align,
+   
MachineMemOperand::Flags,
+   unsigned *Fast) const {
+  // allows-misaligned-mem-access is disabled
+  if (!AllowsMisalignedMemAccess)
+return false;
+
+  // only allow misalignment for simple value types
+  if (!VT.isSimple())
+return false;
+
+  // always assume fast mode when misalignment is allowed
+  if (Fast)
+*Fast = true;
+
+  return true;
 }
 
 bool BPFTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) 
const {
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.h 
b/llvm/lib/Target/BPF/BPFISelLowering.h
index 8f60261c10e9e..fe01bd5b8cf85 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.h
+++ b/llvm/lib/Target/BPF/BPFISelLowering.h
@@ -46,6 +46,10 @@ class BPFTargetLowering : public TargetLowering {
   // with the given GlobalAddress is legal.
   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
 
+  bool allowsMisalignedMemoryAccesses(EVT VT, unsigned, Align,
+  MachineMemOperand::Flags,
+  unsigned *) const override;
+
   BPFTargetLowering::ConstraintType
   getConstraintType(StringRef Constraint) const override;
 
@@ -73,6 +77,9 @@ class BPFTargetLowering : public TargetLowering {
   bool HasJmpExt;
   bool HasMovsx;
 
+  // Allows Misalignment
+  bool AllowsMisalignedMemAccess;
+
   SDValue LowerSDIVSREM(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
   SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.cpp 
b/llvm/lib/Target/BPF/BPFSubtarget.cpp
index 4167547680b12..925537710efb0 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.cpp
+++ b/llvm/lib/Target/BPF/BPFSubtarget.cpp
@@ -66,6 +66,7 @@ void BPFSubtarget::initializeEnvironment() {
   HasGotol = false;
   HasStoreImm = false;
   HasLoadAcqStoreRel = false;
+  AllowsMisalignedMemAccess = false;
 }
 
 void BPFSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.h 
b/llvm/lib/Target/BPF/BPFSubtarget.h
index aed2211265e23..a9a20008733c9 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.h
+++ b/llvm/lib/Target/BPF/BPFSubtarget.h
@@ -63,6 +63,9 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
   // whether we should enable MCAsmInfo DwarfUsesRelocationsAcrossSections
   bool UseDwarfRIS;
 
+  // whether we allows misaligned memory access
+  bool AllowsMisalignedMemAccess;
+
   // whether cpu v4 insns are enabled.
   bool HasLdsx, HasMovsx, HasBswap, HasSdivSmod, HasGotol, HasStoreImm,
   HasLoadAcqStoreRel;
@@ -87,6 +90,9 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
   bool getHasJmp32() const { return HasJmp32; }
   bool getHasAlu32() const { return HasAlu32; }
   bool g

[llvm-branch-commits] [clang] release/21.x: [clang-format] Fix a crash in AlignArrayOfStructures (#167099) (PR #170967)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-format

Author: None (llvmbot)


Changes

Backport 836919bb3449767fc1734e402d3ebf989acb

Requested by: @owenca

---
Full diff: https://github.com/llvm/llvm-project/pull/170967.diff


2 Files Affected:

- (modified) clang/lib/Format/WhitespaceManager.cpp (+4-1) 
- (modified) clang/unittests/Format/FormatTest.cpp (+13) 


``diff
diff --git a/clang/lib/Format/WhitespaceManager.cpp 
b/clang/lib/Format/WhitespaceManager.cpp
index cc3cc0f6906cc..ecc696c539226 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -1295,7 +1295,10 @@ void WhitespaceManager::alignArrayInitializers() {
   bool FoundComplete = false;
   for (unsigned InsideIndex = ChangeIndex + 1; InsideIndex < ChangeEnd;
++InsideIndex) {
-if (Changes[InsideIndex].Tok == C.Tok->MatchingParen) {
+const auto *Tok = Changes[InsideIndex].Tok;
+if (Tok->is(tok::pp_define))
+  break;
+if (Tok == C.Tok->MatchingParen) {
   alignArrayInitializers(ChangeIndex, InsideIndex + 1);
   ChangeIndex = InsideIndex + 1;
   FoundComplete = true;
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 8db0500573ec0..760c5a4ce4195 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -22429,6 +22429,19 @@ TEST_F(FormatTest, 
CatchAlignArrayOfStructuresLeftAlignment) {
"});",
Style);
 
+  verifyNoCrash(
+  "PANEL_Ic PANEL_ic[PANEL_IC_NUMBER] =\n"
+  "{\n"
+  "{PIC(0),   PIC(0),   PIC(99),  PIC(81),  0}, // Backbox\n"
+  "{PIC(1),   PIC(83),  PIC(191), PIC(137), 0}, // AK47\n"
+  "\n"
+  "#define PICALL1(a, b, c, d) \\\n"
+  "{ PIC(a), PIC(b), PIC(c), PIC(d), 1 }\n"
+  "\n"
+  "PICALL1(1, 1, 75, 50),\n"
+  "};",
+  Style);
+
   Style.AlignEscapedNewlines = FormatStyle::ENAS_DontAlign;
   verifyFormat("#define FOO \\\n"
"  int foo[][2] = { \\\n"

``




https://github.com/llvm/llvm-project/pull/170967
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/21.x: [clang-format] Fix a crash in AlignArrayOfStructures (#167099) (PR #170967)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:

@HazardyKnusperkeks What do you think about merging this PR to the release 
branch?

https://github.com/llvm/llvm-project/pull/170967
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [libc] [libc][printf] De-string-viewify writer internals. (PR #170959)

2025-12-05 Thread Roland McGrath via llvm-branch-commits

frobtech wrote:

I very much think this is the wrong direction. Using span / string_view style 
types rather than raw pointer / size pairs is something I really think we 
should aspire to stick to and move more outlier code towards.  
`cpp::string_view` is a polyfill for `std::string_view`, which is already 
actually just `std::basic_string_view`; it's easy enough to templatize 
the polyfill as well and I don't see why we wouldn't just do that.

In the long run, more Hand-in-Hand work with libc++ will probably give us 
fuller string_view / span implementations to use directly in our hermetic 
namespace without reimplementing them all ourselves are we have now in 
`__support`. So I think putting a bit more work into our `cpp::*` types now--in 
the direction of being more faithful and complete polyfills of `std::*` 
counterparts--is not a slippery slope of complicating maintenance, but a 
sensible interim approach that just further motivates our established long-term 
intent to collaborate more extensively with libc++ on implementation sharing.

On the contrary, I think reverting from span/view-style types to an earlier 
era's C conventions is itself a slippery slope of backsliding to lose the 
benefits of our rigorous and modern C++ approach to libc implementation 
internals.

https://github.com/llvm/llvm-project/pull/170959
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [FlowSensitive] [StatusOr] [12/N] Add support for smart pointers (PR #170943)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Florian Mayer (fmayer)


Changes



---
Full diff: https://github.com/llvm/llvm-project/pull/170943.diff


2 Files Affected:

- (modified) 
clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp (+48) 
- (modified) 
clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
 (+74) 


``diff
diff --git 
a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp 
b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
index 038f2b0338c8d..3e56094fcbc32 100644
--- a/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.cpp
@@ -25,6 +25,7 @@
 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
 #include "clang/Analysis/FlowSensitive/MatchSwitch.h"
 #include "clang/Analysis/FlowSensitive/RecordOps.h"
+#include "clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h"
 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
 #include "clang/Analysis/FlowSensitive/Value.h"
 #include "clang/Basic/LLVM.h"
@@ -842,6 +843,16 @@ transferNonConstMemberOperatorCall(const 
CXXOperatorCallExpr *Expr,
   handleNonConstMemberCall(Expr, RecordLoc, Result, State);
 }
 
+static RecordStorageLocation *
+getSmartPtrLikeStorageLocation(const Expr &E, const Environment &Env) {
+  if (!E.isPRValue())
+return dyn_cast_or_null(Env.getStorageLocation(E));
+  if (auto *PointerVal = dyn_cast_or_null(Env.getValue(E)))
+return dyn_cast_or_null(
+&PointerVal->getPointeeLoc());
+  return nullptr;
+}
+
 CFGMatchSwitch
 buildTransferMatchSwitch(ASTContext &Ctx,
  CFGMatchSwitchBuilder Builder) {
@@ -899,6 +910,43 @@ buildTransferMatchSwitch(ASTContext &Ctx,
transferLoggingGetReferenceableValueCall)
   .CaseOfCFGStmt(isLoggingCheckEqImpl(),
transferLoggingCheckEqImpl)
+  // This needs to go before the const accessor call matcher, because these
+  // look like them, but we model `operator`* and `get` to return the same
+  // object. Also, we model them for non-const cases.
+  .CaseOfCFGStmt(
+  isPointerLikeOperatorStar(),
+  [](const CXXOperatorCallExpr *E,
+ const MatchFinder::MatchResult &Result,
+ LatticeTransferState &State) {
+transferSmartPointerLikeCachedDeref(
+E, getSmartPtrLikeStorageLocation(*E->getArg(0), State.Env),
+State, [](StorageLocation &Loc) {});
+  })
+  .CaseOfCFGStmt(
+  isPointerLikeOperatorArrow(),
+  [](const CXXOperatorCallExpr *E,
+ const MatchFinder::MatchResult &Result,
+ LatticeTransferState &State) {
+transferSmartPointerLikeCachedGet(
+E, getSmartPtrLikeStorageLocation(*E->getArg(0), State.Env),
+State, [](StorageLocation &Loc) {});
+  })
+  .CaseOfCFGStmt(
+  isSmartPointerLikeValueMethodCall(),
+  [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult 
&Result,
+ LatticeTransferState &State) {
+transferSmartPointerLikeCachedDeref(
+E, getImplicitObjectLocation(*E, State.Env), State,
+[](StorageLocation &Loc) {});
+  })
+  .CaseOfCFGStmt(
+  isSmartPointerLikeGetMethodCall(),
+  [](const CXXMemberCallExpr *E, const MatchFinder::MatchResult 
&Result,
+ LatticeTransferState &State) {
+transferSmartPointerLikeCachedGet(
+E, getImplicitObjectLocation(*E, State.Env), State,
+[](StorageLocation &Loc) {});
+  })
   // const accessor calls
   .CaseOfCFGStmt(isConstStatusOrAccessorMemberCall(),
 
transferConstStatusOrAccessorMemberCall)
diff --git 
a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
 
b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
index e075818f8a2c1..dcb1cc13146bd 100644
--- 
a/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
+++ 
b/clang/unittests/Analysis/FlowSensitive/UncheckedStatusOrAccessModelTestFixture.cpp
@@ -3443,6 +3443,79 @@ TEST_P(UncheckedStatusOrAccessModelTest, AccessorCall) {
   )cc");
 }
 
+TEST_P(UncheckedStatusOrAccessModelTest, PointerLike) {
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_statusor_access_test_defs.h"
+
+class Foo {
+ public:
+  std::pair& operator*() const;
+  std::pair* operator->() const;
+  bool operator!=(const Foo& other) const;
+};
+
+void target() {
+  Foo foo;
+  if (foo->second.ok() && *foo->second != nullptr) {
+*foo->second;
+(*foo).second.value();
+  }
+}
+  )cc");
+  ExpectDiagnosticsFor(R"cc(
+#include "unchecked_s

[llvm-branch-commits] [llvm] DAG: Check if deoptimize call is available before emitting it (PR #170940)

2025-12-05 Thread Matt Arsenault via llvm-branch-commits

https://github.com/arsenm ready_for_review 
https://github.com/llvm/llvm-project/pull/170940
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [FlowSensitive] [StatusOr] [12/N] Add support for smart pointers (PR #170943)

2025-12-05 Thread Florian Mayer via llvm-branch-commits

https://github.com/fmayer created 
https://github.com/llvm/llvm-project/pull/170943

None


___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] AArch64: Relax restriction on discriminator when PAuth ifunc used. (PR #170945)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-backend-aarch64

Author: Peter Collingbourne (pcc)


Changes

When a PAuth ifunc is being used, we can represent any discriminator that
we want in the code and don't need to be restricted to 16 bits. For now we
only need this capability for address discriminated ptrauth expressions,
so keep the restriction in place for other discriminators.


---
Full diff: https://github.com/llvm/llvm-project/pull/170945.diff


3 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp (+14-9) 
- (modified) llvm/test/CodeGen/AArch64/ptrauth-irelative.ll (+13) 
- (modified) llvm/test/CodeGen/AArch64/ptrauth-reloc.ll (+17) 


``diff
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp 
b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 8ef985451a4c1..3f6be10679517 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -220,7 +220,7 @@ class AArch64AsmPrinter : public AsmPrinter {
   void LowerLOADgotAUTH(const MachineInstr &MI);
 
   const MCExpr *emitPAuthRelocationAsIRelative(
-  const MCExpr *Target, uint16_t Disc, AArch64PACKey::ID KeyID,
+  const MCExpr *Target, uint64_t Disc, AArch64PACKey::ID KeyID,
   bool HasAddressDiversity, bool IsDSOLocal, const MCExpr *DSExpr);
 
   /// tblgen'erated driver function for lowering simple MI->MC
@@ -2461,7 +2461,7 @@ static bool targetSupportsIRelativeRelocation(const 
Triple &TT) {
 // ret
 // .popsection
 const MCExpr *AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
-const MCExpr *Target, uint16_t Disc, AArch64PACKey::ID KeyID,
+const MCExpr *Target, uint64_t Disc, AArch64PACKey::ID KeyID,
 bool HasAddressDiversity, bool IsDSOLocal, const MCExpr *DSExpr) {
   const Triple &TT = TM.getTargetTriple();
 
@@ -2508,12 +2508,16 @@ const MCExpr 
*AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
   if (HasAddressDiversity) {
 auto *PlacePlusDisc = MCBinaryExpr::createAdd(
 MCSymbolRefExpr::create(Place, OutStreamer->getContext()),
-MCConstantExpr::create(static_cast(Disc),
-   OutStreamer->getContext()),
+MCConstantExpr::create(Disc, OutStreamer->getContext()),
 OutStreamer->getContext());
 emitAddress(*OutStreamer, AArch64::X1, PlacePlusDisc, /*IsDSOLocal=*/true,
 *STI);
   } else {
+if (!isUInt<16>(Disc)) {
+  OutContext.reportError(SMLoc(), "AArch64 PAC Discriminator '" +
+  Twine(Disc) +
+  "' out of range [0, 0x]");
+}
 emitMOVZ(AArch64::X1, Disc, 0);
   }
 
@@ -2592,11 +2596,6 @@ AArch64AsmPrinter::lowerConstantPtrAuth(const 
ConstantPtrAuth &CPA) {
   }
 
   uint64_t Disc = CPA.getDiscriminator()->getZExtValue();
-  if (!isUInt<16>(Disc)) {
-CPA.getContext().emitError("AArch64 PAC Discriminator '" + Twine(Disc) +
-   "' out of range [0, 0x]");
-Disc = 0;
-  }
 
   // Check if we need to represent this with an IRELATIVE and emit it if so.
   if (auto *IFuncSym = emitPAuthRelocationAsIRelative(
@@ -2604,6 +2603,12 @@ AArch64AsmPrinter::lowerConstantPtrAuth(const 
ConstantPtrAuth &CPA) {
   BaseGVB && BaseGVB->isDSOLocal(), DSExpr))
 return IFuncSym;
 
+  if (!isUInt<16>(Disc)) {
+CPA.getContext().emitError("AArch64 PAC Discriminator '" + Twine(Disc) +
+   "' out of range [0, 0x]");
+Disc = 0;
+  }
+
   if (DSExpr)
 report_fatal_error("deactivation symbols unsupported in constant "
"expressions on this target");
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll 
b/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
index 6a291497d6c46..c366459a3637d 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
@@ -67,6 +67,19 @@
 ; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
 @disc = constant ptr ptrauth (ptr @dsolocal, i32 2, i64 0, ptr @disc), align 8
 
+; CHECK: disc65536:
+; CHECK-NEXT: [[PLACE:.*]]:
+; CHECK-NEXT: .section .text.startup
+; CHECK-NEXT: [[FUNC:.*]]:
+; CHECK-NEXT: adrp x0, dsolocal
+; CHECK-NEXT: add x0, x0, :lo12:dsolocal
+; CHECK-NEXT: adrp x1, [[PLACE]]+65536
+; CHECK-NEXT: add x1, x1, :lo12:[[PLACE]]+65536
+; CHECK-NEXT: b __emupac_pacda
+; CHECK-NEXT: .section .rodata
+; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
+@disc65536 = constant ptr ptrauth (ptr @dsolocal, i32 2, i64 65536, ptr 
@disc), align 8
+
 @global = external global i8
 
 ; CHECK: globalref:
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll 
b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
index 02c643f101913..f2d080644e93e 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-reloc.ll
@@ -175,3 +175,20 @@
 
 @g = external global i32
 @g.ref.ia.65536 = constant ptr ptrauth (ptr @g, i32 0, i64 65536)
+
+;--- err-disc-elf.ll
+
+; RUN: not llc < err-di

[llvm-branch-commits] [llvm] SROA: Recognize llvm.protected.field.ptr intrinsics. (PR #151650)

2025-12-05 Thread Peter Collingbourne via llvm-branch-commits

https://github.com/pcc updated https://github.com/llvm/llvm-project/pull/151650

>From a4419c94b0812e3b9d4fea97f9f4fe9b9b10793c Mon Sep 17 00:00:00 2001
From: Peter Collingbourne 
Date: Fri, 5 Dec 2025 15:01:45 -0800
Subject: [PATCH] Address review comments

Created using spr 1.3.6-beta.1
---
 llvm/include/llvm/Analysis/PtrUseVisitor.h | 15 --
 llvm/lib/Analysis/PtrUseVisitor.cpp|  5 +-
 llvm/lib/Transforms/Scalar/SROA.cpp| 55 +++---
 3 files changed, 40 insertions(+), 35 deletions(-)

diff --git a/llvm/include/llvm/Analysis/PtrUseVisitor.h 
b/llvm/include/llvm/Analysis/PtrUseVisitor.h
index a39f6881f24f3..0858d8aee2186 100644
--- a/llvm/include/llvm/Analysis/PtrUseVisitor.h
+++ b/llvm/include/llvm/Analysis/PtrUseVisitor.h
@@ -134,7 +134,6 @@ class PtrUseVisitorBase {
 
 UseAndIsOffsetKnownPair UseAndIsOffsetKnown;
 APInt Offset;
-Value *ProtectedFieldDisc;
   };
 
   /// The worklist of to-visit uses.
@@ -159,10 +158,6 @@ class PtrUseVisitorBase {
   /// The constant offset of the use if that is known.
   APInt Offset;
 
-  // When this access is via an llvm.protected.field.ptr intrinsic, contains
-  // the second argument to the intrinsic, the discriminator.
-  Value *ProtectedFieldDisc;
-
   /// @}
 
   /// Note that the constructor is protected because this class must be a base
@@ -235,7 +230,6 @@ class PtrUseVisitor : protected InstVisitor,
 IntegerType *IntIdxTy = cast(DL.getIndexType(I.getType()));
 IsOffsetKnown = true;
 Offset = APInt(IntIdxTy->getBitWidth(), 0);
-ProtectedFieldDisc = nullptr;
 PI.reset();
 
 // Enqueue the uses of this pointer.
@@ -248,7 +242,6 @@ class PtrUseVisitor : protected InstVisitor,
   IsOffsetKnown = ToVisit.UseAndIsOffsetKnown.getInt();
   if (IsOffsetKnown)
 Offset = std::move(ToVisit.Offset);
-  ProtectedFieldDisc = ToVisit.ProtectedFieldDisc;
 
   Instruction *I = cast(U->getUser());
   static_cast(this)->visit(I);
@@ -307,14 +300,6 @@ class PtrUseVisitor : protected InstVisitor,
 case Intrinsic::lifetime_start:
 case Intrinsic::lifetime_end:
   return; // No-op intrinsics.
-
-case Intrinsic::protected_field_ptr: {
-  if (!IsOffsetKnown)
-return Base::visitIntrinsicInst(II);
-  ProtectedFieldDisc = II.getArgOperand(1);
-  enqueueUsers(II);
-  break;
-}
 }
   }
 
diff --git a/llvm/lib/Analysis/PtrUseVisitor.cpp 
b/llvm/lib/Analysis/PtrUseVisitor.cpp
index 0a79f84196602..9c79546f491ef 100644
--- a/llvm/lib/Analysis/PtrUseVisitor.cpp
+++ b/llvm/lib/Analysis/PtrUseVisitor.cpp
@@ -21,9 +21,8 @@ void detail::PtrUseVisitorBase::enqueueUsers(Value &I) {
   for (Use &U : I.uses()) {
 if (VisitedUses.insert(&U).second) {
   UseToVisit NewU = {
-  UseToVisit::UseAndIsOffsetKnownPair(&U, IsOffsetKnown),
-  Offset,
-  ProtectedFieldDisc,
+UseToVisit::UseAndIsOffsetKnownPair(&U, IsOffsetKnown),
+Offset
   };
   Worklist.push_back(std::move(NewU));
 }
diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp 
b/llvm/lib/Transforms/Scalar/SROA.cpp
index 4c5d4a72eebe4..1102699aa04e9 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -648,7 +648,8 @@ class AllocaSlices {
   /// Access the dead users for this alloca.
   ArrayRef getDeadUsers() const { return DeadUsers; }
 
-  /// Access the PFP users for this alloca.
+  /// Access the users for this alloca that are llvm.protected.field.ptr
+  /// intrinsics.
   ArrayRef getPFPUsers() const { return PFPUsers; }
 
   /// Access Uses that should be dropped if the alloca is promotable.
@@ -1043,6 +1044,10 @@ class AllocaSlices::SliceBuilder : public 
PtrUseVisitor {
   /// Set to de-duplicate dead instructions found in the use walk.
   SmallPtrSet VisitedDeadInsts;
 
+  // When this access is via an llvm.protected.field.ptr intrinsic, contains
+  // the second argument to the intrinsic, the discriminator.
+  Value *ProtectedFieldDisc = nullptr;
+
 public:
   SliceBuilder(const DataLayout &DL, AllocaInst &AI, AllocaSlices &AS)
   : PtrUseVisitor(DL),
@@ -1289,8 +1294,26 @@ class AllocaSlices::SliceBuilder : public 
PtrUseVisitor {
   return;
 }
 
-if (II.getIntrinsicID() == Intrinsic::protected_field_ptr)
+if (II.getIntrinsicID() == Intrinsic::protected_field_ptr) {
+  // We only handle loads and stores as users of llvm.protected.field.ptr.
+  // Other uses may add items to the worklist, which will cause
+  // ProtectedFieldDisc to be tracked incorrectly.
   AS.PFPUsers.push_back(&II);
+  ProtectedFieldDisc = II.getArgOperand(1);
+  for (Use &U : II.uses()) {
+this->U = &U;
+if (auto *LI = dyn_cast(U.getUser()))
+  visitLoadInst(*LI);
+else if (auto *SI = dyn_cast(U.getUser()))
+  visitStoreInst(*SI);
+else
+  PI.setAborted(&II);
+if (PI.isAborted())
+  break;
+  }
+  ProtectedFi

[llvm-branch-commits] AArch64: Emit PAuth ifuncs into the same comdat as the containing global. (PR #170944)

2025-12-05 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-backend-aarch64

Author: Peter Collingbourne (pcc)


Changes

PAuth ifuncs contain a relocation pointing to the section they are
relocating (the place), so they need to be in the same comdat in order
to avoid relocations pointing to discarded sections.


---
Full diff: https://github.com/llvm/llvm-project/pull/170944.diff


2 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp (+7-2) 
- (modified) llvm/test/CodeGen/AArch64/ptrauth-irelative.ll (+6) 


``diff
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp 
b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 8267414e78955..8ef985451a4c1 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2484,9 +2484,14 @@ const MCExpr 
*AArch64AsmPrinter::emitPAuthRelocationAsIRelative(
   OutStreamer->emitLabel(Place);
   OutStreamer->pushSection();
 
+  const MCSymbolELF *Group =
+  static_cast(OutStreamer->getCurrentSectionOnly())
+  ->getGroup();
   OutStreamer->switchSection(OutStreamer->getContext().getELFSection(
-  ".text.startup", ELF::SHT_PROGBITS, ELF::SHF_ALLOC | ELF::SHF_EXECINSTR,
-  0, "", true, PAuthIFuncNextUniqueID++, nullptr));
+  ".text.startup", ELF::SHT_PROGBITS,
+  ELF::SHF_ALLOC | ELF::SHF_EXECINSTR | (Group ? ELF::SHF_GROUP : 0), 0,
+  Group, true, Group ? MCSection::NonUniqueID : PAuthIFuncNextUniqueID++,
+  nullptr));
 
   MCSymbol *IRelativeSym =
   OutStreamer->getContext().createLinkerPrivateSymbol("pauth_ifunc");
diff --git a/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll 
b/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
index 4ee1c19a86490..6a291497d6c46 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-irelative.ll
@@ -93,3 +93,9 @@
 ; CHECK-NEXT: .section .rodata
 ; CHECK-NEXT: .xword [[FUNC]]@FUNCINIT
 @globalref8 = constant ptr ptrauth (ptr getelementptr (i8, ptr @global, i64 
8), i32 2, i64 5, ptr null), align 8
+
+$comdat = comdat any
+@comdat = constant ptr ptrauth (ptr null, i32 2, i64 1, ptr null), align 8, 
comdat
+; CHECK: comdat:
+; CHECK-NEXT: [[PLACE:.*]]:
+; CHECK-NEXT: .section .text.startup,"axG",@progbits,comdat,comdat

``




https://github.com/llvm/llvm-project/pull/170944
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] AArch64: Relax restriction on discriminator when PAuth ifunc used. (PR #170945)

2025-12-05 Thread Peter Collingbourne via llvm-branch-commits

https://github.com/pcc created https://github.com/llvm/llvm-project/pull/170945

When a PAuth ifunc is being used, we can represent any discriminator that
we want in the code and don't need to be restricted to 16 bits. For now we
only need this capability for address discriminated ptrauth expressions,
so keep the restriction in place for other discriminators.



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] AArch64: Emit PAuth ifuncs into the same comdat as the containing global. (PR #170944)

2025-12-05 Thread Peter Collingbourne via llvm-branch-commits

https://github.com/pcc created https://github.com/llvm/llvm-project/pull/170944

PAuth ifuncs contain a relocation pointing to the section they are
relocating (the place), so they need to be in the same comdat in order
to avoid relocations pointing to discarded sections.



___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] DAG: Check if deoptimize call is available before emitting it (PR #170940)

2025-12-05 Thread via llvm-branch-commits

https://github.com/dantrushin approved this pull request.

Looks good, though I wonder if deoptimize is unavailable, where it comes from 
then?
(Why it is generated in IR?)

https://github.com/llvm/llvm-project/pull/170940
___
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


  1   2   >