diff --git a/src/amd/compiler/tests/test_optimizer_postRA.cpp b/src/amd/compiler/tests/test_optimizer_postRA.cpp index 6507a361feb..c0189377a48 100644 --- a/src/amd/compiler/tests/test_optimizer_postRA.cpp +++ b/src/amd/compiler/tests/test_optimizer_postRA.cpp @@ -156,6 +156,7 @@ BEGIN_TEST(optimizer_postRA.scc_nocmp_opt) PhysReg reg_s3{3}; PhysReg reg_s4{4}; PhysReg reg_s6{6}; + PhysReg reg_s8{8}; Temp in_0 = inputs[0]; Temp in_1 = inputs[1]; @@ -276,6 +277,25 @@ BEGIN_TEST(optimizer_postRA.scc_nocmp_opt) //; del d, e, f, g, h, x + { + /* SCC is overwritten in between, optimize by pulling down */ + + //! s1: %h:s[3], s1: %x:scc = s_add_u32 %a:s[0], 1 + //! s2: %d:s[8-9], s1: %e:scc = s_and_b64 %b:s[4-5], 0x40018 + //! s2: %f:vcc = p_cbranch_z %g:scc + //! p_unit_test 5, %f:vcc, %h:s[3] + auto salu = bld.sop2(aco_opcode::s_and_b64, bld.def(s2, reg_s8), bld.def(s1, scc), op_in_1, + Operand::c32(0x40018u)); + auto ovrw = bld.sop2(aco_opcode::s_add_u32, bld.def(s1, reg_s3), bld.def(s1, scc), op_in_0, + Operand::c32(1u)); + auto scmp = bld.sopc(aco_opcode::s_cmp_lg_u32, bld.def(s1, scc), Operand(salu, reg_s8), + Operand::zero()); + auto br = bld.branch(aco_opcode::p_cbranch_z, bld.def(s2, vcc), bld.scc(scmp)); + writeout(5, Operand(br, vcc), Operand(ovrw, reg_s3)); + } + + //; del d, e, f, g, h, x + { //! s1: %d:s[2], s1: %e:scc = s_bfe_u32 %a:s[0], 0x40018 //! s1: %f:s[4] = s_cselect_b32 %z:s[6], %a:s[0], %e:scc @@ -518,6 +538,7 @@ BEGIN_TEST(optimizer_postRA.dpp_across_cf_overwritten) Operand a(inputs[0], PhysReg(256)); /* source for DPP */ Operand b(inputs[1], PhysReg(257)); /* source for fadd */ + Operand c(inputs[2], PhysReg(258)); /* buffer store address */ Operand d(inputs[3], PhysReg(259)); /* buffer store value */ Operand e(inputs[4], PhysReg(0)); /* condition */ Operand f(inputs[5], PhysReg(2)); /* buffer store address (scalar) */ @@ -580,3 +601,161 @@ BEGIN_TEST(optimizer_postRA.dpp_across_cf_overwritten) finish_optimizer_postRA_test(); END_TEST + +BEGIN_TEST(optimizer_postRA.scc_nocmp_across_cf) + //>> s2: %a:s[2-3], v1: %c:v[2], v1: %d:v[3], s2: %e:s[0-1] = p_startpgm + if (!setup_cs("s2 v1 v1 s2", GFX10_3)) + return; + + aco_ptr& startpgm = bld.instructions->at(0); + startpgm->definitions[0].setFixed(PhysReg(2)); + startpgm->definitions[1].setFixed(PhysReg(258)); + startpgm->definitions[2].setFixed(PhysReg(259)); + startpgm->definitions[3].setFixed(PhysReg(0)); + + Operand a(inputs[0], PhysReg(2)); /* source for s_and */ + Operand c(inputs[1], PhysReg(258)); /* buffer store address */ + Operand d(inputs[2], PhysReg(259)); /* buffer store value */ + Operand e(inputs[3], PhysReg(0)); /* condition */ + PhysReg reg_s8(8); /* temporary register */ + + auto tmp_salu = bld.sop2(aco_opcode::s_and_b64, bld.def(s2, reg_s8), bld.def(s1, scc), a, + Operand::c32(0x40018u)); + + //! s2: %saved_exec:s[84-85], s1: %0:scc, s2: %0:exec = s_and_saveexec_b64 %e:s[0-1], %0:exec + //! s2: %0:vcc = p_cbranch_nz BB1, BB2 + + emit_divergent_if_else(program.get(), bld, e, [&]() -> void { + /* --- logical then --- */ + //! BB1 + //! /* logical preds: BB0, / linear preds: BB0, / kind: */ + //! p_logical_start + + //! buffer_store_dword %c:v[2], 0, %d:v[3], 0 offen storage: semantics: scope:invocation + bld.mubuf(aco_opcode::buffer_store_dword, c, Operand::zero(), d, Operand::zero(), 0, true); + + //! p_logical_end + //! s2: %0:vcc = p_branch BB3 + + /* --- linear then --- */ + //! BB2 + //! /* logical preds: / linear preds: BB0, / kind: */ + //! s2: %0:vcc = p_branch BB3 + + /* --- invert --- */ + //! BB3 + //! /* logical preds: / linear preds: BB1, BB2, / kind: invert, */ + //! s2: %0:exec, s1: %0:scc = s_andn2_b64 %saved_exec:s[84-85], %0:exec + //! s2: %0:vcc = p_cbranch_nz BB4, BB5 + }, [&]() -> void { + /* --- logical else --- */ + //! BB4 + //! /* logical preds: BB0, / linear preds: BB3, / kind: */ + //! p_logical_start + //! p_logical_end + //! s2: %0:vcc = p_branch BB6 + + /* --- linear else --- */ + //! BB5 + //! /* logical preds: / linear preds: BB3, / kind: */ + //! s2: %0:vcc = p_branch BB6 + }); + + /* --- merge block --- */ + //! BB6 + //! /* logical preds: BB1, BB4, / linear preds: BB4, BB5, / kind: uniform, merge, */ + //! s2: %0:exec = p_parallelcopy %saved_exec:s[84-85] + + //! s2: %tmp_salu:s[8-9], s1: %br_scc:scc = s_and_b64 %a:s[2-3], 0x40018 + //! s2: %br_vcc:vcc = p_cbranch_z %br_scc:scc + //! p_unit_test 5, %br_vcc:vcc + auto scmp = bld.sopc(aco_opcode::s_cmp_lg_u32, bld.def(s1, scc), Operand(tmp_salu, reg_s8), + Operand::zero()); + auto br = bld.branch(aco_opcode::p_cbranch_z, bld.def(s2, vcc), bld.scc(scmp)); + writeout(5, Operand(br, vcc)); + + finish_optimizer_postRA_test(); +END_TEST + + +BEGIN_TEST(optimizer_postRA.scc_nocmp_across_cf_partially_overwritten) + //>> s2: %a:s[2-3], v1: %c:v[2], v1: %d:v[3], s2: %e:s[0-1], s1: %f:s[4] = p_startpgm + if (!setup_cs("s2 v1 v1 s2 s1", GFX10_3)) + return; + + aco_ptr& startpgm = bld.instructions->at(0); + startpgm->definitions[0].setFixed(PhysReg(2)); + startpgm->definitions[1].setFixed(PhysReg(258)); + startpgm->definitions[2].setFixed(PhysReg(259)); + startpgm->definitions[3].setFixed(PhysReg(0)); + startpgm->definitions[4].setFixed(PhysReg(4)); + + Operand a(inputs[0], PhysReg(2)); /* source for s_and */ + Operand c(inputs[1], PhysReg(258)); /* buffer store address */ + Operand d(inputs[2], PhysReg(259)); /* buffer store value */ + Operand e(inputs[3], PhysReg(0)); /* condition */ + Operand f(inputs[4], PhysReg(4)); /* overwrite value */ + PhysReg reg_s3(3); /* temporary register */ + PhysReg reg_s8(8); /* temporary register */ + + //! s2: %tmp_salu:s[8-9], s1: %tmp_salu_scc:scc = s_and_b64 %a:s[2-3], 0x40018 + auto tmp_salu = bld.sop2(aco_opcode::s_and_b64, bld.def(s2, reg_s8), bld.def(s1, scc), a, + Operand::c32(0x40018u)); + + //! s2: %saved_exec:s[84-85], s1: %0:scc, s2: %0:exec = s_and_saveexec_b64 %e:s[0-1], %0:exec + //! s2: %0:vcc = p_cbranch_nz BB1, BB2 + + emit_divergent_if_else(program.get(), bld, e, [&]() -> void { + /* --- logical then --- */ + //! BB1 + //! /* logical preds: BB0, / linear preds: BB0, / kind: */ + //! p_logical_start + + //! s1: %ovrwr:s[3] = p_parallelcopy %f:s[4] + Temp s_addr = bld.pseudo(aco_opcode::p_parallelcopy, bld.def(s1, reg_s3), f); + + //! buffer_store_dword %c:v[2], %ovrwr:s[3], %d:v[3], 0 offen storage: semantics: scope:invocation + bld.mubuf(aco_opcode::buffer_store_dword, c, Operand(s_addr, reg_s3), d, Operand::zero(), 0, true); + + //! p_logical_end + //! s2: %0:vcc = p_branch BB3 + + /* --- linear then --- */ + //! BB2 + //! /* logical preds: / linear preds: BB0, / kind: */ + //! s2: %0:vcc = p_branch BB3 + + /* --- invert --- */ + //! BB3 + //! /* logical preds: / linear preds: BB1, BB2, / kind: invert, */ + //! s2: %0:exec, s1: %0:scc = s_andn2_b64 %saved_exec:s[84-85], %0:exec + //! s2: %0:vcc = p_cbranch_nz BB4, BB5 + }, [&]() -> void { + /* --- logical else --- */ + //! BB4 + //! /* logical preds: BB0, / linear preds: BB3, / kind: */ + //! p_logical_start + //! p_logical_end + //! s2: %0:vcc = p_branch BB6 + + /* --- linear else --- */ + //! BB5 + //! /* logical preds: / linear preds: BB3, / kind: */ + //! s2: %0:vcc = p_branch BB6 + }); + + /* --- merge block --- */ + //! BB6 + //! /* logical preds: BB1, BB4, / linear preds: BB4, BB5, / kind: uniform, merge, */ + //! s2: %0:exec = p_parallelcopy %saved_exec:s[84-85] + + //! s1: %br_scc:scc = s_cmp_lg_u32 %tmp_salu:s[8-9], 0 + //! s2: %br_vcc:vcc = p_cbranch_z %br_scc:scc + //! p_unit_test 5, %br_vcc:vcc + auto scmp = bld.sopc(aco_opcode::s_cmp_lg_u32, bld.def(s1, scc), Operand(tmp_salu, reg_s8), + Operand::zero()); + auto br = bld.branch(aco_opcode::p_cbranch_z, bld.def(s2, vcc), bld.scc(scmp)); + writeout(5, Operand(br, vcc)); + + finish_optimizer_postRA_test(); +END_TEST