[llvm] [SPIR-V] Add partial order tests, assert reducible (PR #117887)

via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 27 06:20:17 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-spir-v

Author: Nathan Gauër (Keenuts)

<details>
<summary>Changes</summary>

Add testing for the visitor and added a note explaining irreducible CFG are not supported.
Related to #<!-- -->116692

---

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


6 Files Affected:

- (modified) llvm/lib/Target/SPIRV/SPIRVUtils.cpp (+9-1) 
- (modified) llvm/lib/Target/SPIRV/SPIRVUtils.h (+4-1) 
- (modified) llvm/test/CodeGen/SPIRV/structurizer/cf.if.nested.ll (+18-18) 
- (modified) llvm/test/CodeGen/SPIRV/structurizer/cf.switch.ifstmt.simple2.ll (+157-190) 
- (modified) llvm/unittests/Target/SPIRV/CMakeLists.txt (+2-2) 
- (added) llvm/unittests/Target/SPIRV/SPIRVSortBlocksTests.cpp (+342) 


``````````diff
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
index ad8dfa0e8811b7..ddba5e76e33fa5 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.cpp
@@ -519,8 +519,11 @@ bool PartialOrderingVisitor::CanBeVisited(BasicBlock *BB) const {
 }
 
 size_t PartialOrderingVisitor::GetNodeRank(BasicBlock *BB) const {
-  size_t result = 0;
+  auto It = BlockToOrder.find(BB);
+  if (It != BlockToOrder.end())
+    return It->second.Rank;
 
+  size_t result = 0;
   for (BasicBlock *P : predecessors(BB)) {
     // Ignore back-edges.
     if (DT.dominates(BB, P))
@@ -552,15 +555,20 @@ size_t PartialOrderingVisitor::visit(BasicBlock *BB, size_t Unused) {
   ToVisit.push(BB);
   Queued.insert(BB);
 
+  size_t QueueIndex = 0;
   while (ToVisit.size() != 0) {
     BasicBlock *BB = ToVisit.front();
     ToVisit.pop();
 
     if (!CanBeVisited(BB)) {
       ToVisit.push(BB);
+      assert(QueueIndex < ToVisit.size() &&
+             "No valid candidate in the queue. Is the graph reducible?");
+      QueueIndex++;
       continue;
     }
 
+    QueueIndex = 0;
     size_t Rank = GetNodeRank(BB);
     OrderInfo Info = {Rank, BlockToOrder.size()};
     BlockToOrder.emplace(BB, Info);
diff --git a/llvm/lib/Target/SPIRV/SPIRVUtils.h b/llvm/lib/Target/SPIRV/SPIRVUtils.h
index da0e8769cac1b6..d218dbd850dc7a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVUtils.h
+++ b/llvm/lib/Target/SPIRV/SPIRVUtils.h
@@ -41,6 +41,8 @@ class SPIRVSubtarget;
 // ignores back-edges. The cycle is visited from the entry in the same
 // topological-like ordering.
 //
+// Note: this visitor REQUIRES a reducible graph.
+//
 // This means once we visit a node, we know all the possible ancestors have been
 // visited.
 //
@@ -84,10 +86,11 @@ class PartialOrderingVisitor {
   // Visits |BB| with the current rank being |Rank|.
   size_t visit(BasicBlock *BB, size_t Rank);
 
-  size_t GetNodeRank(BasicBlock *BB) const;
   bool CanBeVisited(BasicBlock *BB) const;
 
 public:
+  size_t GetNodeRank(BasicBlock *BB) const;
+
   // Build the visitor to operate on the function F.
   PartialOrderingVisitor(Function &F);
 
diff --git a/llvm/test/CodeGen/SPIRV/structurizer/cf.if.nested.ll b/llvm/test/CodeGen/SPIRV/structurizer/cf.if.nested.ll
index a69475a59db6f4..95910edd6b4ce6 100644
--- a/llvm/test/CodeGen/SPIRV/structurizer/cf.if.nested.ll
+++ b/llvm/test/CodeGen/SPIRV/structurizer/cf.if.nested.ll
@@ -34,28 +34,28 @@
 ; CHECK:    %[[#bb30:]] = OpLabel
 ; CHECK:                  OpSelectionMerge %[[#bb31:]] None
 ; CHECK:                  OpBranchConditional %[[#]] %[[#bb32:]] %[[#bb33:]]
-; CHECK:    %[[#bb32:]] = OpLabel
+; CHECK:     %[[#bb32]] = OpLabel
 ; CHECK:                  OpSelectionMerge %[[#bb34:]] None
-; CHECK:                  OpBranchConditional %[[#]] %[[#bb35:]] %[[#bb34:]]
-; CHECK:    %[[#bb33:]] = OpLabel
+; CHECK:                  OpBranchConditional %[[#]] %[[#bb35:]] %[[#bb34]]
+; CHECK:     %[[#bb33]] = OpLabel
 ; CHECK:                  OpSelectionMerge %[[#bb36:]] None
 ; CHECK:                  OpBranchConditional %[[#]] %[[#bb37:]] %[[#bb38:]]
-; CHECK:    %[[#bb35:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb34:]]
-; CHECK:    %[[#bb37:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb36:]]
-; CHECK:    %[[#bb38:]] = OpLabel
+; CHECK:     %[[#bb35]] = OpLabel
+; CHECK:                  OpBranch %[[#bb34]]
+; CHECK:     %[[#bb37]] = OpLabel
+; CHECK:                  OpBranch %[[#bb36]]
+; CHECK:     %[[#bb38]] = OpLabel
 ; CHECK:                  OpSelectionMerge %[[#bb39:]] None
-; CHECK:                  OpBranchConditional %[[#]] %[[#bb40:]] %[[#bb39:]]
-; CHECK:    %[[#bb34:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb31:]]
-; CHECK:    %[[#bb40:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb39:]]
-; CHECK:    %[[#bb39:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb36:]]
-; CHECK:    %[[#bb36:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb31:]]
-; CHECK:    %[[#bb31:]] = OpLabel
+; CHECK:                  OpBranchConditional %[[#]] %[[#bb40:]] %[[#bb39]]
+; CHECK:     %[[#bb34]] = OpLabel
+; CHECK:                  OpBranch %[[#bb31]]
+; CHECK:     %[[#bb40]] = OpLabel
+; CHECK:                  OpBranch %[[#bb39]]
+; CHECK:     %[[#bb39]] = OpLabel
+; CHECK:                  OpBranch %[[#bb36]]
+; CHECK:     %[[#bb36]] = OpLabel
+; CHECK:                  OpBranch %[[#bb31]]
+; CHECK:     %[[#bb31]] = OpLabel
 ; CHECK:                  OpReturnValue %[[#]]
 ; CHECK:                  OpFunctionEnd
 ; CHECK: %[[#func_26:]] = OpFunction %[[#void:]] DontInline %[[#]]
diff --git a/llvm/test/CodeGen/SPIRV/structurizer/cf.switch.ifstmt.simple2.ll b/llvm/test/CodeGen/SPIRV/structurizer/cf.switch.ifstmt.simple2.ll
index cf50b982b23dc8..f2f86ed9e64fa0 100644
--- a/llvm/test/CodeGen/SPIRV/structurizer/cf.switch.ifstmt.simple2.ll
+++ b/llvm/test/CodeGen/SPIRV/structurizer/cf.switch.ifstmt.simple2.ll
@@ -1,10 +1,9 @@
 ; RUN: llc -mtriple=spirv-unknown-vulkan-compute -O0 %s -o - | FileCheck %s
 ; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-vulkan-compute %s -o - -filetype=obj | spirv-val %}
 
+; static int foo() { return 200; }
 ;
-; int foo() { return 200; }
-;
-; int process() {
+; static int process() {
 ;   int a = 0;
 ;   int b = 0;
 ;   int c = 0;
@@ -20,10 +19,10 @@
 ;       b += 2;
 ;       break;
 ;     case 3:
-;     {
-;       b += 3;
-;       break;
-;     }
+;       {
+;         b += 3;
+;         break;
+;       }
 ;     case t:
 ;       b += t;
 ;     case 4:
@@ -31,10 +30,10 @@
 ;       b += 5;
 ;       break;
 ;     case 6: {
-;     case 7:
-;       break;}
+;               case 7:
+;                 break;}
 ;     default:
-;       break;
+;             break;
 ;   }
 ;
 ;   return a + b + c;
@@ -45,198 +44,166 @@
 ;   process();
 ; }
 
-; CHECK: %[[#func_18:]] = OpFunction %[[#uint:]] DontInline %[[#]]
-; CHECK:    %[[#bb52:]] = OpLabel
-; CHECK:                  OpReturnValue %[[#]]
-; CHECK:                  OpFunctionEnd
-; CHECK: %[[#func_19:]] = OpFunction %[[#uint:]] DontInline %[[#]]
-; CHECK:    %[[#bb53:]] = OpLabel
-; CHECK:                  OpSelectionMerge %[[#bb54:]] None
-; CHECK:                  OpBranchConditional %[[#]] %[[#bb55:]] %[[#bb56:]]
-; CHECK:    %[[#bb55:]] = OpLabel
-; CHECK:                  OpSelectionMerge %[[#bb57:]] None
-; CHECK:                  OpBranchConditional %[[#]] %[[#bb58:]] %[[#bb59:]]
-; CHECK:    %[[#bb56:]] = OpLabel
-; CHECK:    %[[#bb58:]] = OpLabel
-; CHECK:                  OpSelectionMerge %[[#bb60:]] None
-; CHECK:                  OpBranchConditional %[[#]] %[[#bb61:]] %[[#bb62:]]
-; CHECK:    %[[#bb59:]] = OpLabel
-; CHECK:    %[[#bb61:]] = OpLabel
-; CHECK:                  OpSelectionMerge %[[#bb63:]] None
-; CHECK:                  OpSwitch %[[#]] %[[#bb64:]] 1 %[[#bb65:]] 2 %[[#bb63:]] 3 %[[#bb66:]] 140 %[[#bb67:]] 4 %[[#bb68:]] 5 %[[#bb69:]] 6 %[[#bb70:]] 7 %[[#bb71:]]
-; CHECK:    %[[#bb62:]] = OpLabel
-; CHECK:    %[[#bb64:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb63:]]
-; CHECK:    %[[#bb65:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb63:]]
-; CHECK:    %[[#bb66:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb63:]]
-; CHECK:    %[[#bb67:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb63:]]
-; CHECK:    %[[#bb68:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb63:]]
-; CHECK:    %[[#bb69:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb63:]]
-; CHECK:    %[[#bb70:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb63:]]
-; CHECK:    %[[#bb71:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb63:]]
-; CHECK:    %[[#bb63:]] = OpLabel
-; CHECK:                  OpSelectionMerge %[[#bb72:]] None
-; CHECK:                  OpSwitch %[[#]] %[[#bb73:]] 1 %[[#bb72:]] 2 %[[#bb74:]] 3 %[[#bb75:]]
-; CHECK:    %[[#bb73:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb72:]]
-; CHECK:    %[[#bb74:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb72:]]
-; CHECK:    %[[#bb75:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb72:]]
-; CHECK:    %[[#bb72:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb60:]]
-; CHECK:    %[[#bb60:]] = OpLabel
-; CHECK:                  OpSelectionMerge %[[#bb76:]] None
-; CHECK:                  OpSwitch %[[#]] %[[#bb77:]] 1 %[[#bb76:]] 2 %[[#bb78:]]
-; CHECK:    %[[#bb77:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb76:]]
-; CHECK:    %[[#bb78:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb76:]]
-; CHECK:    %[[#bb76:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb57:]]
-; CHECK:    %[[#bb57:]] = OpLabel
-; CHECK:                  OpBranch %[[#bb54:]]
-; CHECK:    %[[#bb54:]] = OpLabel
-; CHECK:                  OpReturnValue %[[#]]
-; CHECK:                  OpFunctionEnd
-; CHECK: %[[#func_48:]] = OpFunction %[[#void:]] DontInline %[[#]]
-; CHECK:    %[[#bb79:]] = OpLabel
-; CHECK:                  OpReturn
-; CHECK:                  OpFunctionEnd
-; CHECK: %[[#func_50:]] = OpFunction %[[#void:]] None %[[#]]
-; CHECK:    %[[#bb80:]] = OpLabel
-; CHECK:                  OpReturn
-; CHECK:                  OpFunctionEnd
+; CHECK: %[[#func:]] = OpFunction %[[#]] DontInline %[[#]]
+; CHECK: %[[#bb30:]] = OpLabel
+; CHECK:               OpSelectionMerge %[[#bb31:]] None
+; CHECK:               OpBranchConditional %[[#]] %[[#bb32:]] %[[#bb33:]]
+
+; CHECK:  %[[#bb32]] = OpLabel
+; CHECK:               OpSelectionMerge %[[#bb34:]] None
+; CHECK:               OpBranchConditional %[[#]] %[[#bb35:]] %[[#bb36:]]
+
+; CHECK:  %[[#bb33]] = OpLabel
+; CHECK:               OpUnreachable
+
+; CHECK:  %[[#bb35]] = OpLabel
+; CHECK:               OpSelectionMerge %[[#bb37:]] None
+; CHECK:               OpBranchConditional %[[#]] %[[#bb38:]] %[[#bb39:]]
+
+; CHECK:  %[[#bb36]] = OpLabel
+; CHECK:               OpUnreachable
+
+; CHECK:  %[[#bb38]] = OpLabel
+; CHECK:               OpSelectionMerge %[[#bb40:]] None
+; CHECK:               OpSwitch %[[#]] %[[#bb41:]] 1 %[[#bb42:]] 2 %[[#bb43:]] 3 %[[#bb44:]] 140 %[[#bb45:]] 4 %[[#bb46:]] 5 %[[#bb47:]] 6 %[[#bb48:]] 7 %[[#bb49:]]
+; CHECK:  %[[#bb39]] = OpLabel
+; CHECK:               OpUnreachable
+
+; CHECK:  %[[#bb41]] = OpLabel
+; CHECK:               OpBranch %[[#bb40]]
+; CHECK:  %[[#bb42]] = OpLabel
+; CHECK:               OpBranch %[[#bb40]]
+; CHECK:  %[[#bb43]] = OpLabel
+; CHECK:               OpBranch %[[#bb40]]
+; CHECK:  %[[#bb44]] = OpLabel
+; CHECK:               OpBranch %[[#bb40]]
+; CHECK:  %[[#bb45]] = OpLabel
+; CHECK:               OpBranch %[[#bb40]]
+; CHECK:  %[[#bb46]] = OpLabel
+; CHECK:               OpBranch %[[#bb40]]
+; CHECK:  %[[#bb47]] = OpLabel
+; CHECK:               OpBranch %[[#bb40]]
+; CHECK:  %[[#bb48]] = OpLabel
+; CHECK:               OpBranch %[[#bb40]]
+; CHECK:  %[[#bb49]] = OpLabel
+; CHECK:               OpBranch %[[#bb40]]
+
+; CHECK:  %[[#bb40]] = OpLabel
+; CHECK:               OpSelectionMerge %[[#bb50:]] None
+; CHECK:               OpSwitch %[[#]] %[[#bb50]] 1 %[[#bb51:]] 2 %[[#bb52:]] 3 %[[#bb53:]]
+; CHECK:  %[[#bb51]] = OpLabel
+; CHECK:               OpBranch %[[#bb50]]
+; CHECK:  %[[#bb52]] = OpLabel
+; CHECK:               OpBranch %[[#bb50]]
+; CHECK:  %[[#bb53]] = OpLabel
+; CHECK:               OpBranch %[[#bb50]]
+; CHECK:  %[[#bb50]] = OpLabel
+; CHECK:               OpBranch %[[#bb37]]
+
+; CHECK:  %[[#bb37]] = OpLabel
+; CHECK:               OpSelectionMerge %[[#bb54:]] None
+; CHECK:               OpSwitch %[[#]] %[[#bb54]] 1 %[[#bb55:]] 2 %[[#bb56:]]
+; CHECK:  %[[#bb55]] = OpLabel
+; CHECK:               OpBranch %[[#bb54]]
+; CHECK:  %[[#bb56]] = OpLabel
+; CHECK:               OpBranch %[[#bb54]]
+; CHECK:  %[[#bb54]] = OpLabel
+; CHECK:               OpBranch %[[#bb34]]
+
+; CHECK:  %[[#bb34]] = OpLabel
+; CHECK:               OpBranch %[[#bb31]]
+
+; CHECK:  %[[#bb31]] = OpLabel
+; CHECK:               OpReturn
+; CHECK:               OpFunctionEnd
 
 
 
 target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
 target triple = "spirv-unknown-vulkan1.3-compute"
 
-; Function Attrs: convergent noinline norecurse nounwind optnone
-define spir_func noundef i32 @_Z3foov() #0 {
+; Function Attrs: convergent noinline norecurse
+define void @main() #0 {
 entry:
+  %a.i = alloca i32, align 4
+  %b.i = alloca i32, align 4
+  %c.i = alloca i32, align 4
+  %r.i = alloca i32, align 4
+  %s.i = alloca i32, align 4
+  %t.i = alloca i32, align 4
+  %d.i = alloca i32, align 4
   %0 = call token @llvm.experimental.convergence.entry()
-  ret i32 200
-}
-
-; Function Attrs: convergent nocallback nofree nosync nounwind willreturn memory(none)
-declare token @llvm.experimental.convergence.entry() #1
-
-; Function Attrs: convergent noinline norecurse nounwind optnone
-define spir_func noundef i32 @_Z7processv() #0 {
-entry:
-  %0 = call token @llvm.experimental.convergence.entry()
-  %a = alloca i32, align 4
-  %b = alloca i32, align 4
-  %c = alloca i32, align 4
-  %r = alloca i32, align 4
-  %s = alloca i32, align 4
-  %t = alloca i32, align 4
-  %d = alloca i32, align 4
-  store i32 0, ptr %a, align 4
-  store i32 0, ptr %b, align 4
-  store i32 0, ptr %c, align 4
-  store i32 20, ptr %r, align 4
-  store i32 40, ptr %s, align 4
-  store i32 140, ptr %t, align 4
-  store i32 5, ptr %d, align 4
-  %1 = load i32, ptr %d, align 4
-  switch i32 %1, label %sw.default [
-    i32 1, label %sw.bb
-    i32 2, label %sw.bb3
-    i32 3, label %sw.bb5
-    i32 140, label %sw.bb7
-    i32 4, label %sw.bb9
-    i32 5, label %sw.bb9
-    i32 6, label %sw.bb11
-    i32 7, label %sw.bb12
+  store i32 0, ptr %a.i, align 4
+  store i32 0, ptr %b.i, align 4
+  store i32 0, ptr %c.i, align 4
+  store i32 20, ptr %r.i, align 4
+  store i32 40, ptr %s.i, align 4
+  store i32 140, ptr %t.i, align 4
+  store i32 5, ptr %d.i, align 4
+  %1 = load i32, ptr %d.i, align 4
+  switch i32 %1, label %sw.default.i [
+    i32 1, label %sw.bb.i
+    i32 2, label %sw.bb3.i
+    i32 3, label %sw.bb5.i
+    i32 140, label %sw.bb7.i
+    i32 4, label %sw.bb9.i
+    i32 5, label %sw.bb9.i
+    i32 6, label %sw.bb11.i
+    i32 7, label %sw.bb12.i
   ]
 
-sw.bb:                                            ; preds = %entry
-  %2 = load i32, ptr %b, align 4
-  %add = add nsw i32 %2, 1
-  store i32 %add, ptr %b, align 4
-  %call1 = call spir_func noundef i32 @_Z3foov() #3 [ "convergencectrl"(token %0) ]
-  %3 = load i32, ptr %c, align 4
-  %add2 = add nsw i32 %3, %call1
-  store i32 %add2, ptr %c, align 4
-  br label %sw.bb3
-
-sw.bb3:                                           ; preds = %entry, %sw.bb
-  %4 = load i32, ptr %b, align 4
-  %add4 = add nsw i32 %4, 2
-  store i32 %add4, ptr %b, align 4
-  br label %sw.epilog
-
-sw.bb5:                                           ; preds = %entry
-  %5 = load i32, ptr %b, align 4
-  %add6 = add nsw i32 %5, 3
-  store i32 %add6, ptr %b, align 4
-  br label %sw.epilog
-
-sw.bb7:                                           ; preds = %entry
-  %6 = load i32, ptr %b, align 4
-  %add8 = add nsw i32 %6, 140
-  store i32 %add8, ptr %b, align 4
-  br label %sw.bb9
-
-sw.bb9:                                           ; preds = %entry, %entry, %sw.bb7
-  %7 = load i32, ptr %b, align 4
-  %add10 = add nsw i32 %7, 5
-  store i32 %add10, ptr %b, align 4
-  br label %sw.epilog
-
-sw.bb11:                                          ; preds = %entry
-  br label %sw.bb12
-
-sw.bb12:                                          ; preds = %entry, %sw.bb11
-  br label %sw.epilog
-
-sw.default:                                       ; preds = %entry
-  br label %sw.epilog
-
-sw.epilog:                                        ; preds = %sw.default, %sw.bb12, %sw.bb9, %sw.bb5, %sw.bb3
-  %8 = load i32, ptr %a, align 4
-  %9 = load i32, ptr %b, align 4
-  %add13 = add nsw i32 %8, %9
-  %10 = load i32, ptr %c, align 4
-  %add14 = add nsw i32 %add13, %10
-  ret i32 %add14
-}
-
-; Function Attrs: convergent noinline norecurse nounwind optnone
-define internal spir_func void @main() #0 {
-entry:
-  %0 = call token @llvm.experimental.convergence.entry()
-  %call1 = call spir_func noundef i32 @_Z7processv() #3 [ "convergencectrl"(token %0) ]
+sw.bb.i:
+  %2 = load i32, ptr %b.i, align 4
+  %add.i = add nsw i32 %2, 1
+  store i32 %add.i, ptr %b.i, align 4
+  %3 = load i32, ptr %c.i, align 4
+  %add2.i = add nsw i32 %3, 200
+  store i32 %add2.i, ptr %c.i, align 4
+  br label %sw.bb3.i
+
+sw.bb3.i:
+  %4 = load i32, ptr %b.i, align 4
+  %add4.i = add nsw i32 %4, 2
+  store i32 %add4.i, ptr %b.i, align 4
+  br label %_ZL7processv.exit
+
+sw.bb5.i:
+  %5 = load i32, ptr %b.i, align 4
+  %add6.i = add nsw i32 %5, 3
+  store i32 %add6.i, ptr %b.i, align 4
+  br label %_ZL7processv.exit
+
+sw.bb7.i:
+  %6 = load i32, ptr %b.i, align 4
+  %add8.i = add nsw i32 %6, 140
+  store i32 %add8.i, ptr %b.i, align 4
+  br label %sw.bb9.i
+
+sw.bb9.i:
+  %7 = load i32, ptr %b.i, align 4
+  %add10.i = add nsw i32 %7, 5
+  store i32 %add10.i, ptr %b.i, align 4
+  br label %_ZL7processv.exit
+
+sw.bb11.i:
+  br label %sw.bb12.i
+
+sw.bb12.i:
+  br label %_ZL7processv.exit
+
+sw.default.i:
+  br label %_ZL7processv.exit
+
+_ZL7processv.exit:
+  %8 = load i32, ptr %a.i, align 4
+  %9 = load i32, ptr %b.i, align 4
+  %add13.i = add nsw i32 %8, %9
+  %10 = load i32, ptr %c.i, align 4
+  %add14.i = add nsw i32 %add13.i, %10
   ret void
 }
 
-; Function Attrs: convergent norecurse
-define void @main.1() #2 {
-entry:
-  call void @main()
-  ret void
-}
+declare token @llvm.experimental.convergence.entry() #1
 
-attributes #0 = { convergent noinline norecurse nounwind optnone "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #0 = { convergent noinline norecurse "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
 attributes #1 = { convergent nocallback nofree nosync nounwind willreturn memory(none) }
-attributes #2 = { convergent norecurse "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-attributes #3 = { convergent }
-
-!llvm.module.flags = !{!0, !1, !2}
-
-
-!0 = !{i32 1, !"wchar_size", i32 4}
-!1 = !{i32 4, !"dx.disable_optimizations", i32 1}
-!2 = !{i32 7, !"frame-pointer", i32 2}
-
-
diff --git a/llvm/unittests/Target/SPIRV/CMakeLists.txt b/llvm/unittests/Target/SPIRV/CMakeLists.txt
index e9fe4883e5b024..2af36225c5f200 100644
--- a/llvm/unittests/Target/SPIRV/CMakeLists.txt
+++ b/llvm/unittests/Target/SPIRV/CMakeLists.txt
@@ -15,6 +15,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_target_unittest(SPIRVTests
   SPIRVConvergenceRegionAnalysisTests.cpp
+  SPIRVSortBlocksTests.cpp
   SPIRVAPITest.cpp
-  )
-
+)
diff --git a/llvm/unittests/Target/SPIRV/SPIRVSortBlocksTests.cpp b/llvm/unittests/Target/SPIRV/SPIRVSortBlocksTests.cpp
new file mode 100644
index 00000000000000..7f64333eabe950
--- /dev/null
+++ b/llvm/unittests/Target/SPIRV/SPIRVSortBlocksTests.cpp
@@ -0,0 +1,342 @@
+//===- SPIRVSortBlocksTests.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "SPIRVUtils.h"
+#include "llvm/Analysis/DominanceFrontier.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassInstrumentation.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/TypedPointerType.h"
+#include "llvm/Support/SourceMgr.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <queue>
+
+using namespace llvm;
+using namespace llvm::SPIRV;
+
+class SPIRVSortBlocksTest : public testing::Test {
+protected:
+  void TearDown() override { M.reset(); }
+
+  void run(StringRef Assembly) {
+    assert(M == nullptr &&
+           "Calling runAnalysis multiple times is unsafe. See getAnalysis().");
+
+    SMDiagnostic Error;
+    M = parseAssemblyString(Assembly, Error, Context);
+    assert(M && "Bad assembly. Bad test?");
+
+    llvm::Function *F = M->getFunction("main");
+    Visitor = std::make_unique<...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/117887


More information about the llvm-commits mailing list