Commit cd74a5a4 by Nicolas Capens

Fix predicating instructions before return in loops.

Only the instructions following a return statement were being marked as affected by it so predication would be applied. But in a loop the instructions above the return statement are also affected by it. Bug b/25220690 Change-Id: If2490a6e0b4e9cf8b6e28b33cbbbcec8b4ebfdaa Reviewed-on: https://swiftshader-review.googlesource.com/5183Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com> Tested-by: 's avatarNicolas Capens <capn@google.com>
parent e2c7154e
...@@ -1090,14 +1090,14 @@ namespace sw ...@@ -1090,14 +1090,14 @@ namespace sw
return opcode == OPCODE_BREAK || opcode == OPCODE_BREAKC || opcode == OPCODE_BREAKP; return opcode == OPCODE_BREAK || opcode == OPCODE_BREAKC || opcode == OPCODE_BREAKP;
} }
bool Shader::Instruction::isLoopOrSwitch() const bool Shader::Instruction::isLoop() const
{ {
return opcode == OPCODE_LOOP || opcode == OPCODE_REP || opcode == OPCODE_WHILE || opcode == OPCODE_SWITCH; return opcode == OPCODE_LOOP || opcode == OPCODE_REP || opcode == OPCODE_WHILE;
} }
bool Shader::Instruction::isEndLoopOrSwitch() const bool Shader::Instruction::isEndLoop() const
{ {
return opcode == OPCODE_ENDLOOP || opcode == OPCODE_ENDREP || opcode == OPCODE_ENDWHILE || opcode == OPCODE_ENDSWITCH;; return opcode == OPCODE_ENDLOOP || opcode == OPCODE_ENDREP || opcode == OPCODE_ENDWHILE;
} }
bool Shader::Instruction::isPredicated() const bool Shader::Instruction::isPredicated() const
...@@ -1657,6 +1657,7 @@ namespace sw ...@@ -1657,6 +1657,7 @@ namespace sw
int breakDepth = 0; int breakDepth = 0;
int continueDepth = 0; int continueDepth = 0;
bool leaveReturn = false; bool leaveReturn = false;
unsigned int functionBegin = 0;
for(unsigned int i = 0; i < instruction.size(); i++) for(unsigned int i = 0; i < instruction.size(); i++)
{ {
...@@ -1688,11 +1689,11 @@ namespace sw ...@@ -1688,11 +1689,11 @@ namespace sw
if(breakDepth > 0) if(breakDepth > 0)
{ {
if(instruction[i]->isLoopOrSwitch()) // Nested loop or switch, don't make the end of it disable the break execution mask if(instruction[i]->isLoop() || instruction[i]->opcode == OPCODE_SWITCH) // Nested loop or switch, don't make the end of it disable the break execution mask
{ {
breakDepth++; breakDepth++;
} }
else if(instruction[i]->isEndLoopOrSwitch()) else if(instruction[i]->isEndLoop() || instruction[i]->opcode == OPCODE_ENDSWITCH)
{ {
breakDepth--; breakDepth--;
} }
...@@ -1713,11 +1714,11 @@ namespace sw ...@@ -1713,11 +1714,11 @@ namespace sw
if(continueDepth > 0) if(continueDepth > 0)
{ {
if(instruction[i]->isLoopOrSwitch()) // Nested loop or switch, don't make the end of it disable the break execution mask if(instruction[i]->isLoop() || instruction[i]->opcode == OPCODE_SWITCH) // Nested loop or switch, don't make the end of it disable the break execution mask
{ {
continueDepth++; continueDepth++;
} }
else if(instruction[i]->isEndLoopOrSwitch()) else if(instruction[i]->isEndLoop() || instruction[i]->opcode == OPCODE_ENDSWITCH)
{ {
continueDepth--; continueDepth--;
} }
...@@ -1734,11 +1735,29 @@ namespace sw ...@@ -1734,11 +1735,29 @@ namespace sw
if(instruction[i]->opcode == OPCODE_LEAVE) if(instruction[i]->opcode == OPCODE_LEAVE)
{ {
leaveReturn = true; leaveReturn = true;
// Mark loop body instructions prior to the return statement
for(unsigned int l = functionBegin; l < i; l++)
{
if(instruction[l]->isLoop())
{
for(unsigned int r = l + 1; r < i; r++)
{
instruction[r]->analysisLeave = true;
}
break;
}
}
} }
else if(instruction[i]->opcode == OPCODE_RET) // End of the function else if(instruction[i]->opcode == OPCODE_RET) // End of the function
{ {
leaveReturn = false; leaveReturn = false;
} }
else if(instruction[i]->opcode == OPCODE_LABEL)
{
functionBegin = i;
}
if(leaveReturn) if(leaveReturn)
{ {
......
...@@ -495,8 +495,8 @@ namespace sw ...@@ -495,8 +495,8 @@ namespace sw
bool isBranch() const; bool isBranch() const;
bool isCall() const; bool isCall() const;
bool isBreak() const; bool isBreak() const;
bool isLoopOrSwitch() const; bool isLoop() const;
bool isEndLoopOrSwitch() const; bool isEndLoop() const;
bool isPredicated() const; bool isPredicated() const;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment