[llvm] [SPIR-V] Duplicates Tracker accounts for possible changes in Constant usage after optimization (PR #110835)

Vyacheslav Levytskyy via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 3 02:45:52 PDT 2024


https://github.com/VyacheslavLevytskyy updated https://github.com/llvm/llvm-project/pull/110835

>From a8d82ab45309163dc7fcda956bebae1adbf41566 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Tue, 1 Oct 2024 04:56:31 -0700
Subject: [PATCH 1/2] support Branch Folding and If Conversion optimization
 with analyzeBranch/removeBranch/insertBranch functions

---
 llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp      |  45 +++-
 .../SPIRV/branching/analyze-branch-opt.ll     | 250 ++++++++++++++++++
 2 files changed, 283 insertions(+), 12 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/branching/analyze-branch-opt.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
index e8a6b4fdbae977..6a5c95122d7819 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
@@ -197,9 +197,9 @@ bool SPIRVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
   } else if (MI->getOpcode() == SPIRV::OpBranchConditional) {
     Cond.push_back(MI->getOperand(0));
     TBB = MI->getOperand(1).getMBB();
-    if (MI->getNumOperands() == 3) {
-      FBB = MI->getOperand(2).getMBB();
-    }
+    FBB = MI->getOperand(2).getMBB();
+    for (unsigned I = 3, E = MI->getNumOperands(); I < E; ++I)
+      Cond.push_back(MI->getOperand(I));
     return false;
   } else {
     return true;
@@ -212,9 +212,17 @@ bool SPIRVInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
 // If \p BytesRemoved is non-null, report the change in code size from the
 // removed instructions.
 unsigned SPIRVInstrInfo::removeBranch(MachineBasicBlock &MBB,
-                                      int *BytesRemoved) const {
-  report_fatal_error("Branch removal not supported, as MBB info not propagated"
-                     " to OpPhi instructions. Try using -O0 instead.");
+                                      int * /*BytesRemoved*/) const {
+  MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
+  if (I == MBB.end())
+    return 0;
+
+  unsigned Opcode = I->getOpcode();
+  if (Opcode == SPIRV::OpBranch || Opcode == SPIRV::OpBranchConditional) {
+    I->eraseFromParent();
+    return 1;
+  }
+  return 0;
 }
 
 // Insert branch code into the end of the specified MachineBasicBlock. The
@@ -230,12 +238,25 @@ unsigned SPIRVInstrInfo::removeBranch(MachineBasicBlock &MBB,
 //
 // The CFG information in MBB.Predecessors and MBB.Successors must be valid
 // before calling this function.
-unsigned SPIRVInstrInfo::insertBranch(
-    MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
-    ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
-  report_fatal_error("Branch insertion not supported, as MBB info not "
-                     "propagated to OpPhi instructions. Try using "
-                     "-O0 instead.");
+unsigned SPIRVInstrInfo::insertBranch(MachineBasicBlock &MBB,
+                                      MachineBasicBlock *TBB,
+                                      MachineBasicBlock *FBB,
+                                      ArrayRef<MachineOperand> Cond,
+                                      const DebugLoc &DL,
+                                      int * /*BytesAdded*/) const {
+  if (!TBB)
+    return 0;
+  if (Cond.empty()) {
+    BuildMI(&MBB, DL, get(SPIRV::OpBranch)).addMBB(TBB);
+  } else {
+    auto MIB = BuildMI(&MBB, DL, get(SPIRV::OpBranchConditional))
+                   .add(Cond[0])
+                   .addMBB(TBB)
+                   .addMBB(FBB);
+    for (unsigned i = 1; i < Cond.size(); ++i)
+      MIB.add(Cond[i]);
+  }
+  return 1;
 }
 
 void SPIRVInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
diff --git a/llvm/test/CodeGen/SPIRV/branching/analyze-branch-opt.ll b/llvm/test/CodeGen/SPIRV/branching/analyze-branch-opt.ll
new file mode 100644
index 00000000000000..51018ff807a1ac
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/branching/analyze-branch-opt.ll
@@ -0,0 +1,250 @@
+; The goal of this test case is to ensure that translation does not crash when during branching
+; optimization analyzeBranch() requires helper methods of removeBranch() and insertBranch()
+; to manage subsequent operations.
+
+; RUN: llc -O0 -mtriple=spirv64-unknown-linux %s -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; RUN: llc -O0 -mtriple=spirv32-unknown-linux %s -o - | FileCheck %s
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: OpFunction
+
+%struct = type { %arr }
+%arr = type { [3 x i64] }
+
+ at .str.6 = private unnamed_addr addrspace(1) constant [3 x i8] c", \00", align 1
+ at .str.20 = private unnamed_addr addrspace(1) constant [6 x i8] c"item(\00", align 1
+ at .str.21 = private unnamed_addr addrspace(1) constant [8 x i8] c"range: \00", align 1
+ at .str.22 = private unnamed_addr addrspace(1) constant [7 x i8] c", id: \00", align 1
+
+define spir_func i32 @foo(ptr addrspace(4) %Buf, ptr addrspace(4) %Item) {
+entry:
+  %ref.tmp = alloca %struct
+  %ref.tmp7 = alloca %struct
+  br label %for.cond.i
+
+for.cond.i:                                       ; preds = %for.inc.i, %entry
+  %Len.0.i = phi i32 [ 0, %entry ], [ %inc.i, %for.inc.i ]
+  %idxprom.i = zext i32 %Len.0.i to i64
+  %arrayidx.i = getelementptr inbounds i8, ptr addrspace(1) @.str.20, i64 %idxprom.i
+  %0 = load i8, ptr addrspace(1) %arrayidx.i
+  %cmp.not.i = icmp eq i8 %0, 0
+  br i1 %cmp.not.i, label %for.cond1.i, label %for.inc.i
+
+for.inc.i:                                        ; preds = %for.cond.i
+  %inc.i = add i32 %Len.0.i, 1
+  br label %for.cond.i, !llvm.loop !1
+
+for.cond1.i:                                      ; preds = %for.body3.i, %for.cond.i
+  %I.0.i = phi i32 [ %inc9.i, %for.body3.i ], [ 0, %for.cond.i ]
+  %cmp2.i = icmp ult i32 %I.0.i, %Len.0.i
+  br i1 %cmp2.i, label %for.body3.i, label %for.cond.preheader
+
+for.cond.preheader:                               ; preds = %for.cond1.i
+  %MIndex.i = getelementptr inbounds i8, ptr addrspace(4) %Item, i64 24
+  br label %for.cond
+
+for.body3.i:                                      ; preds = %for.cond1.i
+  %idxprom4.i = zext i32 %I.0.i to i64
+  %arrayidx5.i = getelementptr inbounds i8, ptr addrspace(1) @.str.20, i64 %idxprom4.i
+  %1 = load i8, ptr addrspace(1) %arrayidx5.i
+  %arrayidx7.i = getelementptr inbounds i8, ptr addrspace(4) %Buf, i64 %idxprom4.i
+  store i8 %1, ptr addrspace(4) %arrayidx7.i
+  %inc9.i = add nuw i32 %I.0.i, 1
+  br label %for.cond1.i, !llvm.loop !2
+
+for.cond:                                         ; preds = %exit, %for.cond.preheader
+  %Len.0 = phi i32 [ %add9, %exit ], [ %Len.0.i, %for.cond.preheader ]
+  %I.0 = phi i32 [ %inc, %exit ], [ 0, %for.cond.preheader ]
+  %cmp = icmp ult i32 %I.0, 2
+  br i1 %cmp, label %for.body, label %for.cond.cleanup
+
+for.cond.cleanup:                                 ; preds = %for.cond
+  %inc10 = add i32 %Len.0, 1
+  %idxprom = zext i32 %Len.0 to i64
+  %arrayidx = getelementptr inbounds i8, ptr addrspace(4) %Buf, i64 %idxprom
+  store i8 41, ptr addrspace(4) %arrayidx
+  ret i32 %inc10
+
+for.body:                                         ; preds = %for.cond
+  %idx.ext = zext i32 %Len.0 to i64
+  %add.ptr = getelementptr inbounds i8, ptr addrspace(4) %Buf, i64 %idx.ext
+  %cmp1 = icmp eq i32 %I.0, 0
+  %cond = select i1 %cmp1, ptr addrspace(1) @.str.21, ptr addrspace(1) @.str.22
+  br label %for.cond.i25
+
+for.cond.i25:                                     ; preds = %for.inc.i30, %for.body
+  %Len.0.i26 = phi i32 [ 0, %for.body ], [ %inc.i31, %for.inc.i30 ]
+  %idxprom.i27 = zext i32 %Len.0.i26 to i64
+  %arrayidx.i28 = getelementptr inbounds i8, ptr addrspace(1) %cond, i64 %idxprom.i27
+  %2 = load i8, ptr addrspace(1) %arrayidx.i28
+  %cmp.not.i29 = icmp eq i8 %2, 0
+  br i1 %cmp.not.i29, label %for.cond1.i33, label %for.inc.i30
+
+for.inc.i30:                                      ; preds = %for.cond.i25
+  %inc.i31 = add i32 %Len.0.i26, 1
+  br label %for.cond.i25, !llvm.loop !1
+
+for.cond1.i33:                                    ; preds = %for.body3.i36, %for.cond.i25
+  %I.0.i34 = phi i32 [ %inc9.i40, %for.body3.i36 ], [ 0, %for.cond.i25 ]
+  %cmp2.i35 = icmp ult i32 %I.0.i34, %Len.0.i26
+  br i1 %cmp2.i35, label %for.body3.i36, label %detail.exit
+
+for.body3.i36:                                    ; preds = %for.cond1.i33
+  %idxprom4.i37 = zext i32 %I.0.i34 to i64
+  %arrayidx5.i38 = getelementptr inbounds i8, ptr addrspace(1) %cond, i64 %idxprom4.i37
+  %3 = load i8, ptr addrspace(1) %arrayidx5.i38
+  %arrayidx7.i39 = getelementptr inbounds i8, ptr addrspace(4) %add.ptr, i64 %idxprom4.i37
+  store i8 %3, ptr addrspace(4) %arrayidx7.i39
+  %inc9.i40 = add nuw i32 %I.0.i34, 1
+  br label %for.cond1.i33, !llvm.loop !2
+
+detail.exit:          ; preds = %for.cond1.i33
+  %add3 = add i32 %Len.0, %Len.0.i26
+  %idx.ext4 = zext i32 %add3 to i64
+  %add.ptr5 = getelementptr inbounds i8, ptr addrspace(4) %Buf, i64 %idx.ext4
+  br i1 %cmp1, label %cond.true, label %cond.false
+
+cond.true:                                        ; preds = %detail.exit
+  call void @llvm.memcpy.p0.p4.i64(ptr align 8 %ref.tmp7, ptr addrspace(4) align 8 %Item, i64 24, i1 false)
+  call void @llvm.memset.p0.i64(ptr align 8 %ref.tmp, i8 0, i64 24, i1 false)
+  br label %for.cond.i42
+
+for.cond.i42:                                     ; preds = %for.body.i, %cond.true
+  %i.0.i = phi i32 [ 0, %cond.true ], [ %inc.i45, %for.body.i ]
+  %cmp.i = icmp ult i32 %i.0.i, 3
+  br i1 %cmp.i, label %for.body.i, label %cond.end
+
+for.body.i:                                       ; preds = %for.cond.i42
+  %idxprom.i43 = zext nneg i32 %i.0.i to i64
+  %arrayidx.i44 = getelementptr inbounds [3 x i64], ptr %ref.tmp7, i64 0, i64 %idxprom.i43
+  %4 = load i64, ptr %arrayidx.i44, align 8
+  %arrayidx.i.i = getelementptr inbounds [3 x i64], ptr %ref.tmp, i64 0, i64 %idxprom.i43
+  store i64 %4, ptr %arrayidx.i.i, align 8
+  %inc.i45 = add nuw nsw i32 %i.0.i, 1
+  br label %for.cond.i42, !llvm.loop !3
+
+cond.false:                                       ; preds = %detail.exit
+  call void @llvm.memcpy.p0.p4.i64(ptr align 8 %ref.tmp, ptr addrspace(4) align 8 %MIndex.i, i64 24, i1 false)
+  br label %cond.end
+
+cond.end:                                         ; preds = %cond.false, %for.cond.i42
+  store i8 123, ptr addrspace(4) %add.ptr5
+  br label %for.cond.i46
+
+for.cond.i46:                                     ; preds = %for.inc.i52, %cond.end
+  %Len.0.i47 = phi i32 [ 1, %cond.end ], [ %Len.1.i, %for.inc.i52 ]
+  %I.0.i48 = phi i32 [ 0, %cond.end ], [ %inc7.i, %for.inc.i52 ]
+  %cmp.i49 = icmp ult i32 %I.0.i48, 3
+  br i1 %cmp.i49, label %for.body.i50, label %exit
+
+for.body.i50:                                     ; preds = %for.cond.i46
+  %idxprom.i.i = zext nneg i32 %I.0.i48 to i64
+  %arrayidx.i.i51 = getelementptr inbounds [3 x i64], ptr %ref.tmp, i64 0, i64 %idxprom.i.i
+  %5 = load i64, ptr %arrayidx.i.i51, align 8
+  %idx.ext.i = zext i32 %Len.0.i47 to i64
+  %add.ptr.i = getelementptr inbounds i8, ptr addrspace(4) %add.ptr5, i64 %idx.ext.i
+  br label %do.body.i.i.i
+
+do.body.i.i.i:                                    ; preds = %do.body.i.i.i, %for.body.i50
+  %Val.addr.0.i.i.i = phi i64 [ %5, %for.body.i50 ], [ %div.i.i.i, %do.body.i.i.i ]
+  %NumDigits.0.i.i.i = phi i32 [ 0, %for.body.i50 ], [ %inc.i.i.i, %do.body.i.i.i ]
+  %Val.addr.0.i.i.i.frozen = freeze i64 %Val.addr.0.i.i.i
+  %div.i.i.i = udiv i64 %Val.addr.0.i.i.i.frozen, 10
+  %6 = mul i64 %div.i.i.i, 10
+  %rem.i.i.i.decomposed = sub i64 %Val.addr.0.i.i.i.frozen, %6
+  %7 = trunc i64 %rem.i.i.i.decomposed to i8
+  %retval.0.i.i.i.i = or disjoint i8 %7, 48
+  %inc.i.i.i = add i32 %NumDigits.0.i.i.i, 1
+  %idxprom.i.i.i = zext i32 %NumDigits.0.i.i.i to i64
+  %arrayidx.i.i.i = getelementptr inbounds i8, ptr addrspace(4) %add.ptr.i, i64 %idxprom.i.i.i
+  store i8 %retval.0.i.i.i.i, ptr addrspace(4) %arrayidx.i.i.i
+  %tobool.not.i.i.i = icmp ult i64 %Val.addr.0.i.i.i, 10
+  br i1 %tobool.not.i.i.i, label %while.cond.i.i.i, label %do.body.i.i.i, !llvm.loop !4
+
+while.cond.i.i.i:                                 ; preds = %while.body.i.i.i, %do.body.i.i.i
+  %J.0.i.i.i = phi i32 [ %inc.i54.i.i, %while.body.i.i.i ], [ 0, %do.body.i.i.i ]
+  %I.0.in.i.i.i = phi i32 [ %I.0.i.i.i, %while.body.i.i.i ], [ %inc.i.i.i, %do.body.i.i.i ]
+  %I.0.i.i.i = add i32 %I.0.in.i.i.i, -1
+  %cmp.i.i.i = icmp sgt i32 %I.0.i.i.i, %J.0.i.i.i
+  br i1 %cmp.i.i.i, label %while.body.i.i.i, label %enable.exit
+
+while.body.i.i.i:                                 ; preds = %while.cond.i.i.i
+  %idxprom.i52.i.i = sext i32 %I.0.i.i.i to i64
+  %arrayidx.i53.i.i = getelementptr inbounds i8, ptr addrspace(4) %add.ptr.i, i64 %idxprom.i52.i.i
+  %8 = load i8, ptr addrspace(4) %arrayidx.i53.i.i
+  %idxprom1.i.i.i = zext nneg i32 %J.0.i.i.i to i64
+  %arrayidx2.i.i.i = getelementptr inbounds i8, ptr addrspace(4) %add.ptr.i, i64 %idxprom1.i.i.i
+  %9 = load i8, ptr addrspace(4) %arrayidx2.i.i.i
+  store i8 %9, ptr addrspace(4) %arrayidx.i53.i.i
+  store i8 %8, ptr addrspace(4) %arrayidx2.i.i.i
+  %inc.i54.i.i = add nuw nsw i32 %J.0.i.i.i, 1
+  br label %while.cond.i.i.i, !llvm.loop !5
+
+enable.exit: ; preds = %while.cond.i.i.i
+  %add.i = add i32 %Len.0.i47, %inc.i.i.i
+  %cmp2.not.i = icmp eq i32 %I.0.i48, 2
+  br i1 %cmp2.not.i, label %for.inc.i52, label %if.then.i
+
+if.then.i:                                        ; preds = %enable.exit
+  %idx.ext3.i = zext i32 %add.i to i64
+  %add.ptr4.i = getelementptr inbounds i8, ptr addrspace(4) %add.ptr5, i64 %idx.ext3.i
+  br label %for.cond.i.i
+
+for.cond.i.i:                                     ; preds = %for.inc.i.i, %if.then.i
+  %Len.0.i.i = phi i32 [ 0, %if.then.i ], [ %inc.i.i, %for.inc.i.i ]
+  %idxprom.i24.i = zext i32 %Len.0.i.i to i64
+  %arrayidx.i25.i = getelementptr inbounds i8, ptr addrspace(1) @.str.6, i64 %idxprom.i24.i
+  %10 = load i8, ptr addrspace(1) %arrayidx.i25.i
+  %cmp.not.i.i = icmp eq i8 %10, 0
+  br i1 %cmp.not.i.i, label %for.cond1.i.i, label %for.inc.i.i
+
+for.inc.i.i:                                      ; preds = %for.cond.i.i
+  %inc.i.i = add i32 %Len.0.i.i, 1
+  br label %for.cond.i.i, !llvm.loop !1
+
+for.cond1.i.i:                                    ; preds = %for.body3.i.i, %for.cond.i.i
+  %I.0.i.i = phi i32 [ %inc9.i.i, %for.body3.i.i ], [ 0, %for.cond.i.i ]
+  %cmp2.i.i = icmp ult i32 %I.0.i.i, %Len.0.i.i
+  br i1 %cmp2.i.i, label %for.body3.i.i, label %append.exit
+
+for.body3.i.i:                                    ; preds = %for.cond1.i.i
+  %idxprom4.i.i = zext i32 %I.0.i.i to i64
+  %arrayidx5.i.i = getelementptr inbounds i8, ptr addrspace(1) @.str.6, i64 %idxprom4.i.i
+  %11 = load i8, ptr addrspace(1) %arrayidx5.i.i
+  %arrayidx7.i.i = getelementptr inbounds i8, ptr addrspace(4) %add.ptr4.i, i64 %idxprom4.i.i
+  store i8 %11, ptr addrspace(4) %arrayidx7.i.i
+  %inc9.i.i = add nuw i32 %I.0.i.i, 1
+  br label %for.cond1.i.i, !llvm.loop !2
+
+append.exit:          ; preds = %for.cond1.i.i
+  %add6.i = add i32 %add.i, %Len.0.i.i
+  br label %for.inc.i52
+
+for.inc.i52:                                      ; preds = %append.exit, %enable.exit
+  %Len.1.i = phi i32 [ %add6.i, %append.exit ], [ %add.i, %enable.exit ]
+  %inc7.i = add nuw nsw i32 %I.0.i48, 1
+  br label %for.cond.i46, !llvm.loop !6
+
+exit: ; preds = %for.cond.i46
+  %inc8.i = add i32 %Len.0.i47, 1
+  %idxprom9.i = zext i32 %Len.0.i47 to i64
+  %arrayidx10.i = getelementptr inbounds i8, ptr addrspace(4) %add.ptr5, i64 %idxprom9.i
+  store i8 125, ptr addrspace(4) %arrayidx10.i
+  %add9 = add i32 %add3, %inc8.i
+  %inc = add nuw nsw i32 %I.0, 1
+  br label %for.cond, !llvm.loop !7
+}
+
+declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
+declare void @llvm.memcpy.p0.p4.i64(ptr noalias nocapture writeonly, ptr addrspace(4) noalias nocapture readonly, i64, i1 immarg)
+
+!0 = !{!"llvm.loop.mustprogress"}
+!1 = distinct !{!1, !0}
+!2 = distinct !{!2, !0}
+!3 = distinct !{!3, !0}
+!4 = distinct !{!4, !0}
+!5 = distinct !{!5, !0}
+!6 = distinct !{!6, !0}
+!7 = distinct !{!7, !0}

>From 1d1021f13632ce127187d9d3f1ac3f38ea2813d0 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Wed, 2 Oct 2024 05:26:21 -0700
Subject: [PATCH 2/2] Duplicates Tracket accounts for possible changes in
 Constant usage after optimization

---
 .../Target/SPIRV/SPIRVDuplicatesTracker.cpp   | 49 ++++++++++---------
 .../lib/Target/SPIRV/SPIRVDuplicatesTracker.h | 15 ++++--
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h   |  3 +-
 llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp |  2 +-
 4 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp
index 832ca0ba5a82d7..b82c2538a81368 100644
--- a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "SPIRVDuplicatesTracker.h"
+#include "SPIRVInstrInfo.h"
 
 #define DEBUG_TYPE "build-dep-graph"
 
@@ -19,13 +20,14 @@ using namespace llvm;
 
 template <typename T>
 void SPIRVGeneralDuplicatesTracker::prebuildReg2Entry(
-    SPIRVDuplicatesTracker<T> &DT, SPIRVReg2EntryTy &Reg2Entry) {
+    SPIRVDuplicatesTracker<T> &DT, SPIRVReg2EntryTy &Reg2Entry,
+    const SPIRVInstrInfo *TII) {
   for (auto &TPair : DT.getAllUses()) {
     for (auto &RegPair : TPair.second) {
       const MachineFunction *MF = RegPair.first;
       Register R = RegPair.second;
       MachineInstr *MI = MF->getRegInfo().getUniqueVRegDef(R);
-      if (!MI)
+      if (!MI || (TPair.second.getIsConst() && !TII->isConstantInstr(*MI)))
         continue;
       Reg2Entry[&MI->getOperand(0)] = &TPair.second;
     }
@@ -33,16 +35,16 @@ void SPIRVGeneralDuplicatesTracker::prebuildReg2Entry(
 }
 
 void SPIRVGeneralDuplicatesTracker::buildDepsGraph(
-    std::vector<SPIRV::DTSortableEntry *> &Graph,
+    std::vector<SPIRV::DTSortableEntry *> &Graph, const SPIRVInstrInfo *TII,
     MachineModuleInfo *MMI = nullptr) {
   SPIRVReg2EntryTy Reg2Entry;
-  prebuildReg2Entry(TT, Reg2Entry);
-  prebuildReg2Entry(CT, Reg2Entry);
-  prebuildReg2Entry(GT, Reg2Entry);
-  prebuildReg2Entry(FT, Reg2Entry);
-  prebuildReg2Entry(AT, Reg2Entry);
-  prebuildReg2Entry(MT, Reg2Entry);
-  prebuildReg2Entry(ST, Reg2Entry);
+  prebuildReg2Entry(TT, Reg2Entry, TII);
+  prebuildReg2Entry(CT, Reg2Entry, TII);
+  prebuildReg2Entry(GT, Reg2Entry, TII);
+  prebuildReg2Entry(FT, Reg2Entry, TII);
+  prebuildReg2Entry(AT, Reg2Entry, TII);
+  prebuildReg2Entry(MT, Reg2Entry, TII);
+  prebuildReg2Entry(ST, Reg2Entry, TII);
 
   for (auto &Op2E : Reg2Entry) {
     SPIRV::DTSortableEntry *E = Op2E.second;
@@ -65,20 +67,19 @@ void SPIRVGeneralDuplicatesTracker::buildDepsGraph(
         if (MI->getOpcode() == SPIRV::OpConstantFunctionPointerINTEL && i == 2)
           continue;
         MachineOperand *RegOp = &VRegDef->getOperand(0);
-        LLVM_DEBUG({
-          if (Reg2Entry.count(RegOp) == 0 &&
-              (MI->getOpcode() != SPIRV::OpVariable || i != 3)) {
-            dbgs() << "Unexpected pattern while building a dependency "
-                      "graph.\nInstruction: ";
-            MI->print(dbgs());
-            dbgs() << "Operand: ";
-            Op.print(dbgs());
-            dbgs() << "\nOperand definition: ";
-            VRegDef->print(dbgs());
-          }
-        });
-        assert((MI->getOpcode() == SPIRV::OpVariable && i == 3) ||
-               Reg2Entry.count(RegOp));
+        if (Reg2Entry.count(RegOp) == 0 &&
+            (MI->getOpcode() != SPIRV::OpVariable || i != 3)) {
+          std::string DiagMsg;
+          raw_string_ostream OS(DiagMsg);
+          OS << "Unexpected pattern while building a dependency "
+                "graph.\nInstruction: ";
+          MI->print(OS);
+          OS << "Operand: ";
+          Op.print(OS);
+          OS << "\nOperand definition: ";
+          VRegDef->print(OS);
+          report_fatal_error(DiagMsg.c_str());
+        }
         if (Reg2Entry.count(RegOp))
           E->addDep(Reg2Entry[RegOp]);
       }
diff --git a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
index a37e65a47eda04..47391bf63b5947 100644
--- a/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
+++ b/llvm/lib/Target/SPIRV/SPIRVDuplicatesTracker.h
@@ -26,6 +26,7 @@
 
 namespace llvm {
 namespace SPIRV {
+class SPIRVInstrInfo;
 // NOTE: using MapVector instead of DenseMap because it helps getting
 // everything ordered in a stable manner for a price of extra (NumKeys)*PtrSize
 // memory and expensive removals which do not happen anyway.
@@ -35,8 +36,9 @@ class DTSortableEntry : public MapVector<const MachineFunction *, Register> {
   struct FlagsTy {
     unsigned IsFunc : 1;
     unsigned IsGV : 1;
+    unsigned IsConst : 1;
     // NOTE: bit-field default init is a C++20 feature.
-    FlagsTy() : IsFunc(0), IsGV(0) {}
+    FlagsTy() : IsFunc(0), IsGV(0), IsConst(0) {}
   };
   FlagsTy Flags;
 
@@ -45,8 +47,10 @@ class DTSortableEntry : public MapVector<const MachineFunction *, Register> {
   // require hoisting of params as well.
   bool getIsFunc() const { return Flags.IsFunc; }
   bool getIsGV() const { return Flags.IsGV; }
+  bool getIsConst() const { return Flags.IsConst; }
   void setIsFunc(bool V) { Flags.IsFunc = V; }
   void setIsGV(bool V) { Flags.IsGV = V; }
+  void setIsConst(bool V) { Flags.IsConst = V; }
 
   const SmallVector<DTSortableEntry *, 2> &getDeps() const { return Deps; }
   void addDep(DTSortableEntry *E) { Deps.push_back(E); }
@@ -160,6 +164,10 @@ template <typename KeyTy> class SPIRVDuplicatesTrackerBase {
                      typename std::remove_const<
                          typename std::remove_pointer<KeyTy>::type>::type>())
       Storage[V].setIsGV(true);
+    if (std::is_same<Constant,
+                     typename std::remove_const<
+                         typename std::remove_pointer<KeyTy>::type>::type>())
+      Storage[V].setIsConst(true);
   }
 
   Register find(KeyTy V, const MachineFunction *MF) const {
@@ -211,11 +219,12 @@ class SPIRVGeneralDuplicatesTracker {
 
   template <typename T>
   void prebuildReg2Entry(SPIRVDuplicatesTracker<T> &DT,
-                         SPIRVReg2EntryTy &Reg2Entry);
+                         SPIRVReg2EntryTy &Reg2Entry,
+                         const SPIRVInstrInfo *TII);
 
 public:
   void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph,
-                      MachineModuleInfo *MMI);
+                      const SPIRVInstrInfo *TII, MachineModuleInfo *MMI);
 
   void add(const Type *Ty, const MachineFunction *MF, Register R) {
     TT.add(unifyPtrType(Ty), MF, R);
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index ace5cfe91ebe48..d301e119e16c8e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -152,8 +152,9 @@ class SPIRVGlobalRegistry {
   }
 
   void buildDepsGraph(std::vector<SPIRV::DTSortableEntry *> &Graph,
+                      const SPIRVInstrInfo *TII,
                       MachineModuleInfo *MMI = nullptr) {
-    DT.buildDepsGraph(Graph, MMI);
+    DT.buildDepsGraph(Graph, TII, MMI);
   }
 
   void setBound(unsigned V) { Bound = V; }
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 8908d8965b67c5..2083f18da9c590 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -282,7 +282,7 @@ void SPIRVModuleAnalysis::collectGlobalEntities(
 void SPIRVModuleAnalysis::processDefInstrs(const Module &M) {
   std::vector<SPIRV::DTSortableEntry *> DepsGraph;
 
-  GR->buildDepsGraph(DepsGraph, SPVDumpDeps ? MMI : nullptr);
+  GR->buildDepsGraph(DepsGraph, TII, SPVDumpDeps ? MMI : nullptr);
 
   collectGlobalEntities(
       DepsGraph, SPIRV::MB_TypeConstVars,



More information about the llvm-commits mailing list