ReductionOpportunities { public static List<IReductionOpportunity> getReductionOpportunities( ShaderJob shaderJob, ReducerContext context, ShaderJobFileOperations fileOps) { final List<IReductionOpportunity> opportunities = new ArrayList<>(); for (IReductionOpportunityFinder<?> ros : Arrays.asList( IReductionOpportunityFinder.loopMergeFinder(), IReductionOpportunityFinder.removeStructFieldFinder(), IReductionOpportunityFinder.destructifyFinder(), IReductionOpportunityFinder.inlineStructFieldFinder(), IReductionOpportunityFinder.outlinedStatementFinder(), IReductionOpportunityFinder.variableDeclFinder(), IReductionOpportunityFinder.globalVariablesDeclarationFinder(), IReductionOpportunityFinder.globalPrecisionDeclarationFinder(), IReductionOpportunityFinder.unwrapFinder(), IReductionOpportunityFinder.unswitchifyFinder(), IReductionOpportunityFinder.vectorizationFinder(), IReductionOpportunityFinder.functionFinder(), IReductionOpportunityFinder.stmtFinder(), IReductionOpportunityFinder.exprToConstantFinder(), IReductionOpportunityFinder.compoundExprToSubExprFinder(), IReductionOpportunityFinder.mutationFinder(), IReductionOpportunityFinder.flattenControlFlowFinder(), IReductionOpportunityFinder.inlineInitializerFinder(), IReductionOpportunityFinder.inlineFunctionFinder(), IReductionOpportunityFinder.liveFragColorWriteFinder(), IReductionOpportunityFinder.unusedParamFinder(), IReductionOpportunityFinder.foldConstantFinder(), IReductionOpportunityFinder.inlineUniformFinder(), IReductionOpportunityFinder.redundantUniformMetadataFinder(), IReductionOpportunityFinder.variableDeclToExprFinder(), IReductionOpportunityFinder.switchToLoopFinder(), IReductionOpportunityFinder.globalVariableDeclToExprFinder())) { final List<? extends IReductionOpportunity> currentOpportunities = ros .findOpportunities(shaderJob, context); if (ReductionDriver.DEBUG_REDUCER) { opportunities.addAll(currentOpportunities.stream() .map(item -> new CheckValidReductionOpportunityDecorator(item, shaderJob, context.getShadingLanguageVersion(), fileOps)) .collect(Collectors.toList())); } else { opportunities.addAll(currentOpportunities); } } return opportunities; } private  ReductionOpportunities(); static List<IReductionOpportunity> getReductionOpportunities(
      ShaderJob shaderJob,
      ReducerContext context,
      ShaderJobFileOperations fileOps);  }
@Test public void testDeadConditionalNotReplaced() throws Exception { String prog = "void main() {" + "if(" + Constants.GLF_DEAD + "(" + Constants.GLF_IDENTITY + "(false, true && " + Constants.GLF_IDENTITY + "(false, (true ? false : " + Constants.GLF_FUZZED + "(true)))))) {" + " }" + "}\n"; TranslationUnit tu = ParseHelper.parse(prog); List<IReductionOpportunity> opportunities = ReductionOpportunities.getReductionOpportunities(MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false, ShadingLanguageVersion.ESSL_100, new RandomWrapper(0), new IdGenerator()), fileOps); assertFalse(opportunities.stream().anyMatch( item -> item instanceof SimplifyExprReductionOpportunity)); }
@Test public void testPopScope() throws Exception { String program = "void foo(int x) { x; } void main() { }\n"; TranslationUnit tu = ParseHelper.parse(program); ReductionOpportunities.getReductionOpportunities(MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false, ShadingLanguageVersion.ESSL_100, new RandomWrapper(0), new IdGenerator()), fileOps); }
@Test public void exprSimplificationAndLoopSplitInteraction() throws Exception { String program = "void main() {" + " if(_GLF_DEAD(_GLF_FALSE(false, false))) {" + " for(\n" + " int _GLF_SPLIT_LOOP_COUNTER_1n = 0;\n" + " _GLF_SPLIT_LOOP_COUNTER_1n < 3;\n" + " _GLF_SPLIT_LOOP_COUNTER_1n ++\n" + " )\n" + " {\n" + " }\n" + " for(\n" + " int _GLF_SPLIT_LOOP_COUNTER_1n = 3;\n" + " _GLF_SPLIT_LOOP_COUNTER_1n < 3;\n" + " _GLF_SPLIT_LOOP_COUNTER_1n ++\n" + " )\n" + " {\n" + " }\n" + " }\n" + "}\n"; TranslationUnit tu = ParseHelper.parse(program); List<Integer> indicesOfExprToConstOps = new ArrayList<>(); { List<IReductionOpportunity> ops = ReductionOpportunities .getReductionOpportunities(MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false, ShadingLanguageVersion.ESSL_100, new RandomWrapper(0), new IdGenerator()), fileOps); for (int i = 0; i < ops.size(); i++) { if (ops.get(i) instanceof SimplifyExprReductionOpportunity) { indicesOfExprToConstOps.add(i); } } } for (Integer index : indicesOfExprToConstOps) { final TranslationUnit tuClone = tu.clone(); { final List<IReductionOpportunity> ops = ReductionOpportunities.getReductionOpportunities( MakeShaderJobFromFragmentShader.make(tuClone), new ReducerContext(false, ShadingLanguageVersion.ESSL_100, new RandomWrapper(0), new IdGenerator()), fileOps); ((SimplifyExprReductionOpportunity) ops.get(index)).applyReduction(); } for (IReductionOpportunity op : ReductionOpportunities .getReductionOpportunities(MakeShaderJobFromFragmentShader.make(tuClone), new ReducerContext(false, ShadingLanguageVersion.ESSL_100, new RandomWrapper(0), new IdGenerator()), fileOps)) { if (op instanceof LoopMergeReductionOpportunity) { op.applyReduction(); } } } }
@Test public void reduceRedundantStuff() throws Exception { final String program = "void main() { int a; a = a; }"; final String expected = "void main() { }"; final TranslationUnit tu = ParseHelper.parse(program); while (true) { List<IReductionOpportunity> ops = ReductionOpportunities.getReductionOpportunities( MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false, ShadingLanguageVersion.GLSL_440, new RandomWrapper(0), new IdGenerator()), fileOps); if (ops.isEmpty()) { break; } ops.get(0).applyReduction(); } assertEquals(PrettyPrinterVisitor.prettyPrintAsString(ParseHelper.parse(expected)), PrettyPrinterVisitor.prettyPrintAsString(tu)); }
@Test public void testRemoveLoopLimiter2() throws Exception { TranslationUnit tu = ParseHelper.parse("" + "void main() {\n" + " int GLF_live3_looplimiter0 = 0;\n" + " for(\n" + " float GLF_live3sphereNo = 0.0;\n" + " GLF_live3sphereNo < 10.0;\n" + " GLF_live3sphereNo ++\n" + " )\n" + " {\n" + " if(GLF_live3_looplimiter0 >= 5)\n" + " {\n" + " break;\n" + " }\n" + " GLF_live3_looplimiter0 ++;\n" + " }\n" + "}\n"); while (true) { List<IReductionOpportunity> ops = ReductionOpportunities .getReductionOpportunities(MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false, ShadingLanguageVersion.GLSL_440, new RandomWrapper(0), new IdGenerator()), fileOps); if (ops.isEmpty()) { break; } ops.get(0).applyReduction(); } final String expected = "" + "void main() {\n" + "}\n"; CompareAsts.assertEqualAsts(expected, tu); }
@Test public void testUniformsGetRemoved() throws Exception { final String program = "#version 310 es\n" + "\n" + "#ifdef GL_ES\n" + "#ifdef GL_FRAGMENT_PRECISION_HIGH\n" + "precision highp float;\n" + "precision highp int;\n" + "#else\n" + "precision mediump float;\n" + "precision mediump int;\n" + "#endif\n" + "#endif\n" + "\n" + "#ifndef REDUCER\n" + "#define _GLF_ZERO(X, Y) (Y)\n" + "#define _GLF_ONE(X, Y) (Y)\n" + "#define _GLF_FALSE(X, Y) (Y)\n" + "#define _GLF_TRUE(X, Y) (Y)\n" + "#define _GLF_IDENTITY(X, Y) (Y)\n" + "#define _GLF_DEAD(X) (X)\n" + "#define _GLF_FUZZED(X) (X)\n" + "#define _GLF_WRAPPED_LOOP(X) X\n" + "#define _GLF_WRAPPED_IF_TRUE(X) X\n" + "#define _GLF_WRAPPED_IF_FALSE(X) X\n" + "#define _GLF_SWITCH(X) X\n" + "#endif\n" + "\n" + " + "\n" + "layout(set=0,binding=0) uniform buf0 {\n" + " vec2 injectionSwitch;\n" + "} ;\n" + "void main() { }"; final TranslationUnit tu = ParseHelper.parse(program); final String json = "{ \"injectionSwitch\": { \"args\": [ 1.0, 2.0 ], " + " \"func\": \"glUniform2f\", \"binding\": 0 } }"; final ShaderJob shaderJob = new GlslShaderJob(Optional.empty(), new PipelineInfo(json), tu); shaderJob.removeUniformBindings(); List<IReductionOpportunity> ops = ReductionOpportunities.getReductionOpportunities( MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false, ShadingLanguageVersion.GLSL_440, new RandomWrapper(0), new IdGenerator()), fileOps); assertEquals(1, ops.size()); assertTrue(ops.get(0) instanceof VariableDeclReductionOpportunity); ops.get(0).applyReduction(); shaderJob.makeUniformBindings(Optional.empty()); CompareAsts.assertEqualAsts("#version 310 es\nvoid main() { }", tu); }
@Test public void testReductionOpportunitiesOnEmptyForLoops() throws Exception { final TranslationUnit tu = ParseHelper.parse("#version 310 es\n" + "precision highp float;\n" + "int x = 0;\n" + "void main() {\n" + " for(int i1 = 0;;) {\n" + " for(int i2 = 0;;) {\n" + " for(;;) {\n" + " for(int i3 = 0;;) {\n" + " x++;\n" + " if (x > 10) break;\n" + " }\n" + " for(int i3 = 0;;) {\n" + " x++;\n" + " if (x > 10) break;\n" + " }\n" + " x++;\n" + " if(x > 20) break;\n" + " }\n" + " x++;\n" + " if(x > 30) break;\n" + " }\n" + " x++;\n" + " if(x > 40) break;\n" + " };\n" + "}\n"); List<IReductionOpportunity> ops = ReductionOpportunities.getReductionOpportunities( MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(true, ShadingLanguageVersion.GLSL_440, new RandomWrapper(0), new IdGenerator()), fileOps); ops.forEach(IReductionOpportunity::applyReduction); }
@Test public void testCanRemoveLiveInjectedVariables() throws Exception { final String shader = "#version 310 es\n" + "void main() {\n" + " vec4 GLF_live6c = vec4(1.0);\n" + " GLF_live6c[0] = 1.0;\n" + "}\n"; final TranslationUnit tu = ParseHelper.parse(shader); List<IReductionOpportunity> ops = ReductionOpportunities.getReductionOpportunities( MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false, ShadingLanguageVersion.ESSL_310, new RandomWrapper(0), new IdGenerator()), fileOps); assertFalse(ops.isEmpty()); }
@Test public void testCanRemovePrecisionStatements() throws Exception { final String shader = "#version 310 es\n" + "precision highp float;\n" + "precision highp int;\n" + "precision mediump float;\n" + "precision lowp int;\n" + "precision highp int;\n" + "precision highp float;\n" + "void main() {\n" + "}\n"; final TranslationUnit tu = ParseHelper.parse(shader); List<IReductionOpportunity> ops = ReductionOpportunities.getReductionOpportunities( MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false, ShadingLanguageVersion.ESSL_310, new RandomWrapper(0), new IdGenerator()), fileOps); assertEquals(4, ops.size()); }
@Test public void testCannotRemovePrecisionStatements() throws Exception { final String shader = "#version 310 es\n" + "precision mediump float;\n" + "float f;\n" + "precision highp float;\n" + "float g;\n" + "void main() {\n" + " f = g;\n" + "}\n"; final TranslationUnit tu = ParseHelper.parse(shader); List<IReductionOpportunity> ops = ReductionOpportunities.getReductionOpportunities( MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false, ShadingLanguageVersion.ESSL_310, new RandomWrapper(0), new IdGenerator()), fileOps); assertTrue(ops.isEmpty()); }
@Test public void testCanRemoveOnePrecisionStatement() throws Exception { final String shader = "#version 310 es\n" + "precision mediump float;\n" + "precision highp float;\n" + "float f;\n" + "void main() {\n" + " f = 1.0;\n" + "}\n"; final TranslationUnit tu = ParseHelper.parse(shader); List<IReductionOpportunity> ops = ReductionOpportunities.getReductionOpportunities( MakeShaderJobFromFragmentShader.make(tu), new ReducerContext(false, ShadingLanguageVersion.ESSL_310, new RandomWrapper(0), new IdGenerator()), fileOps); assertEquals(1, ops.size()); ops.get(0).applyReduction(); final String expected = "#version 310 es\n" + "precision highp float;\n" + "float f;\n" + "void main() {\n" + " f = 1.0;\n" + "}\n"; CompareAsts.assertEqualAsts(expected, tu); }