• Home
Name Date Size #Lines LOC

..--

tests/03-May-2024-3,4152,297

README-ISA.mdD03-May-20247.5 KiB230151

README.mdD03-May-202415.9 KiB262180

aco_assembler.cppD03-May-202435.8 KiB955833

aco_builder_h.pyD03-May-202419.1 KiB564500

aco_dead_code_analysis.cppD03-May-20243.4 KiB10962

aco_dominance.cppD03-May-20243.1 KiB9446

aco_form_hard_clauses.cppD03-May-20243.7 KiB11269

aco_insert_NOPs.cppD03-May-202433.6 KiB816606

aco_insert_exec_mask.cppD03-May-202446.1 KiB1,154899

aco_insert_waitcnt.cppD03-May-202433.9 KiB1,016804

aco_instruction_selection.cppD03-May-2024501.4 KiB12,01110,013

aco_instruction_selection.hD03-May-20247.5 KiB229159

aco_instruction_selection_setup.cppD03-May-202450.2 KiB1,188994

aco_interface.cppD03-May-20248.7 KiB241163

aco_interface.hD03-May-20241.7 KiB5624

aco_ir.cppD03-May-202412.1 KiB410343

aco_ir.hD03-May-202455.5 KiB1,8121,370

aco_live_var_analysis.cppD03-May-202414.4 KiB408296

aco_lower_phis.cppD03-May-202411 KiB300225

aco_lower_to_cssa.cppD03-May-20248.4 KiB213133

aco_lower_to_hw_instr.cppD03-May-202491 KiB2,0241,649

aco_opcodes.pyD03-May-202479.8 KiB1,6571,490

aco_opcodes_cpp.pyD03-May-20242.7 KiB8777

aco_opcodes_h.pyD03-May-20241.6 KiB4840

aco_opt_value_numbering.cppD03-May-202419 KiB496396

aco_optimizer.cppD03-May-2024122.5 KiB3,2952,717

aco_print_asm.cppD03-May-20247.7 KiB250206

aco_print_ir.cppD03-May-202430.7 KiB892856

aco_reduce_assign.cppD03-May-20246.8 KiB161100

aco_register_allocation.cppD03-May-202496.6 KiB2,4871,993

aco_scheduler.cppD03-May-202433.4 KiB954710

aco_spill.cppD03-May-202478 KiB1,8071,392

aco_ssa_elimination.cppD03-May-202410.7 KiB303219

aco_statistics.cppD03-May-20243.5 KiB8949

aco_util.hD03-May-202410.9 KiB386215

aco_validate.cppD03-May-202441.6 KiB897754

meson.buildD03-May-20243.3 KiB114101

README-ISA.md

1# Unofficial GCN/RDNA ISA reference errata
2
3## `v_sad_u32`
4
5The Vega ISA reference writes its behaviour as:
6
7```
8D.u = abs(S0.i - S1.i) + S2.u.
9```
10
11This is incorrect. The actual behaviour is what is written in the GCN3 reference
12guide:
13
14```
15ABS_DIFF (A,B) = (A>B) ? (A-B) : (B-A)
16D.u = ABS_DIFF (S0.u,S1.u) + S2.u
17```
18
19The instruction doesn't subtract the S0 and S1 and use the absolute value (the
20_signed_ distance), it uses the _unsigned_ distance between the operands. So
21`v_sad_u32(-5, 0, 0)` would return `4294967291` (`-5` interpreted as unsigned),
22not `5`.
23
24## `s_bfe_*`
25
26Both the RDNA, Vega and GCN3 ISA references write that these instructions don't write
27SCC. They do.
28
29## `v_bcnt_u32_b32`
30
31The Vega ISA reference writes its behaviour as:
32
33```
34D.u = 0;
35for i in 0 ... 31 do
36D.u += (S0.u[i] == 1 ? 1 : 0);
37endfor.
38```
39
40This is incorrect. The actual behaviour (and number of operands) is what
41is written in the GCN3 reference guide:
42
43```
44D.u = CountOneBits(S0.u) + S1.u.
45```
46
47## SMEM stores
48
49The Vega ISA references doesn't say this (or doesn't make it clear), but
50the offset for SMEM stores must be in m0 if IMM == 0.
51
52The RDNA ISA doesn't mention SMEM stores at all, but they seem to be supported
53by the chip and are present in LLVM. AMD devs however highly recommend avoiding
54these instructions.
55
56## SMEM atomics
57
58RDNA ISA: same as the SMEM stores, the ISA pretends they don't exist, but they
59are there in LLVM.
60
61## VMEM stores
62
63All reference guides say (under "Vector Memory Instruction Data Dependencies"):
64
65> When a VM instruction is issued, the address is immediately read out of VGPRs
66> and sent to the texture cache. Any texture or buffer resources and samplers
67> are also sent immediately. However, write-data is not immediately sent to the
68> texture cache.
69
70Reading that, one might think that waitcnts need to be added when writing to
71the registers used for a VMEM store's data. Experimentation has shown that this
72does not seem to be the case on GFX8 and GFX9 (GFX6 and GFX7 are untested). It
73also seems unlikely, since NOPs are apparently needed in a subset of these
74situations.
75
76## MIMG opcodes on GFX8/GCN3
77
78The `image_atomic_{swap,cmpswap,add,sub}` opcodes in the GCN3 ISA reference
79guide are incorrect. The Vega ISA reference guide has the correct ones.
80
81## VINTRP encoding
82
83VEGA ISA doc says the encoding should be `110010` but `110101` works.
84
85## VOP1 instructions encoded as VOP3
86
87RDNA ISA doc says that `0x140` should be added to the opcode, but that doesn't
88work. What works is adding `0x180`, which LLVM also does.
89
90## FLAT, Scratch, Global instructions
91
92The NV bit was removed in RDNA, but some parts of the doc still mention it.
93
94RDNA ISA doc 13.8.1 says that SADDR should be set to 0x7f when ADDR is used, but
959.3.1 says it should be set to NULL. We assume 9.3.1 is correct and set it to
96SGPR_NULL.
97
98## Legacy instructions
99
100Some instructions have a `_LEGACY` variant which implements "DX9 rules", in which
101the zero "wins" in multiplications, ie. `0.0*x` is always `0.0`. The VEGA ISA
102mentions `V_MAC_LEGACY_F32` but this instruction is not really there on VEGA.
103
104## RDNA L0, L1 cache and DLC, GLC bits
105
106The old L1 cache was renamed to L0, and a new L1 cache was added to RDNA. The
107L1 cache is 1 cache per shader array. Some instruction encodings have DLC and
108GLC bits that interact with the cache.
109
110* DLC ("device level coherent") bit: controls the L1 cache
111* GLC ("globally coherent") bit: controls the L0 cache
112
113The recommendation from AMD devs is to always set these two bits at the same time,
114as it doesn't make too much sense to set them independently, aside from some
115circumstances (eg. we needn't set DLC when only one shader array is used).
116
117Stores and atomics always bypass the L1 cache, so they don't support the DLC bit,
118and it shouldn't be set in these cases. Setting the DLC for these cases can result
119in graphical glitches or hangs.
120
121## RDNA `s_dcache_wb`
122
123The `s_dcache_wb` is not mentioned in the RDNA ISA doc, but it is needed in order
124to achieve correct behavior in some SSBO CTS tests.
125
126## RDNA subvector mode
127
128The documentation of `s_subvector_loop_begin` and `s_subvector_mode_end` is not clear
129on what sort of addressing should be used, but it says that it
130"is equivalent to an `S_CBRANCH` with extra math", so the subvector loop handling
131in ACO is done according to the `s_cbranch` doc.
132
133# Hardware Bugs
134
135## SMEM corrupts VCCZ on SI/CI
136
137[See this LLVM source.](https://github.com/llvm/llvm-project/blob/acb089e12ae48b82c0b05c42326196a030df9b82/llvm/lib/Target/AMDGPU/SIInsertWaits.cpp#L580-L616)
138
139After issuing a SMEM instructions, we need to wait for the SMEM instructions to
140finish and then write to vcc (for example, `s_mov_b64 vcc, vcc`) to correct vccz
141
142Currently, we don't do this.
143
144## GCN / GFX6 hazards
145
146### VINTRP followed by a read with `v_readfirstlane` or `v_readlane`
147
148It's required to insert 1 wait state if the dst VGPR of any  `v_interp_*` is
149followed by a read with `v_readfirstlane` or `v_readlane` to fix GPU hangs on GFX6.
150Note that `v_writelane_*` is apparently not affected. This hazard isn't
151documented anywhere but AMD confirmed it.
152
153## RDNA / GFX10 hazards
154
155### SMEM store followed by a load with the same address
156
157We found that an `s_buffer_load` will produce incorrect results if it is preceded
158by an `s_buffer_store` with the same address. Inserting an `s_nop` between them
159does not mitigate the issue, so an `s_waitcnt lgkmcnt(0)` must be inserted.
160This is not mentioned by LLVM among the other GFX10 bugs, but LLVM doesn't use
161SMEM stores, so it's not surprising that they didn't notice it.
162
163### VMEMtoScalarWriteHazard
164
165Triggered by:
166VMEM/FLAT/GLOBAL/SCRATCH/DS instruction reads an SGPR (or EXEC, or M0).
167Then, a SALU/SMEM instruction writes the same SGPR.
168
169Mitigated by:
170A VALU instruction or an `s_waitcnt vmcnt(0)` between the two instructions.
171
172### SMEMtoVectorWriteHazard
173
174Triggered by:
175An SMEM instruction reads an SGPR. Then, a VALU instruction writes that same SGPR.
176
177Mitigated by:
178Any non-SOPP SALU instruction (except `s_setvskip`, `s_version`, and any non-lgkmcnt `s_waitcnt`).
179
180### Offset3fBug
181
182Any branch that is located at offset 0x3f will be buggy. Just insert some NOPs to make sure no branch
183is located at this offset.
184
185### InstFwdPrefetchBug
186
187According to LLVM, the `s_inst_prefetch` instruction can cause a hang.
188There are no further details.
189
190### LdsMisalignedBug
191
192When there is a misaligned multi-dword FLAT load/store instruction in WGP mode,
193it needs to be split into multiple single-dword FLAT instructions.
194
195ACO doesn't use FLAT load/store on GFX10, so is unaffected.
196
197### FlatSegmentOffsetBug
198
199The 12-bit immediate OFFSET field of FLAT instructions must always be 0.
200GLOBAL and SCRATCH are unaffected.
201
202ACO doesn't use FLAT load/store on GFX10, so is unaffected.
203
204### VcmpxPermlaneHazard
205
206Triggered by:
207Any permlane instruction that follows any VOPC instruction.
208Confirmed by AMD devs that despite the name, this doesn't only affect v_cmpx.
209
210Mitigated by: any VALU instruction except `v_nop`.
211
212### VcmpxExecWARHazard
213
214Triggered by:
215Any non-VALU instruction reads the EXEC mask. Then, any VALU instruction writes the EXEC mask.
216
217Mitigated by:
218A VALU instruction that writes an SGPR (or has a valid SDST operand), or `s_waitcnt_depctr 0xfffe`.
219Note: `s_waitcnt_depctr` is an internal instruction, so there is no further information
220about what it does or what its operand means.
221
222### LdsBranchVmemWARHazard
223
224Triggered by:
225VMEM/GLOBAL/SCRATCH instruction, then a branch, then a DS instruction,
226or vice versa: DS instruction, then a branch, then a VMEM/GLOBAL/SCRATCH instruction.
227
228Mitigated by:
229Only `s_waitcnt_vscnt null, 0`. Needed even if the first instruction is a load.
230

README.md

1# Welcome to ACO
2
3ACO (short for *AMD compiler*) is a back-end compiler for AMD GCN / RDNA GPUs, based on the NIR compiler infrastructure.
4Simply put, ACO translates shader programs from the NIR intermediate representation into a GCN / RDNA binary which the GPU can execute.
5
6## Motivation
7
8Why did we choose to develop a new compiler backend?
9
101. We'd like to give gamers a fluid, stutter-free experience, so we prioritize compilation speed.
112. Good divergence analysis allows us to better optimize runtime performance.
123. Issues can be fixed within mesa releases, independently of the schedule of other projects.
13
14## Control flow
15
16Modern GPUs are SIMD machines that execute the shader in parallel.
17In case of GCN / RDNA the parallelism is achieved by executing the shader on several waves, and each wave has several lanes (32 or 64).
18When every lane executes exactly the same instructions, and takes the same path, it's uniform control flow;
19otherwise when some lanes take one path while other lanes take a different path, it's divergent.
20
21Each hardware lane corresponds to a shader invocation from a software perspective.
22
23The hardware doesn't directly support divergence,
24so in case of divergent control flow, the GPU must execute both code paths, each with some lanes disabled.
25This is why divergence is a performance concern in shader programming.
26
27ACO deals with divergent control flow by maintaining two control flow graphs (CFG):
28
29* logical CFG - directly translated from NIR and shows the intended control flow of the program.
30* linear CFG - created according to Whole-Function Vectorization by Ralf Karrenberg and Sebastian Hack.
31  The linear CFG represents how the program is physically executed on GPU and may contain additional blocks for control flow handling and to avoid critical edges.
32  Note that all nodes of the logical CFG also participate in the linear CFG, but not vice versa.
33
34## Compilation phases
35
36#### Instruction Selection
37
38The instruction selection is based around the divergence analysis and works in 3 passes on the NIR shader.
39
401. The divergence analysis pass calculates for each SSA definition if its value is guaranteed to be uniform across all threads of the workgroup.
412. We determine the register class for each SSA definition.
423. Actual instruction selection. The advanced divergence analysis allows for better usage of the scalar unit, scalar memory loads and the scalar register file.
43
44We have two types of instructions:
45
46* Hardware instructions as specified by the GCN / RDNA instruction set architecture manuals.
47* Pseudo instructions which are helpers that encapsulate more complex functionality.
48  They eventually get lowered to real hardware instructions.
49
50Each instruction can have operands (temporaries that it reads), and definitions (temporaries that it writes).
51Temporaries can be fixed to a specific register, or just specify a register class (either a single register, or a vector of several registers).
52
53#### Value Numbering
54
55The value numbering pass is necessary for two reasons: the lack of descriptor load representation in NIR,
56and every NIR instruction that gets emitted as multiple ACO instructions also has potential for CSE.
57This pass does dominator-tree value numbering.
58
59#### Optimization
60
61In this phase, simpler instructions are combined into more complex instructions (like the different versions of multiply-add as well as neg, abs, clamp, and output modifiers) and constants are inlined, moves are eliminated, etc.
62Exactly which optimizations are performed depends on the hardware for which the shader is being compiled.
63
64#### Setup of reduction temporaries
65
66This pass is responsible for making sure that register allocation is correct for reductions, by adding pseudo instructions that utilize linear VGPRs.
67When a temporary has a linear VGPR register class, this means that the variable is considered *live* in the linear control flow graph.
68
69#### Insert exec mask
70
71In the GCN/RDNA architecture, there is a special register called `exec` which is used for manually controlling which VALU threads (aka. *lanes*) are active. The value of `exec` has to change in divergent branches, loops, etc. and it needs to be restored after the branch or loop is complete. This pass ensures that the correct lanes are active in every branch.
72
73#### Live-Variable Analysis
74
75A live-variable analysis is used to calculate the register need of the shader.
76This information is used for spilling and scheduling before register allocation.
77
78#### Spilling
79
80First, we lower the shader program to CSSA form.
81Then, if the register demand exceeds the global limit, this pass lowers register usage by temporarily storing excess scalar values in free vector registers, or excess vector values in scratch memory, and reloading them when needed. It is based on the paper "Register Spilling and Live-Range Splitting for SSA-Form Programs".
82
83#### Instruction Scheduling
84
85Scheduling is another NP-complete problem where basically all known heuristics suffer from unpredictable change in register pressure. For that reason, the implemented scheduler does not completely re-schedule all instructions, but only aims to move up memory loads as far as possible without exceeding the maximum register limit for the pre-calculated wave count. The reason this works is that ILP is very limited on GCN. This approach looks promising so far.
86
87#### Register Allocation
88
89The register allocator works on SSA (as opposed to LLVM's which works on virtual registers). The SSA properties guarantee that there are always as many registers available as needed. The problem is that some instructions require a vector of neighboring registers to be available, but the free regs might be scattered. In this case, the register allocator inserts shuffle code (moving some temporaries to other registers) to make space for the variable. The assumption is that it is (almost) always better to have a few more moves than to sacrifice a wave. The RA does SSA-reconstruction on the fly, which makes its runtime linear.
90
91#### SSA Elimination
92
93The next step is a pass out of SSA by inserting parallelcopies at the end of blocks to match the phi nodes' semantics.
94
95#### Lower to HW instructions
96
97Most pseudo instructions are lowered to actual machine instructions.
98These are mostly parallel copy instructions created by instruction selection or register allocation and spill/reload code.
99
100#### Insert wait states
101
102GCN requires some wait states to be manually inserted in order to ensure correct behavior on memory instructions and some register dependencies.
103This means that we need to insert `s_waitcnt` instructions (and its variants) so that the shader program waits until the eg. a memory operation is complete.
104
105#### Resolve hazards and insert NOPs
106
107Some instructions require wait states or other instructions to resolve hazards which are not handled by the hardware.
108This pass makes sure that no known hazards occour.
109
110#### Emit program - Assembler
111
112The assembler emits the actual binary that will be sent to the hardware for execution. ACO's assembler is straight-forward because all instructions have their format, opcode, registers and potential fields already available, so it only needs to cater to the some differences between each hardware generation.
113
114## Supported shader stages
115
116Hardware stages (as executed on the chip) don't exactly match software stages (as defined in OpenGL / Vulkan).
117Which software stage gets executed on which hardware stage depends on what kind of software stages are present in the current pipeline.
118
119An important difference is that VS is always the first stage to run in SW models,
120whereas HW VS refers to the last HW stage before fragment shading in GCN/RDNA terminology.
121That's why, among other things, the HW VS is no longer used to execute the SW VS when tesselation or geometry shading are used.
122
123#### Glossary of software stages
124
125* VS = Vertex Shader
126* TCS = Tessellation Control Shader, equivalent to D3D HS = Hull Shader
127* TES = Tessellation Evaluation Shader, equivalent to D3D DS = Domain Shader
128* GS = Geometry Shader
129* FS = Fragment Shader, equivalent to D3D PS = Pixel Shader
130* CS = Compute Shader
131
132#### Glossary of hardware stages
133
134* LS = Local Shader (merged into HS on GFX9+), only runs SW VS when tessellation is used
135* HS = Hull Shader, the HW equivalent of a Tessellation Control Shader, runs before the fixed function hardware performs tessellation
136* ES = Export Shader (merged into GS on GFX9+), if there is a GS in the SW pipeline, the preceding stage (ie. SW VS or SW TES) always has to run on this HW stage
137* GS = Geometry Shader, also known as legacy GS
138* VS = Vertex Shader, **not equivalent to SW VS**: when there is a GS in the SW pipeline this stage runs a "GS copy" shader, otherwise it always runs the SW stage before FS
139* NGG = Next Generation Geometry, a new hardware stage that replaces legacy HW GS and HW VS on RDNA GPUs
140* PS = Pixel Shader, the HW equivalent to SW FS
141* CS = Compute Shader
142
143##### Notes about HW VS and the "GS copy" shader
144
145HW PS reads its inputs from a special buffer that only HW VS can write to, using export instructions.
146However, GS store their output in VRAM (except GFX10/NGG).
147So in order for HW PS to be able to read the GS outputs, we must run something on the VS stage which reads the GS outputs
148from VRAM and exports them to this special buffer. This is what we call a "GS copy" shader.
149From a HW perspective the "GS copy" shader is in fact VS (it runs on the HW VS stage),
150but from a SW perspective it's not part of the traditional pipeline,
151it's just some "glue code" that we need for outputs to play nicely.
152
153On GFX10/NGG this limitation no longer exists, as the HW NGG GS can now export directly where it needs to.
154
155##### Notes about merged shaders
156
157The merged stages on GFX9 (and GFX10/legacy) are: LSHS and ESGS. On GFX10/NGG the ESGS is merged with HW VS into NGG GS.
158
159This might be confusing due to a mismatch between the number of invocations of these shaders.
160For example, ES is per-vertex, but GS is per-primitive.
161This is why merged shaders get an argument called `merged_wave_info` which tells how many invocations each part needs,
162and there is some code at the beginning of each part to ensure the correct number of invocations by disabling some threads.
163So, think about these as two independent shader programs slapped together.
164
165### Which software stage runs on which hardware stage?
166
167#### Graphics Pipeline
168
169##### GFX6-8:
170
171* Each SW stage has its own HW stage
172* LS and HS share the same LDS space, so LS can store its output to LDS, where HS can read it
173* HS, ES, GS outputs are stored in VRAM, next stage reads these from VRAM
174* GS outputs got to VRAM, so they have to be copied by a GS copy shader running on the HW VS stage
175
176| GFX6-8 HW stages:       | LS  | HS  | ES  | GS  | VS     | PS | ACO terminology |
177| -----------------------:|:----|:----|:----|:----|:-------|:---|:----------------|
178| SW stages: only VS+PS:  |     |     |     |     | VS     | FS | `vertex_vs`, `fragment_fs` |
179|            with tess:   | VS  | TCS |     |     | TES    | FS | `vertex_ls`, `tess_control_hs`, `tess_eval_vs`, `fragment_fs` |
180|            with GS:     |     |     | VS  | GS  | GS copy| FS | `vertex_es`, `geometry_gs`, `gs_copy_vs`, `fragment_fs` |
181|            with both:   | VS  | TCS | TES | GS  | GS copy| FS | `vertex_ls`, `tess_control_hs`, `tess_eval_es`, `geometry_gs`, `gs_copy_vs`, `fragment_fs` |
182
183##### GFX9+ (including GFX10/legacy):
184
185* HW LS and HS stages are merged, and the merged shader still uses LDS in the same way as before
186* HW ES and GS stages are merged, so ES outputs can go to LDS instead of VRAM
187* LSHS outputs and ESGS outputs are still stored in VRAM, so a GS copy shader is still necessary
188
189| GFX9+ HW stages:        | LSHS      | ESGS      | VS     | PS | ACO terminology |
190| -----------------------:|:----------|:----------|:-------|:---|:----------------|
191| SW stages: only VS+PS:  |           |           | VS     | FS | `vertex_vs`, `fragment_fs` |
192|            with tess:   | VS + TCS  |           | TES    | FS | `vertex_tess_control_hs`, `tess_eval_vs`, `fragment_fs` |
193|            with GS:     |           | VS + GS   | GS copy| FS | `vertex_geometry_gs`, `gs_copy_vs`, `fragment_fs` |
194|            with both:   | VS + TCS  | TES + GS  | GS copy| FS | `vertex_tess_control_hs`, `tess_eval_geometry_gs`, `gs_copy_vs`, `fragment_fs` |
195
196##### NGG (GFX10+ only):
197
198 * HW GS and VS stages are now merged, and NGG GS can export directly
199 * GS copy shaders are no longer needed
200
201| GFX10/NGG HW stages:    | LSHS      | NGG GS             | PS | ACO terminology |
202| -----------------------:|:----------|:-------------------|:---|:----------------|
203| SW stages: only VS+PS:  |           | VS                 | FS | `vertex_ngg`, `fragment_fs` |
204|            with tess:   | VS + TCS  | TES                | FS | `vertex_tess_control_hs`, `tess_eval_ngg`, `fragment_fs` |
205|            with GS:     |           | VS + GS            | FS | `vertex_geometry_ngg`, `fragment_fs` |
206|            with both:   | VS + TCS  | TES + GS           | FS | `vertex_tess_control_hs`, `tess_eval_geometry_ngg`, `fragment_fs` |
207
208#### Compute pipeline
209
210GFX6-10:
211
212* Note that the SW CS always runs on the HW CS stage on all HW generations.
213
214| GFX6-10 HW stage        | CS   | ACO terminology |
215| -----------------------:|:-----|:----------------|
216| SW stage                | CS   | `compute_cs`    |
217
218
219## How to debug
220
221Handy `RADV_DEBUG` options that help with ACO debugging:
222
223* `nocache` - you always want to use this when debugging, otherwise you risk using a broken shader from the cache.
224* `shaders` - makes ACO print the IR after register allocation, as well as the disassembled shader binary.
225* `metashaders` - does the same thing as `shaders` but for built-in RADV shaders.
226* `preoptir` - makes ACO print the final NIR shader before instruction selection, as well as the ACO IR after instruction selection.
227* `nongg` - disables NGG support
228
229We also have `ACO_DEBUG` options:
230
231* `validateir` - Validate the ACO IR between compilation stages. By default, enabled in debug builds and disabled in release builds.
232* `validatera` - Perform a RA (register allocation) validation.
233* `perfwarn` - Warn when sub-optimal instructions are found.
234* `force-waitcnt` - Forces ACO to emit a wait state after each instruction when there is something to wait for. Harms performance.
235* `novn` - Disables the ACO value numbering stage.
236* `noopt` - Disables the ACO optimizer.
237* `nosched` - Disables the ACO scheduler.
238
239Note that you need to **combine these options into a comma-separated list**, for example: `RADV_DEBUG=nocache,shaders` otherwise only the last one will take effect. (This is how all environment variables work, yet this is an often made mistake.) Example:
240
241```
242RADV_DEBUG=nocache,shaders ACO_DEBUG=validateir,validatera vkcube
243```
244
245Here are some good practices we learned while debugging visual corruption and hangs.
246
2471. Bisecting shaders:
248    * Use renderdoc when examining shaders. This is deterministic while real games often use multi-threading or change the order in which shaders get compiled.
249    * Edit `radv_shader.c` or `radv_pipeline.c` to change if they are compiled with LLVM or ACO.
2502. Things to check early:
251    * Disable value_numbering, optimizer and/or scheduler.
252      Note that if any of these change the output, it does not necessarily mean that the error is there, as register assignment does also change.
2533. Finding the instruction causing a hang:
254    * The ability to directly manipulate the binaries gives us an easy way to find the exact instruction which causes the hang.
255      Use NULL exports (for FS and VS) and `s_endpgm` to end the shader early to find the problematic instruction.
2564. Other faulty instructions:
257    * Use print_asm and check for illegal instructions.
258    * Compare to the ACO IR to see if the assembly matches what we want (this can take a while).
259      Typical issues might be a wrong instruction format leading to a wrong opcode or an sgpr used for vgpr field.
2605. Comparing to the LLVM backend:
261   * If everything else didn't help, we probably just do something wrong. The LLVM backend is quite mature, so its output might help find differences, but this can be a long road.
262