mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-26 21:30:07 +00:00
Keep decorations when replacing loads in access-chain-convert. (#1829)
In local-access-chain-convert, we replace loads by load the entire variable, then doing the extract. The extract will have the same value as the load. However, if the load has a decoration on it, the decoration is lost because we do not copy any them to the new id. This is fixed by rewritting the load into the extract and keeping the same result id. This change has the effect that we do not call DCEInst on the loads because the load is not being deleted, but replaced. This could leave OpAccessChain instructions around that are not used. This is not a problem for -O and -Os. They run local_single_*_elim passes and then dead code elimination. The dce will remove the unused access chains, and the load elimination passes work even if there are unused access chains. I have added test to them to ensure they will not loss opportunities. Fixes #1787.
This commit is contained in:
parent
ef678672fb
commit
e065cc208f
@ -16,8 +16,9 @@
|
||||
|
||||
#include "source/opt/local_access_chain_convert_pass.h"
|
||||
|
||||
#include "source/opt/ir_context.h"
|
||||
#include "source/opt/iterator.h"
|
||||
#include "ir_builder.h"
|
||||
#include "ir_context.h"
|
||||
#include "iterator.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
@ -69,24 +70,29 @@ void LocalAccessChainConvertPass::AppendConstantOperands(
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t LocalAccessChainConvertPass::GenAccessChainLoadReplacement(
|
||||
const Instruction* ptrInst,
|
||||
std::vector<std::unique_ptr<Instruction>>* newInsts) {
|
||||
void LocalAccessChainConvertPass::ReplaceAccessChainLoad(
|
||||
const Instruction* address_inst, Instruction* original_load) {
|
||||
// Build and append load of variable in ptrInst
|
||||
std::vector<std::unique_ptr<Instruction>> new_inst;
|
||||
uint32_t varId;
|
||||
uint32_t varPteTypeId;
|
||||
const uint32_t ldResultId =
|
||||
BuildAndAppendVarLoad(ptrInst, &varId, &varPteTypeId, newInsts);
|
||||
BuildAndAppendVarLoad(address_inst, &varId, &varPteTypeId, &new_inst);
|
||||
original_load->InsertBefore(std::move(new_inst));
|
||||
|
||||
// Build and append Extract
|
||||
const uint32_t extResultId = TakeNextId();
|
||||
const uint32_t ptrPteTypeId = GetPointeeTypeId(ptrInst);
|
||||
std::vector<Operand> ext_in_opnds = {
|
||||
{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ldResultId}}};
|
||||
AppendConstantOperands(ptrInst, &ext_in_opnds);
|
||||
BuildAndAppendInst(SpvOpCompositeExtract, ptrPteTypeId, extResultId,
|
||||
ext_in_opnds, newInsts);
|
||||
return extResultId;
|
||||
// Rewrite |original_load| into an extract.
|
||||
Instruction::OperandList new_operands;
|
||||
|
||||
// copy the result id and the type id to the new operand list.
|
||||
new_operands.emplace_back(original_load->GetOperand(0));
|
||||
new_operands.emplace_back(original_load->GetOperand(1));
|
||||
|
||||
new_operands.emplace_back(
|
||||
Operand({spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ldResultId}}));
|
||||
AppendConstantOperands(address_inst, &new_operands);
|
||||
original_load->SetOpcode(SpvOpCompositeExtract);
|
||||
original_load->ReplaceOperands(new_operands);
|
||||
context()->UpdateDefUse(original_load);
|
||||
}
|
||||
|
||||
void LocalAccessChainConvertPass::GenAccessChainStoreReplacement(
|
||||
@ -200,13 +206,7 @@ bool LocalAccessChainConvertPass::ConvertLocalAccessChains(Function* func) {
|
||||
if (!IsNonPtrAccessChain(ptrInst->opcode())) break;
|
||||
if (!IsTargetVar(varId)) break;
|
||||
std::vector<std::unique_ptr<Instruction>> newInsts;
|
||||
uint32_t replId = GenAccessChainLoadReplacement(ptrInst, &newInsts);
|
||||
context()->KillNamesAndDecorates(&*ii);
|
||||
context()->ReplaceAllUsesWith(ii->result_id(), replId);
|
||||
dead_instructions.push_back(&*ii);
|
||||
++ii;
|
||||
ii = ii.InsertBefore(std::move(newInsts));
|
||||
++ii;
|
||||
ReplaceAccessChainLoad(ptrInst, &*ii);
|
||||
modified = true;
|
||||
} break;
|
||||
case SpvOpStore: {
|
||||
|
@ -86,11 +86,12 @@ class LocalAccessChainConvertPass : public MemPass {
|
||||
const Instruction* ptrInst, uint32_t valId,
|
||||
std::vector<std::unique_ptr<Instruction>>* newInsts);
|
||||
|
||||
// For the (constant index) access chain |ptrInst|, create an
|
||||
// equivalent load and extract. Append to |newInsts|.
|
||||
uint32_t GenAccessChainLoadReplacement(
|
||||
const Instruction* ptrInst,
|
||||
std::vector<std::unique_ptr<Instruction>>* newInsts);
|
||||
// For the (constant index) access chain |address_inst|, create an
|
||||
// equivalent load and extract that replaces |original_load|. The result id
|
||||
// of the extract will be the same as the original result id of
|
||||
// |original_load|.
|
||||
void ReplaceAccessChainLoad(const Instruction* address_inst,
|
||||
Instruction* original_load);
|
||||
|
||||
// Return true if all indices of access chain |acp| are OpConstant integers
|
||||
bool IsConstantIndexAccessChain(const Instruction* acp) const;
|
||||
|
@ -78,6 +78,7 @@ bool LocalSingleBlockLoadStoreElimPass::LocalSingleBlockLoadStoreElim(
|
||||
if (prev_store != var2store_.end() &&
|
||||
instructions_to_save.count(prev_store->second) == 0) {
|
||||
instructions_to_kill.push_back(prev_store->second);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
bool kill_store = false;
|
||||
|
@ -24,6 +24,8 @@ namespace {
|
||||
|
||||
using LocalAccessChainConvertTest = PassTest<::testing::Test>;
|
||||
|
||||
#ifdef SPIRV_EFFCEE
|
||||
|
||||
TEST_F(LocalAccessChainConvertTest, StructOfVecsOfFloatConverted) {
|
||||
// #version 140
|
||||
//
|
||||
@ -68,38 +70,18 @@ OpName %gl_FragColor "gl_FragColor"
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%gl_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
)";
|
||||
|
||||
const std::string predefs_after =
|
||||
R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 140
|
||||
OpName %main "main"
|
||||
OpName %S_t "S_t"
|
||||
OpMemberName %S_t 0 "v0"
|
||||
OpMemberName %S_t 1 "v1"
|
||||
OpName %s0 "s0"
|
||||
OpName %BaseColor "BaseColor"
|
||||
OpName %gl_FragColor "gl_FragColor"
|
||||
%void = OpTypeVoid
|
||||
%8 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%S_t = OpTypeStruct %v4float %v4float
|
||||
%_ptr_Function_S_t = OpTypePointer Function %S_t
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%BaseColor = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%gl_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
)";
|
||||
|
||||
const std::string before =
|
||||
R"(%main = OpFunction %void None %8
|
||||
R"(
|
||||
; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
|
||||
; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
|
||||
; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
|
||||
; CHECK: OpStore %s0 [[ex1]]
|
||||
; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
|
||||
; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
|
||||
; CHECK: OpStore %gl_FragColor [[ex2]]
|
||||
%main = OpFunction %void None %8
|
||||
%17 = OpLabel
|
||||
%s0 = OpVariable %_ptr_Function_S_t Function
|
||||
%18 = OpLoad %v4float %BaseColor
|
||||
@ -112,23 +94,8 @@ OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%main = OpFunction %void None %8
|
||||
%17 = OpLabel
|
||||
%s0 = OpVariable %_ptr_Function_S_t Function
|
||||
%18 = OpLoad %v4float %BaseColor
|
||||
%22 = OpLoad %S_t %s0
|
||||
%23 = OpCompositeInsert %S_t %18 %22 1
|
||||
OpStore %s0 %23
|
||||
%24 = OpLoad %S_t %s0
|
||||
%25 = OpCompositeExtract %v4float %24 1
|
||||
OpStore %gl_FragColor %25
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<LocalAccessChainConvertPass>(
|
||||
predefs_before + before, predefs_after + after, true, true);
|
||||
SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
|
||||
true);
|
||||
}
|
||||
|
||||
TEST_F(LocalAccessChainConvertTest, InBoundsAccessChainsConverted) {
|
||||
@ -175,38 +142,18 @@ OpName %gl_FragColor "gl_FragColor"
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%gl_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
)";
|
||||
|
||||
const std::string predefs_after =
|
||||
R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 140
|
||||
OpName %main "main"
|
||||
OpName %S_t "S_t"
|
||||
OpMemberName %S_t 0 "v0"
|
||||
OpMemberName %S_t 1 "v1"
|
||||
OpName %s0 "s0"
|
||||
OpName %BaseColor "BaseColor"
|
||||
OpName %gl_FragColor "gl_FragColor"
|
||||
%void = OpTypeVoid
|
||||
%8 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%S_t = OpTypeStruct %v4float %v4float
|
||||
%_ptr_Function_S_t = OpTypePointer Function %S_t
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%BaseColor = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%gl_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
)";
|
||||
|
||||
const std::string before =
|
||||
R"(%main = OpFunction %void None %8
|
||||
R"(
|
||||
; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
|
||||
; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
|
||||
; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
|
||||
; CHECK: OpStore %s0 [[ex1]]
|
||||
; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
|
||||
; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
|
||||
; CHECK: OpStore %gl_FragColor [[ex2]]
|
||||
%main = OpFunction %void None %8
|
||||
%17 = OpLabel
|
||||
%s0 = OpVariable %_ptr_Function_S_t Function
|
||||
%18 = OpLoad %v4float %BaseColor
|
||||
@ -219,23 +166,8 @@ OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%main = OpFunction %void None %8
|
||||
%17 = OpLabel
|
||||
%s0 = OpVariable %_ptr_Function_S_t Function
|
||||
%18 = OpLoad %v4float %BaseColor
|
||||
%22 = OpLoad %S_t %s0
|
||||
%23 = OpCompositeInsert %S_t %18 %22 1
|
||||
OpStore %s0 %23
|
||||
%24 = OpLoad %S_t %s0
|
||||
%25 = OpCompositeExtract %v4float %24 1
|
||||
OpStore %gl_FragColor %25
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<LocalAccessChainConvertPass>(
|
||||
predefs_before + before, predefs_after + after, true, true);
|
||||
SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
|
||||
true);
|
||||
}
|
||||
|
||||
TEST_F(LocalAccessChainConvertTest, TwoUsesofSingleChainConverted) {
|
||||
@ -282,38 +214,18 @@ OpName %gl_FragColor "gl_FragColor"
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%gl_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
)";
|
||||
|
||||
const std::string predefs_after =
|
||||
R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 140
|
||||
OpName %main "main"
|
||||
OpName %S_t "S_t"
|
||||
OpMemberName %S_t 0 "v0"
|
||||
OpMemberName %S_t 1 "v1"
|
||||
OpName %s0 "s0"
|
||||
OpName %BaseColor "BaseColor"
|
||||
OpName %gl_FragColor "gl_FragColor"
|
||||
%void = OpTypeVoid
|
||||
%8 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%S_t = OpTypeStruct %v4float %v4float
|
||||
%_ptr_Function_S_t = OpTypePointer Function %S_t
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%BaseColor = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%gl_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
)";
|
||||
|
||||
const std::string before =
|
||||
R"(%main = OpFunction %void None %8
|
||||
R"(
|
||||
; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
|
||||
; CHECK: [[ld1:%\w+]] = OpLoad %S_t %s0
|
||||
; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S_t [[st_id]] [[ld1]] 1
|
||||
; CHECK: OpStore %s0 [[ex1]]
|
||||
; CHECK: [[ld2:%\w+]] = OpLoad %S_t %s0
|
||||
; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1
|
||||
; CHECK: OpStore %gl_FragColor [[ex2]]
|
||||
%main = OpFunction %void None %8
|
||||
%17 = OpLabel
|
||||
%s0 = OpVariable %_ptr_Function_S_t Function
|
||||
%18 = OpLoad %v4float %BaseColor
|
||||
@ -325,23 +237,8 @@ OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%main = OpFunction %void None %8
|
||||
%17 = OpLabel
|
||||
%s0 = OpVariable %_ptr_Function_S_t Function
|
||||
%18 = OpLoad %v4float %BaseColor
|
||||
%21 = OpLoad %S_t %s0
|
||||
%22 = OpCompositeInsert %S_t %18 %21 1
|
||||
OpStore %s0 %22
|
||||
%23 = OpLoad %S_t %s0
|
||||
%24 = OpCompositeExtract %v4float %23 1
|
||||
OpStore %gl_FragColor %24
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<LocalAccessChainConvertPass>(
|
||||
predefs_before + before, predefs_after + after, true, true);
|
||||
SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
|
||||
true);
|
||||
}
|
||||
|
||||
TEST_F(LocalAccessChainConvertTest, OpaqueConverted) {
|
||||
@ -349,7 +246,8 @@ TEST_F(LocalAccessChainConvertTest, OpaqueConverted) {
|
||||
// at the moment
|
||||
|
||||
const std::string predefs =
|
||||
R"(OpCapability Shader
|
||||
R"(
|
||||
OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %outColor %texCoords
|
||||
@ -392,7 +290,13 @@ OpDecorate %sampler15 DescriptorSet 0
|
||||
)";
|
||||
|
||||
const std::string before =
|
||||
R"(%main = OpFunction %void None %12
|
||||
R"(
|
||||
; CHECK: [[l1:%\w+]] = OpLoad %S_t %param
|
||||
; CHECK: [[e1:%\w+]] = OpCompositeExtract {{%\w+}} [[l1]] 2
|
||||
; CHECK: [[l2:%\w+]] = OpLoad %S_t %param
|
||||
; CHECK: [[e2:%\w+]] = OpCompositeExtract {{%\w+}} [[l2]] 0
|
||||
; CHECK: OpImageSampleImplicitLod {{%\w+}} [[e1]] [[e2]]
|
||||
%main = OpFunction %void None %12
|
||||
%28 = OpLabel
|
||||
%s0 = OpVariable %_ptr_Function_S_t Function
|
||||
%param = OpVariable %_ptr_Function_S_t Function
|
||||
@ -412,31 +316,6 @@ OpStore %param %33
|
||||
OpStore %outColor %38
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%main = OpFunction %void None %12
|
||||
%28 = OpLabel
|
||||
%s0 = OpVariable %_ptr_Function_S_t Function
|
||||
%param = OpVariable %_ptr_Function_S_t Function
|
||||
%29 = OpLoad %v2float %texCoords
|
||||
%45 = OpLoad %S_t %s0
|
||||
%46 = OpCompositeInsert %S_t %29 %45 0
|
||||
OpStore %s0 %46
|
||||
%31 = OpLoad %18 %sampler15
|
||||
%47 = OpLoad %S_t %s0
|
||||
%48 = OpCompositeInsert %S_t %31 %47 2
|
||||
OpStore %s0 %48
|
||||
%33 = OpLoad %S_t %s0
|
||||
OpStore %param %33
|
||||
%49 = OpLoad %S_t %param
|
||||
%50 = OpCompositeExtract %18 %49 2
|
||||
%51 = OpLoad %S_t %param
|
||||
%52 = OpCompositeExtract %v2float %51 0
|
||||
%38 = OpImageSampleImplicitLod %v4float %50 %52
|
||||
OpStore %outColor %38
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string remain =
|
||||
@ -453,8 +332,8 @@ OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<LocalAccessChainConvertPass>(
|
||||
predefs + before + remain, predefs + after + remain, true, true);
|
||||
SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs + before + remain,
|
||||
true);
|
||||
}
|
||||
|
||||
TEST_F(LocalAccessChainConvertTest, NestedStructsConverted) {
|
||||
@ -509,41 +388,18 @@ OpName %gl_FragColor "gl_FragColor"
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%gl_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
)";
|
||||
|
||||
const std::string predefs_after =
|
||||
R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 140
|
||||
OpName %main "main"
|
||||
OpName %S1_t "S1_t"
|
||||
OpMemberName %S1_t 0 "v1"
|
||||
OpName %S2_t "S2_t"
|
||||
OpMemberName %S2_t 0 "v2"
|
||||
OpMemberName %S2_t 1 "s1"
|
||||
OpName %s2 "s2"
|
||||
OpName %BaseColor "BaseColor"
|
||||
OpName %gl_FragColor "gl_FragColor"
|
||||
%void = OpTypeVoid
|
||||
%9 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%S1_t = OpTypeStruct %v4float
|
||||
%S2_t = OpTypeStruct %v4float %S1_t
|
||||
%_ptr_Function_S2_t = OpTypePointer Function %S2_t
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%BaseColor = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%gl_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
)";
|
||||
|
||||
const std::string before =
|
||||
R"(%main = OpFunction %void None %9
|
||||
R"(
|
||||
; CHECK: [[st_id:%\w+]] = OpLoad %v4float %BaseColor
|
||||
; CHECK: [[ld1:%\w+]] = OpLoad %S2_t %s2
|
||||
; CHECK: [[ex1:%\w+]] = OpCompositeInsert %S2_t [[st_id]] [[ld1]] 1 0
|
||||
; CHECK: OpStore %s2 [[ex1]]
|
||||
; CHECK: [[ld2:%\w+]] = OpLoad %S2_t %s2
|
||||
; CHECK: [[ex2:%\w+]] = OpCompositeExtract %v4float [[ld2]] 1 0
|
||||
; CHECK: OpStore %gl_FragColor [[ex2]]
|
||||
%main = OpFunction %void None %9
|
||||
%19 = OpLabel
|
||||
%s2 = OpVariable %_ptr_Function_S2_t Function
|
||||
%20 = OpLoad %v4float %BaseColor
|
||||
@ -556,25 +412,67 @@ OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%main = OpFunction %void None %9
|
||||
%19 = OpLabel
|
||||
%s2 = OpVariable %_ptr_Function_S2_t Function
|
||||
%20 = OpLoad %v4float %BaseColor
|
||||
%24 = OpLoad %S2_t %s2
|
||||
%25 = OpCompositeInsert %S2_t %20 %24 1 0
|
||||
OpStore %s2 %25
|
||||
%26 = OpLoad %S2_t %s2
|
||||
%27 = OpCompositeExtract %v4float %26 1 0
|
||||
OpStore %gl_FragColor %27
|
||||
SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs_before + before,
|
||||
true);
|
||||
}
|
||||
|
||||
TEST_F(LocalAccessChainConvertTest, SomeAccessChainsHaveNoUse) {
|
||||
// Based on HLSL source code:
|
||||
// struct S {
|
||||
// float f;
|
||||
// };
|
||||
|
||||
// float main(float input : A) : B {
|
||||
// S local = { input };
|
||||
// return local.f;
|
||||
// }
|
||||
|
||||
const std::string predefs = R"(OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main" %in_var_A %out_var_B
|
||||
OpName %main "main"
|
||||
OpName %in_var_A "in.var.A"
|
||||
OpName %out_var_B "out.var.B"
|
||||
OpName %S "S"
|
||||
OpName %local "local"
|
||||
%int = OpTypeInt 32 1
|
||||
%void = OpTypeVoid
|
||||
%8 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%_ptr_Output_float = OpTypePointer Output %float
|
||||
%S = OpTypeStruct %float
|
||||
%_ptr_Function_S = OpTypePointer Function %S
|
||||
%int_0 = OpConstant %int 0
|
||||
%in_var_A = OpVariable %_ptr_Input_float Input
|
||||
%out_var_B = OpVariable %_ptr_Output_float Output
|
||||
%main = OpFunction %void None %8
|
||||
%15 = OpLabel
|
||||
%local = OpVariable %_ptr_Function_S Function
|
||||
%16 = OpLoad %float %in_var_A
|
||||
%17 = OpCompositeConstruct %S %16
|
||||
OpStore %local %17
|
||||
)";
|
||||
|
||||
const std::string before =
|
||||
R"(
|
||||
; CHECK: [[ld:%\w+]] = OpLoad %S %local
|
||||
; CHECK: [[ex:%\w+]] = OpCompositeExtract %float [[ld]] 0
|
||||
; CHECK: OpStore %out_var_B [[ex]]
|
||||
%18 = OpAccessChain %_ptr_Function_float %local %int_0
|
||||
%19 = OpAccessChain %_ptr_Function_float %local %int_0
|
||||
%20 = OpLoad %float %18
|
||||
OpStore %out_var_B %20
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<LocalAccessChainConvertPass>(
|
||||
predefs_before + before, predefs_after + after, true, true);
|
||||
SinglePassRunAndMatch<LocalAccessChainConvertPass>(predefs + before, true);
|
||||
}
|
||||
|
||||
#endif // SPIRV_EFFCEE
|
||||
|
||||
TEST_F(LocalAccessChainConvertTest, DynamicallyIndexedVarNotConverted) {
|
||||
// #version 140
|
||||
//
|
||||
@ -651,67 +549,6 @@ OpFunctionEnd
|
||||
true);
|
||||
}
|
||||
|
||||
TEST_F(LocalAccessChainConvertTest, SomeAccessChainsHaveNoUse) {
|
||||
// Based on HLSL source code:
|
||||
// struct S {
|
||||
// float f;
|
||||
// };
|
||||
|
||||
// float main(float input : A) : B {
|
||||
// S local = { input };
|
||||
// return local.f;
|
||||
// }
|
||||
|
||||
const std::string predefs = R"(OpCapability Shader
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Vertex %main "main" %in_var_A %out_var_B
|
||||
OpName %main "main"
|
||||
OpName %in_var_A "in.var.A"
|
||||
OpName %out_var_B "out.var.B"
|
||||
OpName %S "S"
|
||||
OpName %local "local"
|
||||
%int = OpTypeInt 32 1
|
||||
%void = OpTypeVoid
|
||||
%8 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%_ptr_Input_float = OpTypePointer Input %float
|
||||
%_ptr_Output_float = OpTypePointer Output %float
|
||||
%S = OpTypeStruct %float
|
||||
%_ptr_Function_S = OpTypePointer Function %S
|
||||
%int_0 = OpConstant %int 0
|
||||
%in_var_A = OpVariable %_ptr_Input_float Input
|
||||
%out_var_B = OpVariable %_ptr_Output_float Output
|
||||
%main = OpFunction %void None %8
|
||||
%15 = OpLabel
|
||||
%local = OpVariable %_ptr_Function_S Function
|
||||
%16 = OpLoad %float %in_var_A
|
||||
%17 = OpCompositeConstruct %S %16
|
||||
OpStore %local %17
|
||||
)";
|
||||
|
||||
const std::string before =
|
||||
R"(%18 = OpAccessChain %_ptr_Function_float %local %int_0
|
||||
%19 = OpAccessChain %_ptr_Function_float %local %int_0
|
||||
%20 = OpLoad %float %18
|
||||
OpStore %out_var_B %20
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%19 = OpAccessChain %_ptr_Function_float %local %int_0
|
||||
%21 = OpLoad %S %local
|
||||
%22 = OpCompositeExtract %float %21 0
|
||||
OpStore %out_var_B %22
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SinglePassRunAndCheck<LocalAccessChainConvertPass>(
|
||||
predefs + before, predefs + after, true, true);
|
||||
}
|
||||
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// Assorted vector and matrix types
|
||||
|
@ -983,6 +983,83 @@ OpFunctionEnd
|
||||
SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
|
||||
predefs_before + before, predefs_before + after, true, true);
|
||||
}
|
||||
|
||||
// Test that that an unused OpAccessChain between two store does does not
|
||||
// hinders the removal of the first store. We need to check this because
|
||||
// local-access-chain-convert does always remove the OpAccessChain instructions
|
||||
// that become dead.
|
||||
|
||||
TEST_F(LocalSingleBlockLoadStoreElimTest,
|
||||
StoreElimIfInterveningUnusedAccessChain) {
|
||||
const std::string predefs =
|
||||
R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %BaseColor0 %Idx %BaseColor1 %OutColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 450
|
||||
OpName %main "main"
|
||||
OpName %v "v"
|
||||
OpName %BaseColor0 "BaseColor0"
|
||||
OpName %Idx "Idx"
|
||||
OpName %BaseColor1 "BaseColor1"
|
||||
OpName %OutColor "OutColor"
|
||||
OpDecorate %BaseColor0 Location 0
|
||||
OpDecorate %Idx Flat
|
||||
OpDecorate %Idx Location 2
|
||||
OpDecorate %BaseColor1 Location 1
|
||||
OpDecorate %OutColor Location 0
|
||||
%void = OpTypeVoid
|
||||
%10 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%BaseColor0 = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%int = OpTypeInt 32 1
|
||||
%_ptr_Input_int = OpTypePointer Input %int
|
||||
%Idx = OpVariable %_ptr_Input_int Input
|
||||
%BaseColor1 = OpVariable %_ptr_Input_v4float Input
|
||||
%float_0_100000001 = OpConstant %float 0.100000001
|
||||
%19 = OpConstantComposite %v4float %float_0_100000001 %float_0_100000001 %float_0_100000001 %float_0_100000001
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%OutColor = OpVariable %_ptr_Output_v4float Output
|
||||
)";
|
||||
|
||||
const std::string before =
|
||||
R"(%main = OpFunction %void None %10
|
||||
%21 = OpLabel
|
||||
%v = OpVariable %_ptr_Function_v4float Function
|
||||
%22 = OpLoad %v4float %BaseColor0
|
||||
OpStore %v %22
|
||||
%23 = OpLoad %int %Idx
|
||||
%24 = OpAccessChain %_ptr_Function_float %v %23
|
||||
%26 = OpLoad %v4float %BaseColor1
|
||||
%27 = OpFAdd %v4float %26 %19
|
||||
OpStore %v %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%main = OpFunction %void None %10
|
||||
%21 = OpLabel
|
||||
%v = OpVariable %_ptr_Function_v4float Function
|
||||
%22 = OpLoad %v4float %BaseColor0
|
||||
%23 = OpLoad %int %Idx
|
||||
%24 = OpAccessChain %_ptr_Function_float %v %23
|
||||
%26 = OpLoad %v4float %BaseColor1
|
||||
%27 = OpFAdd %v4float %26 %19
|
||||
OpStore %v %27
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<LocalSingleBlockLoadStoreElimPass>(
|
||||
predefs + before, predefs + after, true, true);
|
||||
}
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// Other target variable types
|
||||
|
@ -771,6 +771,80 @@ OpFunctionEnd
|
||||
SinglePassRunAndCheck<LocalSingleStoreElimPass>(before, after, true, true);
|
||||
}
|
||||
|
||||
// Test that that an unused OpAccessChain between a store and a use does does
|
||||
// not hinders the replacement of the use. We need to check this because
|
||||
// local-access-chain-convert does always remove the OpAccessChain instructions
|
||||
// that become dead.
|
||||
|
||||
TEST_F(LocalSingleStoreElimTest,
|
||||
StoreElimWithUnusedInterveningAccessChainLoad) {
|
||||
// Last load of v is eliminated, but access chain load and store of v isn't
|
||||
//
|
||||
// #version 140
|
||||
//
|
||||
// in vec4 BaseColor;
|
||||
//
|
||||
// void main()
|
||||
// {
|
||||
// vec4 v = BaseColor;
|
||||
// float f = v[3];
|
||||
// gl_FragColor = v * f;
|
||||
// }
|
||||
|
||||
const std::string predefs =
|
||||
R"(OpCapability Shader
|
||||
%1 = OpExtInstImport "GLSL.std.450"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
|
||||
OpExecutionMode %main OriginUpperLeft
|
||||
OpSource GLSL 140
|
||||
OpName %main "main"
|
||||
OpName %v "v"
|
||||
OpName %BaseColor "BaseColor"
|
||||
OpName %gl_FragColor "gl_FragColor"
|
||||
%void = OpTypeVoid
|
||||
%8 = OpTypeFunction %void
|
||||
%float = OpTypeFloat 32
|
||||
%v4float = OpTypeVector %float 4
|
||||
%_ptr_Function_v4float = OpTypePointer Function %v4float
|
||||
%_ptr_Input_v4float = OpTypePointer Input %v4float
|
||||
%BaseColor = OpVariable %_ptr_Input_v4float Input
|
||||
%_ptr_Function_float = OpTypePointer Function %float
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%_ptr_Output_v4float = OpTypePointer Output %v4float
|
||||
%gl_FragColor = OpVariable %_ptr_Output_v4float Output
|
||||
)";
|
||||
|
||||
const std::string before =
|
||||
R"(%main = OpFunction %void None %8
|
||||
%17 = OpLabel
|
||||
%v = OpVariable %_ptr_Function_v4float Function
|
||||
%18 = OpLoad %v4float %BaseColor
|
||||
OpStore %v %18
|
||||
%19 = OpAccessChain %_ptr_Function_float %v %uint_3
|
||||
%21 = OpLoad %v4float %v
|
||||
OpStore %gl_FragColor %21
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
const std::string after =
|
||||
R"(%main = OpFunction %void None %8
|
||||
%17 = OpLabel
|
||||
%v = OpVariable %_ptr_Function_v4float Function
|
||||
%18 = OpLoad %v4float %BaseColor
|
||||
OpStore %v %18
|
||||
%19 = OpAccessChain %_ptr_Function_float %v %uint_3
|
||||
OpStore %gl_FragColor %18
|
||||
OpReturn
|
||||
OpFunctionEnd
|
||||
)";
|
||||
|
||||
SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||
SinglePassRunAndCheck<LocalSingleStoreElimPass>(predefs + before,
|
||||
predefs + after, true, true);
|
||||
}
|
||||
// TODO(greg-lunarg): Add tests to verify handling of these cases:
|
||||
//
|
||||
// Other types
|
||||
|
Loading…
Reference in New Issue
Block a user