@Override void applyReductionImpl() { if (!variablesDeclaration.getDeclInfos().contains(variableDeclInfo)) { // The declaration must have been removed by another reduction opportunity return; } for (int i = 0; i < variablesDeclaration.getNumDecls(); i++) { if (variablesDeclaration.getDeclInfo(i) == variableDeclInfo) { variablesDeclaration.removeDeclInfo(i); return; } } throw new RuntimeException("Should be unreachable."); }
private static void replaceLoopCounterInInitializer(Stmt init, String newLoopCounter) { ((DeclarationStmt) init).getVariablesDeclaration().getDeclInfo(0).setName(newLoopCounter); }
@Override public void applyReductionImpl() { firstLoop.setCondition(secondLoop.getCondition()); enclosingBlock.removeStmt(secondLoop); final String splitLoopCounter = ((DeclarationStmt) firstLoop.getInit()) .getVariablesDeclaration().getDeclInfo(0).getName(); int originalNameBeginIndex = Constants.SPLIT_LOOP_COUNTER_PREFIX.length(); assert Character.isDigit(splitLoopCounter.charAt(originalNameBeginIndex)); while (Character.isDigit(splitLoopCounter.charAt(originalNameBeginIndex))) { originalNameBeginIndex++; } final String mergedLoopCounter = splitLoopCounter.substring(originalNameBeginIndex); ReplaceLoopCounter.replaceLoopCounter(firstLoop, splitLoopCounter, mergedLoopCounter); }
static boolean isStructifiedDeclaration(DeclarationStmt declarationStmt) { return declarationStmt.getVariablesDeclaration().getNumDecls() == 1 && declarationStmt.getVariablesDeclaration().getDeclInfo(0).getName() .startsWith(Constants.STRUCTIFICATION_STRUCT_PREFIX); }
private Optional<String> extractLoopCounter(ForStmt loop) { if (!(loop.getInit() instanceof DeclarationStmt)) { return Optional.empty(); } final DeclarationStmt init = (DeclarationStmt) loop.getInit(); if (init.getVariablesDeclaration().getNumDecls() != 1) { return Optional.empty(); } return Optional.of(init.getVariablesDeclaration().getDeclInfo(0).getName()); }
private boolean referencesBackup(Stmt stmt) { final VariableDeclInfo backupVdi = ((DeclarationStmt) block.getStmt(indexOfBackupDeclaration().get())) .getVariablesDeclaration().getDeclInfo(0); return new ScopeTreeBuilder() { private boolean found = false; @Override public void visitVariableIdentifierExpr(VariableIdentifierExpr variableIdentifierExpr) { super.visitVariableIdentifierExpr(variableIdentifierExpr); final ScopeEntry se = currentScope.lookupScopeEntry(variableIdentifierExpr.getName()); if (se != null && se.hasVariableDeclInfo() && se.getVariableDeclInfo() == backupVdi) { found = true; } } private boolean check(Stmt stmt) { visit(stmt); return found; } }.check(stmt); }
private StructifiedVariableInfo findOriginalVariableInfo() { return findOriginalVariableInfo( (StructNameType) declaration.getVariablesDeclaration().getBaseType() .getWithoutQualifiers(), Optional.ofNullable((ScalarInitializer) declaration.getVariablesDeclaration() .getDeclInfo(0).getInitializer())) .get(); }
public StructificationOpportunity(DeclarationStmt declToTransform, BlockStmt block, TranslationUnit tu, ShadingLanguageVersion shadingLanguageVersion) { assert declToTransform.getVariablesDeclaration().getNumDecls() == 1 : "Only solo declarations can be structified"; assert !declToTransform.getVariablesDeclaration().getDeclInfo(0).hasArrayInfo() : "Structification of arrays not supported"; this.declToTransform = declToTransform; this.block = block; this.tu = tu; this.shadingLanguageVersion = shadingLanguageVersion; }
private Expr insertFieldIntoStruct(String enclosingStructName, StructDefinitionType enclosingStruct, IRandom generator) { Expr result = new VariableIdentifierExpr(enclosingStructName); StructDefinitionType currentStruct = enclosingStruct; while (true) { Map<String, StructDefinitionType> structFields = getStructFields(currentStruct); if (!structFields.keySet().isEmpty() && generator.nextBoolean()) { String fieldName = structFields.keySet().stream().collect(Collectors.toList()) .get(generator.nextInt(structFields.size())); result = new MemberLookupExpr(result, fieldName); currentStruct = structFields.get(fieldName); } else { // Choose random position at which to insert the field. currentStruct.insertField(generator.nextInt(currentStruct.getNumFields() + 1), declToTransform.getVariablesDeclaration().getDeclInfo(0).getName(), declToTransform.getVariablesDeclaration().getBaseType()); result = new MemberLookupExpr(result, declToTransform.getVariablesDeclaration() .getDeclInfo(0).getName()); return result; } } }
private void adjustInitializer(ForStmt loop, int numIterationsToSplitAfter, LoopSplitInfo loopSplitInfo) { final Integer newStart = new Integer(loopSplitInfo.getStartValue() + (loopSplitInfo.getIncreasing() ? 1 : -1) * numIterationsToSplitAfter); VariablesDeclaration varDecl = ((DeclarationStmt) loop.getInit()).getVariablesDeclaration(); varDecl.getDeclInfo(0).setInitializer(new ScalarInitializer(new IntConstantExpr( newStart.toString()))); }
private void sweep(TranslationUnit tu) { final List<Declaration> oldTopLevelDecls = new ArrayList<>(); oldTopLevelDecls.addAll(tu.getTopLevelDeclarations()); for (Declaration decl : oldTopLevelDecls) { if (!(decl instanceof VariablesDeclaration)) { continue; } final VariablesDeclaration variablesDeclaration = (VariablesDeclaration) decl; int index = 0; while (index < variablesDeclaration.getNumDecls()) { if (unusedGlobals.contains(variablesDeclaration.getDeclInfo(index))) { variablesDeclaration.removeDeclInfo(index); } else { index++; } } if (variablesDeclaration.getNumDecls() == 0 && !isUsedStructType(variablesDeclaration.getBaseType())) { tu.removeTopLevelDeclaration(variablesDeclaration); } } }
private boolean canMergeLoops(Stmt first, Stmt second) { if (!(first instanceof ForStmt && second instanceof ForStmt)) { return false; } ForStmt firstLoop = (ForStmt) first; ForStmt secondLoop = (ForStmt) second; Optional<String> commonLoopCounter = checkForCommonLoopCounter(firstLoop, secondLoop); if (!commonLoopCounter.isPresent()) { return false; } if (!commonLoopCounter.get().startsWith(Constants.SPLIT_LOOP_COUNTER_PREFIX)) { return false; } if (!hasRegularLoopGuard(firstLoop, commonLoopCounter.get())) { return false; } if (!hasRegularLoopGuard(secondLoop, commonLoopCounter.get())) { return false; } final Integer firstLoopEnd = new Integer(((IntConstantExpr) ((BinaryExpr) firstLoop.getCondition()).getRhs()).getValue()); final BinOp firstLoopOp = ((BinaryExpr) firstLoop.getCondition()).getOp(); final Integer secondLoopStart = new Integer(((IntConstantExpr) ((ScalarInitializer) ((DeclarationStmt) secondLoop.getInit()).getVariablesDeclaration().getDeclInfo(0) .getInitializer()).getExpr()).getValue()); assert firstLoopOp == BinOp.LT || firstLoopOp == BinOp.GT : "Unexpected operator in split loops."; return firstLoopEnd.equals(secondLoopStart); }
private void addGlobalInitializers(FunctionDefinition mainFunction) { assert mainFunction.getPrototype().getName().equals("main"); for (int i = globalsToBeReInitialized.size() - 1; i >= 0; i--) { for (int j = globalsToBeReInitialized.get(i).getNumDecls() - 1; j >= 0; j--) { final VariableDeclInfo vdi = globalsToBeReInitialized.get(i).getDeclInfo(j); if (!(vdi.getInitializer() instanceof ScalarInitializer)) { throw new RuntimeException("Only know how to deal with scalar initializers at present."); } mainFunction.getBody().insertStmt(0, new ExprStmt(new BinaryExpr(new VariableIdentifierExpr(vdi.getName()), ((ScalarInitializer) vdi.getInitializer()).getExpr(), BinOp.ASSIGN))); vdi.setInitializer(null); } } }
} else if (init instanceof DeclarationStmt && ((DeclarationStmt) init).getVariablesDeclaration().getNumDecls() == 1 && ((DeclarationStmt) init).getVariablesDeclaration().getDeclInfo(0) .getInitializer() instanceof ScalarInitializer) { name = ((DeclarationStmt) init).getVariablesDeclaration() .getDeclInfo(0).getName(); expr = ((ScalarInitializer)((DeclarationStmt) init) .getVariablesDeclaration().getDeclInfo(0) .getInitializer()).getExpr();
@Override public void applyReductionImpl() { if (originalNumVariables != declaration.getVariablesDeclaration().getNumDecls()) { // Something else changed how many declarations there are, so bail out. return; } final StructifiedVariableInfo originalVariableInfo = findOriginalVariableInfo(); // First, replace all occurrences in the translation unit deStructify(originalVariableInfo); // Now change the declaration declaration.getVariablesDeclaration().getDeclInfo(0).setName(originalVariableInfo.getName()); declaration.getVariablesDeclaration().setBaseType(originalVariableInfo.getType()); declaration.getVariablesDeclaration().getDeclInfo(0).setInitializer(originalVariableInfo .getInitializer().orElse(null)); }
@Override public void visitFunctionCallExpr(FunctionCallExpr functionCallExpr) { super.visitFunctionCallExpr(functionCallExpr); for (int i = 0; i < functionCallExpr.getNumArgs(); i++) { Expr arg = functionCallExpr.getArg(i); if (arg instanceof VariableIdentifierExpr && ((VariableIdentifierExpr) arg) .getName().equals(declaration.getVariablesDeclaration().getDeclInfo(0).getName())) { functionCallExpr.setArg(i, new VariableIdentifierExpr(originalVariableInfo.getName())); } } }
private boolean isLoopLimiterBlock(Stmt stmt) { // Identifies when a block starts with a loop-limiter declaration, in which case the whole // block can go. We are really careful about otherwise removing loop-limiters, so this is // the chance to do it! if (!(stmt instanceof BlockStmt)) { return false; } final BlockStmt blockStmt = (BlockStmt) stmt; if (blockStmt.getNumStmts() == 0) { return false; } final Stmt firstStmt = blockStmt.getStmt(0); if (!(firstStmt instanceof DeclarationStmt)) { return false; } final DeclarationStmt declarationStmt = (DeclarationStmt) firstStmt; if (declarationStmt.getVariablesDeclaration().getNumDecls() == 0) { return false; } return isLooplimiter(declarationStmt.getVariablesDeclaration().getDeclInfo(0).getName()); }
@Override public void visitDeclarationStmt(DeclarationStmt declarationStmt) { super.visitDeclarationStmt(declarationStmt); // Currently we only structify solo declarations if (declarationStmt.getVariablesDeclaration().getNumDecls() != 1) { return; } // We don't currently structify arrays if (declarationStmt.getVariablesDeclaration().getDeclInfo(0).hasArrayInfo()) { return; } final Type baseType = declarationStmt.getVariablesDeclaration().getBaseType(); if (hasQualifiers(baseType)) { return; } // TODO: For simplicity, at present we do not structify non-basic types. The issue is that // if a struct S is to be structified, we need to declare the structs that enclose S *after* // S is declared, which is a bit fiddly (currently they all go at the top of the translation // unit). if (!(baseType.getWithoutQualifiers() instanceof BasicType)) { return; } opportunities.add(new StructificationOpportunity(declarationStmt, currentBlock(), tu, shadingLanguageVersion)); }
@Override public void visitFunctionPrototype(FunctionPrototype functionPrototype) { super.visitFunctionPrototype(functionPrototype); for (int i = 0; i < functionPrototype.getNumParameters(); i++) { if (functionPrototype.getParameter(i).getType().getWithoutQualifiers() .equals(declaration.getVariablesDeclaration().getBaseType().getWithoutQualifiers())) { assert declaration.getVariablesDeclaration().getDeclInfo(0).getName() .equals(functionPrototype.getParameter(i).getName()); functionPrototype.getParameter(i).setName(originalVariableInfo.getName()); functionPrototype.getParameter(i).setType(originalVariableInfo.getType()); } } }
private void structifyDeclaration(String enclosingStructVariableName, StructDefinitionType enclosingStructType) { declToTransform.getVariablesDeclaration() .setBaseType(enclosingStructType.getStructNameType()); final VariableDeclInfo declInfo = declToTransform.getVariablesDeclaration().getDeclInfo(0); declInfo.setName(enclosingStructVariableName); if (declInfo.hasInitializer()) { declInfo.setInitializer( new ScalarInitializer( makeInitializationExpr(enclosingStructType, ((ScalarInitializer) declInfo.getInitializer()).getExpr()) ) ); } }