Add unrolling to the legalization passes (#1903)

Adds unrolling to the legalization passes.

After enabling unrolling I found a bug when there is a self-referencing
phi node.  That has been fixed.

The test that checks for that the order of optimizations is correct also
needed to be updated.
This commit is contained in:
Steven Perron 2018-09-19 16:40:09 -04:00 committed by GitHub
parent 9e99d8b691
commit 9fbcce4ca1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 11 deletions

View File

@ -244,6 +244,10 @@ class LoopUnrollerUtilsImpl {
// ect).
void AssignNewResultIds(BasicBlock* basic_block);
// Using the map built by AssignNewResultIds, replace the uses in |inst|
// by the id that the use maps to.
void RemapOperands(Instruction* inst);
// Using the map built by AssignNewResultIds, for each instruction in
// |basic_block| use
// that map to substitute the IDs used by instructions (in the operands) with
@ -757,6 +761,11 @@ void LoopUnrollerUtilsImpl::CloseUnrolledLoop(Loop* loop) {
for (BasicBlock* block : loop_blocks_inorder_) {
RemapOperands(block);
}
// Rewrite the last phis, since they may still reference the original phi.
for (Instruction* last_phi : state_.previous_phis_) {
RemapOperands(last_phi);
}
}
// Uses the first loop to create a copy of the loop with new IDs.
@ -842,19 +851,21 @@ void LoopUnrollerUtilsImpl::AssignNewResultIds(BasicBlock* basic_block) {
}
}
// For all instructions in |basic_block| check if the operands used are from a
// copied instruction and if so swap out the operand for the copy of it.
void LoopUnrollerUtilsImpl::RemapOperands(Instruction* inst) {
auto remap_operands_to_new_ids = [this](uint32_t* id) {
auto itr = state_.new_inst.find(*id);
if (itr != state_.new_inst.end()) {
*id = itr->second;
}
};
inst->ForEachInId(remap_operands_to_new_ids);
}
void LoopUnrollerUtilsImpl::RemapOperands(BasicBlock* basic_block) {
for (Instruction& inst : *basic_block) {
auto remap_operands_to_new_ids = [this](uint32_t* id) {
auto itr = state_.new_inst.find(*id);
if (itr != state_.new_inst.end()) {
*id = itr->second;
}
};
inst.ForEachInId(remap_operands_to_new_ids);
RemapOperands(&inst);
}
}

View File

@ -131,6 +131,7 @@ Optimizer& Optimizer::RegisterLegalizationPasses() {
// Propagate constants to get as many constant conditions on branches
// as possible.
.RegisterPass(CreateCCPPass())
.RegisterPass(CreateLoopUnrollPass(true))
.RegisterPass(CreateDeadBranchElimPass())
// Copy propagate members. Cleans up code sequences generated by
// scalar replacement. Also important for removing OpPhi nodes.

View File

@ -2952,6 +2952,52 @@ OpFunctionEnd
EXPECT_NE(loop_2.GetLatchBlock(), loop_2.GetContinueBlock());
}
// Test that a loop with a self-referencing OpPhi instruction is handled
// correctly.
TEST_F(PassClassTest, OpPhiSelfReference) {
const std::string text = R"(
; Find the two adds from the unrolled loop
; CHECK: OpIAdd
; CHECK: OpIAdd
; CHECK: OpIAdd %uint %uint_0 %uint_1
; CHECK-NEXT: OpReturn
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint GLCompute %2 "main"
OpExecutionMode %2 LocalSize 8 8 1
OpSource HLSL 600
%uint = OpTypeInt 32 0
%void = OpTypeVoid
%5 = OpTypeFunction %void
%uint_0 = OpConstant %uint 0
%uint_1 = OpConstant %uint 1
%bool = OpTypeBool
%true = OpConstantTrue %bool
%2 = OpFunction %void None %5
%10 = OpLabel
OpBranch %19
%19 = OpLabel
%20 = OpPhi %uint %uint_0 %10 %20 %21
%22 = OpPhi %uint %uint_0 %10 %23 %21
%24 = OpULessThanEqual %bool %22 %uint_1
OpLoopMerge %25 %21 Unroll
OpBranchConditional %24 %21 %25
%21 = OpLabel
%23 = OpIAdd %uint %22 %uint_1
OpBranch %19
%25 = OpLabel
%14 = OpIAdd %uint %20 %uint_1
OpReturn
OpFunctionEnd
)";
const bool kFullyUnroll = true;
const uint32_t kUnrollFactor = 0;
SinglePassRunAndMatch<opt::LoopUnroller>(text, true, kFullyUnroll,
kUnrollFactor);
}
} // namespace
} // namespace opt
} // namespace spvtools

View File

@ -235,6 +235,7 @@ class TestLegalizationPasses(expect.ValidObjectFile1_3,
'eliminate-local-multi-store',
'eliminate-dead-code-aggressive',
'ccp',
'loop-unroll',
'eliminate-dead-branches',
'simplify-instructions',
'eliminate-dead-code-aggressive',