Skip to content

Commit b7fac1c

Browse files
committed
Better reduction for array indices
Improves the reducer's ability to reduce array indexing expressions, by being less conservative about l-values. Part of #1179.
1 parent b5bfc72 commit b7fac1c

File tree

4 files changed

+135
-7
lines changed

4 files changed

+135
-7
lines changed

reducer/src/main/java/com/graphicsfuzz/reducer/reductionopportunities/CompoundExprToSubExprReductionOpportunities.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.graphicsfuzz.common.ast.IAstNode;
2020
import com.graphicsfuzz.common.ast.TranslationUnit;
21+
import com.graphicsfuzz.common.ast.expr.ArrayIndexExpr;
2122
import com.graphicsfuzz.common.ast.expr.BinOp;
2223
import com.graphicsfuzz.common.ast.expr.BinaryExpr;
2324
import com.graphicsfuzz.common.ast.expr.ConstantExpr;
@@ -51,7 +52,7 @@ void identifyReductionOpportunitiesForChild(IAstNode parent, Expr child) {
5152
if (child instanceof ParenExpr) {
5253
// We need to be careful about removing parentheses, as this can change precedence.
5354
// We only remove parentheses if they are at the root of an expression, immediately under
54-
// other parentheses, or immediately under a function call.
55+
// other parentheses, immediately under a function call, or immediately under array brackets.
5556
if (!isOkToRemoveParens(parent, (ParenExpr) child)) {
5657
return;
5758
}
@@ -97,6 +98,10 @@ private boolean isOkToRemoveParens(IAstNode parent, ParenExpr child) {
9798
// These are parentheses within parentheses; fine to remove them.
9899
return true;
99100
}
101+
if (parent instanceof ArrayIndexExpr && child == ((ArrayIndexExpr)parent).getIndex()) {
102+
// These are parenthesis directly under array indexing brackets; fine to remove them.
103+
return true;
104+
}
100105
if (parent instanceof FunctionCallExpr) {
101106
// These are parentheses under a function call argument. Fine to remove them *unless*
102107
// they enclose a use of the comma operator; e.g. we don't want to turn sin((a, b)) into

reducer/src/main/java/com/graphicsfuzz/reducer/reductionopportunities/ReductionOpportunitiesBase.java

+21-6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.graphicsfuzz.common.ast.IAstNode;
2020
import com.graphicsfuzz.common.ast.TranslationUnit;
2121
import com.graphicsfuzz.common.ast.decl.VariableDeclInfo;
22+
import com.graphicsfuzz.common.ast.expr.ArrayIndexExpr;
2223
import com.graphicsfuzz.common.ast.expr.BinaryExpr;
2324
import com.graphicsfuzz.common.ast.expr.Expr;
2425
import com.graphicsfuzz.common.ast.expr.UnaryExpr;
@@ -38,7 +39,11 @@ public abstract class ReductionOpportunitiesBase
3839

3940
final ShaderKind shaderKind;
4041

41-
private int numEnclosingLValues;
42+
// Each entry in this stack records how many l-values enclose the current expression. A new
43+
// stack entry is pushed each time an array indexing expression is encountered, because even when
44+
// an array indexing expression is an l-value, this does not mean that the index expression
45+
// itself is an l-value.
46+
private final List<Integer> enclosingLValuesStack;
4247

4348
/**
4449
* Construct base class for finding reduction opportunities, with respect to a translation unit.
@@ -51,7 +56,8 @@ public ReductionOpportunitiesBase(TranslationUnit tu, ReducerContext context) {
5156
this.opportunities = new ArrayList<>();
5257
this.context = context;
5358
this.shaderKind = tu.getShaderKind();
54-
this.numEnclosingLValues = 0;
59+
this.enclosingLValuesStack = new ArrayList<>();
60+
this.enclosingLValuesStack.add(0);
5561
}
5662

5763
@Override
@@ -86,6 +92,13 @@ public void visitUnaryExpr(UnaryExpr unaryExpr) {
8692
}
8793
}
8894

95+
@Override
96+
public void visitArrayIndexExpr(ArrayIndexExpr arrayIndexExpr) {
97+
enclosingLValuesStack.add(0);
98+
super.visitArrayIndexExpr(arrayIndexExpr);
99+
enclosingLValuesStack.remove(enclosingLValuesStack.size() - 1);
100+
}
101+
89102
@Override
90103
protected void visitChildFromParent(IAstNode child, IAstNode parent) {
91104
super.visitChildFromParent(child, parent);
@@ -99,16 +112,18 @@ void identifyReductionOpportunitiesForChild(IAstNode parent, Expr child) {
99112
}
100113

101114
private void enterLValueContext() {
102-
numEnclosingLValues++;
115+
enclosingLValuesStack.set(enclosingLValuesStack.size() - 1,
116+
enclosingLValuesStack.get(enclosingLValuesStack.size() - 1) + 1);
103117
}
104118

105119
private void exitLValueContext() {
106-
assert numEnclosingLValues > 0;
107-
numEnclosingLValues--;
120+
assert enclosingLValuesStack.get(enclosingLValuesStack.size() - 1) > 0;
121+
enclosingLValuesStack.set(enclosingLValuesStack.size() - 1,
122+
enclosingLValuesStack.get(enclosingLValuesStack.size() - 1) - 1);
108123
}
109124

110125
boolean inLValueContext() {
111-
return numEnclosingLValues > 0;
126+
return enclosingLValuesStack.get(enclosingLValuesStack.size() - 1) > 0;
112127
}
113128

114129
boolean initializerIsScalarAndSideEffectFree(VariableDeclInfo variableDeclInfo) {

reducer/src/test/java/com/graphicsfuzz/reducer/ReductionDriverTest.java

+56
Original file line numberDiff line numberDiff line change
@@ -1064,4 +1064,60 @@ public boolean isInteresting(
10641064
resultsPrefix + ".frag")));
10651065
}
10661066

1067+
@Test
1068+
public void testSimplificationOfTernaryWithArray() throws Exception {
1069+
final String shader = "#version 310 es\n"
1070+
+ "void main()\n"
1071+
+ "{\n"
1072+
+ " int ext_0;\n"
1073+
+ " int ext_1[3];\n"
1074+
+ " int ext_2[3];\n"
1075+
+ " ext_2[(all(bvec2(true)) ? (+ abs(ext_1[1])) : (ext_0 & -- ext_2[2]))] |= 1;\n"
1076+
+ "}\n";
1077+
1078+
final String expected = "#version 310 es\n"
1079+
+ "void main()\n"
1080+
+ "{\n"
1081+
+ " int ext_1[3];\n"
1082+
+ " int ext_2[3];\n"
1083+
+ " int[3](1, 1, 1)[abs(ext_1[1])] |= 1;\n"
1084+
+ "}\n";
1085+
1086+
final ShaderJob shaderJob = new GlslShaderJob(Optional.empty(),
1087+
new PipelineInfo(),
1088+
ParseHelper.parse(shader));
1089+
1090+
final File workDir = testFolder.getRoot();
1091+
final File tempShaderJobFile = new File(workDir, "temp.json");
1092+
fileOps.writeShaderJobFile(shaderJob, tempShaderJobFile);
1093+
1094+
final IFileJudge customJudge = (file, unused) -> {
1095+
try {
1096+
ShaderJob customJudgeShaderJob = fileOps.readShaderJobFile(file);
1097+
assert customJudgeShaderJob.getShaders().size() == 1;
1098+
final TranslationUnit tu = customJudgeShaderJob.getShaders().get(0);
1099+
final String shaderString = tu.getText();
1100+
return shaderString.contains("ext_2[") && shaderString.contains("abs(ext_1[1])")
1101+
&& shaderString.contains(" |= 1");
1102+
} catch (Exception exception) {
1103+
throw new RuntimeException(exception);
1104+
}
1105+
};
1106+
1107+
final String resultsPrefix = new ReductionDriver(new ReducerContext(true,
1108+
false,
1109+
ShadingLanguageVersion.ESSL_310,
1110+
new RandomWrapper(0),
1111+
new IdGenerator()),
1112+
false,
1113+
fileOps,
1114+
customJudge,
1115+
workDir)
1116+
.doReduction(shaderJob, "temp", 0, 100);
1117+
1118+
CompareAsts.assertEqualAsts(expected, ParseHelper.parse(new File(testFolder.getRoot(),
1119+
resultsPrefix + ".frag")));
1120+
1121+
}
1122+
10671123
}

reducer/src/test/java/com/graphicsfuzz/reducer/reductionopportunities/CompoundExprToSubExprReductionOpportunitiesTest.java

+52
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.graphicsfuzz.common.ast.TranslationUnit;
2323
import com.graphicsfuzz.common.glslversion.ShadingLanguageVersion;
2424
import com.graphicsfuzz.common.tool.PrettyPrinterVisitor;
25+
import com.graphicsfuzz.common.util.CompareAsts;
2526
import com.graphicsfuzz.common.util.GlslParserException;
2627
import com.graphicsfuzz.common.util.IdGenerator;
2728
import com.graphicsfuzz.common.util.ParseHelper;
@@ -191,4 +192,55 @@ public void testSwitch() throws Exception {
191192
assertEquals(0, ops.size());
192193
}
193194

195+
@Test
196+
public void testTernary() throws Exception {
197+
final String program = "#version 310 es\n"
198+
+ "void main() {\n"
199+
+ " true ? 1 : 0;\n"
200+
+ "}\n";
201+
final TranslationUnit tu = ParseHelper.parse(program);
202+
final List<SimplifyExprReductionOpportunity> ops = CompoundExprToSubExprReductionOpportunities
203+
.findOpportunities(MakeShaderJobFromFragmentShader.make(tu),
204+
new ReducerContext(true, true, ShadingLanguageVersion.ESSL_310, new RandomWrapper(0),
205+
new IdGenerator()));
206+
assertEquals(2, ops.size());
207+
ops.get(0).applyReduction();
208+
final String expected = "#version 310 es\n"
209+
+ "void main() {\n"
210+
+ " 1;\n"
211+
+ "}\n";
212+
CompareAsts.assertEqualAsts(expected, tu);
213+
}
214+
215+
@Test
216+
public void testArrayIndexWithParentheses() throws Exception {
217+
final String program = "#version 310 es\n"
218+
+ "void main() {\n"
219+
+ " int x, y;"
220+
+ " int A[1];\n"
221+
+ " A[(x + y)];\n"
222+
+ "}\n";
223+
final TranslationUnit tu = ParseHelper.parse(program);
224+
final List<SimplifyExprReductionOpportunity> ops = CompoundExprToSubExprReductionOpportunities
225+
.findOpportunities(MakeShaderJobFromFragmentShader.make(tu),
226+
new ReducerContext(true, true, ShadingLanguageVersion.ESSL_310, new RandomWrapper(0),
227+
new IdGenerator()));
228+
assertEquals(4, ops.size());
229+
}
230+
231+
@Test
232+
public void testSimplifyArrayIndexOfLValue() throws Exception {
233+
final String program = "#version 310 es\n"
234+
+ "void main() {\n"
235+
+ " int A[1];\n"
236+
+ " A[(0)] = 1;\n"
237+
+ "}\n";
238+
final TranslationUnit tu = ParseHelper.parse(program);
239+
final List<SimplifyExprReductionOpportunity> ops = CompoundExprToSubExprReductionOpportunities
240+
.findOpportunities(MakeShaderJobFromFragmentShader.make(tu),
241+
new ReducerContext(true, true, ShadingLanguageVersion.ESSL_310, new RandomWrapper(0),
242+
new IdGenerator()));
243+
assertEquals(3, ops.size());
244+
}
245+
194246
}

0 commit comments

Comments
 (0)