Module: Mesa
Branch: main
Commit: dca65f62c8d2d3b76cd974802852b5d8441344f2
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=dca65f62c8d2d3b76cd974802852b5d8441344f2

Author: Faith Ekstrand <faith.ekstr...@collabora.com>
Date:   Fri Dec  1 13:22:44 2023 -0600

nak: Add support for spilling barriers

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26463>

---

 src/nouveau/compiler/nak_assign_regs.rs      | 18 ++++++++++----
 src/nouveau/compiler/nak_lower_copy_swap.rs  | 20 +++++++++++++++
 src/nouveau/compiler/nak_lower_par_copies.rs |  7 +++---
 src/nouveau/compiler/nak_spill_values.rs     | 37 ++++++++++++++++++++++++++++
 4 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/src/nouveau/compiler/nak_assign_regs.rs 
b/src/nouveau/compiler/nak_assign_regs.rs
index c4b5752785b..9bda8a4cae4 100644
--- a/src/nouveau/compiler/nak_assign_regs.rs
+++ b/src/nouveau/compiler/nak_assign_regs.rs
@@ -1154,7 +1154,10 @@ impl Shader {
         let mut live = SimpleLiveness::for_function(f);
         let mut max_live = live.calc_max_live(f);
 
-        let spill_files = [RegFile::Pred];
+        // We want at least one temporary GPR reserved for parallel copies.
+        let mut tmp_gprs = 1_u8;
+
+        let spill_files = [RegFile::Pred, RegFile::Bar];
         for file in spill_files {
             let num_regs = file.num_regs(self.info.sm);
             if max_live[file] > num_regs {
@@ -1163,14 +1166,19 @@ impl Shader {
                 // Re-calculate liveness after we spill
                 live = SimpleLiveness::for_function(f);
                 max_live = live.calc_max_live(f);
+
+                match file {
+                    RegFile::Bar => {
+                        tmp_gprs = max(tmp_gprs, 2);
+                    }
+                    _ => (),
+                }
             }
         }
 
         // An instruction can have at most 4 vector sources/destinations.  In
         // order to ensure we always succeed at allocation, regardless of
-        // arbitrary choices, we need at least 16 GPRs.  We also want at least
-        // one temporary GPR reserved for parallel copies.
-        let mut tmp_gprs = 1_u8;
+        // arbitrary choices, we need at least 16 GPRs.
         let mut gpr_limit = max(max_live[RegFile::GPR], 16);
         let mut total_gprs = gpr_limit + u32::from(tmp_gprs);
 
@@ -1179,7 +1187,7 @@ impl Shader {
             // If we're spilling GPRs, we need to reserve 2 GPRs for OpParCopy
             // lowering because it needs to be able lower Mem copies which
             // require a temporary
-            tmp_gprs = 2_u8;
+            tmp_gprs = max(tmp_gprs, 2);
             total_gprs = max_gprs;
             gpr_limit = total_gprs - u32::from(tmp_gprs);
 
diff --git a/src/nouveau/compiler/nak_lower_copy_swap.rs 
b/src/nouveau/compiler/nak_lower_copy_swap.rs
index 476310cc457..e6300426bef 100644
--- a/src/nouveau/compiler/nak_lower_copy_swap.rs
+++ b/src/nouveau/compiler/nak_lower_copy_swap.rs
@@ -43,6 +43,13 @@ impl LowerCopySwap {
                             quad_lanes: 0xf,
                         });
                     }
+                    RegFile::Bar => {
+                        b.push_op(OpBMov {
+                            dst: copy.dst,
+                            src: copy.src,
+                            clear: false,
+                        });
+                    }
                     RegFile::Mem => {
                         let access = MemAccess {
                             mem_type: MemType::B32,
@@ -96,6 +103,19 @@ impl LowerCopySwap {
                 },
                 SrcRef::SSA(_) => panic!("Should be run after RA"),
             },
+            RegFile::Bar => match copy.src.src_ref {
+                SrcRef::Reg(src_reg) => match src_reg.file() {
+                    RegFile::GPR => {
+                        b.push_op(OpBMov {
+                            dst: copy.dst,
+                            src: copy.src,
+                            clear: false,
+                        });
+                    }
+                    _ => panic!("Cannot copy to Bar"),
+                },
+                _ => panic!("Cannot copy to Bar"),
+            },
             RegFile::Mem => match copy.src.src_ref {
                 SrcRef::Reg(src_reg) => match src_reg.file() {
                     RegFile::GPR => {
diff --git a/src/nouveau/compiler/nak_lower_par_copies.rs 
b/src/nouveau/compiler/nak_lower_par_copies.rs
index 28176da3c28..c28f7a98d61 100644
--- a/src/nouveau/compiler/nak_lower_par_copies.rs
+++ b/src/nouveau/compiler/nak_lower_par_copies.rs
@@ -62,7 +62,8 @@ impl CopyGraph {
 
 fn copy_needs_tmp(dst: &RegRef, src: &SrcRef) -> bool {
     if let Some(src_reg) = src.as_reg() {
-        dst.file() == RegFile::Mem && src_reg.file() == RegFile::Mem
+        (dst.file() == RegFile::Mem && src_reg.file() == RegFile::Mem)
+            || (dst.file() == RegFile::Bar && src_reg.file() == RegFile::Bar)
     } else {
         false
     }
@@ -78,7 +79,7 @@ fn cycle_use_swap(pc: &OpParCopy, file: RegFile) -> bool {
                 true
             }
         }
-        RegFile::Mem => {
+        RegFile::Bar | RegFile::Mem => {
             let tmp = &pc.tmp.expect("This copy needs a temporary");
             assert!(tmp.comps() >= 2, "Memory cycles need 2 temporaries");
             false
@@ -230,7 +231,7 @@ fn lower_par_copy(pc: OpParCopy) -> MappedInstrs {
                 let j_reg = *vals[j].as_reg().unwrap();
                 debug_assert!(j_reg.file() == file);
 
-                if file == RegFile::Mem {
+                if file == RegFile::Bar || file == RegFile::Mem {
                     let copy_tmp = pc_tmp.comp(1);
                     b.copy_to(copy_tmp.into(), j_reg.into());
                     b.copy_to(p_reg.into(), copy_tmp.into());
diff --git a/src/nouveau/compiler/nak_spill_values.rs 
b/src/nouveau/compiler/nak_spill_values.rs
index ea8240da355..9c398f3aa26 100644
--- a/src/nouveau/compiler/nak_spill_values.rs
+++ b/src/nouveau/compiler/nak_spill_values.rs
@@ -138,6 +138,39 @@ impl Spill for SpillPred {
     }
 }
 
+struct SpillBar {}
+
+impl SpillBar {
+    fn new() -> Self {
+        Self {}
+    }
+}
+
+impl Spill for SpillBar {
+    fn spill_file(&self, file: RegFile) -> RegFile {
+        assert!(file == RegFile::Bar);
+        RegFile::GPR
+    }
+
+    fn spill(&self, dst: SSAValue, src: Src) -> Box<Instr> {
+        assert!(dst.file() == RegFile::GPR);
+        Instr::new_boxed(OpBMov {
+            dst: dst.into(),
+            src: src.into(),
+            clear: false,
+        })
+    }
+
+    fn fill(&self, dst: Dst, src: SSAValue) -> Box<Instr> {
+        assert!(src.file() == RegFile::GPR);
+        Instr::new_boxed(OpBMov {
+            dst: dst.into(),
+            src: src.into(),
+            clear: false,
+        })
+    }
+}
+
 struct SpillGPR {}
 
 impl SpillGPR {
@@ -864,6 +897,10 @@ impl Function {
                 let spill = SpillPred::new();
                 spill_values(self, file, limit, spill);
             }
+            RegFile::Bar => {
+                let spill = SpillBar::new();
+                spill_values(self, file, limit, spill);
+            }
             _ => panic!("Don't know how to spill {} registers", file),
         }
 

Reply via email to