1/* 2 * Copyright © 2020 Valve Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 */ 24#include "helpers.h" 25 26using namespace aco; 27 28void create_mubuf(unsigned offset) 29{ 30 bld.mubuf(aco_opcode::buffer_load_dword, Definition(PhysReg(256), v1), Operand(PhysReg(0), s4), 31 Operand(PhysReg(256), v1), Operand::zero(), offset, true); 32} 33 34void create_mimg(bool nsa, unsigned addrs, unsigned instr_dwords) 35{ 36 aco_ptr<MIMG_instruction> mimg{create_instruction<MIMG_instruction>( 37 aco_opcode::image_sample, Format::MIMG, 3 + addrs, 1)}; 38 mimg->definitions[0] = Definition(PhysReg(256), v1); 39 mimg->operands[0] = Operand(PhysReg(0), s8); 40 mimg->operands[1] = Operand(PhysReg(0), s4); 41 mimg->operands[2] = Operand(v1); 42 for (unsigned i = 0; i < addrs; i++) 43 mimg->operands[3 + i] = Operand(PhysReg(256 + (nsa ? i * 2 : i)), v1); 44 mimg->dmask = 0x1; 45 mimg->dim = ac_image_2d; 46 47 assert(get_mimg_nsa_dwords(mimg.get()) + 2 == instr_dwords); 48 49 bld.insert(std::move(mimg)); 50} 51 52BEGIN_TEST(insert_nops.nsa_to_vmem_bug) 53 if (!setup_cs(NULL, GFX10)) 54 return; 55 56 /* no nop needed because offset&6==0 */ 57 //>> p_unit_test 0 58 //! v1: %0:v[0] = image_sample %0:s[0-7], %0:s[0-3], v1: undef, %0:v[0], %0:v[2], %0:v[4], %0:v[6], %0:v[8], %0:v[10] 2d storage: semantics: scope:invocation 59 //! v1: %0:v[0] = buffer_load_dword %0:s[0-3], %0:v[0], 0 offset:8 offen storage: semantics: scope:invocation 60 bld.pseudo(aco_opcode::p_unit_test, Operand::zero()); 61 create_mimg(true, 6, 4); 62 create_mubuf(8); 63 64 /* nop needed */ 65 //! p_unit_test 1 66 //! v1: %0:v[0] = image_sample %0:s[0-7], %0:s[0-3], v1: undef, %0:v[0], %0:v[2], %0:v[4], %0:v[6], %0:v[8], %0:v[10] 2d storage: semantics: scope:invocation 67 //! s_nop 68 //! v1: %0:v[0] = buffer_load_dword %0:s[0-3], %0:v[0], 0 offset:4 offen storage: semantics: scope:invocation 69 bld.pseudo(aco_opcode::p_unit_test, Operand::c32(1u)); 70 create_mimg(true, 6, 4); 71 create_mubuf(4); 72 73 /* no nop needed because the MIMG is not NSA */ 74 //! p_unit_test 2 75 //! v1: %0:v[0] = image_sample %0:s[0-7], %0:s[0-3], v1: undef, %0:v[0], %0:v[1], %0:v[2], %0:v[3], %0:v[4], %0:v[5] 2d storage: semantics: scope:invocation 76 //! v1: %0:v[0] = buffer_load_dword %0:s[0-3], %0:v[0], 0 offset:4 offen storage: semantics: scope:invocation 77 bld.pseudo(aco_opcode::p_unit_test, Operand::c32(2u)); 78 create_mimg(false, 6, 2); 79 create_mubuf(4); 80 81 /* no nop needed because there's already an instruction in-between */ 82 //! p_unit_test 3 83 //! v1: %0:v[0] = image_sample %0:s[0-7], %0:s[0-3], v1: undef, %0:v[0], %0:v[2], %0:v[4], %0:v[6], %0:v[8], %0:v[10] 2d storage: semantics: scope:invocation 84 //! v_nop 85 //! v1: %0:v[0] = buffer_load_dword %0:s[0-3], %0:v[0], 0 offset:4 offen storage: semantics: scope:invocation 86 bld.pseudo(aco_opcode::p_unit_test, Operand::c32(3u)); 87 create_mimg(true, 6, 4); 88 bld.vop1(aco_opcode::v_nop); 89 create_mubuf(4); 90 91 /* no nop needed because the NSA instruction is under 4 dwords */ 92 //! p_unit_test 4 93 //! v1: %0:v[0] = image_sample %0:s[0-7], %0:s[0-3], v1: undef, %0:v[0], %0:v[2] 2d storage: semantics: scope:invocation 94 //! v1: %0:v[0] = buffer_load_dword %0:s[0-3], %0:v[0], 0 offset:4 offen storage: semantics: scope:invocation 95 bld.pseudo(aco_opcode::p_unit_test, Operand::c32(4u)); 96 create_mimg(true, 2, 3); 97 create_mubuf(4); 98 99 /* NSA instruction and MUBUF/MTBUF in a different block */ 100 //! p_unit_test 5 101 //! v1: %0:v[0] = image_sample %0:s[0-7], %0:s[0-3], v1: undef, %0:v[0], %0:v[2], %0:v[4], %0:v[6], %0:v[8], %0:v[10] 2d storage: semantics: scope:invocation 102 //! BB1 103 //! /* logical preds: / linear preds: BB0, / kind: uniform, */ 104 //! s_nop 105 //! v1: %0:v[0] = buffer_load_dword %0:s[0-3], %0:v[0], 0 offset:4 offen storage: semantics: scope:invocation 106 bld.pseudo(aco_opcode::p_unit_test, Operand::c32(5u)); 107 create_mimg(true, 6, 4); 108 bld.reset(program->create_and_insert_block()); 109 create_mubuf(4); 110 program->blocks[0].linear_succs.push_back(1); 111 program->blocks[1].linear_preds.push_back(0); 112 113 finish_insert_nops_test(); 114END_TEST 115 116BEGIN_TEST(insert_nops.writelane_to_nsa_bug) 117 if (!setup_cs(NULL, GFX10)) 118 return; 119 120 /* nop needed */ 121 //>> p_unit_test 0 122 //! v1: %0:v[255] = v_writelane_b32_e64 0, 0, %0:v[255] 123 //! s_nop 124 //! v1: %0:v[0] = image_sample %0:s[0-7], %0:s[0-3], v1: undef, %0:v[0], %0:v[2] 2d storage: semantics: scope:invocation 125 bld.pseudo(aco_opcode::p_unit_test, Operand::zero()); 126 bld.writelane(Definition(PhysReg(511), v1), Operand::zero(), Operand::zero(), 127 Operand(PhysReg(511), v1)); 128 create_mimg(true, 2, 3); 129 130 /* no nop needed because the MIMG is not NSA */ 131 //! p_unit_test 1 132 //! v1: %0:v[255] = v_writelane_b32_e64 0, 0, %0:v[255] 133 //! v1: %0:v[0] = image_sample %0:s[0-7], %0:s[0-3], v1: undef, %0:v[0], %0:v[1] 2d storage: semantics: scope:invocation 134 bld.pseudo(aco_opcode::p_unit_test, Operand::c32(1u)); 135 bld.writelane(Definition(PhysReg(511), v1), Operand::zero(), Operand::zero(), 136 Operand(PhysReg(511), v1)); 137 create_mimg(false, 2, 2); 138 139 /* no nop needed because there's already an instruction in-between */ 140 //! p_unit_test 2 141 //! v1: %0:v[255] = v_writelane_b32_e64 0, 0, %0:v[255] 142 //! v_nop 143 //! v1: %0:v[0] = image_sample %0:s[0-7], %0:s[0-3], v1: undef, %0:v[0], %0:v[2] 2d storage: semantics: scope:invocation 144 bld.pseudo(aco_opcode::p_unit_test, Operand::c32(2u)); 145 bld.writelane(Definition(PhysReg(511), v1), Operand::zero(), Operand::zero(), 146 Operand(PhysReg(511), v1)); 147 bld.vop1(aco_opcode::v_nop); 148 create_mimg(true, 2, 3); 149 150 /* writelane and NSA instruction in different blocks */ 151 //! p_unit_test 3 152 //! v1: %0:v[255] = v_writelane_b32_e64 0, 0, %0:v[255] 153 //! BB1 154 //! /* logical preds: / linear preds: BB0, / kind: uniform, */ 155 //! s_nop 156 //! v1: %0:v[0] = image_sample %0:s[0-7], %0:s[0-3], v1: undef, %0:v[0], %0:v[2] 2d storage: semantics: scope:invocation 157 bld.pseudo(aco_opcode::p_unit_test, Operand::c32(3u)); 158 bld.writelane(Definition(PhysReg(511), v1), Operand::zero(), Operand::zero(), 159 Operand(PhysReg(511), v1)); 160 bld.reset(program->create_and_insert_block()); 161 create_mimg(true, 2, 3); 162 program->blocks[0].linear_succs.push_back(1); 163 program->blocks[1].linear_preds.push_back(0); 164 165 finish_insert_nops_test(); 166END_TEST 167