Implemented short-circuiting for logical OR and AND operators.

TRAC #11866 Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@1061 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 44fffeef
#define MAJOR_VERSION 1 #define MAJOR_VERSION 1
#define MINOR_VERSION 0 #define MINOR_VERSION 0
#define BUILD_VERSION 0 #define BUILD_VERSION 0
#define BUILD_REVISION 1060 #define BUILD_REVISION 1061
#define STRINGIFY(x) #x #define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x) #define MACRO_STRINGIFY(x) STRINGIFY(x)
......
...@@ -1055,12 +1055,16 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) ...@@ -1055,12 +1055,16 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break; case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break; case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break; case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
case EOpLogicalOr: outputTriplet(visit, "(", " || ", ")"); break; case EOpLogicalOr:
out << "s" << mUnfoldSelect->getNextTemporaryIndex();
return false;
case EOpLogicalXor: case EOpLogicalXor:
mUsesXor = true; mUsesXor = true;
outputTriplet(visit, "xor(", ", ", ")"); outputTriplet(visit, "xor(", ", ", ")");
break; break;
case EOpLogicalAnd: outputTriplet(visit, "(", " && ", ")"); break; case EOpLogicalAnd:
out << "s" << mUnfoldSelect->getNextTemporaryIndex();
return false;
default: UNREACHABLE(); default: UNREACHABLE();
} }
......
// //
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// UnfoldSelect is an AST traverser to output the select operator ?: as if-else statements // UnfoldSelect is an AST traverser to output short-circuiting operators as if-else statements.
// The results are assigned to s# temporaries, which are used by the main translator instead of
// the original expression.
// //
#include "compiler/UnfoldSelect.h" #include "compiler/UnfoldSelect.h"
...@@ -25,10 +27,84 @@ void UnfoldSelect::traverse(TIntermNode *node) ...@@ -25,10 +27,84 @@ void UnfoldSelect::traverse(TIntermNode *node)
mTemporaryIndex = rewindIndex; mTemporaryIndex = rewindIndex;
} }
bool UnfoldSelect::visitBinary(Visit visit, TIntermBinary *node)
{
TInfoSinkBase &out = mOutputHLSL->getBodyStream();
switch (node->getOp())
{
case EOpLogicalOr:
// "x || y" is equivalent to "x ? true : y", which unfolds to "bool s; if(x) s = true; else s = y;",
// and then further simplifies down to "bool s = x; if(!s) s = y;".
{
int i = mTemporaryIndex;
out << "bool s" << i << ";\n";
out << "{\n";
mTemporaryIndex = i + 1;
node->getLeft()->traverse(this);
out << "s" << i << " = ";
mTemporaryIndex = i + 1;
node->getLeft()->traverse(mOutputHLSL);
out << ";\n";
out << "if(!s" << i << ")\n"
"{\n";
mTemporaryIndex = i + 1;
node->getRight()->traverse(this);
out << " s" << i << " = ";
mTemporaryIndex = i + 1;
node->getRight()->traverse(mOutputHLSL);
out << ";\n"
"}\n";
out << "}\n";
mTemporaryIndex = i + 1;
}
return false;
case EOpLogicalAnd:
// "x && y" is equivalent to "x ? y : false", which unfolds to "bool s; if(x) s = y; else s = false;",
// and then further simplifies down to "bool s = x; if(s) s = y;".
{
int i = mTemporaryIndex;
out << "bool s" << i << ";\n";
out << "{\n";
mTemporaryIndex = i + 1;
node->getLeft()->traverse(this);
out << "s" << i << " = ";
mTemporaryIndex = i + 1;
node->getLeft()->traverse(mOutputHLSL);
out << ";\n";
out << "if(s" << i << ")\n"
"{\n";
mTemporaryIndex = i + 1;
node->getRight()->traverse(this);
out << " s" << i << " = ";
mTemporaryIndex = i + 1;
node->getRight()->traverse(mOutputHLSL);
out << ";\n"
"}\n";
out << "}\n";
mTemporaryIndex = i + 1;
}
return false;
}
return true;
}
bool UnfoldSelect::visitSelection(Visit visit, TIntermSelection *node) bool UnfoldSelect::visitSelection(Visit visit, TIntermSelection *node)
{ {
TInfoSinkBase &out = mOutputHLSL->getBodyStream(); TInfoSinkBase &out = mOutputHLSL->getBodyStream();
// Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
if (node->usesTernaryOperator()) if (node->usesTernaryOperator())
{ {
int i = mTemporaryIndex; int i = mTemporaryIndex;
......
// //
// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
// UnfoldSelect is an AST traverser to output the select operator ?: as if-else statements // UnfoldSelect is an AST traverser to output short-circuiting operators as if-else statements
// //
#ifndef COMPILER_UNFOLDSELECT_H_ #ifndef COMPILER_UNFOLDSELECT_H_
...@@ -22,6 +22,7 @@ class UnfoldSelect : public TIntermTraverser ...@@ -22,6 +22,7 @@ class UnfoldSelect : public TIntermTraverser
UnfoldSelect(TParseContext &context, OutputHLSL *outputHLSL); UnfoldSelect(TParseContext &context, OutputHLSL *outputHLSL);
void traverse(TIntermNode *node); void traverse(TIntermNode *node);
bool visitBinary(Visit visit, TIntermBinary*);
bool visitSelection(Visit visit, TIntermSelection *node); bool visitSelection(Visit visit, TIntermSelection *node);
bool visitLoop(Visit visit, TIntermLoop *node); bool visitLoop(Visit visit, TIntermLoop *node);
......
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