Commit d469de2d by Nicolas Capens Committed by Nicolas Capens

Reduce temporaries used during rvalue evaluation.

This optimizes evaluation of chained indexing operations by first looking for an lvalue 'root' node and copying from it directly into the topmost rvalue, instead of creating potentially many temporaries. Change-Id: I47cf9b0230bd305695e7b2a44ddc44bc1320b764 Reviewed-on: https://swiftshader-review.googlesource.com/13908Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 3ae571ed
...@@ -564,92 +564,12 @@ namespace glsl ...@@ -564,92 +564,12 @@ namespace glsl
} }
return false; return false;
case EOpIndexDirect: case EOpIndexDirect:
if(visit == PostVisit)
{
int index = right->getAsConstantUnion()->getIConst(0);
if(result->isMatrix() || result->isStruct() || result->isInterfaceBlock())
{
ASSERT(left->isArray());
copy(result, left, index * left->elementRegisterCount());
}
else if(result->isRegister())
{
int srcIndex = 0;
if(left->isRegister())
{
srcIndex = 0;
}
else if(left->isArray())
{
srcIndex = index * left->elementRegisterCount();
}
else if(left->isMatrix())
{
ASSERT(index < left->getNominalSize()); // FIXME: Report semantic error
srcIndex = index;
}
else UNREACHABLE(0);
Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, 0, left, srcIndex);
if(left->isRegister())
{
mov->src[0].swizzle = index;
}
}
else UNREACHABLE(0);
}
break;
case EOpIndexIndirect: case EOpIndexIndirect:
if(visit == PostVisit)
{
if(left->isArray() || left->isMatrix())
{
for(int index = 0; index < result->totalRegisterCount(); index++)
{
Instruction *mov = emit(sw::Shader::OPCODE_MOV, result, index, left, index);
mov->dst.mask = writeMask(result, index);
if(left->totalRegisterCount() > 1)
{
sw::Shader::SourceParameter relativeRegister;
source(relativeRegister, right);
mov->src[0].rel.type = relativeRegister.type;
mov->src[0].rel.index = relativeRegister.index;
mov->src[0].rel.scale = result->totalRegisterCount();
mov->src[0].rel.deterministic = !(vertexShader && left->getQualifier() == EvqUniform);
}
}
}
else if(left->isRegister())
{
emit(sw::Shader::OPCODE_EXTRACT, result, left, right);
}
else UNREACHABLE(0);
}
break;
case EOpIndexDirectStruct: case EOpIndexDirectStruct:
case EOpIndexDirectInterfaceBlock: case EOpIndexDirectInterfaceBlock:
if(visit == PostVisit) assert(visit == PreVisit);
{ evaluateRvalue(node);
ASSERT(leftType.isStruct() || (leftType.isInterfaceBlock())); return false;
const TFieldList& fields = (node->getOp() == EOpIndexDirectStruct) ?
leftType.getStruct()->fields() :
leftType.getInterfaceBlock()->fields();
int index = right->getAsConstantUnion()->getIConst(0);
int fieldOffset = 0;
for(int i = 0; i < index; i++)
{
fieldOffset += fields[i]->type()->totalRegisterCount();
}
copy(result, left, fieldOffset);
}
break;
case EOpVectorSwizzle: case EOpVectorSwizzle:
if(visit == PostVisit) if(visit == PostVisit)
{ {
...@@ -2362,6 +2282,54 @@ namespace glsl ...@@ -2362,6 +2282,54 @@ namespace glsl
} }
} }
void OutputASM::evaluateRvalue(TIntermTyped *node)
{
TIntermBinary *binary = node->getAsBinaryNode();
if(binary && binary->getOp() == EOpIndexIndirect && binary->getLeft()->isVector() && node->isScalar())
{
Instruction *insert = new Instruction(sw::Shader::OPCODE_EXTRACT);
destination(insert->dst, node);
Temporary address(this);
unsigned char mask;
TIntermTyped *root = nullptr;
unsigned int offset = 0;
int swizzle = lvalue(root, offset, insert->src[0].rel, mask, address, node);
source(insert->src[0], root, offset);
insert->src[0].swizzle = swizzleSwizzle(insert->src[0].swizzle, swizzle);
source(insert->src[1], binary->getRight());
shader->append(insert);
}
else
{
Instruction *mov1 = new Instruction(sw::Shader::OPCODE_MOV);
destination(mov1->dst, node, 0);
Temporary address(this);
unsigned char mask;
TIntermTyped *root = nullptr;
unsigned int offset = 0;
int swizzle = lvalue(root, offset, mov1->src[0].rel, mask, address, node);
source(mov1->src[0], root, offset);
mov1->src[0].swizzle = swizzleSwizzle(mov1->src[0].swizzle, swizzle);
shader->append(mov1);
for(int i = 1; i < node->totalRegisterCount(); i++)
{
Instruction *mov = emit(sw::Shader::OPCODE_MOV, node, i, root, offset + i);
mov->src[0].rel = mov1->src[0].rel;
}
}
}
int OutputASM::lvalue(sw::Shader::DestinationParameter &dst, TIntermTyped *node) int OutputASM::lvalue(sw::Shader::DestinationParameter &dst, TIntermTyped *node)
{ {
Temporary address(this); Temporary address(this);
......
...@@ -274,6 +274,7 @@ namespace glsl ...@@ -274,6 +274,7 @@ namespace glsl
void destination(sw::Shader::DestinationParameter &parameter, TIntermTyped *argument, int index = 0); void destination(sw::Shader::DestinationParameter &parameter, TIntermTyped *argument, int index = 0);
void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0); void copy(TIntermTyped *dst, TIntermNode *src, int offset = 0);
void assignLvalue(TIntermTyped *dst, TIntermTyped *src); void assignLvalue(TIntermTyped *dst, TIntermTyped *src);
void evaluateRvalue(TIntermTyped *node);
int lvalue(sw::Shader::DestinationParameter &dst, TIntermTyped *node); int lvalue(sw::Shader::DestinationParameter &dst, TIntermTyped *node);
int lvalue(TIntermTyped *&root, unsigned int &offset, sw::Shader::Relative &rel, unsigned char &mask, Temporary &address, TIntermTyped *node); int lvalue(TIntermTyped *&root, unsigned int &offset, sw::Shader::Relative &rel, unsigned char &mask, Temporary &address, TIntermTyped *node);
sw::Shader::ParameterType registerType(TIntermTyped *operand); sw::Shader::ParameterType registerType(TIntermTyped *operand);
......
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