Disable optimizations for shaders with conditional discard in D3D9, and
only use expanded short-circuiting conditionals for expressions with
potential side-effects.

Conservatively assume aggreate and selection operators have side effects for now.

BUG=
ANGLEBUG=486
R=geofflang@chromium.org, kbr@chromium.org, nicolas@transgaming.com, shannonwoods@chromium.org

Review URL: https://codereview.appspot.com/14441075

Conflicts:
	src/common/version.h
	src/compiler/translator.vcxproj
	src/compiler/translator.vcxproj.filters
	src/compiler/translator/OutputHLSL.cpp
	src/libGLESv2/ProgramBinary.cpp
	src/libGLESv2/Shader.cpp
	src/libGLESv2/Shader.h

Change-Id: Iaf9f10b5de7b33c927ef032f3c4fe9d5095f64dd
diff --git a/src/compiler/translator/intermediate.h b/src/compiler/translator/intermediate.h
index c286149..f252298 100644
--- a/src/compiler/translator/intermediate.h
+++ b/src/compiler/translator/intermediate.h
@@ -258,6 +258,8 @@
     TIntermTyped(const TType& t) : type(t)  { }
     virtual TIntermTyped* getAsTyped() { return this; }
 
+    virtual bool hasSideEffects() const = 0;
+
     void setType(const TType& t) { type = t; }
     const TType& getType() const { return type; }
     TType* getTypePointer() { return &type; }
@@ -359,6 +361,8 @@
     TIntermSymbol(int i, const TString& sym, const TType& t) : 
             TIntermTyped(t), id(i)  { symbol = sym; originalSymbol = sym; } 
 
+    virtual bool hasSideEffects() const { return false; }
+
     int getId() const { return id; }
     const TString& getSymbol() const { return symbol; }
 
@@ -380,6 +384,8 @@
 public:
     TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
 
+    virtual bool hasSideEffects() const { return false; }
+
     ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
     
     int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
@@ -404,7 +410,7 @@
     TOperator getOp() const { return op; }
     void setOp(TOperator o) { op = o; }
 
-    bool modifiesState() const;
+    virtual bool hasSideEffects() const;
     bool isConstructor() const;
 
 protected:
@@ -423,6 +429,8 @@
     virtual TIntermBinary* getAsBinaryNode() { return this; }
     virtual void traverse(TIntermTraverser*);
 
+    virtual bool hasSideEffects() const { return (TIntermOperator::hasSideEffects() || left->hasSideEffects() || right->hasSideEffects()); }
+
     void setLeft(TIntermTyped* n) { left = n; }
     void setRight(TIntermTyped* n) { right = n; }
     TIntermTyped* getLeft() const { return left; }
@@ -451,6 +459,8 @@
     virtual void traverse(TIntermTraverser*);
     virtual TIntermUnary* getAsUnaryNode() { return this; }
 
+    virtual bool hasSideEffects() const { return (TIntermOperator::hasSideEffects() || operand->hasSideEffects()); }
+
     void setOperand(TIntermTyped* o) { operand = o; }
     TIntermTyped* getOperand() { return operand; }    
     bool promote(TInfoSink&);
@@ -481,6 +491,9 @@
     virtual TIntermAggregate* getAsAggregate() { return this; }
     virtual void traverse(TIntermTraverser*);
 
+    // Conservatively assume function calls and other aggregate operators have side-effects
+    virtual bool hasSideEffects() const { return true; }
+
     TIntermSequence& getSequence() { return sequence; }
 
     void setName(const TString& n) { name = n; }
@@ -524,6 +537,9 @@
 
     virtual void traverse(TIntermTraverser*);
 
+    // Conservatively assume selections have side-effects
+    virtual bool hasSideEffects() const { return true; }
+
     bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
     TIntermNode* getCondition() const { return condition; }
     TIntermNode* getTrueBlock() const { return trueBlock; }