[clang-tools-extra] [llvm] [clang] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-10 Thread Michal Paszkowski via cfe-commits

michalpaszkowski wrote:

[Here are the 
slides](https://llvm.org/devmtg/2019-10/slides/Paszkowski-LLVMCanon.pdf) that 
were presented at the LLVM Dev Meeting in 2019. It might be useful to include 
the link in the commit message for reference.

@nikic Thanks for catching more things in the review! Especially the 
commutative ordering of operands/arguments.

When it comes to including hashes in the naming algorithm (renaming is 
controlled using an option for already named values), the ideas is that by just 
looking at an instruction further down (a use) you can tell whether any inputs 
are different. And the other way around, by looking at initial instructions you 
can see how their "output footprint" has changed after transformations.

The example below is a bit outdated, but reflects the general idea we had when 
considering naming algorithms:
https://github.com/llvm/llvm-project/assets/13875746/fdb85b98-bce9-48df-91c0-35ffd115bae0";>
https://github.com/llvm/llvm-project/assets/13875746/24d74cf1-ad21-47c0-9057-6065c7a4f472";>


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


[llvm] [clang] [clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Michal Paszkowski via cfe-commits

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

Thank you for working on this! LGTM!

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


[clang] [llvm] [HLSL][SPIR-V] Add Vulkan to target triple (PR #76749)

2024-01-04 Thread Michal Paszkowski via cfe-commits

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


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


[clang] [llvm] [HLSL][SPIR-V] Add create.handle intrinsic (PR #81038)

2024-02-08 Thread Michal Paszkowski via cfe-commits

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


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


[clang] [Offload] Move HIP and CUDA to new driver by default (PR #84420)

2024-03-12 Thread Michal Paszkowski via cfe-commits

michalpaszkowski wrote:

Hi @jhuber6! Thank you for the pull request!

> This is not intended to be landed immediately, but to allow for greater
> testing. One potential issue I've discovered is the lack of SPIR-V
> support or handling for `--offload`.

Do you mean the SPIR-V target (backend)? I have not followed this area of work 
closely. What is missing or what exactly needs to be supported by the SPIR-V 
target? Any help or pointers would be greatly appreciated!

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


[clang] [llvm] [HLSL][SPIR-V] Add SV_DispatchThreadID semantic support (PR #82536)

2024-02-29 Thread Michal Paszkowski via cfe-commits

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


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


[clang] llvm-canon (PR #68176)

2023-10-03 Thread Michal Paszkowski via cfe-commits

michalpaszkowski wrote:

Thank you @justinfargnoli and @AidanGoldfarb for taking over this work and 
reaching out! I will review your changes in the coming week.

CC @ChrisCummins FYI

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


[clang-tools-extra] llvm-canon (PR #68176)

2023-10-03 Thread Michal Paszkowski via cfe-commits

michalpaszkowski wrote:

Thank you @justinfargnoli and @AidanGoldfarb for taking over this work and 
reaching out! I will review your changes in the coming week.

CC @ChrisCummins FYI

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


[clang] llvm-canon (PR #68176)

2023-10-03 Thread Michal Paszkowski via cfe-commits


@@ -0,0 +1,638 @@
+//===--- IRCanonicalizer.cpp - IR Canonicalizer 
---===//
+//
+// 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
+/// This file implements the IRCanonicalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The canonicalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include "llvm/Transforms/Utils/IRCanonicalizer.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "canon"
+
+using namespace llvm;
+
+namespace {
+/// IRCanonicalizer aims to transform LLVM IR into canonical form.
+class IRCanonicalizer {
+public:
+  /// \name Canonicalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRCanonicalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRCanonicalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRCanonicalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRCanonicalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRCanonicalizer.
+///
+/// \param M Module to canonicalize.
+bool IRCanonicalizer::runOnFunction(Function &F) {
+  nameFunctionArguments(F);
+  nameBasicBlocks(F);
+
+  SmallVector Outputs = collectOutputInstructions(F);
+
+  if (!PreserveOrder)
+reorderInstructions(Outputs);
+
+  for (auto &I : Outputs)
+nameInstruction(I);
+
+  for (auto &I : instructions(F)) {
+if (!PreserveOrder) {
+  if (ReorderOperands && I.isCommutative())
+reorderInstructionOperandsByNames(&I);
+
+  if (auto *PN = dyn_cast(&I))
+reorderPHIIncomingValues(PN);
+}
+
+foldInstructionName(&I);
+  }
+
+  return true;
+}
+
+/// Numbers arguments.
+///
+/// \param F Function whose arguments will be renamed.
+void IRCanonicalizer::nameFunctionArguments(Function &F) {
+  int ArgumentCounter = 0;
+  for (auto &A : F.args()) {
+if (RenameAll || A.getName().empty()) {
+  A.setName("a" + Twine(ArgumentCounter));
+  ++ArgumentCounter;
+}
+  }
+}
+
+/// Names basic blocks using a generated hash for each basic block in
+/// a function considering the opcode and the order of output instructions.
+///
+/// \param F Function containing basic blocks to rename.
+void IRCanonicalizer::nameBas

[clang-tools-extra] llvm-canon (PR #68176)

2023-10-03 Thread Michal Paszkowski via cfe-commits


@@ -0,0 +1,638 @@
+//===--- IRCanonicalizer.cpp - IR Canonicalizer 
---===//
+//
+// 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
+/// This file implements the IRCanonicalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The canonicalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include "llvm/Transforms/Utils/IRCanonicalizer.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "canon"
+
+using namespace llvm;
+
+namespace {
+/// IRCanonicalizer aims to transform LLVM IR into canonical form.
+class IRCanonicalizer {
+public:
+  /// \name Canonicalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRCanonicalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRCanonicalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRCanonicalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRCanonicalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRCanonicalizer.
+///
+/// \param M Module to canonicalize.
+bool IRCanonicalizer::runOnFunction(Function &F) {
+  nameFunctionArguments(F);
+  nameBasicBlocks(F);
+
+  SmallVector Outputs = collectOutputInstructions(F);
+
+  if (!PreserveOrder)
+reorderInstructions(Outputs);
+
+  for (auto &I : Outputs)
+nameInstruction(I);
+
+  for (auto &I : instructions(F)) {
+if (!PreserveOrder) {
+  if (ReorderOperands && I.isCommutative())
+reorderInstructionOperandsByNames(&I);
+
+  if (auto *PN = dyn_cast(&I))
+reorderPHIIncomingValues(PN);
+}
+
+foldInstructionName(&I);
+  }
+
+  return true;
+}
+
+/// Numbers arguments.
+///
+/// \param F Function whose arguments will be renamed.
+void IRCanonicalizer::nameFunctionArguments(Function &F) {
+  int ArgumentCounter = 0;
+  for (auto &A : F.args()) {
+if (RenameAll || A.getName().empty()) {
+  A.setName("a" + Twine(ArgumentCounter));
+  ++ArgumentCounter;
+}
+  }
+}
+
+/// Names basic blocks using a generated hash for each basic block in
+/// a function considering the opcode and the order of output instructions.
+///
+/// \param F Function containing basic blocks to rename.
+void IRCanonicalizer::nameBas

[clang] llvm-canon (PR #68176)

2023-10-08 Thread Michal Paszkowski via cfe-commits

michalpaszkowski wrote:

> Please don't use the term canon/canonicalize for this pass or tool. LLVM has 
> an existing notion of "canonicalization" which does not coincide with what is 
> being done here.

@nikic I don't think the name "canon" or "canonicalizer" will lead to any 
confusion here. This is in fact what the pass is doing and mimics the name of 
MIR canonicalizer with similar assumptions as @plotfi noted . Using the term 
"canonicalization" for the current/existing set of passes is not really common 
or well defined.

As for the RFC, there was a discussion thread in the LLVM Dev Mailing: 
https://lists.llvm.org/pipermail/llvm-dev/2019-August/134475.html

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


[clang-tools-extra] llvm-canon (PR #68176)

2023-10-08 Thread Michal Paszkowski via cfe-commits

michalpaszkowski wrote:

> Please don't use the term canon/canonicalize for this pass or tool. LLVM has 
> an existing notion of "canonicalization" which does not coincide with what is 
> being done here.

@nikic I don't think the name "canon" or "canonicalizer" will lead to any 
confusion here. This is in fact what the pass is doing and mimics the name of 
MIR canonicalizer with similar assumptions as @plotfi noted . Using the term 
"canonicalization" for the current/existing set of passes is not really common 
or well defined.

As for the RFC, there was a discussion thread in the LLVM Dev Mailing: 
https://lists.llvm.org/pipermail/llvm-dev/2019-August/134475.html

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


[clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-10-18 Thread Michal Paszkowski via cfe-commits


@@ -543,6 +543,15 @@ variables with initializers are marked as internal.
 An interprocedural variant of :ref:`Sparse Conditional Constant Propagation
 `.
 
+``ir-normalizer``: Transforms IR into a canonical form that's easier to diff
+
+
+This pass aims to transform LLVM Modules into a canonical form by reordering 
and
+renaming instructions while preserving the same semantics. The canonicalizer 
makes
+it easier to spot semantic differences while diffing two modules which have 
undergone
+two different passes.
+
+---

michalpaszkowski wrote:

Shouldn't this line be removed? and the line underscoring the 
"``ir-normalizer``: Transforms IR into a canonical form that's easier to diff" 
be made a bit longer?

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


[clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-10-18 Thread Michal Paszkowski via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Canonicalizer ---===//

michalpaszkowski wrote:

Canonicalizer -> Normalizer

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


[clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-10-18 Thread Michal Paszkowski via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Canonicalizer ---===//
+//
+// 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
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Canonicalizer flags.

michalpaszkowski wrote:

Canonicalizer -> Normalizer

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


[clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-10-18 Thread Michal Paszkowski via cfe-commits


@@ -543,6 +543,15 @@ variables with initializers are marked as internal.
 An interprocedural variant of :ref:`Sparse Conditional Constant Propagation
 `.
 
+``ir-normalizer``: Transforms IR into a canonical form that's easier to diff
+
+
+This pass aims to transform LLVM Modules into a canonical form by reordering 
and
+renaming instructions while preserving the same semantics. The canonicalizer 
makes

michalpaszkowski wrote:

canonicalizer -> normalizer

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


[clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-10-18 Thread Michal Paszkowski via cfe-commits


@@ -42,7 +42,10 @@ Non-comprehensive list of changes in this release
functionality, or simply have a lot to talk about), see the `NOTE` below
for adding a new subsection.
 
-* ...
+* Added a new IRNormalizer pass which aims to transform LLVM modules into
+  a canonical form by reordering and renaming instructions while preserving the
+  same semantics. The canonicalizer makes it easier to spot semantic 
differences

michalpaszkowski wrote:

canonicalizer -> normalizer

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


[clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-10-18 Thread Michal Paszkowski via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Canonicalizer ---===//
+//
+// 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
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Canonicalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRNormalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRNormalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRNormalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRNormalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRNormalizer.
+///
+/// \param M Module to canonicalize.

michalpaszkowski wrote:

canonicalize -> normalize

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


[clang] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-10-18 Thread Michal Paszkowski via cfe-commits

michalpaszkowski wrote:

I added a couple more comments regarding the name change and formatting of the 
docs, but apart from these the patch looks good to me. 

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


[clang] [llvm] [HLSL][SPIRV] Add any intrinsic lowering (PR #88325)

2024-04-14 Thread Michal Paszkowski via cfe-commits

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


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


[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)

2024-06-05 Thread Michal Paszkowski via cfe-commits


@@ -1,4 +1,5 @@
 ; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: llc -O0 -mtriple=spirv64-amd-amdhsa %s -o - | FileCheck %s

michalpaszkowski wrote:

I am okay with either approach. I think we can assume that the core 
functionality will stay the same for all "flavors". In case of any changes in 
the future to this assumption, we could create larger tests covering multiple 
features, which will not provide any isolation value but just ensure the 
features are still there.

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


[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)

2024-06-05 Thread Michal Paszkowski via cfe-commits

https://github.com/michalpaszkowski edited 
https://github.com/llvm/llvm-project/pull/89796
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)

2024-06-05 Thread Michal Paszkowski via cfe-commits

https://github.com/michalpaszkowski requested changes to this pull request.


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


[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)

2024-06-05 Thread Michal Paszkowski via cfe-commits


@@ -56,6 +56,10 @@ static std::string computeDataLayout(const Triple &TT) {
   if (Arch == Triple::spirv32)
 return "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1";
+  if (TT.getVendor() == Triple::VendorType::AMD &&

michalpaszkowski wrote:

@AlexVlx Thanks for the pull request. Could you also please update the 
[SPIRVUsage](https://llvm.org/docs/SPIRVUsage.html) document? Any relevant 
information in the target triple section would be really appreciated.

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


[clang] [llvm] [clang][SPIR-V] Add support for AMDGCN flavoured SPIRV (PR #89796)

2024-06-06 Thread Michal Paszkowski via cfe-commits

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

@AlexVlx LGTM! Thank you!

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


[clang] [clang][CodeGen] Add AS for Globals to SPIR & SPIRV datalayouts (PR #88455)

2024-04-14 Thread Michal Paszkowski via cfe-commits

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

LGTM (from the SPIR-V backend side)!

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


[clang] [llvm] [clang][HLSL] Add WaveIsFirstLane() intrinsic (PR #103299)

2024-08-19 Thread Michal Paszkowski via cfe-commits

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


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


[clang] [HLSL][SPIRV] Fix calling convention for call in entry function. (PR #110275)

2024-09-29 Thread Michal Paszkowski via cfe-commits

michalpaszkowski wrote:

LGTM! I think changing the mangling for Vulkan is the best solution here.

One small comment, later on if/when you decide to use SPIRVBuiltins.cpp/.td for 
lowering builtins, there might be additional changes needed. The lookup 
function expects Itanium demangled strings.

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


[clang] [HLSL][SPIRV] Fix calling convention for call in entry function. (PR #110275)

2024-09-29 Thread Michal Paszkowski via cfe-commits


@@ -316,6 +316,11 @@ class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public 
BaseSPIRVTargetInfo {
 SizeType = TargetInfo::UnsignedInt;
 resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
 "v96:128-v192:256-v256:256-v512:512-v1024:1024-G1");
+
+if (Triple.getOS() == llvm::Triple::Vulkan) {
+  // For Vulkan we want to same mangling as DirectX.

michalpaszkowski wrote:

Typo: `to` -> `the`?

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


[clang] [llvm] [clang][llvm][SPIR-V] Explicitly encode native integer widths for SPIR-V (PR #110695)

2024-10-01 Thread Michal Paszkowski via cfe-commits


@@ -1,56 +0,0 @@
-; This test aims to check ability to support "Arithmetic with Overflow" 
intrinsics

michalpaszkowski wrote:

@AlexVlx I am not sure I follow the reasoning here. The idea behind those 
various tests in `/SPIRV/optimizations/` (including this one) is to ensure the 
backend can accept any IR. Either coming from the standard -O3 or some custom 
pipeline.

I do agree that we should not expect specific optimizations (or even more sets 
of optimizations) to do specific things when writing a test for an independent 
component. Hence, after some thinking, I believe the test could be improved by 
already containing a specific pattern that would be coming from the 
optimization. However, by the same principle, we should not expect that the 
issue will be "optimized away" by another optimization.

I would also oppose removing existing test cases. Any improvements, 
strengthening, or necessary changes are (of course) desirable.

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


[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,1242 @@
+//===-- SPIRVStructurizer.cpp --*- 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
+//
+//===--===//
+//
+//===--===//
+
+#include "Analysis/SPIRVConvergenceRegionAnalysis.h"
+#include "SPIRV.h"
+#include "SPIRVSubtarget.h"
+#include "SPIRVTargetMachine.h"
+#include "SPIRVUtils.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/LoopSimplify.h"
+#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
+#include 
+#include 
+#include 
+
+using namespace llvm;
+using namespace SPIRV;
+
+namespace llvm {
+
+void initializeSPIRVStructurizerPass(PassRegistry &);
+
+namespace {
+
+using BlockSet = std::unordered_set;
+using Edge = std::pair;
+
+// Helper function to do a partial order visit from the block |Start|, calling
+// |Op| on each visited node.
+void partialOrderVisit(BasicBlock &Start,
+   std::function Op) {
+  PartialOrderingVisitor V(*Start.getParent());
+  V.partialOrderVisit(Start, Op);
+}
+
+// Returns the exact convergence region in the tree defined by `Node` for which
+// `BB` is the header, nullptr otherwise.
+const ConvergenceRegion *getRegionForHeader(const ConvergenceRegion *Node,
+BasicBlock *BB) {
+  if (Node->Entry == BB)
+return Node;
+
+  for (auto *Child : Node->Children) {
+const auto *CR = getRegionForHeader(Child, BB);
+if (CR != nullptr)
+  return CR;
+  }
+  return nullptr;
+}
+
+// Returns the single BasicBlock exiting the convergence region `CR`,
+// nullptr if no such exit exists.
+BasicBlock *getExitFor(const ConvergenceRegion *CR) {
+  std::unordered_set ExitTargets;
+  for (BasicBlock *Exit : CR->Exits) {
+for (BasicBlock *Successor : successors(Exit)) {
+  if (CR->Blocks.count(Successor) == 0)
+ExitTargets.insert(Successor);
+}
+  }
+
+  assert(ExitTargets.size() <= 1);
+  if (ExitTargets.size() == 0)
+return nullptr;
+
+  return *ExitTargets.begin();
+}
+
+// Returns the merge block designated by I if I is a merge instruction, nullptr
+// otherwise.
+BasicBlock *getDesignatedMergeBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge &&
+  II->getIntrinsicID() != Intrinsic::spv_selection_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(0));
+  return BA->getBasicBlock();
+}
+
+// Returns the continue block designated by I if I is an OpLoopMerge, nullptr
+// otherwise.
+BasicBlock *getDesignatedContinueBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(1));
+  return BA->getBasicBlock();
+}
+
+// Returns true if Header has one merge instruction which designated Merge as
+// merge block.
+bool isDefinedAsSelectionMergeBy(BasicBlock &Header, BasicBlock &Merge) {
+  for (auto &I : Header) {
+BasicBlock *MB = getDesignatedMergeBlock(&I);
+if (MB == &Merge)
+  return true;
+  }
+  return false;
+}
+
+// Returns true if the BB has one OpLoopMerge instruction.
+bool hasLoopMergeInstruction(BasicBlock &BB) {
+  for (auto &I : BB)
+if (getDesignatedContinueBlock(&I))
+  return true;
+  return false;
+}
+
+// Returns true is I is an OpSelectionMerge or OpLoopMerge instruction, false
+// otherwise.
+bool isMergeInstruction(Instruction *I) {
+  return getDesignatedMergeBlock(I) != nullptr;
+}
+
+// Returns all blocks in F having at least one OpLoopMerge or OpSelectionMerge
+// instruction.
+SmallPtrSet getHeaderBlocks(Function &F) {
+  SmallPtrSet Output;
+  for (BasicBlock &BB : F) {
+for (Instruction &I : BB) {
+  if (getDesignatedMergeBlock(&I) != nullptr)
+   

[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,1242 @@
+//===-- SPIRVStructurizer.cpp --*- 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
+//
+//===--===//
+//
+//===--===//
+
+#include "Analysis/SPIRVConvergenceRegionAnalysis.h"
+#include "SPIRV.h"
+#include "SPIRVSubtarget.h"
+#include "SPIRVTargetMachine.h"
+#include "SPIRVUtils.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/LoopSimplify.h"
+#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
+#include 
+#include 
+#include 
+
+using namespace llvm;
+using namespace SPIRV;
+
+namespace llvm {
+
+void initializeSPIRVStructurizerPass(PassRegistry &);
+
+namespace {
+
+using BlockSet = std::unordered_set;
+using Edge = std::pair;
+
+// Helper function to do a partial order visit from the block |Start|, calling
+// |Op| on each visited node.
+void partialOrderVisit(BasicBlock &Start,
+   std::function Op) {
+  PartialOrderingVisitor V(*Start.getParent());
+  V.partialOrderVisit(Start, Op);
+}
+
+// Returns the exact convergence region in the tree defined by `Node` for which
+// `BB` is the header, nullptr otherwise.
+const ConvergenceRegion *getRegionForHeader(const ConvergenceRegion *Node,
+BasicBlock *BB) {
+  if (Node->Entry == BB)
+return Node;
+
+  for (auto *Child : Node->Children) {
+const auto *CR = getRegionForHeader(Child, BB);
+if (CR != nullptr)
+  return CR;
+  }
+  return nullptr;
+}
+
+// Returns the single BasicBlock exiting the convergence region `CR`,
+// nullptr if no such exit exists.
+BasicBlock *getExitFor(const ConvergenceRegion *CR) {
+  std::unordered_set ExitTargets;
+  for (BasicBlock *Exit : CR->Exits) {
+for (BasicBlock *Successor : successors(Exit)) {
+  if (CR->Blocks.count(Successor) == 0)
+ExitTargets.insert(Successor);
+}
+  }
+
+  assert(ExitTargets.size() <= 1);
+  if (ExitTargets.size() == 0)
+return nullptr;
+
+  return *ExitTargets.begin();
+}
+
+// Returns the merge block designated by I if I is a merge instruction, nullptr
+// otherwise.
+BasicBlock *getDesignatedMergeBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge &&
+  II->getIntrinsicID() != Intrinsic::spv_selection_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(0));
+  return BA->getBasicBlock();
+}
+
+// Returns the continue block designated by I if I is an OpLoopMerge, nullptr
+// otherwise.
+BasicBlock *getDesignatedContinueBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(1));
+  return BA->getBasicBlock();
+}
+
+// Returns true if Header has one merge instruction which designated Merge as
+// merge block.
+bool isDefinedAsSelectionMergeBy(BasicBlock &Header, BasicBlock &Merge) {
+  for (auto &I : Header) {
+BasicBlock *MB = getDesignatedMergeBlock(&I);
+if (MB == &Merge)
+  return true;
+  }
+  return false;
+}
+
+// Returns true if the BB has one OpLoopMerge instruction.
+bool hasLoopMergeInstruction(BasicBlock &BB) {
+  for (auto &I : BB)
+if (getDesignatedContinueBlock(&I))
+  return true;
+  return false;
+}
+
+// Returns true is I is an OpSelectionMerge or OpLoopMerge instruction, false
+// otherwise.
+bool isMergeInstruction(Instruction *I) {
+  return getDesignatedMergeBlock(I) != nullptr;
+}
+
+// Returns all blocks in F having at least one OpLoopMerge or OpSelectionMerge
+// instruction.
+SmallPtrSet getHeaderBlocks(Function &F) {
+  SmallPtrSet Output;
+  for (BasicBlock &BB : F) {
+for (Instruction &I : BB) {
+  if (getDesignatedMergeBlock(&I) != nullptr)
+   

[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= 
Message-ID:
In-Reply-To: 


michalpaszkowski wrote:

@Keenuts Apologies for the delay! The patch looks good to me. I added a couple 
of minor comments (above), but if the pass would be extended in subsequent 
commits, please feel free to address these in the next pull request or reply 
later. Thank you for working on this, this is really exciting work!

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


[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= ,
Nathan =?utf-8?q?Gau=C3=ABr?= 
Message-ID:
In-Reply-To: 


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


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


[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,1242 @@
+//===-- SPIRVStructurizer.cpp --*- 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
+//
+//===--===//
+//
+//===--===//
+
+#include "Analysis/SPIRVConvergenceRegionAnalysis.h"
+#include "SPIRV.h"
+#include "SPIRVSubtarget.h"
+#include "SPIRVTargetMachine.h"
+#include "SPIRVUtils.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/LoopSimplify.h"
+#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
+#include 
+#include 
+#include 
+
+using namespace llvm;
+using namespace SPIRV;
+
+namespace llvm {
+
+void initializeSPIRVStructurizerPass(PassRegistry &);
+
+namespace {
+
+using BlockSet = std::unordered_set;
+using Edge = std::pair;
+
+// Helper function to do a partial order visit from the block |Start|, calling
+// |Op| on each visited node.
+void partialOrderVisit(BasicBlock &Start,
+   std::function Op) {
+  PartialOrderingVisitor V(*Start.getParent());
+  V.partialOrderVisit(Start, Op);
+}
+
+// Returns the exact convergence region in the tree defined by `Node` for which
+// `BB` is the header, nullptr otherwise.
+const ConvergenceRegion *getRegionForHeader(const ConvergenceRegion *Node,
+BasicBlock *BB) {
+  if (Node->Entry == BB)
+return Node;
+
+  for (auto *Child : Node->Children) {
+const auto *CR = getRegionForHeader(Child, BB);
+if (CR != nullptr)
+  return CR;
+  }
+  return nullptr;
+}
+
+// Returns the single BasicBlock exiting the convergence region `CR`,
+// nullptr if no such exit exists.
+BasicBlock *getExitFor(const ConvergenceRegion *CR) {
+  std::unordered_set ExitTargets;
+  for (BasicBlock *Exit : CR->Exits) {
+for (BasicBlock *Successor : successors(Exit)) {
+  if (CR->Blocks.count(Successor) == 0)
+ExitTargets.insert(Successor);
+}
+  }
+
+  assert(ExitTargets.size() <= 1);
+  if (ExitTargets.size() == 0)
+return nullptr;
+
+  return *ExitTargets.begin();
+}
+
+// Returns the merge block designated by I if I is a merge instruction, nullptr
+// otherwise.
+BasicBlock *getDesignatedMergeBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge &&
+  II->getIntrinsicID() != Intrinsic::spv_selection_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(0));
+  return BA->getBasicBlock();
+}
+
+// Returns the continue block designated by I if I is an OpLoopMerge, nullptr
+// otherwise.
+BasicBlock *getDesignatedContinueBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(1));
+  return BA->getBasicBlock();
+}
+
+// Returns true if Header has one merge instruction which designated Merge as
+// merge block.
+bool isDefinedAsSelectionMergeBy(BasicBlock &Header, BasicBlock &Merge) {
+  for (auto &I : Header) {
+BasicBlock *MB = getDesignatedMergeBlock(&I);
+if (MB == &Merge)
+  return true;
+  }
+  return false;
+}
+
+// Returns true if the BB has one OpLoopMerge instruction.
+bool hasLoopMergeInstruction(BasicBlock &BB) {
+  for (auto &I : BB)
+if (getDesignatedContinueBlock(&I))
+  return true;
+  return false;
+}
+
+// Returns true is I is an OpSelectionMerge or OpLoopMerge instruction, false
+// otherwise.
+bool isMergeInstruction(Instruction *I) {
+  return getDesignatedMergeBlock(I) != nullptr;
+}
+
+// Returns all blocks in F having at least one OpLoopMerge or OpSelectionMerge
+// instruction.
+SmallPtrSet getHeaderBlocks(Function &F) {
+  SmallPtrSet Output;
+  for (BasicBlock &BB : F) {
+for (Instruction &I : BB) {
+  if (getDesignatedMergeBlock(&I) != nullptr)
+   

[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,1242 @@
+//===-- SPIRVStructurizer.cpp --*- 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
+//
+//===--===//
+//
+//===--===//
+
+#include "Analysis/SPIRVConvergenceRegionAnalysis.h"
+#include "SPIRV.h"
+#include "SPIRVSubtarget.h"
+#include "SPIRVTargetMachine.h"
+#include "SPIRVUtils.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/LoopSimplify.h"
+#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
+#include 
+#include 
+#include 
+
+using namespace llvm;
+using namespace SPIRV;
+
+namespace llvm {
+
+void initializeSPIRVStructurizerPass(PassRegistry &);
+
+namespace {
+
+using BlockSet = std::unordered_set;
+using Edge = std::pair;
+
+// Helper function to do a partial order visit from the block |Start|, calling
+// |Op| on each visited node.
+void partialOrderVisit(BasicBlock &Start,
+   std::function Op) {
+  PartialOrderingVisitor V(*Start.getParent());
+  V.partialOrderVisit(Start, Op);
+}
+
+// Returns the exact convergence region in the tree defined by `Node` for which
+// `BB` is the header, nullptr otherwise.
+const ConvergenceRegion *getRegionForHeader(const ConvergenceRegion *Node,
+BasicBlock *BB) {
+  if (Node->Entry == BB)
+return Node;
+
+  for (auto *Child : Node->Children) {
+const auto *CR = getRegionForHeader(Child, BB);
+if (CR != nullptr)
+  return CR;
+  }
+  return nullptr;
+}
+
+// Returns the single BasicBlock exiting the convergence region `CR`,
+// nullptr if no such exit exists.
+BasicBlock *getExitFor(const ConvergenceRegion *CR) {
+  std::unordered_set ExitTargets;
+  for (BasicBlock *Exit : CR->Exits) {
+for (BasicBlock *Successor : successors(Exit)) {
+  if (CR->Blocks.count(Successor) == 0)
+ExitTargets.insert(Successor);
+}
+  }
+
+  assert(ExitTargets.size() <= 1);
+  if (ExitTargets.size() == 0)
+return nullptr;
+
+  return *ExitTargets.begin();
+}
+
+// Returns the merge block designated by I if I is a merge instruction, nullptr
+// otherwise.
+BasicBlock *getDesignatedMergeBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge &&
+  II->getIntrinsicID() != Intrinsic::spv_selection_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(0));
+  return BA->getBasicBlock();
+}
+
+// Returns the continue block designated by I if I is an OpLoopMerge, nullptr
+// otherwise.
+BasicBlock *getDesignatedContinueBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(1));
+  return BA->getBasicBlock();
+}
+
+// Returns true if Header has one merge instruction which designated Merge as
+// merge block.
+bool isDefinedAsSelectionMergeBy(BasicBlock &Header, BasicBlock &Merge) {
+  for (auto &I : Header) {
+BasicBlock *MB = getDesignatedMergeBlock(&I);
+if (MB == &Merge)
+  return true;
+  }
+  return false;
+}
+
+// Returns true if the BB has one OpLoopMerge instruction.
+bool hasLoopMergeInstruction(BasicBlock &BB) {
+  for (auto &I : BB)
+if (getDesignatedContinueBlock(&I))
+  return true;
+  return false;
+}
+
+// Returns true is I is an OpSelectionMerge or OpLoopMerge instruction, false
+// otherwise.
+bool isMergeInstruction(Instruction *I) {
+  return getDesignatedMergeBlock(I) != nullptr;
+}
+
+// Returns all blocks in F having at least one OpLoopMerge or OpSelectionMerge
+// instruction.
+SmallPtrSet getHeaderBlocks(Function &F) {
+  SmallPtrSet Output;
+  for (BasicBlock &BB : F) {
+for (Instruction &I : BB) {
+  if (getDesignatedMergeBlock(&I) != nullptr)
+   

[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,1242 @@
+//===-- SPIRVStructurizer.cpp --*- 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
+//
+//===--===//
+//
+//===--===//
+
+#include "Analysis/SPIRVConvergenceRegionAnalysis.h"
+#include "SPIRV.h"
+#include "SPIRVSubtarget.h"
+#include "SPIRVTargetMachine.h"
+#include "SPIRVUtils.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/LoopSimplify.h"
+#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
+#include 
+#include 
+#include 
+
+using namespace llvm;
+using namespace SPIRV;
+
+namespace llvm {
+
+void initializeSPIRVStructurizerPass(PassRegistry &);
+
+namespace {
+
+using BlockSet = std::unordered_set;
+using Edge = std::pair;
+
+// Helper function to do a partial order visit from the block |Start|, calling
+// |Op| on each visited node.
+void partialOrderVisit(BasicBlock &Start,
+   std::function Op) {
+  PartialOrderingVisitor V(*Start.getParent());
+  V.partialOrderVisit(Start, Op);
+}
+
+// Returns the exact convergence region in the tree defined by `Node` for which
+// `BB` is the header, nullptr otherwise.
+const ConvergenceRegion *getRegionForHeader(const ConvergenceRegion *Node,
+BasicBlock *BB) {
+  if (Node->Entry == BB)
+return Node;
+
+  for (auto *Child : Node->Children) {
+const auto *CR = getRegionForHeader(Child, BB);
+if (CR != nullptr)
+  return CR;
+  }
+  return nullptr;
+}
+
+// Returns the single BasicBlock exiting the convergence region `CR`,
+// nullptr if no such exit exists.
+BasicBlock *getExitFor(const ConvergenceRegion *CR) {
+  std::unordered_set ExitTargets;
+  for (BasicBlock *Exit : CR->Exits) {
+for (BasicBlock *Successor : successors(Exit)) {
+  if (CR->Blocks.count(Successor) == 0)
+ExitTargets.insert(Successor);
+}
+  }
+
+  assert(ExitTargets.size() <= 1);
+  if (ExitTargets.size() == 0)
+return nullptr;
+
+  return *ExitTargets.begin();
+}
+
+// Returns the merge block designated by I if I is a merge instruction, nullptr
+// otherwise.
+BasicBlock *getDesignatedMergeBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge &&
+  II->getIntrinsicID() != Intrinsic::spv_selection_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(0));
+  return BA->getBasicBlock();
+}
+
+// Returns the continue block designated by I if I is an OpLoopMerge, nullptr
+// otherwise.
+BasicBlock *getDesignatedContinueBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(1));
+  return BA->getBasicBlock();
+}
+
+// Returns true if Header has one merge instruction which designated Merge as
+// merge block.
+bool isDefinedAsSelectionMergeBy(BasicBlock &Header, BasicBlock &Merge) {
+  for (auto &I : Header) {
+BasicBlock *MB = getDesignatedMergeBlock(&I);
+if (MB == &Merge)
+  return true;
+  }
+  return false;
+}
+
+// Returns true if the BB has one OpLoopMerge instruction.
+bool hasLoopMergeInstruction(BasicBlock &BB) {
+  for (auto &I : BB)
+if (getDesignatedContinueBlock(&I))
+  return true;
+  return false;
+}
+
+// Returns true is I is an OpSelectionMerge or OpLoopMerge instruction, false
+// otherwise.
+bool isMergeInstruction(Instruction *I) {
+  return getDesignatedMergeBlock(I) != nullptr;
+}
+
+// Returns all blocks in F having at least one OpLoopMerge or OpSelectionMerge
+// instruction.
+SmallPtrSet getHeaderBlocks(Function &F) {
+  SmallPtrSet Output;
+  for (BasicBlock &BB : F) {
+for (Instruction &I : BB) {
+  if (getDesignatedMergeBlock(&I) != nullptr)
+   

[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= 
Message-ID:
In-Reply-To: 


https://github.com/michalpaszkowski edited 
https://github.com/llvm/llvm-project/pull/107408
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= 
Message-ID:
In-Reply-To: 


https://github.com/michalpaszkowski edited 
https://github.com/llvm/llvm-project/pull/107408
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,1242 @@
+//===-- SPIRVStructurizer.cpp --*- 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
+//
+//===--===//
+//
+//===--===//
+
+#include "Analysis/SPIRVConvergenceRegionAnalysis.h"
+#include "SPIRV.h"
+#include "SPIRVSubtarget.h"
+#include "SPIRVTargetMachine.h"
+#include "SPIRVUtils.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/LoopSimplify.h"
+#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
+#include 
+#include 
+#include 
+
+using namespace llvm;
+using namespace SPIRV;
+
+namespace llvm {
+
+void initializeSPIRVStructurizerPass(PassRegistry &);
+
+namespace {
+
+using BlockSet = std::unordered_set;
+using Edge = std::pair;
+
+// Helper function to do a partial order visit from the block |Start|, calling
+// |Op| on each visited node.
+void partialOrderVisit(BasicBlock &Start,
+   std::function Op) {
+  PartialOrderingVisitor V(*Start.getParent());
+  V.partialOrderVisit(Start, Op);
+}
+
+// Returns the exact convergence region in the tree defined by `Node` for which
+// `BB` is the header, nullptr otherwise.
+const ConvergenceRegion *getRegionForHeader(const ConvergenceRegion *Node,
+BasicBlock *BB) {
+  if (Node->Entry == BB)
+return Node;
+
+  for (auto *Child : Node->Children) {
+const auto *CR = getRegionForHeader(Child, BB);
+if (CR != nullptr)
+  return CR;
+  }
+  return nullptr;
+}
+
+// Returns the single BasicBlock exiting the convergence region `CR`,
+// nullptr if no such exit exists.
+BasicBlock *getExitFor(const ConvergenceRegion *CR) {
+  std::unordered_set ExitTargets;
+  for (BasicBlock *Exit : CR->Exits) {
+for (BasicBlock *Successor : successors(Exit)) {
+  if (CR->Blocks.count(Successor) == 0)
+ExitTargets.insert(Successor);
+}
+  }
+
+  assert(ExitTargets.size() <= 1);
+  if (ExitTargets.size() == 0)
+return nullptr;
+
+  return *ExitTargets.begin();
+}
+
+// Returns the merge block designated by I if I is a merge instruction, nullptr
+// otherwise.
+BasicBlock *getDesignatedMergeBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge &&
+  II->getIntrinsicID() != Intrinsic::spv_selection_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(0));
+  return BA->getBasicBlock();
+}
+
+// Returns the continue block designated by I if I is an OpLoopMerge, nullptr
+// otherwise.
+BasicBlock *getDesignatedContinueBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(1));
+  return BA->getBasicBlock();
+}
+
+// Returns true if Header has one merge instruction which designated Merge as
+// merge block.
+bool isDefinedAsSelectionMergeBy(BasicBlock &Header, BasicBlock &Merge) {
+  for (auto &I : Header) {
+BasicBlock *MB = getDesignatedMergeBlock(&I);
+if (MB == &Merge)
+  return true;
+  }
+  return false;
+}
+
+// Returns true if the BB has one OpLoopMerge instruction.
+bool hasLoopMergeInstruction(BasicBlock &BB) {
+  for (auto &I : BB)
+if (getDesignatedContinueBlock(&I))
+  return true;
+  return false;
+}
+
+// Returns true is I is an OpSelectionMerge or OpLoopMerge instruction, false
+// otherwise.
+bool isMergeInstruction(Instruction *I) {
+  return getDesignatedMergeBlock(I) != nullptr;
+}
+
+// Returns all blocks in F having at least one OpLoopMerge or OpSelectionMerge
+// instruction.
+SmallPtrSet getHeaderBlocks(Function &F) {
+  SmallPtrSet Output;
+  for (BasicBlock &BB : F) {
+for (Instruction &I : BB) {
+  if (getDesignatedMergeBlock(&I) != nullptr)
+   

[clang] [llvm] [SPIR-V] Add SPIR-V structurizer (PR #107408)

2024-09-19 Thread Michal Paszkowski via cfe-commits
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= ,
Nathan =?utf-8?q?Gauër?= 
Message-ID:
In-Reply-To: 



@@ -0,0 +1,1242 @@
+//===-- SPIRVStructurizer.cpp --*- 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
+//
+//===--===//
+//
+//===--===//
+
+#include "Analysis/SPIRVConvergenceRegionAnalysis.h"
+#include "SPIRV.h"
+#include "SPIRVSubtarget.h"
+#include "SPIRVTargetMachine.h"
+#include "SPIRVUtils.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/CodeGen/IntrinsicLowering.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/LoopSimplify.h"
+#include "llvm/Transforms/Utils/LowerMemIntrinsics.h"
+#include 
+#include 
+#include 
+
+using namespace llvm;
+using namespace SPIRV;
+
+namespace llvm {
+
+void initializeSPIRVStructurizerPass(PassRegistry &);
+
+namespace {
+
+using BlockSet = std::unordered_set;
+using Edge = std::pair;
+
+// Helper function to do a partial order visit from the block |Start|, calling
+// |Op| on each visited node.
+void partialOrderVisit(BasicBlock &Start,
+   std::function Op) {
+  PartialOrderingVisitor V(*Start.getParent());
+  V.partialOrderVisit(Start, Op);
+}
+
+// Returns the exact convergence region in the tree defined by `Node` for which
+// `BB` is the header, nullptr otherwise.
+const ConvergenceRegion *getRegionForHeader(const ConvergenceRegion *Node,
+BasicBlock *BB) {
+  if (Node->Entry == BB)
+return Node;
+
+  for (auto *Child : Node->Children) {
+const auto *CR = getRegionForHeader(Child, BB);
+if (CR != nullptr)
+  return CR;
+  }
+  return nullptr;
+}
+
+// Returns the single BasicBlock exiting the convergence region `CR`,
+// nullptr if no such exit exists.
+BasicBlock *getExitFor(const ConvergenceRegion *CR) {
+  std::unordered_set ExitTargets;
+  for (BasicBlock *Exit : CR->Exits) {
+for (BasicBlock *Successor : successors(Exit)) {
+  if (CR->Blocks.count(Successor) == 0)
+ExitTargets.insert(Successor);
+}
+  }
+
+  assert(ExitTargets.size() <= 1);
+  if (ExitTargets.size() == 0)
+return nullptr;
+
+  return *ExitTargets.begin();
+}
+
+// Returns the merge block designated by I if I is a merge instruction, nullptr
+// otherwise.
+BasicBlock *getDesignatedMergeBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge &&
+  II->getIntrinsicID() != Intrinsic::spv_selection_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(0));
+  return BA->getBasicBlock();
+}
+
+// Returns the continue block designated by I if I is an OpLoopMerge, nullptr
+// otherwise.
+BasicBlock *getDesignatedContinueBlock(Instruction *I) {
+  IntrinsicInst *II = dyn_cast(I);
+  if (II == nullptr)
+return nullptr;
+
+  if (II->getIntrinsicID() != Intrinsic::spv_loop_merge)
+return nullptr;
+
+  BlockAddress *BA = cast(II->getOperand(1));
+  return BA->getBasicBlock();
+}
+
+// Returns true if Header has one merge instruction which designated Merge as
+// merge block.
+bool isDefinedAsSelectionMergeBy(BasicBlock &Header, BasicBlock &Merge) {
+  for (auto &I : Header) {
+BasicBlock *MB = getDesignatedMergeBlock(&I);
+if (MB == &Merge)
+  return true;
+  }
+  return false;
+}
+
+// Returns true if the BB has one OpLoopMerge instruction.
+bool hasLoopMergeInstruction(BasicBlock &BB) {
+  for (auto &I : BB)
+if (getDesignatedContinueBlock(&I))
+  return true;
+  return false;
+}
+
+// Returns true is I is an OpSelectionMerge or OpLoopMerge instruction, false
+// otherwise.
+bool isMergeInstruction(Instruction *I) {
+  return getDesignatedMergeBlock(I) != nullptr;
+}
+
+// Returns all blocks in F having at least one OpLoopMerge or OpSelectionMerge
+// instruction.
+SmallPtrSet getHeaderBlocks(Function &F) {
+  SmallPtrSet Output;
+  for (BasicBlock &BB : F) {
+for (Instruction &I : BB) {
+  if (getDesignatedMergeBlock(&I) != nullptr)
+   

[clang] [Clang][TableGen] Add missing __bf16 type to the builtins parser (PR #120662)

2025-01-09 Thread Michal Paszkowski via cfe-commits

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


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


[clang] [Clang][TableGen] Add missing __bf16 type to the builtins parser (PR #120662)

2025-01-09 Thread Michal Paszkowski via cfe-commits

https://github.com/michalpaszkowski closed 
https://github.com/llvm/llvm-project/pull/120662
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [SPIRV] add pre legalization instruction combine (PR #122839)

2025-01-15 Thread Michal Paszkowski via cfe-commits


@@ -0,0 +1,26 @@
+//=- SPIRVCombine.td - Define SPIRV Combine Rules -*-tablegen 
-*-=//
+//
+// 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
+//
+//===--===//
+//

michalpaszkowski wrote:

Should the file include some comment? Otherwise, I think this part could be 
removed.

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


[clang] [clang][SPIR-V] Use the SPIR-V backend by default (PR #129545)

2025-03-07 Thread Michal Paszkowski via cfe-commits

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


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


[clang] [Clang] Add support for missing OpenCL extensions (PR #129777)

2025-03-04 Thread Michal Paszkowski via cfe-commits

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


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


[clang] [llvm] [SPIRV] GPU intrinsics (PR #131190)

2025-03-14 Thread Michal Paszkowski via cfe-commits

https://github.com/michalpaszkowski requested changes to this pull request.


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


[clang] [llvm] [SPIRV] GPU intrinsics (PR #131190)

2025-03-14 Thread Michal Paszkowski via cfe-commits


@@ -0,0 +1,501 @@
+//===- LowerGPUIntrinsic.cpp 
--===//
+//
+// 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
+//
+//===--===//
+//
+// Lower the llvm.gpu intrinsics to target specific code sequences.
+// Can be called from clang if building for a specific GPU or from the backend
+// as part of a SPIRV lowering pipeline. Initial pass can lower to amdgcn or

michalpaszkowski wrote:

I don't understand how this pass fits into the SPIR-V lowering pipeline. Is 
this confusing [SPIR and 
SPIR-V](https://en.wikipedia.org/wiki/Standard_Portable_Intermediate_Representation)?
 SPIR being the format based on LLVM IR (although on an old version of LLVM 
3.4)? SPIR-V being a custom [Khronos-defined 
format](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html).

[While SPIR-V easily maps to LLVM 
IR](https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/docs/SPIRVRepresentationInLLVM.rst),
 it is far from being a standardized mapping and the actual translation is 
usually handled by either 
[SPIRV-LLVM-Translator](https://github.com/KhronosGroup/SPIRV-LLVM-Translator) 
or the in-tree SPIR-V backend.

Could you please comment on how this pass and the changes would fit into the 
current SPIR-V code generation flow through the SPIR-V backend?

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


[clang] [llvm] [SPIRV] GPU intrinsics (PR #131190)

2025-03-14 Thread Michal Paszkowski via cfe-commits

https://github.com/michalpaszkowski edited 
https://github.com/llvm/llvm-project/pull/131190
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [SPIRV] GPU intrinsics (PR #131190)

2025-03-15 Thread Michal Paszkowski via cfe-commits




michalpaszkowski wrote:

I need to read through the RFC and the changes in the PR yet but I think 
`llvm/test/CodeGen/SPIRV/` is not really the best place for this test as it is 
not testing the SPIR-V backend.

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


[clang] [llvm] [SPIRV] GPU intrinsics (PR #131190)

2025-03-17 Thread Michal Paszkowski via cfe-commits


@@ -0,0 +1,501 @@
+//===- LowerGPUIntrinsic.cpp 
--===//
+//
+// 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
+//
+//===--===//
+//
+// Lower the llvm.gpu intrinsics to target specific code sequences.
+// Can be called from clang if building for a specific GPU or from the backend
+// as part of a SPIRV lowering pipeline. Initial pass can lower to amdgcn or

michalpaszkowski wrote:

I would like to better understand your goal here with this patch and potential 
future patches. How is this written in terms of the spirv64 triple? What is 
specific about the intrinsics that they only "work" for SPIR-V triple or the 
other way around?

The SPIR-V triple in a module does describe characteristics about the module 
and obviously the architecture -- including a calling convention, vendor, 
address spaces, environment, etc. and most importantly indicates the target 
used -- in this case the in-tree SPIR-V backend. However, I do not see how the 
SPIR-V triple in case of this patch is relevant to the SPIR-V backend. If the 
goal is to define new intrinsics which could be handled by AMDGPU and NVPTX, 
then I don't think those should be associated with the SPIR-V triple in LLVM.

Is your goal to have SPIR-V backend implement these intrinsics (lower into 
proper spec defined SPIR-V builtin calls or primitive instructions)? Or would 
you see the backend just keep these as function calls? If the latter, then I am 
not sure this is the right use of `llvm.` intrinicis [according to the 
guidelines](https://llvm.org/docs/ExtendingLLVM.html#adding-a-new-intrinsic-function)?
 In theory, I would expect all `llvm.` intrinsics to be handled by the backends.

Having SPIR-V backend emit abstract function calls for intrinsics which could 
be lowered into the SPIR-V spec defined instructions or builtins is a very 
dangerous path and opposes the idea of the SPIR-V spec altogether.

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


[clang] [llvm] [SPIRV] GPU intrinsics (PR #131190)

2025-03-17 Thread Michal Paszkowski via cfe-commits


@@ -0,0 +1,501 @@
+//===- LowerGPUIntrinsic.cpp 
--===//
+//
+// 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
+//
+//===--===//
+//
+// Lower the llvm.gpu intrinsics to target specific code sequences.
+// Can be called from clang if building for a specific GPU or from the backend
+// as part of a SPIRV lowering pipeline. Initial pass can lower to amdgcn or

michalpaszkowski wrote:

The problem is that SPIR-V in itself is an architecture (although a synthetic 
one) and the SPIR-V backend is what lowers LLVM IR to this architecture. There 
are proprietary SPIR-V consumers which are not LLVM-based. For this reason it 
might be unreasonable to expect those to accept `llvm.` calls and it would be 
good to plan early how the new `llvm.gpu` intrinsics would be handled in the 
SPIR-V backend case by case.

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


[clang] [llvm] [SPIRV] GPU intrinsics (PR #131190)

2025-03-17 Thread Michal Paszkowski via cfe-commits

https://github.com/michalpaszkowski edited 
https://github.com/llvm/llvm-project/pull/131190
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits