[llvm-branch-commits] [clang] [KeyInstr][Clang] Scalar init atom (PR #134633)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams updated 
https://github.com/llvm/llvm-project/pull/134633

>From 8534d6e34772867640665bfa3ad3547babd1a12d Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Tue, 1 Apr 2025 14:50:41 +0100
Subject: [PATCH 1/2] [KeyInstr][Clang] Scalar init atom

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
 clang/lib/CodeGen/CGDecl.cpp  |  1 +
 clang/lib/CodeGen/CGExpr.cpp  |  2 ++
 .../DebugInfo/KeyInstructions/init-scalar.c   | 19 +++
 3 files changed, 22 insertions(+)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/init-scalar.c

diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 4a8f7f6a42ecb..d02f2ad09d2f1 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -1925,6 +1925,7 @@ void CodeGenFunction::EmitAutoVarInit(const 
AutoVarEmission &emission) {
 
   const VarDecl &D = *emission.Variable;
   auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, 
D.getLocation());
+  ApplyAtomGroup Grp(getDebugInfo());
   QualType type = D.getType();
 
   // If this local has an initializer, emit it now.
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 708002a7f9ab3..1e426586620a2 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -,6 +,8 @@ void CodeGenFunction::EmitStoreOfScalar(llvm::Value 
*Value, Address Addr,
   }
 
   llvm::StoreInst *Store = Builder.CreateStore(Value, Addr, Volatile);
+  addInstToCurrentSourceAtom(Store, Value);
+
   if (isNontemporal) {
 llvm::MDNode *Node =
 llvm::MDNode::get(Store->getContext(),
diff --git a/clang/test/DebugInfo/KeyInstructions/init-scalar.c 
b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
new file mode 100644
index 0..c212c2a4fd623
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
@@ -0,0 +1,19 @@
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm 
-o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o 
- \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+void a() {
+// CHECK: store i32 0, ptr %A{{.*}}, !dbg [[G1R1:!.*]]
+int A = 0;
+// CHECK: %add = add {{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: store i32 %add, ptr %B, align 4, !dbg [[G2R1:!.*]]
+int B = 2 * A + 1;
+// CHECK-TODO: ret{{.*}}, !dbg [[G3R1:!.*]]
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK-TODO: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)

>From 2935186830de115687e4841e0d4c3fba4161a177 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Wed, 21 May 2025 10:21:18 +0100
Subject: [PATCH 2/2] use %clang_cc1 in test

---
 clang/test/DebugInfo/KeyInstructions/init-scalar.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/clang/test/DebugInfo/KeyInstructions/init-scalar.c 
b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
index c212c2a4fd623..a86c029e47e8c 100644
--- a/clang/test/DebugInfo/KeyInstructions/init-scalar.c
+++ b/clang/test/DebugInfo/KeyInstructions/init-scalar.c
@@ -1,7 +1,7 @@
-// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm 
-o - \
+// RUN: %clang_cc1 -gkey-instructions -x c++ %s 
-debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
 
-// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o 
- \
+// RUN: %clang_cc1 -gkey-instructions -x c %s 
-debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
 
 void a() {
@@ -10,10 +10,8 @@ void a() {
 // CHECK: %add = add {{.*}}, !dbg [[G2R2:!.*]]
 // CHECK: store i32 %add, ptr %B, align 4, !dbg [[G2R1:!.*]]
 int B = 2 * A + 1;
-// CHECK-TODO: ret{{.*}}, !dbg [[G3R1:!.*]]
 }
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
-// CHECK-TODO: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)

___

[llvm-branch-commits] [clang] [KeyInstr][Clang] Scalar init atom (PR #134633)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits


@@ -0,0 +1,19 @@
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm 
-o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o 
- \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+void a() {
+// CHECK: store i32 0, ptr %A{{.*}}, !dbg [[G1R1:!.*]]
+int A = 0;
+// CHECK: %add = add {{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: store i32 %add, ptr %B, align 4, !dbg [[G2R1:!.*]]
+int B = 2 * A + 1;
+// CHECK-TODO: ret{{.*}}, !dbg [[G3R1:!.*]]

OCHyams wrote:

Removed the CHECK-TODOs, to avoid confusion. The checks get added later on and 
aren't needed for this patch.

https://github.com/llvm/llvm-project/pull/134633
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] [flang][OpenMP] use attribute for delayed privatization barrier (PR #140092)

2025-05-21 Thread Tom Eccles via llvm-branch-commits

tblah wrote:

ping for review

https://github.com/llvm/llvm-project/pull/140092
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Scalar init atom (PR #134633)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits


@@ -0,0 +1,19 @@
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm 
-o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o 
- \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank

OCHyams wrote:

Done.

https://github.com/llvm/llvm-project/pull/134633
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Scalar init atom (PR #134633)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

OCHyams wrote:

> Looks good with a test tweak and question. My understanding of what's going 
> on here is that:
> 
> * Assignment-expressions that store a scalar to memory are added to the 
> "current" source atom,
> * For source constructs that haven't been instrumented yet, that's 
> potentially a no-op as the atom group will be zero,
> * In this scenario of the initialization of an automatic variable, the group 
> is set, and so the store gets the group number and rank.

That's right.

> I suppose this is a good way of decoupling the code that identifies the 
> source construct that is "interesting" into the thing that calls 
> ApplyAtomGroup, and the code that actually instruments instructions into the 
> helper functions. That's got the upside that we don't have to 
> think-about-and-manipulate the AST past an "interesting" construct; with the 
> downside that things can leak out:
> 
> * "Uncovered" stores that aren't in an atom group, or that /would/ be in a 
> "better" atom group but leak into an "outer" construct (as it were)
> * Unexpectedly multiple stores entering an atom group?,

It's possible yep. OTOH, there are times we want to do that on purposes 
(aggregate init), so it's an important use case.

> * Atom groups that unexpectedly don't cover anything.

This is indeed a fear, as there's many ways to create a 
store/store-like-intrinsic that don't go through the instrumented functions. 
This current stack takes the approach of trying to instrument every one of 
those sites. Another approach is to do it inside the builder class so that all 
call sites are automatically covered. Then instead of "opt in" we'd need a 
mechanism for some call sites to "opt out" which feels overall probably safer. 
I was going to play around with the idea once all these patches land, as we'll 
have good test coverage by then.

> ...and thinking about all those different scenarios that can pop up, this 
> feels like a _good_ abstraction that avoids having to think about that. Maybe 
> we don't cover every single construct / combination that's expressible, but 
> this is all strictly an improvement in stepping anyway.

---

I've addressed the inline comments (which have been eaten by github) - how does 
this look now?


https://github.com/llvm/llvm-project/pull/134633
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] AMDGPU: Fix tracking subreg defs when folding through reg_sequence (PR #140608)

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

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

>From 4ec9c56a126192e016127e5fa5aa4416d26bcac8 Mon Sep 17 00:00:00 2001
From: Matt Arsenault 
Date: Thu, 15 May 2025 10:51:39 +0200
Subject: [PATCH] AMDGPU: Fix tracking subreg defs when folding through
 reg_sequence

We weren't fully respecting the type of a def of an immediate vs.
the type at the use point. Refactor the folding logic to track the
value to fold, as well as a subregister to apply to the underlying
value. This is similar to how PeepholeOpt tracks subregisters (though
only for pure copy-like instructions, no constants).

Fixes #139317
---
 llvm/lib/Target/AMDGPU/SIFoldOperands.cpp | 406 +++---
 ...issue139317-bad-opsel-reg-sequence-fold.ll |   3 +-
 .../si-fold-operands-subreg-imm.gfx942.mir|   8 +-
 .../AMDGPU/si-fold-operands-subreg-imm.mir|   4 +-
 4 files changed, 250 insertions(+), 171 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp 
b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
index 9bbc8e75fd31b..eb7fb94e25f5c 100644
--- a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
+++ b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
@@ -25,52 +25,151 @@ using namespace llvm;
 
 namespace {
 
-struct FoldCandidate {
-  MachineInstr *UseMI;
+/// Track a value we may want to fold into downstream users, applying
+/// subregister extracts along the way.
+struct FoldableDef {
   union {
-MachineOperand *OpToFold;
+MachineOperand *OpToFold = nullptr;
 uint64_t ImmToFold;
 int FrameIndexToFold;
   };
-  int ShrinkOpcode;
-  unsigned UseOpNo;
+
+  /// Register class of the originally defined value.
+  const TargetRegisterClass *DefRC = nullptr;
+
+  /// Track the original defining instruction for the value.
+  const MachineInstr *DefMI = nullptr;
+
+  /// Subregister to apply to the value at the use point.
+  unsigned DefSubReg = AMDGPU::NoSubRegister;
+
+  /// Kind of value stored in the union.
   MachineOperand::MachineOperandType Kind;
-  bool Commuted;
 
-  FoldCandidate(MachineInstr *MI, unsigned OpNo, MachineOperand *FoldOp,
-bool Commuted_ = false,
-int ShrinkOp = -1) :
-UseMI(MI), OpToFold(nullptr), ShrinkOpcode(ShrinkOp), UseOpNo(OpNo),
-Kind(FoldOp->getType()),
-Commuted(Commuted_) {
-if (FoldOp->isImm()) {
-  ImmToFold = FoldOp->getImm();
-} else if (FoldOp->isFI()) {
-  FrameIndexToFold = FoldOp->getIndex();
+  FoldableDef() = delete;
+  FoldableDef(MachineOperand &FoldOp, const TargetRegisterClass *DefRC,
+  unsigned DefSubReg = AMDGPU::NoSubRegister)
+  : DefRC(DefRC), DefSubReg(DefSubReg), Kind(FoldOp.getType()) {
+
+if (FoldOp.isImm()) {
+  ImmToFold = FoldOp.getImm();
+} else if (FoldOp.isFI()) {
+  FrameIndexToFold = FoldOp.getIndex();
 } else {
-  assert(FoldOp->isReg() || FoldOp->isGlobal());
-  OpToFold = FoldOp;
+  assert(FoldOp.isReg() || FoldOp.isGlobal());
+  OpToFold = &FoldOp;
 }
+
+DefMI = FoldOp.getParent();
   }
 
-  FoldCandidate(MachineInstr *MI, unsigned OpNo, int64_t FoldImm,
-bool Commuted_ = false, int ShrinkOp = -1)
-  : UseMI(MI), ImmToFold(FoldImm), ShrinkOpcode(ShrinkOp), UseOpNo(OpNo),
-Kind(MachineOperand::MO_Immediate), Commuted(Commuted_) {}
+  FoldableDef(int64_t FoldImm, const TargetRegisterClass *DefRC,
+  unsigned DefSubReg = AMDGPU::NoSubRegister)
+  : ImmToFold(FoldImm), DefRC(DefRC), DefSubReg(DefSubReg),
+Kind(MachineOperand::MO_Immediate) {}
+
+  /// Copy the current def and apply \p SubReg to the value.
+  FoldableDef getWithSubReg(const SIRegisterInfo &TRI, unsigned SubReg) const {
+FoldableDef Copy(*this);
+Copy.DefSubReg = TRI.composeSubRegIndices(DefSubReg, SubReg);
+return Copy;
+  }
+
+  bool isReg() const { return Kind == MachineOperand::MO_Register; }
+
+  Register getReg() const {
+assert(isReg());
+return OpToFold->getReg();
+  }
+
+  unsigned getSubReg() const {
+assert(isReg());
+return OpToFold->getSubReg();
+  }
+
+  bool isImm() const { return Kind == MachineOperand::MO_Immediate; }
 
   bool isFI() const {
 return Kind == MachineOperand::MO_FrameIndex;
   }
 
-  bool isImm() const {
-return Kind == MachineOperand::MO_Immediate;
+  int getFI() const {
+assert(isFI());
+return FrameIndexToFold;
   }
 
-  bool isReg() const {
-return Kind == MachineOperand::MO_Register;
+  bool isGlobal() const { return OpToFold->isGlobal(); }
+
+  /// Return the effective immediate value defined by this instruction, after
+  /// application of any subregister extracts which may exist between the use
+  /// and def instruction.
+  std::optional getEffectiveImmVal() const {
+assert(isImm());
+return SIInstrInfo::extractSubregFromImm(ImmToFold, DefSubReg);
   }
 
-  bool isGlobal() const { return Kind == MachineOperand::MO_GlobalAddress; }
+  /// Check if it is legal to fold this effective value into 

[llvm-branch-commits] [llvm] AMDGPU: Add baseline tests for #139317 (PR #140607)

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

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

>From ad698bf9bb2558de0934c04390a246950c83da81 Mon Sep 17 00:00:00 2001
From: Matt Arsenault 
Date: Wed, 14 May 2025 08:50:59 +0200
Subject: [PATCH] AMDGPU: Add baseline tests for #139317

---
 .../CodeGen/AMDGPU/fold-imm-copy-agpr.mir | 135 +
 llvm/test/CodeGen/AMDGPU/fold-imm-copy.mir| 513 ++
 .../AMDGPU/fold-short-64-bit-literals.mir | 392 -
 ...issue139317-bad-opsel-reg-sequence-fold.ll |  66 +++
 .../si-fold-operands-subreg-imm.gfx942.mir| 202 +++
 .../AMDGPU/si-fold-operands-subreg-imm.mir|  26 +
 6 files changed, 1329 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/CodeGen/AMDGPU/fold-imm-copy-agpr.mir
 create mode 100644 
llvm/test/CodeGen/AMDGPU/issue139317-bad-opsel-reg-sequence-fold.ll
 create mode 100644 
llvm/test/CodeGen/AMDGPU/si-fold-operands-subreg-imm.gfx942.mir

diff --git a/llvm/test/CodeGen/AMDGPU/fold-imm-copy-agpr.mir 
b/llvm/test/CodeGen/AMDGPU/fold-imm-copy-agpr.mir
new file mode 100644
index 0..a079ee1296f41
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/fold-imm-copy-agpr.mir
@@ -0,0 +1,135 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py 
UTC_ARGS: --version 5
+# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -run-pass=si-fold-operands %s -o - | 
FileCheck -check-prefix=GCN %s
+
+---
+name: v_mov_b64_pseudo_imm_0_copy_to_areg_64
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_imm_0_copy_to_areg_64
+; GCN: [[V_MOV_B:%[0-9]+]]:vreg_64_align2 = V_MOV_B64_PSEUDO 0, implicit 
$exec
+; GCN-NEXT: [[COPY:%[0-9]+]]:areg_64_align2 = COPY [[V_MOV_B]]
+; GCN-NEXT: $agpr0_agpr1 = COPY [[COPY]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO 0, implicit $exec
+%1:areg_64_align2 = COPY %0
+$agpr0_agpr1 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_imm_neg1_copy_to_areg_64
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_imm_neg1_copy_to_areg_64
+; GCN: [[V_MOV_B:%[0-9]+]]:vreg_64_align2 = V_MOV_B64_PSEUDO -1, implicit 
$exec
+; GCN-NEXT: [[COPY:%[0-9]+]]:areg_64_align2 = COPY [[V_MOV_B]]
+; GCN-NEXT: $agpr0_agpr1 = COPY [[COPY]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO -1, implicit $exec
+%1:areg_64_align2 = COPY %0
+$agpr0_agpr1 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_literal_copy_to_areg_64
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_literal_copy_to_areg_64
+; GCN: [[V_MOV_B:%[0-9]+]]:vreg_64_align2 = V_MOV_B64_PSEUDO 999, implicit 
$exec
+; GCN-NEXT: [[COPY:%[0-9]+]]:areg_64_align2 = COPY [[V_MOV_B]]
+; GCN-NEXT: $agpr0_agpr1 = COPY [[COPY]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO 999, implicit $exec
+%1:areg_64_align2 = COPY %0
+$agpr0_agpr1 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_imm_0_copy_sub0_to_agpr_32
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_imm_0_copy_sub0_to_agpr_32
+; GCN: [[V_ACCVGPR_WRITE_B32_e64_:%[0-9]+]]:agpr_32 = 
V_ACCVGPR_WRITE_B32_e64 0, implicit $exec
+; GCN-NEXT: $agpr0 = COPY [[V_ACCVGPR_WRITE_B32_e64_]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO 0, implicit $exec
+%1:agpr_32 = COPY %0.sub0
+$agpr0 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_imm_0_copy_sub1_to_agpr_32
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_imm_0_copy_sub1_to_agpr_32
+; GCN: [[V_ACCVGPR_WRITE_B32_e64_:%[0-9]+]]:agpr_32 = 
V_ACCVGPR_WRITE_B32_e64 0, implicit $exec
+; GCN-NEXT: $agpr0 = COPY [[V_ACCVGPR_WRITE_B32_e64_]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO 0, implicit $exec
+%1:agpr_32 = COPY %0.sub1
+$agpr0 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_lit_copy_sub0_to_agpr_32
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_lit_copy_sub0_to_agpr_32
+; GCN: [[V_MOV_B:%[0-9]+]]:vreg_64_align2 = V_MOV_B64_PSEUDO 
4290672329592, implicit $exec
+; GCN-NEXT: [[COPY:%[0-9]+]]:agpr_32 = COPY [[V_MOV_B]].sub0
+; GCN-NEXT: $agpr0 = COPY [[COPY]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO 4290672329592, implicit $exec
+%1:agpr_32 = COPY %0.sub0
+$agpr0 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_lit_copy_sub1_to_agpr_32
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_lit_copy_sub1_to_agpr_32
+; GCN: [[V_MOV_B:%[0-9]+]]:vreg_64_align2 = V_MOV_B64_PSEUDO 
4290672329592, implicit $exec
+; GCN-NEXT: [[COPY:%[0-9]+]]:agpr_32 = COPY [[V_MOV_B]].sub1
+; GCN-NEXT: $agpr0 = COPY [[CO

[llvm-branch-commits] [llvm] AMDGPU: Remove redundant operand folding checks (PR #140587)

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

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

>From 82fd0c72c28b7bb3694d58fe4b9b885ec320d914 Mon Sep 17 00:00:00 2001
From: Matt Arsenault 
Date: Mon, 19 May 2025 20:02:54 +0200
Subject: [PATCH 1/2] AMDGPU: Remove redundant operand folding checks

This was pre-filtering out a specific situation from being
added to the fold candidate list. The operand legality will
ultimately be checked with isOperandLegal before the fold is
performed, so I don't see the plus in pre-filtering this one
case.
---
 llvm/lib/Target/AMDGPU/SIFoldOperands.cpp |  18 
 .../AMDGPU/fold-operands-frame-index.mir  | 101 ++
 2 files changed, 101 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp 
b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
index b62230d4dc28c..9bbc8e75fd31b 100644
--- a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
+++ b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
@@ -778,24 +778,6 @@ bool SIFoldOperandsImpl::tryAddToFoldList(
   return true;
   }
 
-  // Check the case where we might introduce a second constant operand to a
-  // scalar instruction
-  if (TII->isSALU(MI->getOpcode())) {
-const MCInstrDesc &InstDesc = MI->getDesc();
-const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
-
-// Fine if the operand can be encoded as an inline constant
-if (!OpToFold->isReg() && !TII->isInlineConstant(*OpToFold, OpInfo)) {
-  // Otherwise check for another constant
-  for (unsigned i = 0, e = InstDesc.getNumOperands(); i != e; ++i) {
-auto &Op = MI->getOperand(i);
-if (OpNo != i && !Op.isReg() &&
-!TII->isInlineConstant(Op, InstDesc.operands()[i]))
-  return false;
-  }
-}
-  }
-
   appendFoldCandidate(FoldList, MI, OpNo, OpToFold);
   return true;
 }
diff --git a/llvm/test/CodeGen/AMDGPU/fold-operands-frame-index.mir 
b/llvm/test/CodeGen/AMDGPU/fold-operands-frame-index.mir
index 4417f205646ee..7fad2f466bc9f 100644
--- a/llvm/test/CodeGen/AMDGPU/fold-operands-frame-index.mir
+++ b/llvm/test/CodeGen/AMDGPU/fold-operands-frame-index.mir
@@ -573,3 +573,104 @@ body: |
 S_ENDPGM 0, implicit %2
 
 ...
+
+---
+name:no_fold_multiple_fi_s_cselect_b32
+tracksRegLiveness: true
+stack:
+  - { id: 0, size: 64, alignment: 4 }
+  - { id: 1, size: 32, alignment: 4 }
+body: |
+  bb.0:
+; CHECK-LABEL: name: no_fold_multiple_fi_s_cselect_b32
+; CHECK: [[S_MOV_B32_:%[0-9]+]]:sreg_32 = S_MOV_B32 %stack.1
+; CHECK-NEXT: [[S_CSELECT_B32_:%[0-9]+]]:sreg_32 = S_CSELECT_B32 killed 
[[S_MOV_B32_]], %stack.0, implicit undef $scc
+; CHECK-NEXT: S_ENDPGM 0, implicit [[S_CSELECT_B32_]]
+%0:sreg_32 = S_MOV_B32 %stack.0
+%1:sreg_32 = S_MOV_B32 %stack.1
+%2:sreg_32 = S_CSELECT_B32 killed %1, killed %0, implicit undef $scc
+S_ENDPGM 0, implicit %2
+
+...
+
+---
+name:no_fold_multiple_fi_v_cndmask_b32_e64
+tracksRegLiveness: true
+stack:
+  - { id: 0, size: 64, alignment: 4 }
+  - { id: 1, size: 32, alignment: 4 }
+body: |
+  bb.0:
+liveins: $sgpr8_sgpr9
+; GFX9-LABEL: name: no_fold_multiple_fi_v_cndmask_b32_e64
+; GFX9: liveins: $sgpr8_sgpr9
+; GFX9-NEXT: {{  $}}
+; GFX9-NEXT: [[COPY:%[0-9]+]]:sreg_64_xexec = COPY $sgpr8_sgpr9
+; GFX9-NEXT: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.0, 
implicit $exec
+; GFX9-NEXT: [[V_MOV_B32_e32_1:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.1, 
implicit $exec
+; GFX9-NEXT: [[V_CNDMASK_B32_e64_:%[0-9]+]]:vgpr_32 = V_CNDMASK_B32_e64 0, 
killed [[V_MOV_B32_e32_]], 0, killed [[V_MOV_B32_e32_1]], [[COPY]], implicit 
$exec
+; GFX9-NEXT: S_ENDPGM 0, implicit [[V_CNDMASK_B32_e64_]]
+;
+; GFX10-LABEL: name: no_fold_multiple_fi_v_cndmask_b32_e64
+; GFX10: liveins: $sgpr8_sgpr9
+; GFX10-NEXT: {{  $}}
+; GFX10-NEXT: [[COPY:%[0-9]+]]:sreg_64_xexec = COPY $sgpr8_sgpr9
+; GFX10-NEXT: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.1, 
implicit $exec
+; GFX10-NEXT: [[V_CNDMASK_B32_e64_:%[0-9]+]]:vgpr_32 = V_CNDMASK_B32_e64 
0, %stack.0, 0, killed [[V_MOV_B32_e32_]], [[COPY]], implicit $exec
+; GFX10-NEXT: S_ENDPGM 0, implicit [[V_CNDMASK_B32_e64_]]
+;
+; GFX12-LABEL: name: no_fold_multiple_fi_v_cndmask_b32_e64
+; GFX12: liveins: $sgpr8_sgpr9
+; GFX12-NEXT: {{  $}}
+; GFX12-NEXT: [[COPY:%[0-9]+]]:sreg_64_xexec = COPY $sgpr8_sgpr9
+; GFX12-NEXT: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.1, 
implicit $exec
+; GFX12-NEXT: [[V_CNDMASK_B32_e64_:%[0-9]+]]:vgpr_32 = V_CNDMASK_B32_e64 
0, %stack.0, 0, killed [[V_MOV_B32_e32_]], [[COPY]], implicit $exec
+; GFX12-NEXT: S_ENDPGM 0, implicit [[V_CNDMASK_B32_e64_]]
+%0:sreg_64_xexec = COPY $sgpr8_sgpr9
+%1:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec
+%2:vgpr_32 = V_MOV_B32_e32 %stack.1, implicit $exec
+%3:vgpr_32 = V_CNDMASK_B32_e64 0, killed %1, 0, killed %2, %0, implicit 
$exec
+

[llvm-branch-commits] [llvm] AMDGPU: Fix tracking subreg defs when folding through reg_sequence (PR #140608)

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

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

>From 4ec9c56a126192e016127e5fa5aa4416d26bcac8 Mon Sep 17 00:00:00 2001
From: Matt Arsenault 
Date: Thu, 15 May 2025 10:51:39 +0200
Subject: [PATCH] AMDGPU: Fix tracking subreg defs when folding through
 reg_sequence

We weren't fully respecting the type of a def of an immediate vs.
the type at the use point. Refactor the folding logic to track the
value to fold, as well as a subregister to apply to the underlying
value. This is similar to how PeepholeOpt tracks subregisters (though
only for pure copy-like instructions, no constants).

Fixes #139317
---
 llvm/lib/Target/AMDGPU/SIFoldOperands.cpp | 406 +++---
 ...issue139317-bad-opsel-reg-sequence-fold.ll |   3 +-
 .../si-fold-operands-subreg-imm.gfx942.mir|   8 +-
 .../AMDGPU/si-fold-operands-subreg-imm.mir|   4 +-
 4 files changed, 250 insertions(+), 171 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp 
b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
index 9bbc8e75fd31b..eb7fb94e25f5c 100644
--- a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
+++ b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
@@ -25,52 +25,151 @@ using namespace llvm;
 
 namespace {
 
-struct FoldCandidate {
-  MachineInstr *UseMI;
+/// Track a value we may want to fold into downstream users, applying
+/// subregister extracts along the way.
+struct FoldableDef {
   union {
-MachineOperand *OpToFold;
+MachineOperand *OpToFold = nullptr;
 uint64_t ImmToFold;
 int FrameIndexToFold;
   };
-  int ShrinkOpcode;
-  unsigned UseOpNo;
+
+  /// Register class of the originally defined value.
+  const TargetRegisterClass *DefRC = nullptr;
+
+  /// Track the original defining instruction for the value.
+  const MachineInstr *DefMI = nullptr;
+
+  /// Subregister to apply to the value at the use point.
+  unsigned DefSubReg = AMDGPU::NoSubRegister;
+
+  /// Kind of value stored in the union.
   MachineOperand::MachineOperandType Kind;
-  bool Commuted;
 
-  FoldCandidate(MachineInstr *MI, unsigned OpNo, MachineOperand *FoldOp,
-bool Commuted_ = false,
-int ShrinkOp = -1) :
-UseMI(MI), OpToFold(nullptr), ShrinkOpcode(ShrinkOp), UseOpNo(OpNo),
-Kind(FoldOp->getType()),
-Commuted(Commuted_) {
-if (FoldOp->isImm()) {
-  ImmToFold = FoldOp->getImm();
-} else if (FoldOp->isFI()) {
-  FrameIndexToFold = FoldOp->getIndex();
+  FoldableDef() = delete;
+  FoldableDef(MachineOperand &FoldOp, const TargetRegisterClass *DefRC,
+  unsigned DefSubReg = AMDGPU::NoSubRegister)
+  : DefRC(DefRC), DefSubReg(DefSubReg), Kind(FoldOp.getType()) {
+
+if (FoldOp.isImm()) {
+  ImmToFold = FoldOp.getImm();
+} else if (FoldOp.isFI()) {
+  FrameIndexToFold = FoldOp.getIndex();
 } else {
-  assert(FoldOp->isReg() || FoldOp->isGlobal());
-  OpToFold = FoldOp;
+  assert(FoldOp.isReg() || FoldOp.isGlobal());
+  OpToFold = &FoldOp;
 }
+
+DefMI = FoldOp.getParent();
   }
 
-  FoldCandidate(MachineInstr *MI, unsigned OpNo, int64_t FoldImm,
-bool Commuted_ = false, int ShrinkOp = -1)
-  : UseMI(MI), ImmToFold(FoldImm), ShrinkOpcode(ShrinkOp), UseOpNo(OpNo),
-Kind(MachineOperand::MO_Immediate), Commuted(Commuted_) {}
+  FoldableDef(int64_t FoldImm, const TargetRegisterClass *DefRC,
+  unsigned DefSubReg = AMDGPU::NoSubRegister)
+  : ImmToFold(FoldImm), DefRC(DefRC), DefSubReg(DefSubReg),
+Kind(MachineOperand::MO_Immediate) {}
+
+  /// Copy the current def and apply \p SubReg to the value.
+  FoldableDef getWithSubReg(const SIRegisterInfo &TRI, unsigned SubReg) const {
+FoldableDef Copy(*this);
+Copy.DefSubReg = TRI.composeSubRegIndices(DefSubReg, SubReg);
+return Copy;
+  }
+
+  bool isReg() const { return Kind == MachineOperand::MO_Register; }
+
+  Register getReg() const {
+assert(isReg());
+return OpToFold->getReg();
+  }
+
+  unsigned getSubReg() const {
+assert(isReg());
+return OpToFold->getSubReg();
+  }
+
+  bool isImm() const { return Kind == MachineOperand::MO_Immediate; }
 
   bool isFI() const {
 return Kind == MachineOperand::MO_FrameIndex;
   }
 
-  bool isImm() const {
-return Kind == MachineOperand::MO_Immediate;
+  int getFI() const {
+assert(isFI());
+return FrameIndexToFold;
   }
 
-  bool isReg() const {
-return Kind == MachineOperand::MO_Register;
+  bool isGlobal() const { return OpToFold->isGlobal(); }
+
+  /// Return the effective immediate value defined by this instruction, after
+  /// application of any subregister extracts which may exist between the use
+  /// and def instruction.
+  std::optional getEffectiveImmVal() const {
+assert(isImm());
+return SIInstrInfo::extractSubregFromImm(ImmToFold, DefSubReg);
   }
 
-  bool isGlobal() const { return Kind == MachineOperand::MO_GlobalAddress; }
+  /// Check if it is legal to fold this effective value into 

[llvm-branch-commits] [llvm] AMDGPU: Remove redundant operand folding checks (PR #140587)

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

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

>From 82fd0c72c28b7bb3694d58fe4b9b885ec320d914 Mon Sep 17 00:00:00 2001
From: Matt Arsenault 
Date: Mon, 19 May 2025 20:02:54 +0200
Subject: [PATCH 1/2] AMDGPU: Remove redundant operand folding checks

This was pre-filtering out a specific situation from being
added to the fold candidate list. The operand legality will
ultimately be checked with isOperandLegal before the fold is
performed, so I don't see the plus in pre-filtering this one
case.
---
 llvm/lib/Target/AMDGPU/SIFoldOperands.cpp |  18 
 .../AMDGPU/fold-operands-frame-index.mir  | 101 ++
 2 files changed, 101 insertions(+), 18 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp 
b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
index b62230d4dc28c..9bbc8e75fd31b 100644
--- a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
+++ b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
@@ -778,24 +778,6 @@ bool SIFoldOperandsImpl::tryAddToFoldList(
   return true;
   }
 
-  // Check the case where we might introduce a second constant operand to a
-  // scalar instruction
-  if (TII->isSALU(MI->getOpcode())) {
-const MCInstrDesc &InstDesc = MI->getDesc();
-const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
-
-// Fine if the operand can be encoded as an inline constant
-if (!OpToFold->isReg() && !TII->isInlineConstant(*OpToFold, OpInfo)) {
-  // Otherwise check for another constant
-  for (unsigned i = 0, e = InstDesc.getNumOperands(); i != e; ++i) {
-auto &Op = MI->getOperand(i);
-if (OpNo != i && !Op.isReg() &&
-!TII->isInlineConstant(Op, InstDesc.operands()[i]))
-  return false;
-  }
-}
-  }
-
   appendFoldCandidate(FoldList, MI, OpNo, OpToFold);
   return true;
 }
diff --git a/llvm/test/CodeGen/AMDGPU/fold-operands-frame-index.mir 
b/llvm/test/CodeGen/AMDGPU/fold-operands-frame-index.mir
index 4417f205646ee..7fad2f466bc9f 100644
--- a/llvm/test/CodeGen/AMDGPU/fold-operands-frame-index.mir
+++ b/llvm/test/CodeGen/AMDGPU/fold-operands-frame-index.mir
@@ -573,3 +573,104 @@ body: |
 S_ENDPGM 0, implicit %2
 
 ...
+
+---
+name:no_fold_multiple_fi_s_cselect_b32
+tracksRegLiveness: true
+stack:
+  - { id: 0, size: 64, alignment: 4 }
+  - { id: 1, size: 32, alignment: 4 }
+body: |
+  bb.0:
+; CHECK-LABEL: name: no_fold_multiple_fi_s_cselect_b32
+; CHECK: [[S_MOV_B32_:%[0-9]+]]:sreg_32 = S_MOV_B32 %stack.1
+; CHECK-NEXT: [[S_CSELECT_B32_:%[0-9]+]]:sreg_32 = S_CSELECT_B32 killed 
[[S_MOV_B32_]], %stack.0, implicit undef $scc
+; CHECK-NEXT: S_ENDPGM 0, implicit [[S_CSELECT_B32_]]
+%0:sreg_32 = S_MOV_B32 %stack.0
+%1:sreg_32 = S_MOV_B32 %stack.1
+%2:sreg_32 = S_CSELECT_B32 killed %1, killed %0, implicit undef $scc
+S_ENDPGM 0, implicit %2
+
+...
+
+---
+name:no_fold_multiple_fi_v_cndmask_b32_e64
+tracksRegLiveness: true
+stack:
+  - { id: 0, size: 64, alignment: 4 }
+  - { id: 1, size: 32, alignment: 4 }
+body: |
+  bb.0:
+liveins: $sgpr8_sgpr9
+; GFX9-LABEL: name: no_fold_multiple_fi_v_cndmask_b32_e64
+; GFX9: liveins: $sgpr8_sgpr9
+; GFX9-NEXT: {{  $}}
+; GFX9-NEXT: [[COPY:%[0-9]+]]:sreg_64_xexec = COPY $sgpr8_sgpr9
+; GFX9-NEXT: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.0, 
implicit $exec
+; GFX9-NEXT: [[V_MOV_B32_e32_1:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.1, 
implicit $exec
+; GFX9-NEXT: [[V_CNDMASK_B32_e64_:%[0-9]+]]:vgpr_32 = V_CNDMASK_B32_e64 0, 
killed [[V_MOV_B32_e32_]], 0, killed [[V_MOV_B32_e32_1]], [[COPY]], implicit 
$exec
+; GFX9-NEXT: S_ENDPGM 0, implicit [[V_CNDMASK_B32_e64_]]
+;
+; GFX10-LABEL: name: no_fold_multiple_fi_v_cndmask_b32_e64
+; GFX10: liveins: $sgpr8_sgpr9
+; GFX10-NEXT: {{  $}}
+; GFX10-NEXT: [[COPY:%[0-9]+]]:sreg_64_xexec = COPY $sgpr8_sgpr9
+; GFX10-NEXT: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.1, 
implicit $exec
+; GFX10-NEXT: [[V_CNDMASK_B32_e64_:%[0-9]+]]:vgpr_32 = V_CNDMASK_B32_e64 
0, %stack.0, 0, killed [[V_MOV_B32_e32_]], [[COPY]], implicit $exec
+; GFX10-NEXT: S_ENDPGM 0, implicit [[V_CNDMASK_B32_e64_]]
+;
+; GFX12-LABEL: name: no_fold_multiple_fi_v_cndmask_b32_e64
+; GFX12: liveins: $sgpr8_sgpr9
+; GFX12-NEXT: {{  $}}
+; GFX12-NEXT: [[COPY:%[0-9]+]]:sreg_64_xexec = COPY $sgpr8_sgpr9
+; GFX12-NEXT: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 %stack.1, 
implicit $exec
+; GFX12-NEXT: [[V_CNDMASK_B32_e64_:%[0-9]+]]:vgpr_32 = V_CNDMASK_B32_e64 
0, %stack.0, 0, killed [[V_MOV_B32_e32_]], [[COPY]], implicit $exec
+; GFX12-NEXT: S_ENDPGM 0, implicit [[V_CNDMASK_B32_e64_]]
+%0:sreg_64_xexec = COPY $sgpr8_sgpr9
+%1:vgpr_32 = V_MOV_B32_e32 %stack.0, implicit $exec
+%2:vgpr_32 = V_MOV_B32_e32 %stack.1, implicit $exec
+%3:vgpr_32 = V_CNDMASK_B32_e64 0, killed %1, 0, killed %2, %0, implicit 
$exec
+

[llvm-branch-commits] [llvm] AMDGPU: Add baseline tests for #139317 (PR #140607)

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

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

>From ad698bf9bb2558de0934c04390a246950c83da81 Mon Sep 17 00:00:00 2001
From: Matt Arsenault 
Date: Wed, 14 May 2025 08:50:59 +0200
Subject: [PATCH] AMDGPU: Add baseline tests for #139317

---
 .../CodeGen/AMDGPU/fold-imm-copy-agpr.mir | 135 +
 llvm/test/CodeGen/AMDGPU/fold-imm-copy.mir| 513 ++
 .../AMDGPU/fold-short-64-bit-literals.mir | 392 -
 ...issue139317-bad-opsel-reg-sequence-fold.ll |  66 +++
 .../si-fold-operands-subreg-imm.gfx942.mir| 202 +++
 .../AMDGPU/si-fold-operands-subreg-imm.mir|  26 +
 6 files changed, 1329 insertions(+), 5 deletions(-)
 create mode 100644 llvm/test/CodeGen/AMDGPU/fold-imm-copy-agpr.mir
 create mode 100644 
llvm/test/CodeGen/AMDGPU/issue139317-bad-opsel-reg-sequence-fold.ll
 create mode 100644 
llvm/test/CodeGen/AMDGPU/si-fold-operands-subreg-imm.gfx942.mir

diff --git a/llvm/test/CodeGen/AMDGPU/fold-imm-copy-agpr.mir 
b/llvm/test/CodeGen/AMDGPU/fold-imm-copy-agpr.mir
new file mode 100644
index 0..a079ee1296f41
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/fold-imm-copy-agpr.mir
@@ -0,0 +1,135 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py 
UTC_ARGS: --version 5
+# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -run-pass=si-fold-operands %s -o - | 
FileCheck -check-prefix=GCN %s
+
+---
+name: v_mov_b64_pseudo_imm_0_copy_to_areg_64
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_imm_0_copy_to_areg_64
+; GCN: [[V_MOV_B:%[0-9]+]]:vreg_64_align2 = V_MOV_B64_PSEUDO 0, implicit 
$exec
+; GCN-NEXT: [[COPY:%[0-9]+]]:areg_64_align2 = COPY [[V_MOV_B]]
+; GCN-NEXT: $agpr0_agpr1 = COPY [[COPY]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO 0, implicit $exec
+%1:areg_64_align2 = COPY %0
+$agpr0_agpr1 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_imm_neg1_copy_to_areg_64
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_imm_neg1_copy_to_areg_64
+; GCN: [[V_MOV_B:%[0-9]+]]:vreg_64_align2 = V_MOV_B64_PSEUDO -1, implicit 
$exec
+; GCN-NEXT: [[COPY:%[0-9]+]]:areg_64_align2 = COPY [[V_MOV_B]]
+; GCN-NEXT: $agpr0_agpr1 = COPY [[COPY]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO -1, implicit $exec
+%1:areg_64_align2 = COPY %0
+$agpr0_agpr1 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_literal_copy_to_areg_64
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_literal_copy_to_areg_64
+; GCN: [[V_MOV_B:%[0-9]+]]:vreg_64_align2 = V_MOV_B64_PSEUDO 999, implicit 
$exec
+; GCN-NEXT: [[COPY:%[0-9]+]]:areg_64_align2 = COPY [[V_MOV_B]]
+; GCN-NEXT: $agpr0_agpr1 = COPY [[COPY]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO 999, implicit $exec
+%1:areg_64_align2 = COPY %0
+$agpr0_agpr1 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_imm_0_copy_sub0_to_agpr_32
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_imm_0_copy_sub0_to_agpr_32
+; GCN: [[V_ACCVGPR_WRITE_B32_e64_:%[0-9]+]]:agpr_32 = 
V_ACCVGPR_WRITE_B32_e64 0, implicit $exec
+; GCN-NEXT: $agpr0 = COPY [[V_ACCVGPR_WRITE_B32_e64_]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO 0, implicit $exec
+%1:agpr_32 = COPY %0.sub0
+$agpr0 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_imm_0_copy_sub1_to_agpr_32
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_imm_0_copy_sub1_to_agpr_32
+; GCN: [[V_ACCVGPR_WRITE_B32_e64_:%[0-9]+]]:agpr_32 = 
V_ACCVGPR_WRITE_B32_e64 0, implicit $exec
+; GCN-NEXT: $agpr0 = COPY [[V_ACCVGPR_WRITE_B32_e64_]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO 0, implicit $exec
+%1:agpr_32 = COPY %0.sub1
+$agpr0 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_lit_copy_sub0_to_agpr_32
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_lit_copy_sub0_to_agpr_32
+; GCN: [[V_MOV_B:%[0-9]+]]:vreg_64_align2 = V_MOV_B64_PSEUDO 
4290672329592, implicit $exec
+; GCN-NEXT: [[COPY:%[0-9]+]]:agpr_32 = COPY [[V_MOV_B]].sub0
+; GCN-NEXT: $agpr0 = COPY [[COPY]]
+; GCN-NEXT: S_ENDPGM 0
+%0:vreg_64_align2 = V_MOV_B64_PSEUDO 4290672329592, implicit $exec
+%1:agpr_32 = COPY %0.sub0
+$agpr0 = COPY %1
+S_ENDPGM 0
+
+...
+
+---
+name: v_mov_b64_pseudo_lit_copy_sub1_to_agpr_32
+tracksRegLiveness: true
+body: |
+  bb.0:
+; GCN-LABEL: name: v_mov_b64_pseudo_lit_copy_sub1_to_agpr_32
+; GCN: [[V_MOV_B:%[0-9]+]]:vreg_64_align2 = V_MOV_B64_PSEUDO 
4290672329592, implicit $exec
+; GCN-NEXT: [[COPY:%[0-9]+]]:agpr_32 = COPY [[V_MOV_B]].sub1
+; GCN-NEXT: $agpr0 = COPY [[CO

[llvm-branch-commits] [llvm] AMDGPU: Remove redundant operand folding checks (PR #140587)

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

arsenm wrote:

Had to fix regression demonstrated in #140784 by avoiding folding a second 
frame index into an instruction that already uses one 

https://github.com/llvm/llvm-project/pull/140587
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [mlir] [mlir] Unique property constraints where possible (PR #140849)

2025-05-21 Thread Krzysztof Drewniak via llvm-branch-commits

https://github.com/krzysz00 created 
https://github.com/llvm/llvm-project/pull/140849

Now that `Property` is a `PropConstraint`, hook it up to the same 
constraint-uniquing machinery that other types of constraints use. This will 
primarily save on code size for types, like enums, that have inherent 
constraints which are shared across many operations.

>From 3705acd6c9334f76bf95877fcd8e878a015b9955 Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak 
Date: Tue, 20 May 2025 22:38:34 -0700
Subject: [PATCH] [mlir] Unique property constraints where possible

Now that `Property` is a `PropConstraint`, hook it up to the same
constraint-uniquing machinery that other types of constraints use.
This will primarily save on code size for types, like enums, that have
inherent constraints which are shared across many operations.
---
 mlir/include/mlir/TableGen/CodeGenHelpers.h   | 21 ++
 mlir/include/mlir/TableGen/Property.h | 24 +++---
 mlir/lib/TableGen/CodeGenHelpers.cpp  | 64 
 mlir/lib/TableGen/Property.cpp| 18 +++--
 .../mlir-tblgen/op-properties-predicates.td   | 61 +++
 mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp   | 74 +++
 6 files changed, 201 insertions(+), 61 deletions(-)

diff --git a/mlir/include/mlir/TableGen/CodeGenHelpers.h 
b/mlir/include/mlir/TableGen/CodeGenHelpers.h
index 465240907a3de..cf14f65b93ed2 100644
--- a/mlir/include/mlir/TableGen/CodeGenHelpers.h
+++ b/mlir/include/mlir/TableGen/CodeGenHelpers.h
@@ -153,6 +153,23 @@ class StaticVerifierFunctionEmitter {
   std::optional
   getAttrConstraintFn(const Constraint &constraint) const;
 
+  /// Get the name of the static function used for the given property
+  /// constraint. These functions are in the form:
+  ///
+  ///   LogicalResult(Operation *op, T property, StringRef propName);
+  ///
+  /// where T is the interface type specified in the constraint.
+  /// If a uniqued constraint was not found, this function returns 
std::nullopt.
+  /// The uniqued constraints cannot be used in the context of an OpAdaptor.
+  ///
+  /// Pattern constraints have the form:
+  ///
+  ///   LogicalResult(PatternRewriter &rewriter, Operation *op, T property,
+  /// StringRef failureStr);
+  ///
+  std::optional
+  getPropConstraintFn(const Constraint &constraint) const;
+
   /// Get the name of the static function used for the given successor
   /// constraint. These functions are in the form:
   ///
@@ -175,6 +192,8 @@ class StaticVerifierFunctionEmitter {
   void emitTypeConstraints();
   /// Emit static attribute constraint functions.
   void emitAttrConstraints();
+  /// Emit static property constraint functions.
+  void emitPropConstraints();
   /// Emit static successor constraint functions.
   void emitSuccessorConstraints();
   /// Emit static region constraint functions.
@@ -212,6 +231,8 @@ class StaticVerifierFunctionEmitter {
   ConstraintMap typeConstraints;
   /// The set of attribute constraints used in the current file.
   ConstraintMap attrConstraints;
+  /// The set of property constraints used in the current file.
+  ConstraintMap propConstraints;
   /// The set of successor constraints used in the current file.
   ConstraintMap successorConstraints;
   /// The set of region constraints used in the current file.
diff --git a/mlir/include/mlir/TableGen/Property.h 
b/mlir/include/mlir/TableGen/Property.h
index 386159191ef1f..6af96f077efe5 100644
--- a/mlir/include/mlir/TableGen/Property.h
+++ b/mlir/include/mlir/TableGen/Property.h
@@ -29,14 +29,26 @@ class Dialect;
 class Type;
 class Pred;
 
+// Wrapper class providing helper methods for accesing property constraint
+// values.
+class PropConstraint : public Constraint {
+  using Constraint::Constraint;
+
+public:
+  static bool classof(const Constraint *c) { return c->getKind() == CK_Prop; }
+
+  StringRef getInterfaceType() const;
+};
+
 // Wrapper class providing helper methods for accessing MLIR Property defined
 // in TableGen. This class should closely reflect what is defined as class
 // `Property` in TableGen.
-class Property {
+class Property : public PropConstraint {
 public:
-  explicit Property(const llvm::Record *record);
+  explicit Property(const llvm::Record *def);
   explicit Property(const llvm::DefInit *init);
-  Property(StringRef summary, StringRef description, StringRef storageType,
+  Property(const llvm::Record *maybeDef, StringRef summary,
+   StringRef description, StringRef storageType,
StringRef interfaceType, StringRef convertFromStorageCall,
StringRef assignToStorageCall, StringRef convertToAttributeCall,
StringRef convertFromAttributeCall, StringRef parserCall,
@@ -131,13 +143,7 @@ class Property {
   // property constraints, this function is added for future-proofing)
   Property getBaseProperty() const;
 
-  // Returns the TableGen definition this Property was constructed from.
-  const llvm::Record &getDef() const { retu

[llvm-branch-commits] [llvm] [NFCI] Avoid adding duplicated SpecialCaseList::Sections. (PR #140821)

2025-05-21 Thread Vitaly Buka via llvm-branch-commits

vitalybuka wrote:

But why?
We don't use uniqueness any how. We will need to O(N_globs) lookups either way.
I propose to keep all sections as-is, in original order (or reversed), so we 
can interate them in reverse (or straight) order up to the first match.

https://github.com/llvm/llvm-project/pull/140821
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] AMDGPU: Handle folding vector splats of inline split f64 inline immediates (PR #140878)

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

https://github.com/arsenm ready_for_review 
https://github.com/llvm/llvm-project/pull/140878
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] AMDGPU: Handle folding vector splats of inline split f64 inline immediates (PR #140878)

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

llvmbot wrote:




@llvm/pr-subscribers-backend-amdgpu

Author: Matt Arsenault (arsenm)


Changes

Recognize a reg_sequence with 32-bit elements that produce a 64-bit
splat value. This enables folding f64 constants into mfma operands

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


2 Files Affected:

- (modified) llvm/lib/Target/AMDGPU/SIFoldOperands.cpp (+70-33) 
- (modified) llvm/test/CodeGen/AMDGPU/llvm.amdgcn.mfma.gfx90a.ll (+6-35) 


``diff
diff --git a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp 
b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
index eb7fb94e25f5c..70e3974bb22b4 100644
--- a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
+++ b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
@@ -227,12 +227,12 @@ class SIFoldOperandsImpl {
   getRegSeqInit(SmallVectorImpl> &Defs,
 Register UseReg) const;
 
-  std::pair
+  std::pair
   isRegSeqSplat(MachineInstr &RegSeg) const;
 
-  MachineOperand *tryFoldRegSeqSplat(MachineInstr *UseMI, unsigned UseOpIdx,
- MachineOperand *SplatVal,
- const TargetRegisterClass *SplatRC) const;
+  bool tryFoldRegSeqSplat(MachineInstr *UseMI, unsigned UseOpIdx,
+  int64_t SplatVal,
+  const TargetRegisterClass *SplatRC) const;
 
   bool tryToFoldACImm(const FoldableDef &OpToFold, MachineInstr *UseMI,
   unsigned UseOpIdx,
@@ -967,15 +967,15 @@ const TargetRegisterClass 
*SIFoldOperandsImpl::getRegSeqInit(
   return getRegSeqInit(*Def, Defs);
 }
 
-std::pair
+std::pair
 SIFoldOperandsImpl::isRegSeqSplat(MachineInstr &RegSeq) const {
   SmallVector, 32> Defs;
   const TargetRegisterClass *SrcRC = getRegSeqInit(RegSeq, Defs);
   if (!SrcRC)
 return {};
 
-  // TODO: Recognize 64-bit splats broken into 32-bit pieces (i.e. recognize
-  // every other other element is 0 for 64-bit immediates)
+  bool TryToMatchSplat64 = false;
+
   int64_t Imm;
   for (unsigned I = 0, E = Defs.size(); I != E; ++I) {
 const MachineOperand *Op = Defs[I].first;
@@ -987,38 +987,75 @@ SIFoldOperandsImpl::isRegSeqSplat(MachineInstr &RegSeq) 
const {
   Imm = SubImm;
   continue;
 }
-if (Imm != SubImm)
+
+if (Imm != SubImm) {
+  if (I == 1 && (E & 1) == 0) {
+// If we have an even number of inputs, there's a chance this is a
+// 64-bit element splat broken into 32-bit pieces.
+TryToMatchSplat64 = true;
+break;
+  }
+
   return {}; // Can only fold splat constants
+}
+  }
+
+  if (!TryToMatchSplat64)
+return {Defs[0].first->getImm(), SrcRC};
+
+  // Fallback to recognizing 64-bit splats broken into 32-bit pieces
+  // (i.e. recognize every other other element is 0 for 64-bit immediates)
+  int64_t SplatVal64;
+  for (unsigned I = 0, E = Defs.size(); I != E; I += 2) {
+const MachineOperand *Op0 = Defs[I].first;
+const MachineOperand *Op1 = Defs[I + 1].first;
+
+if (!Op0->isImm() || !Op1->isImm())
+  return {};
+
+unsigned SubReg0 = Defs[I].second;
+unsigned SubReg1 = Defs[I + 1].second;
+
+// Assume we're going to generally encounter reg_sequences with sorted
+// subreg indexes, so reject any that aren't consecutive.
+if (TRI->getChannelFromSubReg(SubReg0) + 1 !=
+TRI->getChannelFromSubReg(SubReg1))
+  return {};
+
+int64_t MergedVal = Make_64(Op1->getImm(), Op0->getImm());
+if (I == 0)
+  SplatVal64 = MergedVal;
+else if (SplatVal64 != MergedVal)
+  return {};
   }
 
-  return {Defs[0].first, SrcRC};
+  const TargetRegisterClass *RC64 = TRI->getSubRegisterClass(
+  MRI->getRegClass(RegSeq.getOperand(0).getReg()), AMDGPU::sub0_sub1);
+
+  return {SplatVal64, RC64};
 }
 
-MachineOperand *SIFoldOperandsImpl::tryFoldRegSeqSplat(
-MachineInstr *UseMI, unsigned UseOpIdx, MachineOperand *SplatVal,
+bool SIFoldOperandsImpl::tryFoldRegSeqSplat(
+MachineInstr *UseMI, unsigned UseOpIdx, int64_t SplatVal,
 const TargetRegisterClass *SplatRC) const {
   const MCInstrDesc &Desc = UseMI->getDesc();
   if (UseOpIdx >= Desc.getNumOperands())
-return nullptr;
+return false;
 
   // Filter out unhandled pseudos.
   if (!AMDGPU::isSISrcOperand(Desc, UseOpIdx))
-return nullptr;
+return false;
 
   int16_t RCID = Desc.operands()[UseOpIdx].RegClass;
   if (RCID == -1)
-return nullptr;
+return false;
+
+  const TargetRegisterClass *OpRC = TRI->getRegClass(RCID);
 
   // Special case 0/-1, since when interpreted as a 64-bit element both halves
-  // have the same bits. Effectively this code does not handle 64-bit element
-  // operands correctly, as the incoming 64-bit constants are already split 
into
-  // 32-bit sequence elements.
-  //
-  // TODO: We should try to figure out how to interpret the reg_sequence as a
-  // split 64-bit splat constant, or use 64-bit pseudos for materializing f64
-  // constants.
-  if (SplatVal->getImm() != 0 && SplatVal->getImm() != -1) {
-

[llvm-branch-commits] [llvm] AMDGPU: Handle folding vector splats of inline split f64 inline immediates (PR #140878)

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

https://github.com/arsenm created 
https://github.com/llvm/llvm-project/pull/140878

Recognize a reg_sequence with 32-bit elements that produce a 64-bit
splat value. This enables folding f64 constants into mfma operands

>From b68d880b7872cd90d3aa79419800cfc505305b76 Mon Sep 17 00:00:00 2001
From: Matt Arsenault 
Date: Mon, 19 May 2025 21:51:06 +0200
Subject: [PATCH] AMDGPU: Handle folding vector splats of inline split f64
 inline immediates

Recognize a reg_sequence with 32-bit elements that produce a 64-bit
splat value. This enables folding f64 constants into mfma operands
---
 llvm/lib/Target/AMDGPU/SIFoldOperands.cpp | 103 --
 .../CodeGen/AMDGPU/llvm.amdgcn.mfma.gfx90a.ll |  41 +--
 2 files changed, 76 insertions(+), 68 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp 
b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
index eb7fb94e25f5c..70e3974bb22b4 100644
--- a/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
+++ b/llvm/lib/Target/AMDGPU/SIFoldOperands.cpp
@@ -227,12 +227,12 @@ class SIFoldOperandsImpl {
   getRegSeqInit(SmallVectorImpl> &Defs,
 Register UseReg) const;
 
-  std::pair
+  std::pair
   isRegSeqSplat(MachineInstr &RegSeg) const;
 
-  MachineOperand *tryFoldRegSeqSplat(MachineInstr *UseMI, unsigned UseOpIdx,
- MachineOperand *SplatVal,
- const TargetRegisterClass *SplatRC) const;
+  bool tryFoldRegSeqSplat(MachineInstr *UseMI, unsigned UseOpIdx,
+  int64_t SplatVal,
+  const TargetRegisterClass *SplatRC) const;
 
   bool tryToFoldACImm(const FoldableDef &OpToFold, MachineInstr *UseMI,
   unsigned UseOpIdx,
@@ -967,15 +967,15 @@ const TargetRegisterClass 
*SIFoldOperandsImpl::getRegSeqInit(
   return getRegSeqInit(*Def, Defs);
 }
 
-std::pair
+std::pair
 SIFoldOperandsImpl::isRegSeqSplat(MachineInstr &RegSeq) const {
   SmallVector, 32> Defs;
   const TargetRegisterClass *SrcRC = getRegSeqInit(RegSeq, Defs);
   if (!SrcRC)
 return {};
 
-  // TODO: Recognize 64-bit splats broken into 32-bit pieces (i.e. recognize
-  // every other other element is 0 for 64-bit immediates)
+  bool TryToMatchSplat64 = false;
+
   int64_t Imm;
   for (unsigned I = 0, E = Defs.size(); I != E; ++I) {
 const MachineOperand *Op = Defs[I].first;
@@ -987,38 +987,75 @@ SIFoldOperandsImpl::isRegSeqSplat(MachineInstr &RegSeq) 
const {
   Imm = SubImm;
   continue;
 }
-if (Imm != SubImm)
+
+if (Imm != SubImm) {
+  if (I == 1 && (E & 1) == 0) {
+// If we have an even number of inputs, there's a chance this is a
+// 64-bit element splat broken into 32-bit pieces.
+TryToMatchSplat64 = true;
+break;
+  }
+
   return {}; // Can only fold splat constants
+}
+  }
+
+  if (!TryToMatchSplat64)
+return {Defs[0].first->getImm(), SrcRC};
+
+  // Fallback to recognizing 64-bit splats broken into 32-bit pieces
+  // (i.e. recognize every other other element is 0 for 64-bit immediates)
+  int64_t SplatVal64;
+  for (unsigned I = 0, E = Defs.size(); I != E; I += 2) {
+const MachineOperand *Op0 = Defs[I].first;
+const MachineOperand *Op1 = Defs[I + 1].first;
+
+if (!Op0->isImm() || !Op1->isImm())
+  return {};
+
+unsigned SubReg0 = Defs[I].second;
+unsigned SubReg1 = Defs[I + 1].second;
+
+// Assume we're going to generally encounter reg_sequences with sorted
+// subreg indexes, so reject any that aren't consecutive.
+if (TRI->getChannelFromSubReg(SubReg0) + 1 !=
+TRI->getChannelFromSubReg(SubReg1))
+  return {};
+
+int64_t MergedVal = Make_64(Op1->getImm(), Op0->getImm());
+if (I == 0)
+  SplatVal64 = MergedVal;
+else if (SplatVal64 != MergedVal)
+  return {};
   }
 
-  return {Defs[0].first, SrcRC};
+  const TargetRegisterClass *RC64 = TRI->getSubRegisterClass(
+  MRI->getRegClass(RegSeq.getOperand(0).getReg()), AMDGPU::sub0_sub1);
+
+  return {SplatVal64, RC64};
 }
 
-MachineOperand *SIFoldOperandsImpl::tryFoldRegSeqSplat(
-MachineInstr *UseMI, unsigned UseOpIdx, MachineOperand *SplatVal,
+bool SIFoldOperandsImpl::tryFoldRegSeqSplat(
+MachineInstr *UseMI, unsigned UseOpIdx, int64_t SplatVal,
 const TargetRegisterClass *SplatRC) const {
   const MCInstrDesc &Desc = UseMI->getDesc();
   if (UseOpIdx >= Desc.getNumOperands())
-return nullptr;
+return false;
 
   // Filter out unhandled pseudos.
   if (!AMDGPU::isSISrcOperand(Desc, UseOpIdx))
-return nullptr;
+return false;
 
   int16_t RCID = Desc.operands()[UseOpIdx].RegClass;
   if (RCID == -1)
-return nullptr;
+return false;
+
+  const TargetRegisterClass *OpRC = TRI->getRegClass(RCID);
 
   // Special case 0/-1, since when interpreted as a 64-bit element both halves
-  // have the same bits. Effectively this code does not handle 64-bit element
-  // operands correctly, as the incoming 64-bit constants are alrea

[llvm-branch-commits] [llvm] AMDGPU: Handle folding vector splats of inline split f64 inline immediates (PR #140878)

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

arsenm 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.dev/github/pr/llvm/llvm-project/140878?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

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


[llvm-branch-commits] [llvm] [HLSL][RootSignature] Implement `ResourceRange` as an `IntervalMap` (PR #140957)

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

llvmbot wrote:




@llvm/pr-subscribers-hlsl

Author: Finn Plummer (inbelic)


Changes

A resource range consists of a closed interval, `[a;b]`, denoting which shader 
registers it is bound to.

For instance:
 - `CBV(b1)`  corresponds to the resource range of `[1;1]`
 - `CBV(b0, numDescriptors = 3)` likewise to `[0;2]`

We want to provide an error diagnostic that there is an overlap in the required 
registers for each of the resources (an overlap in the resource ranges). 

The goal of this pr is to implement a structure to model a set of resource 
ranges and provide an api to detect any overlap over a set of resource ranges.

`ResourceRange` models this by implementing an `IntervalMap` to denote a 
mapping from an interval of registers back to a resource range. It allows for a 
new `ResourceRange` to be added to the mapping and it will report the first 
overlap that it denotes.

- Implements `ResourceRange` as an `IntervalMap`
- Adds unit testing of the various `insert` scenarios

Note: it was also considered to implement this as an `IntervalTree`, this would 
allow reporting of a diagnostic for each overlap that is encountered, as 
opposed to just the first. However, error generation of just reporting the 
first error is already rather verbose, and adding the additional diagnostics 
only made this worse.

Part 1 of https://github.com/llvm/llvm-project/issues/129942

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


4 Files Affected:

- (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+56) 
- (modified) llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp (+61) 
- (modified) llvm/unittests/Frontend/CMakeLists.txt (+1) 
- (added) llvm/unittests/Frontend/HLSLRootSignatureRangesTest.cpp (+177) 


``diff
diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h 
b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
index 98fa5f09429e3..3e5054566052b 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -15,6 +15,7 @@
 #define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntervalMap.h"
 #include "llvm/Support/DXILABI.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
@@ -198,6 +199,61 @@ class MetadataBuilder {
   SmallVector GeneratedMetadata;
 };
 
+// RangeInfo holds the information to correctly construct a ResourceRange
+// and retains this information to be used for displaying a better diagnostic
+struct RangeInfo {
+  const static uint32_t Unbounded = static_cast(-1);
+
+  uint32_t LowerBound;
+  uint32_t UpperBound;
+};
+
+class ResourceRange {
+public:
+  using IMap = llvm::IntervalMap>;
+
+private:
+  IMap Intervals;
+
+public:
+  ResourceRange(IMap::Allocator &Allocator) : Intervals(IMap(Allocator)) {}
+
+  // Returns a reference to the first RangeInfo that overlaps with
+  // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
+  std::optional getOverlapping(const RangeInfo &Info) const;
+
+  // Return the mapped RangeInfo at X or nullptr if no mapping exists
+  const RangeInfo *lookup(uint32_t X) const;
+
+  // Insert the required (sub-)intervals such that the interval of [a;b] =
+  // [Info.LowerBound, Info.UpperBound] is covered and points to a valid
+  // RangeInfo &.
+  //
+  // For instance consider the following chain of inserting RangeInfos with the
+  // intervals denoting the Lower/Upper-bounds:
+  //
+  // A = [0;2]
+  //   insert(A) -> false
+  //   intervals: [0;2] -> &A
+  // B = [5;7]
+  //   insert(B) -> false
+  //   intervals: [0;2] -> &A, [5;7] -> &B
+  // C = [4;7]
+  //   insert(C) -> true
+  //   intervals: [0;2] -> &A, [4;7] -> &C
+  // D = [1;5]
+  //   insert(D) -> true
+  //   intervals: [0;2] -> &A, [3;3] -> &D, [4;7] -> &C
+  // E = [0;unbounded]
+  //   insert(E) -> true
+  //   intervals: [0;unbounded] -> E
+  //
+  // Returns if the first overlapping range when inserting
+  // (same return as getOverlapping)
+  std::optional insert(const RangeInfo &Info);
+};
+
 } // namespace rootsig
 } // namespace hlsl
 } // namespace llvm
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp 
b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
index abf076944b273..76fe09e4dc3ee 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -222,6 +222,67 @@ MDNode *MetadataBuilder::BuildDescriptorTableClause(
});
 }
 
+std::optional
+ResourceRange::getOverlapping(const RangeInfo &Info) const {
+  IMap::const_iterator Interval = Intervals.find(Info.LowerBound);
+  if (!Interval.valid() || Info.UpperBound < Interval.start())
+return std::nullopt;
+  return Interval.value();
+}
+
+const RangeInfo *ResourceRange::lookup(uint32_t X) const {
+  return Intervals.lookup(X, nullptr);
+}
+
+std::optional ResourceRange::insert(const RangeInfo &Info) {
+  uint32_t LowerBound = Info.LowerBound;
+  uint32_t UpperBound = Info.UpperBound;
+
+  std::o

[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of Register in params for RootDescriptors (PR #140148)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic edited 
https://github.com/llvm/llvm-project/pull/140148
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of Register in params for RootDescriptors (PR #140148)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic edited 
https://github.com/llvm/llvm-project/pull/140148
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of optional parameters for RootDescriptor (PR #140151)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic edited 
https://github.com/llvm/llvm-project/pull/140151
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of flags to RootDescriptor (PR #140152)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic edited 
https://github.com/llvm/llvm-project/pull/140152
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [SelectionDAGBuilder] Use address width when lowering ptrtoaddr (PR #139423)

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

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


https://github.com/llvm/llvm-project/pull/139423
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of Register in params for RootDescriptors (PR #140148)

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

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


https://github.com/llvm/llvm-project/pull/140148
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [SelectionDAGBuilder] Use address width when lowering ptrtoaddr (PR #139423)

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


@@ -3878,7 +3878,18 @@ void SelectionDAGBuilder::visitSIToFP(const User &I) {
 }
 
 void SelectionDAGBuilder::visitPtrToAddr(const User &I) {
-  visitPtrToInt(I);
+  const auto &TLI = DAG.getTargetLoweringInfo();
+  const DataLayout &DL = DAG.getDataLayout();
+  LLVMContext &Ctx = *DAG.getContext();
+  // ptrtoaddr is equivalent to a truncate of ptrtoint to address/index width
+  SDValue N = getValue(I.getOperand(0));
+  Type *PtrTy = I.getOperand(0)->getType();
+  EVT AddrVT = EVT::getIntegerVT(Ctx, DL.getPointerAddressSizeInBits(PtrTy));
+  if (auto *VTy = dyn_cast(PtrTy))
+AddrVT = EVT::getVectorVT(Ctx, AddrVT, VTy->getElementCount());
+  N = DAG.getPtrExtOrTrunc(N, getCurSDLoc(), AddrVT);

arsenm wrote:

The LangRef says that it's always zero extend, but DAG.getPtrExtOrTrunc's 
comment suggests it may decide to be another extension some day? 

https://github.com/llvm/llvm-project/pull/139423
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [HLSL] Diagnose overlapping resource bindings (PR #140982)

2025-05-21 Thread Helena Kotas via llvm-branch-commits

https://github.com/hekota created 
https://github.com/llvm/llvm-project/pull/140982

Adds reporting of overlapping binding errors to 
`DXILPostOptimizationValidation` pass. Only runs when 
`DXILResourceBindingAnalysis` detects there is an overlapping binding.

Fixes #110723

Depends on #140635, #140645, #140981

>From dc8a3fa961fe05fecd7718ad24d19437d8c4484e Mon Sep 17 00:00:00 2001
From: Helena Kotas 
Date: Wed, 21 May 2025 19:06:38 -0700
Subject: [PATCH] [HLSL] Diagnose overlapping resource bindings

---
 llvm/include/llvm/Analysis/DXILResource.h |  7 ++-
 .../DXILPostOptimizationValidation.cpp| 59 ---
 .../DirectX/Binding/binding-overlap-1.ll  | 17 ++
 .../DirectX/Binding/binding-overlap-2.ll  | 17 ++
 .../DirectX/Binding/binding-overlap-3.ll  | 44 ++
 .../typed-uav-load-additional-formats.ll  |  4 +-
 6 files changed, 136 insertions(+), 12 deletions(-)
 create mode 100644 llvm/test/CodeGen/DirectX/Binding/binding-overlap-1.ll
 create mode 100644 llvm/test/CodeGen/DirectX/Binding/binding-overlap-2.ll
 create mode 100644 llvm/test/CodeGen/DirectX/Binding/binding-overlap-3.ll

diff --git a/llvm/include/llvm/Analysis/DXILResource.h 
b/llvm/include/llvm/Analysis/DXILResource.h
index a274e2294561e..f6e924041da11 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -355,6 +355,9 @@ class ResourceInfo {
   return std::tie(RecordID, Space, LowerBound, Size) <
  std::tie(RHS.RecordID, RHS.Space, RHS.LowerBound, RHS.Size);
 }
+bool overlapsWith(const ResourceBinding &RHS) const {
+  return Space == RHS.Space && LowerBound + Size - 1 >= RHS.LowerBound;
+}
   };
 
 private:
@@ -393,8 +396,8 @@ class ResourceInfo {
   getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const;
 
   bool operator==(const ResourceInfo &RHS) const {
-return std::tie(Binding, HandleTy, Symbol) ==
-   std::tie(RHS.Binding, RHS.HandleTy, RHS.Symbol);
+return std::tie(Binding, HandleTy, Symbol, Name) ==
+   std::tie(RHS.Binding, RHS.HandleTy, RHS.Symbol, RHS.Name);
   }
   bool operator!=(const ResourceInfo &RHS) const { return !(*this == RHS); }
   bool operator<(const ResourceInfo &RHS) const {
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp 
b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 1dc0c2fb13c11..c0bb6a61e8a24 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -9,6 +9,7 @@
 #include "DXILPostOptimizationValidation.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/Analysis/DXILMetadataAnalysis.h"
 #include "llvm/Analysis/DXILResource.h"
 #include "llvm/IR/DiagnosticInfo.h"
@@ -50,15 +51,55 @@ static void reportInvalidDirection(Module &M, 
DXILResourceMap &DRM) {
   }
 }
 
-} // namespace
+static void reportOverlappingError(Module &M, ResourceInfo R1,
+   ResourceInfo R2) {
+  SmallString<64> Message;
+  raw_svector_ostream OS(Message);
+  OS << "resource " << R1.getName() << " at register "
+ << R1.getBinding().LowerBound << " overlaps with resource " << 
R2.getName()
+ << " at register " << R2.getBinding().LowerBound << ", space "
+ << R2.getBinding().Space;
+  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
+}
 
-PreservedAnalyses
-DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
-  DXILResourceMap &DRM = MAM.getResult(M);
+static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
+  if (DRM.empty())
+return;
 
+  for (auto ResList :
+   {DRM.srvs(), DRM.uavs(), DRM.cbuffers(), DRM.samplers()}) {
+if (ResList.empty())
+  continue;
+const ResourceInfo *PrevRI = &*ResList.begin();
+for (auto *I = ResList.begin() + 1; I != ResList.end(); ++I) {
+  const ResourceInfo *RI = &*I;
+  if (PrevRI->getBinding().overlapsWith(RI->getBinding())) {
+reportOverlappingError(M, *PrevRI, *RI);
+continue;
+  }
+  PrevRI = RI;
+}
+  }
+}
+
+static void reportErrors(Module &M, DXILResourceMap &DRM,
+ DXILResourceBindingInfo &DRBI) {
   if (DRM.hasInvalidCounterDirection())
 reportInvalidDirection(M, DRM);
 
+  if (DRBI.hasOverlappingBinding())
+reportOverlappingBinding(M, DRM);
+
+  assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in 
"
+   "DXILResourceImplicitBinding pass");
+}
+} // namespace
+
+PreservedAnalyses
+DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
+  DXILResourceMap &DRM = MAM.getResult(M);
+  DXILResourceBindingInfo &DRBI = 
MAM.getResult(M);
+  reportErrors(M, DRM, DRBI);
   return PreservedAnalyses::all();
 }
 
@@ -68,10 +109,9 @@ class DXILPostOptimizationValidationLegacy : public 
ModulePass {
   

[llvm-branch-commits] [llvm] [HLSL] Diagnose overlapping resource bindings (PR #140982)

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

llvmbot wrote:




@llvm/pr-subscribers-backend-directx

Author: Helena Kotas (hekota)


Changes

Adds reporting of overlapping binding errors to 
`DXILPostOptimizationValidation` pass. Only runs when 
`DXILResourceBindingAnalysis` detects there is an overlapping binding.

Fixes #110723

Depends on #140635, #140645, #140981

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


6 Files Affected:

- (modified) llvm/include/llvm/Analysis/DXILResource.h (+5-2) 
- (modified) llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp (+51-8) 
- (added) llvm/test/CodeGen/DirectX/Binding/binding-overlap-1.ll (+17) 
- (added) llvm/test/CodeGen/DirectX/Binding/binding-overlap-2.ll (+17) 
- (added) llvm/test/CodeGen/DirectX/Binding/binding-overlap-3.ll (+44) 
- (modified) 
llvm/test/CodeGen/DirectX/ShaderFlags/typed-uav-load-additional-formats.ll 
(+2-2) 


``diff
diff --git a/llvm/include/llvm/Analysis/DXILResource.h 
b/llvm/include/llvm/Analysis/DXILResource.h
index a274e2294561e..f6e924041da11 100644
--- a/llvm/include/llvm/Analysis/DXILResource.h
+++ b/llvm/include/llvm/Analysis/DXILResource.h
@@ -355,6 +355,9 @@ class ResourceInfo {
   return std::tie(RecordID, Space, LowerBound, Size) <
  std::tie(RHS.RecordID, RHS.Space, RHS.LowerBound, RHS.Size);
 }
+bool overlapsWith(const ResourceBinding &RHS) const {
+  return Space == RHS.Space && LowerBound + Size - 1 >= RHS.LowerBound;
+}
   };
 
 private:
@@ -393,8 +396,8 @@ class ResourceInfo {
   getAnnotateProps(Module &M, dxil::ResourceTypeInfo &RTI) const;
 
   bool operator==(const ResourceInfo &RHS) const {
-return std::tie(Binding, HandleTy, Symbol) ==
-   std::tie(RHS.Binding, RHS.HandleTy, RHS.Symbol);
+return std::tie(Binding, HandleTy, Symbol, Name) ==
+   std::tie(RHS.Binding, RHS.HandleTy, RHS.Symbol, RHS.Name);
   }
   bool operator!=(const ResourceInfo &RHS) const { return !(*this == RHS); }
   bool operator<(const ResourceInfo &RHS) const {
diff --git a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp 
b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
index 1dc0c2fb13c11..c0bb6a61e8a24 100644
--- a/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
+++ b/llvm/lib/Target/DirectX/DXILPostOptimizationValidation.cpp
@@ -9,6 +9,7 @@
 #include "DXILPostOptimizationValidation.h"
 #include "DXILShaderFlags.h"
 #include "DirectX.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/Analysis/DXILMetadataAnalysis.h"
 #include "llvm/Analysis/DXILResource.h"
 #include "llvm/IR/DiagnosticInfo.h"
@@ -50,15 +51,55 @@ static void reportInvalidDirection(Module &M, 
DXILResourceMap &DRM) {
   }
 }
 
-} // namespace
+static void reportOverlappingError(Module &M, ResourceInfo R1,
+   ResourceInfo R2) {
+  SmallString<64> Message;
+  raw_svector_ostream OS(Message);
+  OS << "resource " << R1.getName() << " at register "
+ << R1.getBinding().LowerBound << " overlaps with resource " << 
R2.getName()
+ << " at register " << R2.getBinding().LowerBound << ", space "
+ << R2.getBinding().Space;
+  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
+}
 
-PreservedAnalyses
-DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
-  DXILResourceMap &DRM = MAM.getResult(M);
+static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
+  if (DRM.empty())
+return;
 
+  for (auto ResList :
+   {DRM.srvs(), DRM.uavs(), DRM.cbuffers(), DRM.samplers()}) {
+if (ResList.empty())
+  continue;
+const ResourceInfo *PrevRI = &*ResList.begin();
+for (auto *I = ResList.begin() + 1; I != ResList.end(); ++I) {
+  const ResourceInfo *RI = &*I;
+  if (PrevRI->getBinding().overlapsWith(RI->getBinding())) {
+reportOverlappingError(M, *PrevRI, *RI);
+continue;
+  }
+  PrevRI = RI;
+}
+  }
+}
+
+static void reportErrors(Module &M, DXILResourceMap &DRM,
+ DXILResourceBindingInfo &DRBI) {
   if (DRM.hasInvalidCounterDirection())
 reportInvalidDirection(M, DRM);
 
+  if (DRBI.hasOverlappingBinding())
+reportOverlappingBinding(M, DRM);
+
+  assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in 
"
+   "DXILResourceImplicitBinding pass");
+}
+} // namespace
+
+PreservedAnalyses
+DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
+  DXILResourceMap &DRM = MAM.getResult(M);
+  DXILResourceBindingInfo &DRBI = 
MAM.getResult(M);
+  reportErrors(M, DRM, DRBI);
   return PreservedAnalyses::all();
 }
 
@@ -68,10 +109,9 @@ class DXILPostOptimizationValidationLegacy : public 
ModulePass {
   bool runOnModule(Module &M) override {
 DXILResourceMap &DRM =
 getAnalysis().getResourceMap();
-
-if (DRM.hasInvalidCounterDirection())
-  reportInvalidDirection(M, DRM);
-
+DXILResourceBindingInfo &DRBI =
+getAnalysis().getBindingInf

[llvm-branch-commits] [llvm] [HLSL] Diagnose overlapping resource bindings (PR #140982)

2025-05-21 Thread Helena Kotas via llvm-branch-commits

https://github.com/hekota edited 
https://github.com/llvm/llvm-project/pull/140982
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Implement validation of resource ranges for `RootDescriptors` (PR #140962)

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

llvmbot wrote:




@llvm/pr-subscribers-hlsl

Author: Finn Plummer (inbelic)


Changes

As was established 
[previously](https://github.com/llvm/llvm-project/pull/140957), we created a 
structure to model a resource range and to detect an overlap in a given set of 
these.

However, a resource range only overlaps with another resource range if they 
have:
- equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
- equivalent resource name-space
- overlapping shader visibility

For instance, the following don't overlap even though they have the same 
register range:
- `CBV(b0)` and `SRV(t0)` (different resource class)
- `CBV(b0, space = 0)` and `CBV(b0, space = 1)` (different space)
- `CBV(b0, visibility = Pixel)` and `CBV(b0, visibility = Domain)` 
(non-overlapping visibility)

The first two clauses are naturally modelled by a mapping, `map;
 
+def err_hlsl_resource_range_overlap: Error<
+  "resource ranges %select{t|u|b|s}0[%1;%2] and %select{t|u|b|s}3[%4;%5] "
+  "overlap within space = %6 and visibility = "
+  "%select{All|Vertex|Hull|Domain|Geometry|Pixel|Amplification|Mesh}7">;
+
 // Layout randomization diagnostics.
 def err_non_designated_init_used : Error<
   "a randomized struct can only be initialized with a designated initializer">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h 
b/clang/include/clang/Sema/SemaHLSL.h
index 15182bb27bbdf..a161236d8baa0 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -119,6 +119,8 @@ class SemaHLSL : public SemaBase {
bool IsCompAssign);
   void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc);
 
+  // Returns true when D is invalid and a diagnostic was produced
+  bool handleRootSignatureDecl(HLSLRootSignatureDecl *D, SourceLocation Loc);
   void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL);
   void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
   void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e6daa67fcee95..cc53f25c766b0 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -39,6 +39,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/DXILABI.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -951,6 +952,101 @@ void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr 
*RHS,
   << NewFnName << FixItHint::CreateReplacement(FullRange, OS.str());
 }
 
+namespace {
+
+// A resource range overlaps with another resource range if they have:
+// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
+// - equivalent resource space
+// - overlapping visbility
+class ResourceRanges {
+public:
+  // KeyT: 32-lsb denotes resource space, and 32-msb denotes resource type enum
+  using KeyT = uint64_t;
+
+  constexpr static KeyT getKey(const llvm::hlsl::rootsig::RangeInfo &Info) {
+uint64_t SpacePack

[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Implement validation of resource ranges for `RootDescriptors` (PR #140962)

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

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Finn Plummer (inbelic)


Changes

As was established 
[previously](https://github.com/llvm/llvm-project/pull/140957), we created a 
structure to model a resource range and to detect an overlap in a given set of 
these.

However, a resource range only overlaps with another resource range if they 
have:
- equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
- equivalent resource name-space
- overlapping shader visibility

For instance, the following don't overlap even though they have the same 
register range:
- `CBV(b0)` and `SRV(t0)` (different resource class)
- `CBV(b0, space = 0)` and `CBV(b0, space = 1)` (different space)
- `CBV(b0, visibility = Pixel)` and `CBV(b0, visibility = Domain)` 
(non-overlapping visibility)

The first two clauses are naturally modelled by a mapping, `map;
 
+def err_hlsl_resource_range_overlap: Error<
+  "resource ranges %select{t|u|b|s}0[%1;%2] and %select{t|u|b|s}3[%4;%5] "
+  "overlap within space = %6 and visibility = "
+  "%select{All|Vertex|Hull|Domain|Geometry|Pixel|Amplification|Mesh}7">;
+
 // Layout randomization diagnostics.
 def err_non_designated_init_used : Error<
   "a randomized struct can only be initialized with a designated initializer">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h 
b/clang/include/clang/Sema/SemaHLSL.h
index 15182bb27bbdf..a161236d8baa0 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -119,6 +119,8 @@ class SemaHLSL : public SemaBase {
bool IsCompAssign);
   void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc);
 
+  // Returns true when D is invalid and a diagnostic was produced
+  bool handleRootSignatureDecl(HLSLRootSignatureDecl *D, SourceLocation Loc);
   void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL);
   void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
   void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e6daa67fcee95..cc53f25c766b0 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -39,6 +39,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/DXILABI.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -951,6 +952,101 @@ void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr 
*RHS,
   << NewFnName << FixItHint::CreateReplacement(FullRange, OS.str());
 }
 
+namespace {
+
+// A resource range overlaps with another resource range if they have:
+// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
+// - equivalent resource space
+// - overlapping visbility
+class ResourceRanges {
+public:
+  // KeyT: 32-lsb denotes resource space, and 32-msb denotes resource type enum
+  using KeyT = uint64_t;
+
+  constexpr static KeyT getKey(const llvm::hlsl::rootsig::RangeInfo &Info) {
+uint64_t SpacePac

[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Implement validation of resource ranges for `RootDescriptors` (PR #140962)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic created 
https://github.com/llvm/llvm-project/pull/140962

As was established 
[previously](https://github.com/llvm/llvm-project/pull/140957), we created a 
structure to model a resource range and to detect an overlap in a given set of 
these.

However, a resource range only overlaps with another resource range if they 
have:
- equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
- equivalent resource name-space
- overlapping shader visibility

For instance, the following don't overlap even though they have the same 
register range:
- `CBV(b0)` and `SRV(t0)` (different resource class)
- `CBV(b0, space = 0)` and `CBV(b0, space = 1)` (different space)
- `CBV(b0, visibility = Pixel)` and `CBV(b0, visibility = Domain)` 
(non-overlapping visibility)

The first two clauses are naturally modelled by a mapping, `maphttps://github.com/llvm/llvm-project/issues/129942

>From 630dae06367b0281f3b2587b7a076accc9e51da5 Mon Sep 17 00:00:00 2001
From: Finn Plummer 
Date: Wed, 21 May 2025 00:12:04 +
Subject: [PATCH] [HLSL][RootSignature] Plug into the thing

---
 .../clang/Basic/DiagnosticSemaKinds.td|  5 +
 clang/include/clang/Sema/SemaHLSL.h   |  2 +
 clang/lib/Sema/SemaHLSL.cpp   | 98 +++
 .../RootSignature-resource-ranges-err.hlsl| 26 +
 .../RootSignature-resource-ranges.hlsl| 22 +
 .../llvm/Frontend/HLSL/HLSLRootSignature.h|  8 +-
 6 files changed, 159 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
 create mode 100644 clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f0bd5a1174020..b1026e733ec37 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12967,6 +12967,11 @@ def err_hlsl_expect_arg_const_int_one_or_neg_one: 
Error<
 def err_invalid_hlsl_resource_type: Error<
   "invalid __hlsl_resource_t type attributes">;
 
+def err_hlsl_resource_range_overlap: Error<
+  "resource ranges %select{t|u|b|s}0[%1;%2] and %select{t|u|b|s}3[%4;%5] "
+  "overlap within space = %6 and visibility = "
+  "%select{All|Vertex|Hull|Domain|Geometry|Pixel|Amplification|Mesh}7">;
+
 // Layout randomization diagnostics.
 def err_non_designated_init_used : Error<
   "a randomized struct can only be initialized with a designated initializer">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h 
b/clang/include/clang/Sema/SemaHLSL.h
index 15182bb27bbdf..a161236d8baa0 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -119,6 +119,8 @@ class SemaHLSL : public SemaBase {
bool IsCompAssign);
   void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc);
 
+  // Returns true when D is invalid and a diagnostic was produced
+  bool handleRootSignatureDecl(HLSLRootSignatureDecl *D, SourceLocation Loc);
   void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL);
   void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
   void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e6daa67fcee95..cc53f25c766b0 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -39,6 +39,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/DXILABI.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -951,6 +952,101 @@ void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr 
*RHS,
   << NewFnName << FixItHint::CreateReplacement(FullRange, OS.str());
 }
 
+namespace {
+
+// A resource range overlaps with another resource range if they have:
+// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
+// - equivalent resource space
+// - overlapping visbility
+class ResourceRanges {
+public:
+  // KeyT: 32-lsb denotes resource space, and 32-msb denotes resource type enum
+  using KeyT = uint64_t;
+
+  constexpr static KeyT getKey(const llvm::hlsl::rootsig::RangeInfo &Info) {
+uint64_t SpacePacked = (uint64_t)Info.Space;
+uint64_t ClassPacked = (uint64_t)llvm::to_underlying(Info.Class);
+return (ClassPacked << 32) | SpacePacked;
+  }
+
+  static const unsigned NumVisEnums = 8;
+// (unsigned)llvm::hlsl::rootsig::ShaderVisibility::NumEnums;
+
+private:
+  llvm::hlsl::rootsig::ResourceRange::IMap::Allocator Allocator;
+
+  using MapT = llvm::SmallDenseMap;
+
+  MapT RangeMaps[NumVisEnums];
+
+public:
+  // Returns std::nullopt if there was no collision. Otherwise, it will
+  // return the RangeInfo of the collision
+  std::optional addRange(const 
llvm::hlsl::rootsig::RangeInfo &Info) {
+MapT &VisRangeMap = RangeMaps[llvm::to_underlying(Info.Vis)];
+

[llvm-branch-commits] [llvm] [HLSL][RootSignature] Implement `ResourceRange` as an `IntervalMap` (PR #140957)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic edited 
https://github.com/llvm/llvm-project/pull/140957
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Implement validation of resource ranges for `RootDescriptors` (PR #140962)

2025-05-21 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 HEAD~1 HEAD --extensions h,cpp -- 
clang/include/clang/Sema/SemaHLSL.h clang/lib/Sema/SemaHLSL.cpp 
llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index cc53f25c7..25a64e4b5 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -970,7 +970,7 @@ public:
   }
 
   static const unsigned NumVisEnums = 8;
-// (unsigned)llvm::hlsl::rootsig::ShaderVisibility::NumEnums;
+  // (unsigned)llvm::hlsl::rootsig::ShaderVisibility::NumEnums;
 
 private:
   llvm::hlsl::rootsig::ResourceRange::IMap::Allocator Allocator;
@@ -982,25 +982,27 @@ private:
 public:
   // Returns std::nullopt if there was no collision. Otherwise, it will
   // return the RangeInfo of the collision
-  std::optional addRange(const 
llvm::hlsl::rootsig::RangeInfo &Info) {
+  std::optional
+  addRange(const llvm::hlsl::rootsig::RangeInfo &Info) {
 MapT &VisRangeMap = RangeMaps[llvm::to_underlying(Info.Vis)];
-auto [It, _] = VisRangeMap.insert({getKey(Info), 
llvm::hlsl::rootsig::ResourceRange(Allocator)});
+auto [It, _] = VisRangeMap.insert(
+{getKey(Info), llvm::hlsl::rootsig::ResourceRange(Allocator)});
 auto Res = It->second.insert(Info);
 if (Res.has_value())
   return Res;
 
 MutableArrayRef Maps =
-  Info.Vis == llvm::hlsl::rootsig::ShaderVisibility::All
-  ? MutableArrayRef{RangeMaps}.drop_front()
-  : MutableArrayRef{RangeMaps}.take_front();
+Info.Vis == llvm::hlsl::rootsig::ShaderVisibility::All
+? MutableArrayRef{RangeMaps}.drop_front()
+: MutableArrayRef{RangeMaps}.take_front();
 
 for (MapT &CurMap : Maps) {
   auto CurIt = CurMap.find(getKey(Info));
   if (CurIt != CurMap.end())
 if (auto Overlapping = CurIt->second.getOverlapping(Info))
- return Overlapping;
+  return Overlapping;
 }
-
+
 return std::nullopt;
   }
 };
@@ -1015,15 +1017,15 @@ bool 
SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
   llvm::SmallVector Infos;
   for (const auto &Elem : Elements) {
 if (const auto *Param =
-std::get_if(&Elem)) {
-  llvm::hlsl::rootsig::RangeInfo Info;
-  Info.LowerBound = Param->Reg.Number;
-  Info.UpperBound = Info.LowerBound; // use inclusive ranges []
+std::get_if(&Elem)) {
+  llvm::hlsl::rootsig::RangeInfo Info;
+  Info.LowerBound = Param->Reg.Number;
+  Info.UpperBound = Info.LowerBound; // use inclusive ranges []
 
-  Info.Class = Param->Type;
-  Info.Space = Param->Space;
-  Info.Vis = Param->Visibility;
-  Infos.push_back(Info);
+  Info.Class = Param->Type;
+  Info.Space = Param->Space;
+  Info.Vis = Param->Visibility;
+  Infos.push_back(Info);
 }
   }
 
@@ -1032,14 +1034,16 @@ bool 
SemaHLSL::handleRootSignatureDecl(HLSLRootSignatureDecl *D,
   bool HadOverlap = false;
   for (const llvm::hlsl::rootsig::RangeInfo &Info : Infos)
 if (auto MaybeOverlappingInfo = Ranges.addRange(Info)) {
-  const llvm::hlsl::rootsig::RangeInfo *OInfo = 
MaybeOverlappingInfo.value();
+  const llvm::hlsl::rootsig::RangeInfo *OInfo =
+  MaybeOverlappingInfo.value();
   auto CommonVis = Info.Vis == llvm::hlsl::rootsig::ShaderVisibility::All
-   ? OInfo->Vis : Info.Vis;
+   ? OInfo->Vis
+   : Info.Vis;
 
   Diag(Loc, diag::err_hlsl_resource_range_overlap)
-<< llvm::to_underlying(Info.Class) << Info.LowerBound << 
Info.UpperBound
-<< llvm::to_underlying(OInfo->Class) << OInfo->LowerBound << 
OInfo->UpperBound
-<< Info.Space << CommonVis;
+  << llvm::to_underlying(Info.Class) << Info.LowerBound
+  << Info.UpperBound << llvm::to_underlying(OInfo->Class)
+  << OInfo->LowerBound << OInfo->UpperBound << Info.Space << CommonVis;
 
   HadOverlap = true;
 }

``




https://github.com/llvm/llvm-project/pull/140962
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [clang] Introduce CallGraphSection option (PR #117037)

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

https://github.com/arsenm commented:

Should get documentation change for the flag 

https://github.com/llvm/llvm-project/pull/117037
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [clang] Introduce CallGraphSection option (PR #117037)

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


@@ -467,6 +467,7 @@ static bool initTargetOptions(const CompilerInstance &CI,
   Options.StackUsageOutput = CodeGenOpts.StackUsageOutput;
   Options.EmitAddrsig = CodeGenOpts.Addrsig;
   Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection;
+  Options.EmitCallGraphSection = CodeGenOpts.CallGraphSection;

arsenm wrote:

TargetOptions :(

https://github.com/llvm/llvm-project/pull/117037
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Implement validation of resource ranges for `RootDescriptors` (PR #140962)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic edited 
https://github.com/llvm/llvm-project/pull/140962
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)

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


@@ -110,6 +110,7 @@ typedef enum {
   LLVMFPTrunc= 37,
   LLVMFPExt  = 38,
   LLVMPtrToInt   = 39,
+  LLVMPtrToAddr  = 69,

arichardson wrote:

fneg and callbr also break the ordering - I think the intention in this file is 
to have them match the grouping in Instruction

https://github.com/llvm/llvm-project/pull/139357
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Add parsing of Register in params for RootParams (PR #140148)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic updated 
https://github.com/llvm/llvm-project/pull/140148

>From 994bc35f7eb1707097511a121d2a5a0b6f42637c Mon Sep 17 00:00:00 2001
From: Finn Plummer 
Date: Thu, 15 May 2025 19:49:44 +
Subject: [PATCH 1/2] [HLSL][RootSignature] Add parsing of Register in params
 for RootParams

- defines the `parseRootParamParams` infastructure for parsing the
params of a RootParam
- defines the register type to illustrate use
- add tests to demonstrate functionality
---
 .../clang/Parse/ParseHLSLRootSignature.h  |  6 +++
 clang/lib/Parse/ParseHLSLRootSignature.cpp| 42 +++
 .../Parse/ParseHLSLRootSignatureTest.cpp  | 13 --
 .../llvm/Frontend/HLSL/HLSLRootSignature.h|  1 +
 4 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Parse/ParseHLSLRootSignature.h 
b/clang/include/clang/Parse/ParseHLSLRootSignature.h
index b96416ab6c6c4..92b8e7389426a 100644
--- a/clang/include/clang/Parse/ParseHLSLRootSignature.h
+++ b/clang/include/clang/Parse/ParseHLSLRootSignature.h
@@ -89,6 +89,12 @@ class RootSignatureParser {
   };
   std::optional parseRootConstantParams();
 
+  struct ParsedRootParamParams {
+std::optional Reg;
+  };
+  std::optional
+  parseRootParamParams(RootSignatureToken::Kind RegType);
+
   struct ParsedClauseParams {
 std::optional Reg;
 std::optional NumDescriptors;
diff --git a/clang/lib/Parse/ParseHLSLRootSignature.cpp 
b/clang/lib/Parse/ParseHLSLRootSignature.cpp
index 3ed60442eaa14..de7c2452b3fd4 100644
--- a/clang/lib/Parse/ParseHLSLRootSignature.cpp
+++ b/clang/lib/Parse/ParseHLSLRootSignature.cpp
@@ -176,20 +176,37 @@ std::optional 
RootSignatureParser::parseRootParam() {
 return std::nullopt;
 
   RootParam Param;
+  TokenKind ExpectedReg;
   switch (ParamKind) {
   default:
 llvm_unreachable("Switch for consumed token was not provided");
   case TokenKind::kw_CBV:
 Param.Type = ParamType::CBuffer;
+ExpectedReg = TokenKind::bReg;
 break;
   case TokenKind::kw_SRV:
 Param.Type = ParamType::SRV;
+ExpectedReg = TokenKind::tReg;
 break;
   case TokenKind::kw_UAV:
 Param.Type = ParamType::UAV;
+ExpectedReg = TokenKind::uReg;
 break;
   }
 
+  auto Params = parseRootParamParams(ExpectedReg);
+  if (!Params.has_value())
+return std::nullopt;
+
+  // Check mandatory parameters were provided
+  if (!Params->Reg.has_value()) {
+getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param)
+<< ExpectedReg;
+return std::nullopt;
+  }
+
+  Param.Reg = Params->Reg.value();
+
   if (consumeExpectedToken(TokenKind::pu_r_paren,
diag::err_hlsl_unexpected_end_of_params,
/*param of=*/TokenKind::kw_RootConstants))
@@ -398,6 +415,31 @@ RootSignatureParser::parseRootConstantParams() {
   return Params;
 }
 
+std::optional
+RootSignatureParser::parseRootParamParams(TokenKind RegType) {
+  assert(CurToken.TokKind == TokenKind::pu_l_paren &&
+ "Expects to only be invoked starting at given token");
+
+  ParsedRootParamParams Params;
+  do {
+// ( `b` | `t` | `u`) POS_INT
+if (tryConsumeExpectedToken(RegType)) {
+  if (Params.Reg.has_value()) {
+getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
+<< CurToken.TokKind;
+return std::nullopt;
+  }
+  auto Reg = parseRegister();
+  if (!Reg.has_value())
+return std::nullopt;
+  Params.Reg = Reg;
+}
+
+  } while (tryConsumeExpectedToken(TokenKind::pu_comma));
+
+  return Params;
+}
+
 std::optional
 RootSignatureParser::parseDescriptorTableClauseParams(TokenKind RegType) {
   assert(CurToken.TokKind == TokenKind::pu_l_paren &&
diff --git a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp 
b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
index 876dcd17f0389..0f32523493a53 100644
--- a/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
+++ b/clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp
@@ -346,9 +346,9 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseRootFlagsTest) 
{
 
 TEST_F(ParseHLSLRootSignatureTest, ValidParseRootParamsTest) {
   const llvm::StringLiteral Source = R"cc(
-CBV(),
-SRV(),
-UAV()
+CBV(b0),
+SRV(t42),
+UAV(u34893247)
   )cc";
 
   TrivialModuleLoader ModLoader;
@@ -368,15 +368,20 @@ TEST_F(ParseHLSLRootSignatureTest, 
ValidParseRootParamsTest) {
 
   RootElement Elem = Elements[0];
   ASSERT_TRUE(std::holds_alternative(Elem));
-  ASSERT_EQ(std::get(Elem).Type, ParamType::CBuffer);
+  ASSERT_EQ(std::get(Elem).Reg.ViewType, RegisterType::BReg);
+  ASSERT_EQ(std::get(Elem).Reg.Number, 0u);
 
   Elem = Elements[1];
   ASSERT_TRUE(std::holds_alternative(Elem));
   ASSERT_EQ(std::get(Elem).Type, ParamType::SRV);
+  ASSERT_EQ(std::get(Elem).Reg.ViewType, RegisterType::TReg);
+  ASSERT_EQ(std::get(Elem).Reg.Number, 42u);
 
   Elem = Elements[2];
   ASSERT_TRUE(std::holds_alternative(Elem));
   ASSERT_EQ(std:

[llvm-branch-commits] [clang] [clang] Introduce CallGraphSection option (PR #117037)

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


@@ -0,0 +1,5 @@
+// RUN: %clang -### -S -fcall-graph-section %s 2>&1 | FileCheck 
--check-prefix=CALL-GRAPH-SECTION %s
+// RUN: %clang -### -S -fcall-graph-section -fno-call-graph-section %s 2>&1 | 
FileCheck --check-prefix=NO-CALL-GRAPH-SECTION %s

arsenm wrote:

```suggestion
// RUN: %clang -### -fcall-graph-section %s 2>&1 | FileCheck 
--check-prefix=CALL-GRAPH-SECTION %s
// RUN: %clang -### -fcall-graph-section -fno-call-graph-section %s 2>&1 | 
FileCheck --check-prefix=NO-CALL-GRAPH-SECTION %s
```

Don't really care about the output type if you aren't using it 

https://github.com/llvm/llvm-project/pull/117037
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [clang] Introduce CallGraphSection option (PR #117037)

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

https://github.com/arsenm edited 
https://github.com/llvm/llvm-project/pull/117037
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)

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


@@ -7,9 +7,9 @@ define i32 @nested(i32 %src) #0 {
 ; CHECK-SAME: i32 [[A0:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  [[BB15160:.*:]]
 ; CHECK-NEXT:[[T1:%.*]] = call token @llvm.experimental.convergence.entry()
-; CHECK-NEXT:%"vl77672llvm.experimental.convergence.anchor()" = call token 
@llvm.experimental.convergence.anchor()
-; CHECK-NEXT:%"op68297(vl77672)" = call i32 
@llvm.amdgcn.readfirstlane.i32(i32 [[A0]]) [ "convergencectrl"(token 
%"vl77672llvm.experimental.convergence.anchor()") ]
-; CHECK-NEXT:ret i32 %"op68297(vl77672)"
+; CHECK-NEXT:%"vl14659llvm.experimental.convergence.anchor()" = call token 
@llvm.experimental.convergence.anchor()
+; CHECK-NEXT:%"op15516(vl14659)" = call i32 
@llvm.amdgcn.readfirstlane.i32(i32 [[A0]]) [ "convergencectrl"(token 
%"vl14659llvm.experimental.convergence.anchor()") ]
+; CHECK-NEXT:ret i32 %"op15516(vl14659)"

arichardson wrote:

I believe this is because all the other instruction kind numbers after the 
casts changed to the overall hash value is different. I can do the same thing 
as the C API and allocate the next unused value but e.g. freeze didn't do this 
either.

https://github.com/llvm/llvm-project/pull/139357
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)

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


@@ -0,0 +1,14 @@
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s

arichardson wrote:

I copied this from another test so assumed there was a reason for it but not 
sure what that would be.

https://github.com/llvm/llvm-project/pull/139357
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [GISelValueTracking] Use representation size for G_PTRTOINT src width (PR #139608)

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

arichardson wrote:

Thanks for the review, I'll update this to use a new baseline test that does 
not depend on the new ptrtoaddr.

https://github.com/llvm/llvm-project/pull/139608
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] CodeGen: Fix implementation of __builtin_trivially_relocate. (PR #140312)

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

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

>From 1399ec4fdf8fe08000b590844f4e24c31a310a01 Mon Sep 17 00:00:00 2001
From: Peter Collingbourne 
Date: Wed, 21 May 2025 16:20:57 -0700
Subject: [PATCH] Add test with variable count

Created using spr 1.3.6-beta.1
---
 .../CodeGenCXX/cxx2c-trivially-relocatable.cpp | 14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/clang/test/CodeGenCXX/cxx2c-trivially-relocatable.cpp 
b/clang/test/CodeGenCXX/cxx2c-trivially-relocatable.cpp
index 63f3ba8e74ed5..465e539d363e8 100644
--- a/clang/test/CodeGenCXX/cxx2c-trivially-relocatable.cpp
+++ b/clang/test/CodeGenCXX/cxx2c-trivially-relocatable.cpp
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -std=c++26 -triple x86_64-linux-gnu -emit-llvm -o - %s | 
FileCheck %s
 
+typedef __SIZE_TYPE__ size_t;
+
 struct S trivially_relocatable_if_eligible {
 S(const S&);
 ~S();
@@ -8,9 +10,13 @@ struct S trivially_relocatable_if_eligible {
 };
 
 // CHECK: @_Z4testP1SS0_
-// CHECK: call void @llvm.memmove.p0.p0.i64({{.*}}, i64 8
-// CHECK-NOT: __builtin
-// CHECK: ret
-void test(S* source, S* dest) {
+void test(S* source, S* dest, size_t count) {
+// CHECK: call void @llvm.memmove.p0.p0.i64({{.*}}, i64 8
+// CHECK-NOT: __builtin
 __builtin_trivially_relocate(dest, source, 1);
+// CHECK: [[A:%.*]] = load i64, ptr %count.addr
+// CHECK: [[M:%.*]] = mul i64 [[A]], 8
+// CHECK: call void @llvm.memmove.p0.p0.i64({{.*}}, i64 [[M]]
+__builtin_trivially_relocate(dest, source, count);
+// CHECK: ret
 };

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] CodeGen: Fix implementation of __builtin_trivially_relocate. (PR #140312)

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


@@ -8,7 +8,7 @@ struct S trivially_relocatable_if_eligible {
 };
 
 // CHECK: @_Z4testP1SS0_
-// CHECK: call void @llvm.memmove.p0.p0.i64
+// CHECK: call void @llvm.memmove.p0.p0.i64({{.*}}, i64 8

pcc wrote:

Done

https://github.com/llvm/llvm-project/pull/140312
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] c5c50f0 - Revert "[llvm] add GenericFloatingPointPredicateUtils (#140254)"

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

Author: ronlieb
Date: 2025-05-21T19:30:12-04:00
New Revision: c5c50f0c35141a7d219d38a8196f19ec2ca6c433

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

LOG: Revert "[llvm] add GenericFloatingPointPredicateUtils (#140254)"

This reverts commit d00d74bb2564103ae3cb5ac6b6ffecf7e1cc2238.

Added: 


Modified: 
llvm/include/llvm/Analysis/ValueTracking.h
llvm/lib/Analysis/CMakeLists.txt
llvm/lib/Analysis/InstructionSimplify.cpp
llvm/lib/Analysis/ValueTracking.cpp
llvm/lib/CodeGen/CMakeLists.txt
llvm/lib/CodeGen/CodeGenPrepare.cpp
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/unittests/Analysis/ValueTrackingTest.cpp

Removed: 
llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
llvm/include/llvm/Analysis/FloatingPointPredicateUtils.h
llvm/include/llvm/CodeGen/MachineFloatingPointPredicateUtils.h
llvm/lib/Analysis/FloatingPointPredicateUtils.cpp
llvm/lib/CodeGen/MachineFloatingPointPredicateUtils.cpp



diff  --git a/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h 
b/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
deleted file mode 100644
index 49c5fe0aed6e1..0
--- a/llvm/include/llvm/ADT/GenericFloatingPointPredicateUtils.h
+++ /dev/null
@@ -1,479 +0,0 @@
-//===- llvm/Support/GenericFloatingPointPredicateUtils.h -*- 
C++-*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===--===//
-///
-/// \file
-/// Utilities for dealing with flags related to floating point properties and
-/// mode controls.
-///
-//===--===/
-
-#ifndef LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
-#define LLVM_ADT_GENERICFLOATINGPOINTPREDICATEUTILS_H
-
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/FloatingPointMode.h"
-#include "llvm/IR/Instructions.h"
-#include 
-
-namespace llvm {
-
-template  class GenericFloatingPointPredicateUtils {
-  using ValueRefT = typename ContextT::ValueRefT;
-  using FunctionT = typename ContextT::FunctionT;
-
-  constexpr static ValueRefT Invalid = {};
-
-private:
-  static DenormalMode queryDenormalMode(const FunctionT &F, ValueRefT Val);
-
-  static bool lookThroughFAbs(const FunctionT &F, ValueRefT LHS,
-  ValueRefT &Src);
-
-  static std::optional matchConstantFloat(const FunctionT &F,
-   ValueRefT Val);
-
-  /// Return the return value for fcmpImpliesClass for a compare that produces
-  /// an exact class test.
-  static std::tuple
-  exactClass(ValueRefT V, FPClassTest M) {
-return {V, M, ~M};
-  }
-
-public:
-  /// Returns a pair of values, which if passed to llvm.is.fpclass, returns the
-  /// same result as an fcmp with the given operands.
-  static std::pair
-  fcmpToClassTest(FCmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-  ValueRefT RHS, bool LookThroughSrc) {
-std::optional ConstRHS = matchConstantFloat(F, RHS);
-if (!ConstRHS)
-  return {Invalid, fcAllFlags};
-
-return fcmpToClassTest(Pred, F, LHS, *ConstRHS, LookThroughSrc);
-  }
-
-  static std::pair
-  fcmpToClassTest(FCmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-  const APFloat &ConstRHS, bool LookThroughSrc) {
-
-auto [Src, ClassIfTrue, ClassIfFalse] =
-fcmpImpliesClass(Pred, F, LHS, ConstRHS, LookThroughSrc);
-
-if (Src && ClassIfTrue == ~ClassIfFalse)
-  return {Src, ClassIfTrue};
-
-return {Invalid, fcAllFlags};
-  }
-
-  /// Compute the possible floating-point classes that \p LHS could be based on
-  /// fcmp \Pred \p LHS, \p RHS.
-  ///
-  /// \returns { TestedValue, ClassesIfTrue, ClassesIfFalse }
-  ///
-  /// If the compare returns an exact class test, ClassesIfTrue ==
-  /// ~ClassesIfFalse
-  ///
-  /// This is a less exact version of fcmpToClassTest (e.g. fcmpToClassTest 
will
-  /// only succeed for a test of x > 0 implies positive, but not x > 1).
-  ///
-  /// If \p LookThroughSrc is true, consider the input value when computing the
-  /// mask. This may look through sign bit operations.
-  ///
-  /// If \p LookThroughSrc is false, ignore the source value (i.e. the first
-  /// pair element will always be LHS.
-  ///
-  static std::tuple
-  fcmpImpliesClass(CmpInst::Predicate Pred, const FunctionT &F, ValueRefT LHS,
-   FPClassTest RHSClass, bool LookThroughSrc) {
-assert(RHSClass != fcNone);
-ValueRefT Src = LHS;
-
-if (Pred == FCmpInst::FCMP_TRUE)
-  return exactClass(Src,

[llvm-branch-commits] [clang] [KeyInstr] Complex assignment atoms (PR #134638)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams updated 
https://github.com/llvm/llvm-project/pull/134638

>From fd282a63fd709cdcdcdc2dacef58144dbf9b15c1 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Thu, 3 Apr 2025 13:36:59 +0100
Subject: [PATCH] [KeyInstr] Complex assignment atoms

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
 clang/lib/CodeGen/CGExprComplex.cpp   | 10 -
 .../test/DebugInfo/KeyInstructions/complex.c  | 40 +++
 2 files changed, 48 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/complex.c

diff --git a/clang/lib/CodeGen/CGExprComplex.cpp 
b/clang/lib/CodeGen/CGExprComplex.cpp
index f556594f4a9ec..600f61f1b325f 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -461,8 +461,12 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy 
Val, LValue lvalue,
   Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType());
   Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType());
 
-  Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
-  Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
+  auto *R =
+  Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
+  CGF.addInstToCurrentSourceAtom(R, Val.first);
+  auto *I =
+  Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
+  CGF.addInstToCurrentSourceAtom(I, Val.second);
 }
 
 
@@ -1209,6 +1213,7 @@ LValue ComplexExprEmitter::
 EmitCompoundAssignLValue(const CompoundAssignOperator *E,
   ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
  RValue &Val) {
+  ApplyAtomGroup Grp(CGF.getDebugInfo());
   TestAndClearIgnoreReal();
   TestAndClearIgnoreImag();
   QualType LHSTy = E->getLHS()->getType();
@@ -1356,6 +1361,7 @@ LValue ComplexExprEmitter::EmitBinAssignLValue(const 
BinaryOperator *E,
 }
 
 ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+  ApplyAtomGroup Grp(CGF.getDebugInfo());
   ComplexPairTy Val;
   LValue LV = EmitBinAssignLValue(E, Val);
 
diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c 
b/clang/test/DebugInfo/KeyInstructions/complex.c
new file mode 100644
index 0..b97314e815bdc
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/complex.c
@@ -0,0 +1,40 @@
+
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm 
-o - -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o 
- -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+_Complex float ci;
+void test() {
+// CHECK: %ci.real = load float, ptr @ci{{.*}}, !dbg [[G1R2:!.*]]
+// CHECK: %ci.imag = load float, ptr getelementptr inbounds nuw ({ float, 
float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G1R2]]
+// CHECK: store float %ci.real, ptr %lc.realp{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: store float %ci.imag, ptr %lc.imagp{{.*}}, !dbg [[G1R1]]
+  _Complex float lc = ci;
+
+// CHECK: %ci.real1 = load float, ptr @ci{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: %ci.imag2 = load float, ptr getelementptr inbounds nuw ({ float, 
float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G2R2]]
+// CHECK: store float %ci.real1, ptr @ci{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK: store float %ci.imag2, ptr getelementptr inbounds nuw ({ float, 
float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G2R1]]
+  ci = ci;
+
+// CHECK: %add.r = fadd float %ci.real5, %ci.real3, !dbg [[G3R2:!.*]]
+// CHECK: %add.i = fadd float %ci.imag6, %ci.imag4, !dbg [[G3R2]]
+// CHECK: store float %add.r, ptr @ci{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK: store float %add.i, ptr getelementptr inbounds nuw ({ float, float 
}, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G3R1]]
+  ci += ci;
+
+// CHECK: %add = fadd float %0, %1, !dbg [[G4R2:!.*]]
+// CHECK: store float %add, ptr getelementptr inbounds nuw ({ float, float }, 
ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G4R1:!.*]]
+  __imag ci = __imag ci + __imag ci;
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R2]] = !DILocation({{.*}}, atomGroup:

[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams updated 
https://github.com/llvm/llvm-project/pull/134637

>From 3b4ca1b09a659e575e022109fd8c607c9df3864f Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Wed, 2 Apr 2025 18:01:48 +0100
Subject: [PATCH 1/6] [KeyInstr][Clang] Assignment atom group

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
 clang/lib/CodeGen/CGExpr.cpp| 9 +
 clang/test/DebugInfo/KeyInstructions/assign.cpp | 9 +
 2 files changed, 18 insertions(+)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/assign.cpp

diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 1e426586620a2..9681fd9325fa7 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -5985,6 +5985,15 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const 
BinaryOperator *E) {
 
   assert(E->getOpcode() == BO_Assign && "unexpected binary l-value");
 
+  // This covers both LHS and RHS expressions, though nested RHS
+  // expressions may get subsequently separately grouped.
+  // FIXME(OCH): Not clear yet if we've got fine enough control
+  // to pick and choose when we need to. Currently looks ok:
+  // a = b = c  -> Two atoms.
+  // x = new(1) -> One atom (for both addr store and value store).
+  // Complex and agg assignment -> One atom.
+  ApplyAtomGroup Grp(getDebugInfo());
+
   // Note that in all of these cases, __block variables need the RHS
   // evaluated first just in case the variable gets moved by the RHS.
 
diff --git a/clang/test/DebugInfo/KeyInstructions/assign.cpp 
b/clang/test/DebugInfo/KeyInstructions/assign.cpp
new file mode 100644
index 0..b09137430156f
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/assign.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang -gkey-instructions %s -gmlt -gcolumn-info -S -emit-llvm -o - 
-Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+unsigned long long g;
+void fun() { g = 0; }
+
+// CHECK: store i64 0, ptr @g{{.*}}, !dbg [[G1R1:!.*]]
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)

>From b6274d2afefac7c4546ba5b295b01ce2a3fa74d9 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Wed, 2 Apr 2025 18:27:59 +0100
Subject: [PATCH 2/6] [KeyInstr][Clang] Multiple assignment  (x = y = z)

---
 clang/lib/CodeGen/CGExprScalar.cpp |  1 +
 .../test/DebugInfo/KeyInstructions/assign.cpp  | 18 --
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 5d618658bc615..1cc5c147c595b 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -5067,6 +5067,7 @@ llvm::Value 
*CodeGenFunction::EmitWithOriginalRHSBitfieldAssignment(
 }
 
 Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+  ApplyAtomGroup Grp(CGF.getDebugInfo());
   bool Ignore = TestAndClearIgnoreResultAssign();
 
   Value *RHS;
diff --git a/clang/test/DebugInfo/KeyInstructions/assign.cpp 
b/clang/test/DebugInfo/KeyInstructions/assign.cpp
index b09137430156f..d50062d21935b 100644
--- a/clang/test/DebugInfo/KeyInstructions/assign.cpp
+++ b/clang/test/DebugInfo/KeyInstructions/assign.cpp
@@ -2,8 +2,22 @@
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
 
 unsigned long long g;
-void fun() { g = 0; }
-
+void fun() {
 // CHECK: store i64 0, ptr @g{{.*}}, !dbg [[G1R1:!.*]]
+g = 0;
+
+// Treat the two assignments as two atoms.
+//
+// FIXME: Because of the atomGroup implementation the load can only be
+// associated with one of the two stores, despite being a good backup
+// loction for both.
+// CHECK-NEXT: %0 = load i64, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK-NEXT: store i64 %0, ptr @g{{.*}}, !dbg [[G2R1:!.*]]
+g = g = g;
+}
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)

>From 0ce86c40443015f1f84d7e75dc60cf3e6fe6f7fa Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Thu, 3 Apr 2025 11:05:29 +0100
Subject: [PATCH 3/6] Compound assign

---
 clang/lib/CodeGen/CGExprScalar.cpp|  2 ++
 .../DebugInfo/KeyInstructions/assign-scal

[llvm-branch-commits] [clang] [KeyInstr] Complex assignment atoms (PR #134638)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams updated 
https://github.com/llvm/llvm-project/pull/134638

>From fd282a63fd709cdcdcdc2dacef58144dbf9b15c1 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Thu, 3 Apr 2025 13:36:59 +0100
Subject: [PATCH 1/2] [KeyInstr] Complex assignment atoms

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
 clang/lib/CodeGen/CGExprComplex.cpp   | 10 -
 .../test/DebugInfo/KeyInstructions/complex.c  | 40 +++
 2 files changed, 48 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/complex.c

diff --git a/clang/lib/CodeGen/CGExprComplex.cpp 
b/clang/lib/CodeGen/CGExprComplex.cpp
index f556594f4a9ec..600f61f1b325f 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -461,8 +461,12 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy 
Val, LValue lvalue,
   Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType());
   Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType());
 
-  Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
-  Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
+  auto *R =
+  Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
+  CGF.addInstToCurrentSourceAtom(R, Val.first);
+  auto *I =
+  Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
+  CGF.addInstToCurrentSourceAtom(I, Val.second);
 }
 
 
@@ -1209,6 +1213,7 @@ LValue ComplexExprEmitter::
 EmitCompoundAssignLValue(const CompoundAssignOperator *E,
   ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
  RValue &Val) {
+  ApplyAtomGroup Grp(CGF.getDebugInfo());
   TestAndClearIgnoreReal();
   TestAndClearIgnoreImag();
   QualType LHSTy = E->getLHS()->getType();
@@ -1356,6 +1361,7 @@ LValue ComplexExprEmitter::EmitBinAssignLValue(const 
BinaryOperator *E,
 }
 
 ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+  ApplyAtomGroup Grp(CGF.getDebugInfo());
   ComplexPairTy Val;
   LValue LV = EmitBinAssignLValue(E, Val);
 
diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c 
b/clang/test/DebugInfo/KeyInstructions/complex.c
new file mode 100644
index 0..b97314e815bdc
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/complex.c
@@ -0,0 +1,40 @@
+
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm 
-o - -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o 
- -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+_Complex float ci;
+void test() {
+// CHECK: %ci.real = load float, ptr @ci{{.*}}, !dbg [[G1R2:!.*]]
+// CHECK: %ci.imag = load float, ptr getelementptr inbounds nuw ({ float, 
float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G1R2]]
+// CHECK: store float %ci.real, ptr %lc.realp{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: store float %ci.imag, ptr %lc.imagp{{.*}}, !dbg [[G1R1]]
+  _Complex float lc = ci;
+
+// CHECK: %ci.real1 = load float, ptr @ci{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: %ci.imag2 = load float, ptr getelementptr inbounds nuw ({ float, 
float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G2R2]]
+// CHECK: store float %ci.real1, ptr @ci{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK: store float %ci.imag2, ptr getelementptr inbounds nuw ({ float, 
float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G2R1]]
+  ci = ci;
+
+// CHECK: %add.r = fadd float %ci.real5, %ci.real3, !dbg [[G3R2:!.*]]
+// CHECK: %add.i = fadd float %ci.imag6, %ci.imag4, !dbg [[G3R2]]
+// CHECK: store float %add.r, ptr @ci{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK: store float %add.i, ptr getelementptr inbounds nuw ({ float, float 
}, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G3R1]]
+  ci += ci;
+
+// CHECK: %add = fadd float %0, %1, !dbg [[G4R2:!.*]]
+// CHECK: store float %add, ptr getelementptr inbounds nuw ({ float, float }, 
ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G4R1:!.*]]
+  __imag ci = __imag ci + __imag ci;
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R2]] = !DILocation({{.*}}, atomGr

[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams edited 
https://github.com/llvm/llvm-project/pull/134637
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [libclc] [libclc] Include isnan implementation for SPIR-V targets (PR #140902)

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

github-actions[bot] wrote:



Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this 
page.

If this is not working for you, it is probably because you do not have write 
permissions for the repository. In which case you can instead tag reviewers by 
name in a comment by using `@` followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a 
review by "ping"ing the PR by adding a comment “Ping”. The common courtesy 
"ping" rate is once a week. Please remember that you are asking for valuable 
time from other developers.

If you have further questions, they may be answered by the [LLVM GitHub User 
Guide](https://llvm.org/docs/GitHub.html).

You can also ask questions in a comment on this PR, on the [LLVM 
Discord](https://discord.com/invite/xS7Z362) or on the 
[forums](https://discourse.llvm.org/).

https://github.com/llvm/llvm-project/pull/140902
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr] Complex assignment atoms (PR #134638)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams updated 
https://github.com/llvm/llvm-project/pull/134638

>From fd282a63fd709cdcdcdc2dacef58144dbf9b15c1 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Thu, 3 Apr 2025 13:36:59 +0100
Subject: [PATCH 1/3] [KeyInstr] Complex assignment atoms

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
 clang/lib/CodeGen/CGExprComplex.cpp   | 10 -
 .../test/DebugInfo/KeyInstructions/complex.c  | 40 +++
 2 files changed, 48 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/complex.c

diff --git a/clang/lib/CodeGen/CGExprComplex.cpp 
b/clang/lib/CodeGen/CGExprComplex.cpp
index f556594f4a9ec..600f61f1b325f 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -461,8 +461,12 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy 
Val, LValue lvalue,
   Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType());
   Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType());
 
-  Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
-  Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
+  auto *R =
+  Builder.CreateStore(Val.first, RealPtr, lvalue.isVolatileQualified());
+  CGF.addInstToCurrentSourceAtom(R, Val.first);
+  auto *I =
+  Builder.CreateStore(Val.second, ImagPtr, lvalue.isVolatileQualified());
+  CGF.addInstToCurrentSourceAtom(I, Val.second);
 }
 
 
@@ -1209,6 +1213,7 @@ LValue ComplexExprEmitter::
 EmitCompoundAssignLValue(const CompoundAssignOperator *E,
   ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
  RValue &Val) {
+  ApplyAtomGroup Grp(CGF.getDebugInfo());
   TestAndClearIgnoreReal();
   TestAndClearIgnoreImag();
   QualType LHSTy = E->getLHS()->getType();
@@ -1356,6 +1361,7 @@ LValue ComplexExprEmitter::EmitBinAssignLValue(const 
BinaryOperator *E,
 }
 
 ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+  ApplyAtomGroup Grp(CGF.getDebugInfo());
   ComplexPairTy Val;
   LValue LV = EmitBinAssignLValue(E, Val);
 
diff --git a/clang/test/DebugInfo/KeyInstructions/complex.c 
b/clang/test/DebugInfo/KeyInstructions/complex.c
new file mode 100644
index 0..b97314e815bdc
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/complex.c
@@ -0,0 +1,40 @@
+
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gcolumn-info -S -emit-llvm 
-o - -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gcolumn-info -S -emit-llvm -o 
- -Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+_Complex float ci;
+void test() {
+// CHECK: %ci.real = load float, ptr @ci{{.*}}, !dbg [[G1R2:!.*]]
+// CHECK: %ci.imag = load float, ptr getelementptr inbounds nuw ({ float, 
float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G1R2]]
+// CHECK: store float %ci.real, ptr %lc.realp{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: store float %ci.imag, ptr %lc.imagp{{.*}}, !dbg [[G1R1]]
+  _Complex float lc = ci;
+
+// CHECK: %ci.real1 = load float, ptr @ci{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: %ci.imag2 = load float, ptr getelementptr inbounds nuw ({ float, 
float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G2R2]]
+// CHECK: store float %ci.real1, ptr @ci{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK: store float %ci.imag2, ptr getelementptr inbounds nuw ({ float, 
float }, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G2R1]]
+  ci = ci;
+
+// CHECK: %add.r = fadd float %ci.real5, %ci.real3, !dbg [[G3R2:!.*]]
+// CHECK: %add.i = fadd float %ci.imag6, %ci.imag4, !dbg [[G3R2]]
+// CHECK: store float %add.r, ptr @ci{{.*}}, !dbg [[G3R1:!.*]]
+// CHECK: store float %add.i, ptr getelementptr inbounds nuw ({ float, float 
}, ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G3R1]]
+  ci += ci;
+
+// CHECK: %add = fadd float %0, %1, !dbg [[G4R2:!.*]]
+// CHECK: store float %add, ptr getelementptr inbounds nuw ({ float, float }, 
ptr @ci, i32 0, i32 1){{.*}}, !dbg [[G4R1:!.*]]
+  __imag ci = __imag ci + __imag ci;
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R2]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 2)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R2]] = !DILocation({{.*}}, atomGr

[llvm-branch-commits] [libclc] [libclc] Include isnan implementation for SPIR-V targets (PR #140902)

2025-05-21 Thread Karol Herbst via llvm-branch-commits

https://github.com/karolherbst updated 
https://github.com/llvm/llvm-project/pull/140902

>From d8ad1f550cf4c32bc07f11a911d0dd7f54d2ba28 Mon Sep 17 00:00:00 2001
From: Karol Herbst 
Date: Wed, 21 May 2025 15:57:38 +0200
Subject: [PATCH] [libclc] Include isnan implementation for SPIR-V targets

The fma software emulation requires it.

Similar to https://github.com/llvm/llvm-project/pull/124614
---
 libclc/spirv/lib/SOURCES   | 1 +
 libclc/spirv64/lib/SOURCES | 1 +
 2 files changed, 2 insertions(+)

diff --git a/libclc/spirv/lib/SOURCES b/libclc/spirv/lib/SOURCES
index 854cba614c8bf..2566620161f93 100644
--- a/libclc/spirv/lib/SOURCES
+++ b/libclc/spirv/lib/SOURCES
@@ -86,5 +86,6 @@ math/fma.cl
 ../../generic/lib/math/clc_tanpi.cl
 ../../generic/lib/math/tanpi.cl
 ../../generic/lib/math/tgamma.cl
+../../generic/lib/relational/isnan.cl
 ../../generic/lib/shared/vload.cl
 ../../generic/lib/shared/vstore.cl
diff --git a/libclc/spirv64/lib/SOURCES b/libclc/spirv64/lib/SOURCES
index 854cba614c8bf..2566620161f93 100644
--- a/libclc/spirv64/lib/SOURCES
+++ b/libclc/spirv64/lib/SOURCES
@@ -86,5 +86,6 @@ math/fma.cl
 ../../generic/lib/math/clc_tanpi.cl
 ../../generic/lib/math/tanpi.cl
 ../../generic/lib/math/tgamma.cl
+../../generic/lib/relational/isnan.cl
 ../../generic/lib/shared/vload.cl
 ../../generic/lib/shared/vstore.cl

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [libclc] release/20.x: [libclc] Include isnan implementation for SPIR-V targets (PR #140902)

2025-05-21 Thread Karol Herbst via llvm-branch-commits

https://github.com/karolherbst edited 
https://github.com/llvm/llvm-project/pull/140902
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/20.x: [clang-format] Fix the indent of StartOfName after Attr… (PR #141004)

2025-05-21 Thread Owen Pan via llvm-branch-commits

https://github.com/owenca created 
https://github.com/llvm/llvm-project/pull/141004

…ibuteMacro (#140361)

Backport 0cac25bcf5a246eb8a1f02d5041731ae9a6f00e0

>From b05983ec62a831de375e96f9ddb9e87e8043049d Mon Sep 17 00:00:00 2001
From: Owen Pan 
Date: Wed, 21 May 2025 21:37:54 -0700
Subject: [PATCH] release/20.x: [clang-format] Fix the indent of StartOfName
 after AttributeMacro (#140361)

Backport 0cac25bcf5a246eb8a1f02d5041731ae9a6f00e0
---
 clang/lib/Format/ContinuationIndenter.cpp | 4 +++-
 clang/unittests/Format/FormatTest.cpp | 7 +++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Format/ContinuationIndenter.cpp 
b/clang/lib/Format/ContinuationIndenter.cpp
index 6f7d213c0b559..d953348b0258d 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -1452,7 +1452,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const 
LineState &State) {
(PreviousNonComment->ClosesTemplateDeclaration ||
 PreviousNonComment->ClosesRequiresClause ||
 (PreviousNonComment->is(TT_AttributeMacro) &&
- Current.isNot(tok::l_paren)) ||
+ Current.isNot(tok::l_paren) &&
+ !Current.endsSequence(TT_StartOfName, TT_AttributeMacro,
+   TT_PointerOrReference)) ||
 PreviousNonComment->isOneOf(
 TT_AttributeRParen, TT_AttributeSquare, 
TT_FunctionAnnotationRParen,
 TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 90a79230e9f4c..1afcc75a2e19e 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -12419,6 +12419,13 @@ TEST_F(FormatTest, UnderstandsAttributes) {
   verifyFormat("SomeType s __unused{InitValue};", CustomAttrs);
   verifyFormat("SomeType *__capability s(InitValue);", CustomAttrs);
   verifyFormat("SomeType *__capability s{InitValue};", CustomAttrs);
+
+  auto Style = getLLVMStyleWithColumns(60);
+  Style.AttributeMacros.push_back("my_fancy_attr");
+  Style.PointerAlignment = FormatStyle::PAS_Left;
+  verifyFormat("void foo(const MyLongTypeName* my_fancy_attr\n"
+   " testt);",
+   Style);
 }
 
 TEST_F(FormatTest, UnderstandsPointerQualifiersInCast) {

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/20.x: [clang-format] Fix the indent of StartOfName after Attr… (PR #141004)

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

llvmbot wrote:




@llvm/pr-subscribers-clang-format

Author: Owen Pan (owenca)


Changes

…ibuteMacro (#140361)

Backport 0cac25bcf5a246eb8a1f02d5041731ae9a6f00e0

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


2 Files Affected:

- (modified) clang/lib/Format/ContinuationIndenter.cpp (+3-1) 
- (modified) clang/unittests/Format/FormatTest.cpp (+7) 


``diff
diff --git a/clang/lib/Format/ContinuationIndenter.cpp 
b/clang/lib/Format/ContinuationIndenter.cpp
index 6f7d213c0b559..d953348b0258d 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -1452,7 +1452,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const 
LineState &State) {
(PreviousNonComment->ClosesTemplateDeclaration ||
 PreviousNonComment->ClosesRequiresClause ||
 (PreviousNonComment->is(TT_AttributeMacro) &&
- Current.isNot(tok::l_paren)) ||
+ Current.isNot(tok::l_paren) &&
+ !Current.endsSequence(TT_StartOfName, TT_AttributeMacro,
+   TT_PointerOrReference)) ||
 PreviousNonComment->isOneOf(
 TT_AttributeRParen, TT_AttributeSquare, 
TT_FunctionAnnotationRParen,
 TT_JavaAnnotation, TT_LeadingJavaAnnotation))) ||
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index 90a79230e9f4c..1afcc75a2e19e 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -12419,6 +12419,13 @@ TEST_F(FormatTest, UnderstandsAttributes) {
   verifyFormat("SomeType s __unused{InitValue};", CustomAttrs);
   verifyFormat("SomeType *__capability s(InitValue);", CustomAttrs);
   verifyFormat("SomeType *__capability s{InitValue};", CustomAttrs);
+
+  auto Style = getLLVMStyleWithColumns(60);
+  Style.AttributeMacros.push_back("my_fancy_attr");
+  Style.PointerAlignment = FormatStyle::PAS_Left;
+  verifyFormat("void foo(const MyLongTypeName* my_fancy_attr\n"
+   " testt);",
+   Style);
 }
 
 TEST_F(FormatTest, UnderstandsPointerQualifiersInCast) {

``




https://github.com/llvm/llvm-project/pull/141004
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/20.x: [clang-format] Fix the indent of StartOfName after Attr… (PR #141004)

2025-05-21 Thread Owen Pan via llvm-branch-commits

https://github.com/owenca milestoned 
https://github.com/llvm/llvm-project/pull/141004
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/20.x: [clang-format] Handle raw string literals containing JSON code (#140666) (PR #141002)

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

https://github.com/llvmbot milestoned 
https://github.com/llvm/llvm-project/pull/141002
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/20.x: [clang-format] Handle raw string literals containing JSON code (#140666) (PR #141002)

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

https://github.com/llvmbot created 
https://github.com/llvm/llvm-project/pull/141002

Backport 0dfdf7efbfe347517eb4c7f544043a71af4e4a25

Requested by: @owenca

>From 3d02c7ce3c8b4c397c3237ed3d5069c829a1808e Mon Sep 17 00:00:00 2001
From: Owen Pan 
Date: Tue, 20 May 2025 19:15:57 -0700
Subject: [PATCH] [clang-format] Handle raw string literals containing JSON
 code (#140666)

Fix #65400

(cherry picked from commit 0dfdf7efbfe347517eb4c7f544043a71af4e4a25)
---
 clang/lib/Format/Format.cpp   |  6 +++--
 clang/tools/clang-format/ClangFormat.cpp  |  4 ++--
 .../unittests/Format/FormatTestRawStrings.cpp | 22 +++
 3 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index b97d8928178b5..aba7db6dd50a8 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -3743,8 +3743,10 @@ reformat(const FormatStyle &Style, StringRef Code,
 tooling::Replacements Replaces =
 Formatter(*Env, Style, Status).process().first;
 // add a replacement to remove the "x = " from the result.
-Replaces = Replaces.merge(
-tooling::Replacements(tooling::Replacement(FileName, 0, 4, "")));
+if (Code.starts_with("x = ")) {
+  Replaces = Replaces.merge(
+  tooling::Replacements(tooling::Replacement(FileName, 0, 4, "")));
+}
 // apply the reformatting changes and the removal of "x = ".
 if (applyAllReplacements(Code, Replaces))
   return {Replaces, 0};
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index 28610052b9b74..96eec7c666a38 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -492,8 +492,8 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // To format JSON insert a variable to trick the code into thinking its
   // JavaScript.
   if (IsJson && !FormatStyle->DisableFormat) {
-auto Err = Replaces.add(tooling::Replacement(
-tooling::Replacement(AssumedFileName, 0, 0, "x = ")));
+auto Err =
+Replaces.add(tooling::Replacement(AssumedFileName, 0, 0, "x = "));
 if (Err)
   llvm::errs() << "Bad Json variable insertion\n";
   }
diff --git a/clang/unittests/Format/FormatTestRawStrings.cpp 
b/clang/unittests/Format/FormatTestRawStrings.cpp
index 0615fb1fad4c5..3f09c7b6086e5 100644
--- a/clang/unittests/Format/FormatTestRawStrings.cpp
+++ b/clang/unittests/Format/FormatTestRawStrings.cpp
@@ -988,6 +988,28 @@ f("aa",
   )pb");)test",
Style));
 }
+
+TEST_F(FormatTestRawStrings, Json) {
+  auto Style = getLLVMStyle();
+  Style.RawStringFormats = {
+  {
+  /*Language=*/FormatStyle::LK_Json,
+  /*Delimiters=*/{"json"},
+  /*EnclosingFunctions=*/{},
+  /*CanonicalDelimiter=*/"",
+  /*BasedOnStyle=*/"llvm",
+  },
+  };
+
+  EXPECT_EQ("json = R\"json({\n"
+"\"str\": \"test\"\n"
+"  })json\";",
+format("json = R\"json({\n"
+   "  \"str\": \"test\"\n"
+   "})json\";",
+   Style));
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/20.x: [clang-format] Handle raw string literals containing JSON code (#140666) (PR #141002)

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

llvmbot wrote:

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

https://github.com/llvm/llvm-project/pull/141002
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/20.x: [clang-format] Handle raw string literals containing JSON code (#140666) (PR #141002)

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

llvmbot wrote:




@llvm/pr-subscribers-clang-format

Author: None (llvmbot)


Changes

Backport 0dfdf7efbfe347517eb4c7f544043a71af4e4a25

Requested by: @owenca

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


3 Files Affected:

- (modified) clang/lib/Format/Format.cpp (+4-2) 
- (modified) clang/tools/clang-format/ClangFormat.cpp (+2-2) 
- (modified) clang/unittests/Format/FormatTestRawStrings.cpp (+22) 


``diff
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index b97d8928178b5..aba7db6dd50a8 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -3743,8 +3743,10 @@ reformat(const FormatStyle &Style, StringRef Code,
 tooling::Replacements Replaces =
 Formatter(*Env, Style, Status).process().first;
 // add a replacement to remove the "x = " from the result.
-Replaces = Replaces.merge(
-tooling::Replacements(tooling::Replacement(FileName, 0, 4, "")));
+if (Code.starts_with("x = ")) {
+  Replaces = Replaces.merge(
+  tooling::Replacements(tooling::Replacement(FileName, 0, 4, "")));
+}
 // apply the reformatting changes and the removal of "x = ".
 if (applyAllReplacements(Code, Replaces))
   return {Replaces, 0};
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index 28610052b9b74..96eec7c666a38 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -492,8 +492,8 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   // To format JSON insert a variable to trick the code into thinking its
   // JavaScript.
   if (IsJson && !FormatStyle->DisableFormat) {
-auto Err = Replaces.add(tooling::Replacement(
-tooling::Replacement(AssumedFileName, 0, 0, "x = ")));
+auto Err =
+Replaces.add(tooling::Replacement(AssumedFileName, 0, 0, "x = "));
 if (Err)
   llvm::errs() << "Bad Json variable insertion\n";
   }
diff --git a/clang/unittests/Format/FormatTestRawStrings.cpp 
b/clang/unittests/Format/FormatTestRawStrings.cpp
index 0615fb1fad4c5..3f09c7b6086e5 100644
--- a/clang/unittests/Format/FormatTestRawStrings.cpp
+++ b/clang/unittests/Format/FormatTestRawStrings.cpp
@@ -988,6 +988,28 @@ f("aa",
   )pb");)test",
Style));
 }
+
+TEST_F(FormatTestRawStrings, Json) {
+  auto Style = getLLVMStyle();
+  Style.RawStringFormats = {
+  {
+  /*Language=*/FormatStyle::LK_Json,
+  /*Delimiters=*/{"json"},
+  /*EnclosingFunctions=*/{},
+  /*CanonicalDelimiter=*/"",
+  /*BasedOnStyle=*/"llvm",
+  },
+  };
+
+  EXPECT_EQ("json = R\"json({\n"
+"\"str\": \"test\"\n"
+"  })json\";",
+format("json = R\"json({\n"
+   "  \"str\": \"test\"\n"
+   "})json\";",
+   Style));
+}
+
 } // end namespace
 } // end namespace format
 } // end namespace clang

``




https://github.com/llvm/llvm-project/pull/141002
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [HLSL][RootSignature] Implement validation of resource ranges for `RootDescriptors` (PR #140962)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic updated 
https://github.com/llvm/llvm-project/pull/140962

>From bcc056ea5c753c3b1fa83d214c6bd14e90d9ee25 Mon Sep 17 00:00:00 2001
From: Finn Plummer 
Date: Wed, 21 May 2025 00:12:04 +
Subject: [PATCH] [HLSL][RootSignature] Plug into the thing

---
 .../clang/Basic/DiagnosticSemaKinds.td|   5 +
 clang/include/clang/Sema/SemaHLSL.h   |   2 +
 clang/lib/Sema/SemaHLSL.cpp   | 105 ++
 .../RootSignature-resource-ranges-err.hlsl|  26 +
 .../RootSignature-resource-ranges.hlsl|  22 
 .../llvm/Frontend/HLSL/HLSLRootSignature.h|   9 +-
 llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp  |   2 +
 7 files changed, 169 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/SemaHLSL/RootSignature-resource-ranges-err.hlsl
 create mode 100644 clang/test/SemaHLSL/RootSignature-resource-ranges.hlsl

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f0bd5a1174020..b1026e733ec37 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12967,6 +12967,11 @@ def err_hlsl_expect_arg_const_int_one_or_neg_one: 
Error<
 def err_invalid_hlsl_resource_type: Error<
   "invalid __hlsl_resource_t type attributes">;
 
+def err_hlsl_resource_range_overlap: Error<
+  "resource ranges %select{t|u|b|s}0[%1;%2] and %select{t|u|b|s}3[%4;%5] "
+  "overlap within space = %6 and visibility = "
+  "%select{All|Vertex|Hull|Domain|Geometry|Pixel|Amplification|Mesh}7">;
+
 // Layout randomization diagnostics.
 def err_non_designated_init_used : Error<
   "a randomized struct can only be initialized with a designated initializer">;
diff --git a/clang/include/clang/Sema/SemaHLSL.h 
b/clang/include/clang/Sema/SemaHLSL.h
index 15182bb27bbdf..a161236d8baa0 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -119,6 +119,8 @@ class SemaHLSL : public SemaBase {
bool IsCompAssign);
   void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc);
 
+  // Returns true when D is invalid and a diagnostic was produced
+  bool handleRootSignatureDecl(HLSLRootSignatureDecl *D, SourceLocation Loc);
   void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL);
   void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
   void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL);
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index e6daa67fcee95..e46cca89db5a4 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -39,6 +39,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/DXILABI.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -951,6 +952,108 @@ void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr 
*RHS,
   << NewFnName << FixItHint::CreateReplacement(FullRange, OS.str());
 }
 
+namespace {
+
+// A resource range overlaps with another resource range if they have:
+// - equivalent ResourceClass (SRV, UAV, CBuffer, Sampler)
+// - equivalent resource space
+// - overlapping visbility
+class ResourceRanges {
+public:
+  // KeyT: 32-lsb denotes resource space, and 32-msb denotes resource type enum
+  using KeyT = uint64_t;
+
+  static const unsigned NumVisEnums =
+  (unsigned)llvm::hlsl::rootsig::ShaderVisibility::NumEnums;
+
+private:
+  llvm::hlsl::rootsig::ResourceRange::IMap::Allocator Allocator;
+
+  // Denotes a mapping of a unique combination of ResourceClass and register
+  // space to a ResourceRange
+  using MapT = llvm::SmallDenseMap;
+
+  // Denotes a mapping for each unique visibility
+  MapT RangeMaps[NumVisEnums];
+
+  constexpr static KeyT getKey(const llvm::hlsl::rootsig::RangeInfo &Info) {
+uint64_t SpacePacked = (uint64_t)Info.Space;
+uint64_t ClassPacked = (uint64_t)llvm::to_underlying(Info.Class);
+return (ClassPacked << 32) | SpacePacked;
+  }
+
+public:
+  // Returns std::nullopt if there was no collision. Otherwise, it will
+  // return the RangeInfo of the collision
+  std::optional
+  addRange(const llvm::hlsl::rootsig::RangeInfo &Info) {
+MapT &VisRangeMap = RangeMaps[llvm::to_underlying(Info.Vis)];
+auto [It, _] = VisRangeMap.insert(
+{getKey(Info), llvm::hlsl::rootsig::ResourceRange(Allocator)});
+auto Res = It->second.insert(Info);
+if (Res.has_value())
+  return Res;
+
+MutableArrayRef Maps =
+Info.Vis == llvm::hlsl::rootsig::ShaderVisibility::All
+? MutableArrayRef{RangeMaps}.drop_front()
+: MutableArrayRef{RangeMaps}.take_front();
+
+for (MapT &CurMap : Maps) {
+  auto CurIt = CurMap.find(getKey(Info));
+  if (CurIt != CurMap.end())
+if (auto Overlapping = CurIt->second.getOverlapping(Info))
+

[llvm-branch-commits] [llvm] [HLSL][RootSignature] Implement `ResourceRange` as an `IntervalMap` (PR #140957)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic created 
https://github.com/llvm/llvm-project/pull/140957

A resource range consists of a closed interval, `[a;b]`, denoting which shader 
registers it is bound to.

For instance:
 - `CBV(b1)`  corresponds to the resource range of `[1;1]`
 - `CBV(b0, numDescriptors = 3)` likewise to `[0;2]`

We want to provide an error diagnostic that there is an overlap in the required 
registers for each of the resources (an overlap in the resource ranges). 

The goal of this pr is to implement a structure to model a set of resource 
ranges and provide an api to detect any overlap over a set of resource ranges.

`ResourceRange` models this by implementing an `IntervalMap` to denote a 
mapping from an interval of registers back to a resource range. It allows for a 
new `ResourceRange` to be added to the mapping and it will report the first 
overlap that it denotes.

- Implements `ResourceRange` as an `IntervalMap`
- Adds unit testing of the various `insert` scenarios

Note: it was also considered to implement this as an `IntervalTree`, this would 
allow reporting of a diagnostic for each overlap that is encountered, as 
opposed to just the first. However, error generation of just reporting the 
first error is already rather verbose, and adding the additional diagnostics 
only made this worse.

Part 1 of https://github.com/llvm/llvm-project/issues/129942

>From a3240de319d3ef455b5db83b66b5bd601cecc0b3 Mon Sep 17 00:00:00 2001
From: Finn Plummer 
Date: Tue, 20 May 2025 19:47:29 +
Subject: [PATCH] [HLSL][RootSignature] Implement resource register validation

---
 .../llvm/Frontend/HLSL/HLSLRootSignature.h|  56 ++
 llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp  |  61 ++
 llvm/unittests/Frontend/CMakeLists.txt|   1 +
 .../Frontend/HLSLRootSignatureRangesTest.cpp  | 177 ++
 4 files changed, 295 insertions(+)
 create mode 100644 llvm/unittests/Frontend/HLSLRootSignatureRangesTest.cpp

diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h 
b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
index 98fa5f09429e3..3e5054566052b 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -15,6 +15,7 @@
 #define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntervalMap.h"
 #include "llvm/Support/DXILABI.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
@@ -198,6 +199,61 @@ class MetadataBuilder {
   SmallVector GeneratedMetadata;
 };
 
+// RangeInfo holds the information to correctly construct a ResourceRange
+// and retains this information to be used for displaying a better diagnostic
+struct RangeInfo {
+  const static uint32_t Unbounded = static_cast(-1);
+
+  uint32_t LowerBound;
+  uint32_t UpperBound;
+};
+
+class ResourceRange {
+public:
+  using IMap = llvm::IntervalMap>;
+
+private:
+  IMap Intervals;
+
+public:
+  ResourceRange(IMap::Allocator &Allocator) : Intervals(IMap(Allocator)) {}
+
+  // Returns a reference to the first RangeInfo that overlaps with
+  // [Info.LowerBound;Info.UpperBound], or, std::nullopt if there is no overlap
+  std::optional getOverlapping(const RangeInfo &Info) const;
+
+  // Return the mapped RangeInfo at X or nullptr if no mapping exists
+  const RangeInfo *lookup(uint32_t X) const;
+
+  // Insert the required (sub-)intervals such that the interval of [a;b] =
+  // [Info.LowerBound, Info.UpperBound] is covered and points to a valid
+  // RangeInfo &.
+  //
+  // For instance consider the following chain of inserting RangeInfos with the
+  // intervals denoting the Lower/Upper-bounds:
+  //
+  // A = [0;2]
+  //   insert(A) -> false
+  //   intervals: [0;2] -> &A
+  // B = [5;7]
+  //   insert(B) -> false
+  //   intervals: [0;2] -> &A, [5;7] -> &B
+  // C = [4;7]
+  //   insert(C) -> true
+  //   intervals: [0;2] -> &A, [4;7] -> &C
+  // D = [1;5]
+  //   insert(D) -> true
+  //   intervals: [0;2] -> &A, [3;3] -> &D, [4;7] -> &C
+  // E = [0;unbounded]
+  //   insert(E) -> true
+  //   intervals: [0;unbounded] -> E
+  //
+  // Returns if the first overlapping range when inserting
+  // (same return as getOverlapping)
+  std::optional insert(const RangeInfo &Info);
+};
+
 } // namespace rootsig
 } // namespace hlsl
 } // namespace llvm
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp 
b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
index abf076944b273..76fe09e4dc3ee 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -222,6 +222,67 @@ MDNode *MetadataBuilder::BuildDescriptorTableClause(
});
 }
 
+std::optional
+ResourceRange::getOverlapping(const RangeInfo &Info) const {
+  IMap::const_iterator Interval = Intervals.find(Info.LowerBound);
+  if (!Interval.valid() || Info.UpperBound < Interval.start())
+return std::nullopt;
+  return Interval.value();
+}
+
+const RangeInfo *ResourceRange::lookup(uint32_t X) const {
+  retu

[llvm-branch-commits] [llvm] [SPARC] Use op-then-halve instructions when we have VIS3 (PR #135718)

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

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


https://github.com/llvm/llvm-project/pull/135718
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [HLSL][RootSignature] Implement `ResourceRange` as an `IntervalMap` (PR #140957)

2025-05-21 Thread Finn Plummer via llvm-branch-commits

https://github.com/inbelic edited 
https://github.com/llvm/llvm-project/pull/140957
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)

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


@@ -0,0 +1,66 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs < %s -o - | 
FileCheck %s --check-prefix=CHECK

arsenm wrote:

```suggestion
; RUN: llc -mtriple=x86_64-linux-gnu < %s -o - | FileCheck %s 
--check-prefix=CHECK
```

https://github.com/llvm/llvm-project/pull/139357
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)

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


@@ -110,6 +110,7 @@ typedef enum {
   LLVMFPTrunc= 37,
   LLVMFPExt  = 38,
   LLVMPtrToInt   = 39,
+  LLVMPtrToAddr  = 69,

arsenm wrote:

I think it would be less confusing to keep these sorted by enum values but I 
see that's been broken for the last few new instructions (or maybe just freeze?)

https://github.com/llvm/llvm-project/pull/139357
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)

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


@@ -0,0 +1,66 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64-linux-gnu -verify-machineinstrs < %s -o - | 
FileCheck %s --check-prefix=CHECK
+
+define i1 @ptrtoaddr_1(ptr %p) {
+; CHECK-LABEL: ptrtoaddr_1:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:movq %rdi, %rax
+; CHECK-NEXT:xorb $1, %al
+; CHECK-NEXT:# kill: def $al killed $al killed $rax
+; CHECK-NEXT:retq
+entry:
+  %addr = ptrtoaddr ptr %p to i1
+  %ret = xor i1 %addr, 1
+  ret i1 %ret
+}
+
+define i8 @ptrtoaddr_8(ptr %p) {
+; CHECK-LABEL: ptrtoaddr_8:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:movq %rdi, %rax
+; CHECK-NEXT:notb %al
+; CHECK-NEXT:# kill: def $al killed $al killed $rax
+; CHECK-NEXT:retq
+entry:
+  %addr = ptrtoaddr ptr %p to i8
+  %ret = xor i8 %addr, -1
+  ret i8 %ret
+}
+
+define i16 @ptrtoaddr_16(ptr %p) {
+; CHECK-LABEL: ptrtoaddr_16:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:movq %rdi, %rax
+; CHECK-NEXT:notl %eax
+; CHECK-NEXT:# kill: def $ax killed $ax killed $rax
+; CHECK-NEXT:retq
+entry:
+  %addr = ptrtoaddr ptr %p to i16
+  %ret = xor i16 %addr, -1
+  ret i16 %ret
+}
+
+define i32 @ptrtoaddr_s32_p0(ptr %p) {
+; CHECK-LABEL: ptrtoaddr_s32_p0:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:movq %rdi, %rax
+; CHECK-NEXT:notl %eax
+; CHECK-NEXT:# kill: def $eax killed $eax killed $rax
+; CHECK-NEXT:retq
+entry:
+  %addr = ptrtoaddr ptr %p to i32
+  %ret = xor i32 %addr, -1
+  ret i32 %ret
+}
+
+define i64 @ptrtoaddr_s64_p0(ptr %p) {
+; CHECK-LABEL: ptrtoaddr_s64_p0:
+; CHECK:   # %bb.0: # %entry
+; CHECK-NEXT:movq %rdi, %rax
+; CHECK-NEXT:notq %rax
+; CHECK-NEXT:retq
+entry:
+  %addr = ptrtoaddr ptr %p to i64
+  %ret = xor i64 %addr, -1
+  ret i64 %ret
+}

arsenm wrote:

Test to an integer > 64? 

https://github.com/llvm/llvm-project/pull/139357
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)

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


@@ -0,0 +1,6 @@
+; RUN: not llvm-as < %s 2>&1 | FileCheck %s

arsenm wrote:

```suggestion
; RUN: not llvm-as --disable-output %s 2>&1 | FileCheck %s
```

https://github.com/llvm/llvm-project/pull/139357
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)

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


@@ -0,0 +1,14 @@
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s

arsenm wrote:

Does it really need to do 2 round trips? I don't think other bitcode tests do 
this? 

https://github.com/llvm/llvm-project/pull/139357
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)

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


@@ -0,0 +1,66 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s 
-o - | FileCheck %s --check-prefix=CHECK

arsenm wrote:

```suggestion
; RUN: llc -mtriple=x86_64-linux-gnu -global-isel < %s -o - | FileCheck %s 
--check-prefix=CHECK
```

https://github.com/llvm/llvm-project/pull/139357
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [clang] callee_type metadata for indirect calls (PR #117036)

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


@@ -2869,9 +2870,23 @@ static void setLinkageForGV(llvm::GlobalValue *GV, const 
NamedDecl *ND) {
 GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
 }
 
+static bool hasExistingGeneralizedTypeMD(llvm::Function *F) {
+  llvm::MDNode *MD = F->getMetadata(llvm::LLVMContext::MD_type);
+  if (!MD)
+return false;
+  return MD->hasGeneralizedMDString();
+}
+
 void CodeGenModule::createFunctionTypeMetadataForIcall(const FunctionDecl *FD,
llvm::Function *F) {
-  // Only if we are checking indirect calls.
+  if (CodeGenOpts.CallGraphSection && !hasExistingGeneralizedTypeMD(F) &&
+  (!F->hasLocalLinkage() ||
+   F->getFunction().hasAddressTaken(nullptr, /*IgnoreCallbackUses=*/true,
+/*IgnoreAssumeLikeCalls=*/true,
+/*IgnoreLLVMUsed=*/false)))
+F->addTypeMetadata(0, CreateMetadataIdentifierGeneralized(FD->getType()));

arsenm wrote:

Relying on the IR function properties feels wrong here, can you detect whether 
this is indirect from the source context? I'm also not sure IgnoreCallbackUses 
is correct here (IgnoreAssumeLikeCalls is also potentially questionable) 

https://github.com/llvm/llvm-project/pull/117036
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [IR] Introduce the `ptrtoaddr` instruction (PR #139357)

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


@@ -7,9 +7,9 @@ define i32 @nested(i32 %src) #0 {
 ; CHECK-SAME: i32 [[A0:%.*]]) #[[ATTR0:[0-9]+]] {
 ; CHECK-NEXT:  [[BB15160:.*:]]
 ; CHECK-NEXT:[[T1:%.*]] = call token @llvm.experimental.convergence.entry()
-; CHECK-NEXT:%"vl77672llvm.experimental.convergence.anchor()" = call token 
@llvm.experimental.convergence.anchor()
-; CHECK-NEXT:%"op68297(vl77672)" = call i32 
@llvm.amdgcn.readfirstlane.i32(i32 [[A0]]) [ "convergencectrl"(token 
%"vl77672llvm.experimental.convergence.anchor()") ]
-; CHECK-NEXT:ret i32 %"op68297(vl77672)"
+; CHECK-NEXT:%"vl14659llvm.experimental.convergence.anchor()" = call token 
@llvm.experimental.convergence.anchor()
+; CHECK-NEXT:%"op15516(vl14659)" = call i32 
@llvm.amdgcn.readfirstlane.i32(i32 [[A0]]) [ "convergencectrl"(token 
%"vl14659llvm.experimental.convergence.anchor()") ]
+; CHECK-NEXT:ret i32 %"op15516(vl14659)"

arsenm wrote:

Not sure why this changed 

https://github.com/llvm/llvm-project/pull/139357
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [llvm] Introduce callee_type metadata (PR #87573)

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


@@ -0,0 +1,30 @@
+;; Test if the callee_type metadata attached to indirect call sites adhere to 
the expected format.
+
+; RUN: not opt -passes=verify < %s 2>&1 | FileCheck %s
+define i32 @_Z13call_indirectPFicEc(ptr %func, i8 signext %x) !type !0 {
+entry:
+  %func.addr = alloca ptr, align 8
+  %x.addr = alloca i8, align 1
+  store ptr %func, ptr %func.addr, align 8
+  store i8 %x, ptr %x.addr, align 1
+  %fptr = load ptr, ptr %func.addr, align 8
+  %x_val = load i8, ptr %x.addr, align 1
+  ;; No failures expected for this callee_type metdata.
+  %call = call i32 %fptr(i8 signext %x_val), !callee_type !1

arsenm wrote:

The valid cases belong in test/Assembler 

https://github.com/llvm/llvm-project/pull/87573
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [llvm] Introduce callee_type metadata (PR #87573)

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


@@ -0,0 +1,30 @@
+;; Test if the callee_type metadata attached to indirect call sites adhere to 
the expected format.
+
+; RUN: not opt -passes=verify < %s 2>&1 | FileCheck %s

arsenm wrote:

```suggestion
; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
```

https://github.com/llvm/llvm-project/pull/87573
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [llvm] Introduce callee_type metadata (PR #87573)

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


@@ -0,0 +1,21 @@
+;; Test if the callee_type metadata is dropped when it is attached
+;; to a direct function call during instcombine.
+
+; RUN: opt -passes="instcombine" -S < %s | FileCheck %s

arsenm wrote:

```suggestion
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
```

https://github.com/llvm/llvm-project/pull/87573
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [llvm] Introduce callee_type metadata (PR #87573)

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


@@ -0,0 +1,21 @@
+;; Test if the callee_type metadata is dropped when it is attached
+;; to a direct function call during instcombine.
+
+; RUN: opt -passes="instcombine" -S < %s | FileCheck %s
+
+define i32 @_Z3barv() local_unnamed_addr !type !3 {

arsenm wrote:

```suggestion
define i32 @_Z3barv() !type !3 {
```

https://github.com/llvm/llvm-project/pull/87573
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [llvm] Introduce callee_type metadata (PR #87573)

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


@@ -0,0 +1,21 @@
+;; Test if the callee_type metadata is dropped when it is attached
+;; to a direct function call during instcombine.
+
+; RUN: opt -passes="instcombine" -S < %s | FileCheck %s
+
+define i32 @_Z3barv() local_unnamed_addr !type !3 {
+entry:
+  ; CHECK-LABEL: define i32 @_Z3barv()
+  ; CHECK-NEXT: entry:
+  ; CHECK-NOT: !callee_type

arsenm wrote:

-NOT checks are fragile, use update_test_checks 

https://github.com/llvm/llvm-project/pull/87573
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [llvm] Introduce callee_type metadata (PR #87573)

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


@@ -0,0 +1,26 @@
+;; Test if the callee_type metadata is dropped when it is
+;; is mapped to a direct function call from an indirect call during inlining.
+
+; RUN: opt -passes="inline" -S < %s | FileCheck %s
+
+define i32 @_Z13call_indirectPFicEc(ptr %func, i8 %x) local_unnamed_addr !type 
!0 {
+entry:
+  %call = call i32 %func(i8 %x), !callee_type !1
+  ret i32 %call
+}
+
+define i32 @_Z3barv() local_unnamed_addr !type !3 {
+entry:
+  ; CHECK-LABEL: define i32 @_Z3barv()
+  ; CHECK-NEXT: entry:
+  ; CHECK-NOT: !callee_type

arsenm wrote:

NOT checks are fragile, use update_test_checks 

https://github.com/llvm/llvm-project/pull/87573
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [llvm] Introduce callee_type metadata (PR #87573)

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


@@ -0,0 +1,26 @@
+;; Test if the callee_type metadata is dropped when it is
+;; is mapped to a direct function call from an indirect call during inlining.
+
+; RUN: opt -passes="inline" -S < %s | FileCheck %s

arsenm wrote:

```suggestion
; RUN: opt -passes=inline -S < %s | FileCheck %s
```

https://github.com/llvm/llvm-project/pull/87573
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] While stmt atom (PR #134645)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams updated 
https://github.com/llvm/llvm-project/pull/134645

>From e3c271ebbf4792bf684acef2af8fbc9df9a9b596 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Thu, 3 Apr 2025 18:49:32 +0100
Subject: [PATCH 1/2] [KeyInstr][Clang] While stmt atom

See test comment for possible future improvement.

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
 clang/lib/CodeGen/CGStmt.cpp |  9 +-
 clang/test/DebugInfo/KeyInstructions/while.c | 34 
 2 files changed, 42 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/while.c

diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index e46cfb433ab89..d9fd406ad64ee 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1130,7 +1130,14 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S,
 if (!Weights && CGM.getCodeGenOpts().OptimizationLevel)
   BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
   BoolCondVal, Stmt::getLikelihood(S.getBody()));
-Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
+auto *I = Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights);
+// Key Instructions: Emit the condition and branch as separate atoms to
+// match existing loop stepping behaviour. FIXME: We could have the branch
+// as the backup location for the condition, which would probably be a
+// better experience. Explore this later.
+if (auto *I = dyn_cast(BoolCondVal))
+  addInstToNewSourceAtom(I, nullptr);
+addInstToNewSourceAtom(I, nullptr);
 
 if (ExitBlock != LoopExit.getBlock()) {
   EmitBlock(ExitBlock);
diff --git a/clang/test/DebugInfo/KeyInstructions/while.c 
b/clang/test/DebugInfo/KeyInstructions/while.c
new file mode 100644
index 0..f1bb91520315a
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/while.c
@@ -0,0 +1,34 @@
+// RUN: %clang -gkey-instructions -x c++ -std=c++17 %s -gmlt -S -emit-llvm -o 
- \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -S -emit-llvm -o -  \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// Perennial quesiton: should the `dec` be in its own source atom or not
+// (currently it is).
+
+// We've made the cmp and br separate source atoms for now, to match existing
+// behaviour in this case:
+// 1. while (
+// 2.   int i = --End
+// 3.   ) {
+// 4.   useValue(i);
+// 5. }
+// Without Key Instructions we go: 2, 1[, 4, 2, 1]+
+// Without separating cmp and br with Key Instructions we'd get:
+// 1[, 4, 1]+. If we made the cmp higher precedence than the
+// br and had them in the same group, we could get:
+// 2, [4, 2]+ which might be nicer. FIXME: do that later.
+
+void a(int A) {
+// CHECK: %dec = add nsw i32 %0, -1, !dbg [[G1R2:!.*]]
+// CHECK: store i32 %dec, ptr %A.addr{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: %tobool = icmp ne i32 %dec, 0, !dbg [[G2R1:!.*]]
+// CHECK: br i1 %tobool, label %while.body, label %while.end, !dbg [[G3R1:!.*]]
+while (--A) { };
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)

>From cdd6ff398508e486bd669f9a441e557824699a98 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Wed, 21 May 2025 15:47:54 +0100
Subject: [PATCH 2/2] cc1

---
 clang/test/DebugInfo/KeyInstructions/while.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/DebugInfo/KeyInstructions/while.c 
b/clang/test/DebugInfo/KeyInstructions/while.c
index f1bb91520315a..d876bd1d93792 100644
--- a/clang/test/DebugInfo/KeyInstructions/while.c
+++ b/clang/test/DebugInfo/KeyInstructions/while.c
@@ -1,7 +1,7 @@
-// RUN: %clang -gkey-instructions -x c++ -std=c++17 %s -gmlt -S -emit-llvm -o 
- \
+// RUN: %clang_cc1 -gkey-instructions -x c++ -std=c++17 %s 
-debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
 
-// RUN: %clang -gkey-instructions -x c %s -gmlt -S -emit-llvm -o -  \
+// RUN: %clang_cc1 -gkey-instructions -x c %s 
-debug-info-kind=line-tables-only -emit-llvm -o -  \
 // RUN: | FileCheck %s --implicit-check

[llvm-branch-commits] [clang] [KeyInstr][Clang] For stmt atom (PR #134646)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams updated 
https://github.com/llvm/llvm-project/pull/134646

>From c4b2db1f76d59927fd54bf7901d6cdadf99ec77a Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Thu, 3 Apr 2025 19:12:47 +0100
Subject: [PATCH 1/2] [KeyInstr][Clang] For stmt atom

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
 clang/lib/CodeGen/CGStmt.cpp   | 18 +--
 clang/test/DebugInfo/KeyInstructions/for.c | 37 ++
 2 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/for.c

diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index d9fd406ad64ee..65b71c39d86c4 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1324,6 +1324,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
 Continue = getJumpDestInCurrentScope("for.inc");
   BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
 
+  llvm::BasicBlock *ForBody = nullptr;
   if (S.getCond()) {
 // If the for statement has a condition scope, emit the local variable
 // declaration.
@@ -1348,7 +1349,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
   ExitBlock = createBasicBlock("for.cond.cleanup");
 
 // As long as the condition is true, iterate the loop.
-llvm::BasicBlock *ForBody = createBasicBlock("for.body");
+ForBody = createBasicBlock("for.body");
 
 // C99 6.8.5p2/p4: The first substatement is executed if the expression
 // compares unequal to 0.  The condition must be a scalar type.
@@ -1362,7 +1363,14 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
   BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
   BoolCondVal, Stmt::getLikelihood(S.getBody()));
 
-Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
+auto *I = Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
+// Key Instructions: Emit the condition and branch as separate atoms to
+// match existing loop stepping behaviour. FIXME: We could have the branch
+// as the backup location for the condition, which would probably be a
+// better experience (no jumping to the brace).
+if (auto *I = dyn_cast(BoolCondVal))
+  addInstToNewSourceAtom(I, nullptr);
+addInstToNewSourceAtom(I, nullptr);
 
 if (ExitBlock != LoopExit.getBlock()) {
   EmitBlock(ExitBlock);
@@ -1416,6 +1424,12 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
 
   if (CGM.shouldEmitConvergenceTokens())
 ConvergenceTokenStack.pop_back();
+
+  if (ForBody) {
+// Key Instructions: We want the for closing brace to be step-able on to
+// match existing behaviour.
+addInstToNewSourceAtom(ForBody->getTerminator(), nullptr);
+  }
 }
 
 void
diff --git a/clang/test/DebugInfo/KeyInstructions/for.c 
b/clang/test/DebugInfo/KeyInstructions/for.c
new file mode 100644
index 0..3221ece69a717
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/for.c
@@ -0,0 +1,37 @@
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -S -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -S -emit-llvm -o -  \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// Perennial quesiton: should the inc be its own source atom or not
+// (currently it is).
+
+// FIXME: See do.c and while.c regarding cmp and cond br groups.
+
+void a(int A) {
+// CHECK: entry:
+// CHECK: store i32 0, ptr %i{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: for.cond:
+// CHECK: %cmp = icmp slt i32 %0, %1, !dbg [[G2R1:!.*]]
+// CHECK: br i1 %cmp, label %for.body, label %for.end, !dbg [[G3R1:!.*]]
+
+// FIXME: Added uncond br group here which is useful for O0, which we're
+// no longer targeting. With optimisations loop rotate puts the condition
+// into for.inc and simplifycfg smooshes that and for.body together, so
+// it's not clear whether it adds any value.
+// CHECK: for.body:
+// CHECK: br label %for.inc, !dbg [[G5R1:!.*]]
+
+// CHECK: for.inc:
+// CHECK: %inc = add{{.*}}, !dbg [[G4R2:!.*]]
+// CHECK: store i32 %inc, ptr %i{{.*}}, !dbg [[G4R1:!.*]]
+for (int i = 0; i < A; ++i) { }
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[G5R1]] = !DILocation

[llvm-branch-commits] [clang] [KeyInstr][Clang] For stmt atom (PR #134646)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams updated 
https://github.com/llvm/llvm-project/pull/134646

>From c4b2db1f76d59927fd54bf7901d6cdadf99ec77a Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Thu, 3 Apr 2025 19:12:47 +0100
Subject: [PATCH] [KeyInstr][Clang] For stmt atom

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
 clang/lib/CodeGen/CGStmt.cpp   | 18 +--
 clang/test/DebugInfo/KeyInstructions/for.c | 37 ++
 2 files changed, 53 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/DebugInfo/KeyInstructions/for.c

diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index d9fd406ad64ee..65b71c39d86c4 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -1324,6 +1324,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
 Continue = getJumpDestInCurrentScope("for.inc");
   BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
 
+  llvm::BasicBlock *ForBody = nullptr;
   if (S.getCond()) {
 // If the for statement has a condition scope, emit the local variable
 // declaration.
@@ -1348,7 +1349,7 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
   ExitBlock = createBasicBlock("for.cond.cleanup");
 
 // As long as the condition is true, iterate the loop.
-llvm::BasicBlock *ForBody = createBasicBlock("for.body");
+ForBody = createBasicBlock("for.body");
 
 // C99 6.8.5p2/p4: The first substatement is executed if the expression
 // compares unequal to 0.  The condition must be a scalar type.
@@ -1362,7 +1363,14 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
   BoolCondVal = emitCondLikelihoodViaExpectIntrinsic(
   BoolCondVal, Stmt::getLikelihood(S.getBody()));
 
-Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
+auto *I = Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
+// Key Instructions: Emit the condition and branch as separate atoms to
+// match existing loop stepping behaviour. FIXME: We could have the branch
+// as the backup location for the condition, which would probably be a
+// better experience (no jumping to the brace).
+if (auto *I = dyn_cast(BoolCondVal))
+  addInstToNewSourceAtom(I, nullptr);
+addInstToNewSourceAtom(I, nullptr);
 
 if (ExitBlock != LoopExit.getBlock()) {
   EmitBlock(ExitBlock);
@@ -1416,6 +1424,12 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
 
   if (CGM.shouldEmitConvergenceTokens())
 ConvergenceTokenStack.pop_back();
+
+  if (ForBody) {
+// Key Instructions: We want the for closing brace to be step-able on to
+// match existing behaviour.
+addInstToNewSourceAtom(ForBody->getTerminator(), nullptr);
+  }
 }
 
 void
diff --git a/clang/test/DebugInfo/KeyInstructions/for.c 
b/clang/test/DebugInfo/KeyInstructions/for.c
new file mode 100644
index 0..3221ece69a717
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/for.c
@@ -0,0 +1,37 @@
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -S -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -S -emit-llvm -o -  \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// Perennial quesiton: should the inc be its own source atom or not
+// (currently it is).
+
+// FIXME: See do.c and while.c regarding cmp and cond br groups.
+
+void a(int A) {
+// CHECK: entry:
+// CHECK: store i32 0, ptr %i{{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: for.cond:
+// CHECK: %cmp = icmp slt i32 %0, %1, !dbg [[G2R1:!.*]]
+// CHECK: br i1 %cmp, label %for.body, label %for.end, !dbg [[G3R1:!.*]]
+
+// FIXME: Added uncond br group here which is useful for O0, which we're
+// no longer targeting. With optimisations loop rotate puts the condition
+// into for.inc and simplifycfg smooshes that and for.body together, so
+// it's not clear whether it adds any value.
+// CHECK: for.body:
+// CHECK: br label %for.inc, !dbg [[G5R1:!.*]]
+
+// CHECK: for.inc:
+// CHECK: %inc = add{{.*}}, !dbg [[G4R2:!.*]]
+// CHECK: store i32 %inc, ptr %i{{.*}}, !dbg [[G4R1:!.*]]
+for (int i = 0; i < A; ++i) { }
+}
+
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)
+// CHECK: [[G5R1]] = !DILocation({{.

[llvm-branch-commits] [clang] [NFC][KeyInstr][Clang] Add some additional tests (PR #134654)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams updated 
https://github.com/llvm/llvm-project/pull/134654

>From 36537a2ede8874fd806d408b186ea33a7d4e1423 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Mon, 7 Apr 2025 12:18:48 +0100
Subject: [PATCH 1/2] [NFC][KeyInstr][Clang] Add some additional tests

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943

new.cpp: Check store of addr and value are both added to same atom
cast.c: Check we look through casts
multi-func.c Check the atom group number is reset between functions
---
 clang/test/KeyInstructions/cast.c   | 19 +
 clang/test/KeyInstructions/multi-func.c | 18 
 clang/test/KeyInstructions/new.cpp  | 37 +
 3 files changed, 74 insertions(+)
 create mode 100644 clang/test/KeyInstructions/cast.c
 create mode 100644 clang/test/KeyInstructions/multi-func.c
 create mode 100644 clang/test/KeyInstructions/new.cpp

diff --git a/clang/test/KeyInstructions/cast.c 
b/clang/test/KeyInstructions/cast.c
new file mode 100644
index 0..b89edcc3089fb
--- /dev/null
+++ b/clang/test/KeyInstructions/cast.c
@@ -0,0 +1,19 @@
+// RUN: %clang -gkey-instructions -gno-column-info -x c++ %s -gmlt -S 
-emit-llvm -o -  \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -gno-column-info -x c %s -gmlt -S -emit-llvm 
-o -  \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+float g;
+void a() {
+// CHECK: %0 = load float, ptr @g{{.*}}, !dbg [[G1R3:!.*]]
+// CHECK: %conv = fptosi float %0 to i32{{.*}}, !dbg [[G1R2:!.*]]
+// CHECK: store i32 %conv, ptr %a{{.*}}, !dbg [[G1R1:!.*]]
+int a = g;
+// CHECK: ret{{.*}}, !dbg [[G2R1:!.*]]
+}
+
+// CHECK: [[G1R3]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 3)
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
diff --git a/clang/test/KeyInstructions/multi-func.c 
b/clang/test/KeyInstructions/multi-func.c
new file mode 100644
index 0..7d441e43444b2
--- /dev/null
+++ b/clang/test/KeyInstructions/multi-func.c
@@ -0,0 +1,18 @@
+// RUN: %clang -gkey-instructions -gno-column-info -x c++ %s -gmlt -S 
-emit-llvm -o -  \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -gno-column-info -x c %s -gmlt -S -emit-llvm 
-o -  \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// Check atomGroup is reset to start at 1 in each function.
+
+// CHECK: ret{{.*}}, !dbg [[AG:!.*]]
+void a() {}
+
+// CHECK: ret{{.*}}, !dbg [[BG:!.*]]
+void b() {}
+
+// CHECK: [[A:!.*]] = distinct !DISubprogram(name: "a",
+// CHECK: [[AG]] = !DILocation({{.*}}, scope: [[A]], atomGroup: 1, atomRank: 1)
+// CHECK: [[B:!.*]] = distinct !DISubprogram(name: "b",
+// CHECK: [[BG]] = !DILocation({{.*}}, scope: [[B]], atomGroup: 1, atomRank: 1)
diff --git a/clang/test/KeyInstructions/new.cpp 
b/clang/test/KeyInstructions/new.cpp
new file mode 100644
index 0..9476e311e746f
--- /dev/null
+++ b/clang/test/KeyInstructions/new.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang -gkey-instructions %s -gmlt -gcolumn-info -S -emit-llvm -o - 
-Wno-unused-variable \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// Check both the addr-store and value-store are part of the same atom.
+
+void f(int x) {
+// CHECK: %call = call noalias noundef nonnull ptr @_Znwm{{.*}}, !dbg 
[[G1R2_C12:!.*]]
+// CHECK: %0 = load i32, ptr %x.addr{{.*}}, !dbg [[G1R2_C20:!.*]]
+// CHECK: store i32 %0, ptr %call{{.*}}, !dbg [[G1R1_C12:!.*]]
+// CHECK: store ptr %call, ptr %{{.*}}, !dbg [[G1R1_C8:!.*]]
+  int *n = new int(x);
+// CHECK: %call1 = call noalias noundef nonnull ptr @_Znwm{{.*}}, !dbg 
[[G2R2_C7:!.*]]
+// CHECK: %1 = load i32, ptr %x.addr{{.*}}, !dbg [[G2R2_C15:!.*]]
+// CHECK: store i32 %1, ptr %call{{.*}}, !dbg [[G2R1_C7:!.*]]
+// CHECK: store ptr %call1, ptr %{{.*}}, !dbg [[G2R1_C5:!.*]]
+  n = new int(x);
+// CHECK: %2 = load i32, ptr %x.addr{{.*}}, !dbg [[G3R2:!.*]]
+// CHECK: %3 = load ptr, ptr %n
+// CHECK: store i32 %2, ptr %3{{.*}}, !dbg [[G3R1:!.*]]
+  *n = x;
+// CHECK: ret void, !dbg [[G4R1:!.*]]
+}
+
+// CHECK: [[G1R2_C12]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R2_C20]] = !DILocation({{

[llvm-branch-commits] [clang] [KeyInstr][Clang] Agg init atom (PR #134635)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams edited 
https://github.com/llvm/llvm-project/pull/134635
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Scalar init atom (PR #134633)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits

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

LGTM

https://github.com/llvm/llvm-project/pull/134633
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Agg init atom (PR #134635)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits

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

LGTM (horray for graphite cc'ing everyone)

https://github.com/llvm/llvm-project/pull/134635
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Assign vector element atom (PR #134649)

2025-05-21 Thread Orlando Cazalet-Hyams via llvm-branch-commits

https://github.com/OCHyams updated 
https://github.com/llvm/llvm-project/pull/134649

>From 7c2a67e1b6be8f8431a87f72446d150a81e23ffd Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams 
Date: Thu, 3 Apr 2025 21:56:37 +0100
Subject: [PATCH] [KeyInstr][Clang] Assign vector element atom

This patch is part of a stack that teaches Clang to generate Key Instructions
metadata for C and C++.

The Key Instructions project is introduced, including a "quick summary" section
at the top which adds context for this PR, here:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668

The feature is only functional in LLVM if LLVM is built with CMake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.

The Clang-side work is demoed here:
https://github.com/llvm/llvm-project/pull/130943
---
 clang/lib/CodeGen/CGExpr.cpp   | 5 +++--
 clang/test/DebugInfo/KeyInstructions/agg.c | 8 
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index f91e284bfdaa0..c03eef1054f7e 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -2507,8 +2507,9 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, 
LValue Dst,
 Vec = Builder.CreateBitCast(Vec, IRStoreTy);
   }
 
-  Builder.CreateStore(Vec, Dst.getVectorAddress(),
-  Dst.isVolatileQualified());
+  auto *I = Builder.CreateStore(Vec, Dst.getVectorAddress(),
+Dst.isVolatileQualified());
+  addInstToCurrentSourceAtom(I, Vec);
   return;
 }
 
diff --git a/clang/test/DebugInfo/KeyInstructions/agg.c 
b/clang/test/DebugInfo/KeyInstructions/agg.c
index 06c9ebbb63369..f3fa7888610e3 100644
--- a/clang/test/DebugInfo/KeyInstructions/agg.c
+++ b/clang/test/DebugInfo/KeyInstructions/agg.c
@@ -4,6 +4,7 @@
 // RUN: %clang_cc1 -gkey-instructions -x c %s 
-debug-info-kind=line-tables-only -emit-llvm -o - \
 // RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
 
+__attribute__((ext_vector_type(1))) char c;
 typedef struct { int a, b, c; } Struct;
 void fun(Struct a) {
 // CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
@@ -11,7 +12,14 @@ void fun(Struct a) {
 
 // CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G2R1:!.*]]
   b = a;
+
+// CHECK: %2 = load <1 x i8>, ptr @c
+// CHECK: %vecins = insertelement <1 x i8> %2, i8 0, i32 0, !dbg [[G3R2:!.*]]
+// CHECK: store <1 x i8> %vecins, ptr @c{{.*}}, !dbg [[G3R1:!.*]]
+  c[0] = 0;
 }
 
 // CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
 // CHECK: [[G2R1]] = !DILocation({{.*}}, atomGroup: 2, atomRank: 1)
+// CHECK: [[G3R2]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 2)
+// CHECK: [[G3R1]] = !DILocation({{.*}}, atomGroup: 3, atomRank: 1)

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits


@@ -5985,6 +5985,15 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const 
BinaryOperator *E) {
 

jmorse wrote:

I wonder whether the comma operator (six or seven lines above here) needs 
instrumenting -- technically if either lhs/rhs of the comma is an assignment, I 
guess it'll come back through this function and be given a separate group?

https://github.com/llvm/llvm-project/pull/134637
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits


@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -gkey-instructions -x c++ %s 
-debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank

jmorse wrote:

This test is great; I feel we can make it even greater by testing:

  ` g += ++h;`

Or something like that, where there are stores on both sides of a compound 
assignment expression.

https://github.com/llvm/llvm-project/pull/134637
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits


@@ -0,0 +1,41 @@
+
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gno-column-info -S 
-emit-llvm -o - -ftrivial-auto-var-init=pattern \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gno-column-info -S -emit-llvm 
-o - -ftrivial-auto-var-init=pattern \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// The implicit-check-not is important; we don't want the GEPs created for the
+// store locations to be included in the atom group.
+
+int g;
+void a() {
+// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
+int A[] = { 1, 2, 3 };
+
+// CHECK: store i32 1, ptr %{{.*}}, !dbg [[G2R1:!.*]]
+// CHECK: store i32 2, ptr %{{.*}}, !dbg [[G2R1]]
+// CHECK: %0 = load i32, ptr @g{{.*}}, !dbg [[G2R2:!.*]]
+// CHECK: store i32 %0, ptr %{{.*}}, !dbg [[G2R1]]
+int B[] = { 1, 2, g };
+
+// CHECK: call void @llvm.memset{{.*}}, !dbg [[G3R1:!.*]]

jmorse wrote:

Similarly, would be nice to have a more specific memset, and the one below.

https://github.com/llvm/llvm-project/pull/134637
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits


@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -gkey-instructions -x c++ %s 
-debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang_cc1 -gkey-instructions -x c %s 
-debug-info-kind=line-tables-only -emit-llvm -o - \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+unsigned long long g;
+void fun() {
+// CHECK: store i64 0, ptr @g{{.*}}, !dbg [[G1R1:!.*]]
+g = 0;
+
+// Treat the two assignments as two atoms.

jmorse wrote:

Duplicate coverage with the `g = g = g` in the test file above?

https://github.com/llvm/llvm-project/pull/134637
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits


@@ -5849,6 +5852,7 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr 
*E) {
 
 LValue CodeGenFunction::EmitCompoundAssignmentLValue(
 const CompoundAssignOperator *E) {
+  ApplyAtomGroup Grp(getDebugInfo());

jmorse wrote:

If I enter via a `VisitBin##OP##Assign` function from above I'll get an atom 
group before calling `EmitCompoundAssign`, then get a second atom group here in 
`EmitcompoundAssignmentLValue` (which is called by `EmitCompoundAssign`). I 
would have expected only one atom group to be generated in that, is that wrong?

https://github.com/llvm/llvm-project/pull/134637
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits


@@ -5985,6 +5985,15 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const 
BinaryOperator *E) {
 
   assert(E->getOpcode() == BO_Assign && "unexpected binary l-value");
 
+  // This covers both LHS and RHS expressions, though nested RHS
+  // expressions may get subsequently separately grouped.

jmorse wrote:

Opening part of the comment should provide context to the reader that you're 
doing something debug-info / stepping related.

https://github.com/llvm/llvm-project/pull/134637
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits


@@ -0,0 +1,41 @@
+
+// RUN: %clang -gkey-instructions -x c++ %s -gmlt -gno-column-info -S 
-emit-llvm -o - -ftrivial-auto-var-init=pattern \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// RUN: %clang -gkey-instructions -x c %s -gmlt -gno-column-info -S -emit-llvm 
-o - -ftrivial-auto-var-init=pattern \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not 
atomRank
+
+// The implicit-check-not is important; we don't want the GEPs created for the
+// store locations to be included in the atom group.
+
+int g;
+void a() {
+// CHECK: call void @llvm.memcpy{{.*}}, !dbg [[G1R1:!.*]]
+int A[] = { 1, 2, 3 };

jmorse wrote:

As with a prior review, tying the memcpy down to its destination SSA name would 
be nice, as it'd be more specific than "there is a memcpy with group 1 rank 1, 
anywhere".

https://github.com/llvm/llvm-project/pull/134637
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits


@@ -5985,6 +5985,15 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const 
BinaryOperator *E) {
 
   assert(E->getOpcode() == BO_Assign && "unexpected binary l-value");
 
+  // This covers both LHS and RHS expressions, though nested RHS
+  // expressions may get subsequently separately grouped.
+  // FIXME(OCH): Not clear yet if we've got fine enough control
+  // to pick and choose when we need to. Currently looks ok:
+  // a = b = c  -> Two atoms.
+  // x = new(1) -> One atom (for both addr store and value store).

jmorse wrote:

Is this TODO still relevant -- it's not clear what's actually to do.

https://github.com/llvm/llvm-project/pull/134637
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr][Clang] Assignment atom group (PR #134637)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits

https://github.com/jmorse edited 
https://github.com/llvm/llvm-project/pull/134637
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr] Complex assignment atoms (PR #134638)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits


@@ -1209,6 +1213,7 @@ LValue ComplexExprEmitter::
 EmitCompoundAssignLValue(const CompoundAssignOperator *E,
   ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&),
  RValue &Val) {
+  ApplyAtomGroup Grp(CGF.getDebugInfo());

jmorse wrote:

This doesn't appear to be symmetrical with the scalar patch, in that 
`EmitCompoundAssign` gets an atom group for the whole assignment -- should this 
be the same?

https://github.com/llvm/llvm-project/pull/134638
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [KeyInstr] Complex assignment atoms (PR #134638)

2025-05-21 Thread Jeremy Morse via llvm-branch-commits


@@ -1356,6 +1361,7 @@ LValue ComplexExprEmitter::EmitBinAssignLValue(const 
BinaryOperator *E,
 }
 
 ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+  ApplyAtomGroup Grp(CGF.getDebugInfo());
   ComplexPairTy Val;
   LValue LV = EmitBinAssignLValue(E, Val);

jmorse wrote:

Similarly, if we followed the pattern of the above hunk, we'd put 
ApplyAtomGroup into `EmitBinAssignLValue` instead. This one covers the 
load-of-lvalue at the end, wheras for compound assignments the equivalent 
wouldn't be covered.

https://github.com/llvm/llvm-project/pull/134638
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


  1   2   >