use of claw.tatsu.xcodeml.abstraction.Xblock in project claw-compiler by C2SM-RCM.
the class ScaForward method transformStd.
/**
* Do the standard transformation for the forward directive. This transformation
* adapt the function call and replicates any necessary changes to the
* containing subroutine.
*
* @param xcodeml Current XcodeML file unit.
* @param translator Current translator.
* @throws Exception If something goes wrong.
*/
private void transformStd(XcodeProgram xcodeml, Translator translator) throws Exception {
ClawTranslator trans = (ClawTranslator) translator;
final Context context = trans.context();
final Configuration cfg = trans.cfg();
FfunctionDefinition fDef = _claw.getPragma().findParentFunction();
if (fDef == null) {
throw new IllegalTransformationException("SCA directive is not " + "nested in a function/subroutine.", _claw.getPragma().lineNo());
}
FfunctionType parentFctType = xcodeml.getTypeTable().getFunctionType(fDef);
if (_fctType.isElemental() || _fctType.getBooleanAttribute(Xattr.WAS_ELEMENTAL)) {
_flatten = true;
}
List<Xnode> params = _fctType.getParameters();
/*
* Compute the position of the first new arguments. In the case of a type-bound
* procedure call, the first parameter declared in the procedure is not actually
* passed as an argument. In this case, we add an offset of one to the starting
* arguments. TODO the check might be change to fit with the XcodeML/F2008
* specs. The TODO cont: attribute data_ref will probably be gone and replaced
* by a TODO cont: FmemberRef element
*/
int argOffset = 0;
if (!params.isEmpty() && FortranType.STRUCT.isOfType(params.get(0).getType()) && _fCall.isTbpCall()) {
argOffset = 1;
}
// 1. Adapt function call with potential new arguments
for (int i = 0; i < params.size(); i++) {
Xnode p = params.get(i);
String varId = p.value();
String type;
FbasicType paramType = xcodeml.getTypeTable().getBasicType(p);
if (!p.getBooleanAttribute(Xattr.IS_INSERTED)) {
continue;
}
if (!fDef.getSymbolTable().contains(varId)) {
if (_flatten && !paramType.getBooleanAttribute(Xattr.IS_OPTIONAL)) {
throw new IllegalTransformationException("Variable " + varId + " must be locally defined where the last call to one_column " + "is made.", _claw.getPragma().lineNo());
}
// Size variable have to be declared
FbasicType bt = xcodeml.createBasicType(FortranType.INTEGER, Intent.IN);
xcodeml.getTypeTable().add(bt);
xcodeml.createIdAndDecl(varId, bt.getType(), XstorageClass.F_PARAM, fDef, DeclarationPosition.FIRST);
type = bt.getType();
Xnode param = xcodeml.createAndAddParam(varId, type, parentFctType);
param.setBooleanAttribute(Xattr.IS_INSERTED, true);
} else {
// Var exists already. Add to the parameters if not here.
type = fDef.getSymbolTable().get(varId).getType();
/*
* If flatten mode, we do not add extra parameters to the function definition.
*/
if (!_flatten && !fDef.getSymbolTable().contains(varId)) {
Xnode param = xcodeml.createAndAddParamIfNotExists(varId, type, parentFctType);
if (param != null) {
param.setBooleanAttribute(Xattr.IS_INSERTED, true);
}
}
}
// Add variable in the function call before the optional parameters
Xnode arg = xcodeml.createNamedValue(varId);
arg.append(xcodeml.createVar(type, varId, Xscope.LOCAL));
Xnode hook = _fCall.arguments().get((i - 1) - argOffset);
if (hook != null) {
hook.insertAfter(arg);
} else {
_fCall.addArguments(arg);
}
}
// In flatten mode, arguments are demoted if needed.
if (_flatten) {
for (Xnode arg : _fCall.arguments()) {
if (arg.is(Xcode.F_ARRAY_REF) && arg.matchDirectDescendant(Arrays.asList(Xcode.INDEX_RANGE, Xcode.ARRAY_INDEX)) != null) {
List<Xnode> arrayIndexes = arg.matchAll(Xcode.ARRAY_INDEX);
for (Xnode n : arrayIndexes) {
if (_doStatements != null && XnodeUtil.isInductionIndex(n, _doStatements.getInductionVariables())) {
n.insertAfter(xcodeml.createEmptyAssumedShaped());
XnodeUtil.safeDelete(n);
}
}
}
}
} else {
// 2. Adapt function/subroutine in which the function call is nested
for (Xnode pBase : _fctType.getParameters()) {
String originalParam = pBase.value();
if (_fctCallMapping.containsKey(originalParam)) {
originalParam = _fctCallMapping.get(originalParam);
}
Xnode pUpdate = null;
for (Xnode param : parentFctType.getParameters()) {
if (originalParam.equals(param.value())) {
pUpdate = param;
}
}
if (pUpdate == null) {
// field is not a parameter but maybe out field
Xnode d = fDef.getDeclarationTable().get(originalParam);
if (d != null) {
pUpdate = d.matchSeq(Xcode.NAME);
}
}
if (pUpdate != null) {
if (pUpdate.getType() == null || FortranType.isBuiltInType(pUpdate.getType())) {
continue;
}
FbasicType typeBase = (_localFct) ? xcodeml.getTypeTable().getBasicType(pBase) : _mod.getTypeTable().getBasicType(pBase);
FbasicType typeToUpdate = xcodeml.getTypeTable().getBasicType(pUpdate);
int targetDim = typeBase.getDimensions();
int baseDim = typeToUpdate.getDimensions();
// Types have different dimensions
if (typeBase.getDimensions() > typeToUpdate.getDimensions()) {
PromotionInfo promotionInfo = new PromotionInfo(originalParam);
promotionInfo.readDimensionsFromString(pBase.getAttribute(Xattr.PROMOTION_INFO));
FbasicType type = _localFct ? Type.duplicateWithDimension(typeBase, typeToUpdate, xcodeml, xcodeml, promotionInfo.getDimensions()) : Type.duplicateWithDimension(typeBase, typeToUpdate, _mod, xcodeml, promotionInfo.getDimensions());
pUpdate.setType(type);
Xid id = fDef.getSymbolTable().get(originalParam);
if (id != null) {
id.setType(type);
}
Xnode varDecl = fDef.getDeclarationTable().get(originalParam);
if (varDecl != null) {
varDecl.matchSeq(Xcode.NAME).setType(type);
}
promotionInfo.setBaseDimension(baseDim);
promotionInfo.setTargetDimension(targetDim);
promotionInfo.setTargetType(type);
_promotions.put(originalParam, promotionInfo);
_promotedVar.add(originalParam);
pBase.copyAttribute(pUpdate, Xattr.PROMOTION_INFO);
}
}
}
if (!parentFctType.getBooleanAttribute(Xattr.IS_PRIVATE)) {
// 3. Replicate the change in a potential module file
FmoduleDefinition modDef = fDef.findParentModule();
if (modDef != null) {
Xmod.updateSignature(modDef.getName(), xcodeml, fDef, parentFctType, false);
}
} else if (_fCall.matchSeq(Xcode.NAME).hasAttribute(Xattr.DATA_REF)) {
/*
* The function/subroutine is private but accessible through the type as a
* type-bound procedure. In this case, the function is not in the type table of
* the .xmod file. We need to insert it first and then we can update it.
*/
FmoduleDefinition modDef = fDef.findParentModule();
if (modDef != null) {
Xmod.updateSignature(modDef.getName(), xcodeml, fDef, parentFctType, true);
}
}
}
updateResultVar(xcodeml);
propagatePromotion(xcodeml, (ClawTranslator) translator);
Xnode fctCallAncestor = _fCall.matchAncestor(Xcode.EXPR_STATEMENT);
if (fctCallAncestor == null) {
fctCallAncestor = _fCall.matchAncestor(Xcode.F_ASSIGN_STATEMENT);
}
if (_claw.hasClause(ClawClause.CREATE) && context.isTarget(Target.GPU)) {
List<String> creates = _fCall.gatherArguments(xcodeml, _fctType, _mod, Intent.INOUT, true, false);
if (_fctType.isFunction()) {
String returnValue = XnodeUtil.gatherReturnValue(xcodeml, _fCall);
if (returnValue != null) {
creates.add(returnValue);
}
}
Xblock fctCallBlock = new Xblock(fctCallAncestor);
Directive.generateDataRegionClause(xcodeml, Collections.emptyList(), creates, fctCallBlock);
}
// Serialization input
if (_claw.hasClause(ClawClause.SAVEPOINT)) {
List<String> inFields = _fCall.gatherArguments(xcodeml, _fctType, _mod != null ? _mod : xcodeml, Intent.IN, true, false);
Serialization.insertImports(cfg, xcodeml, _fCall.findParentFunction());
if (context.isTarget(Target.CPU)) {
Serialization.generateWriteSavepoint(cfg, xcodeml, fctCallAncestor, _claw.getMetadataMap(), inFields, _claw.value(ClawClause.SAVEPOINT), SerializationStep.SER_IN);
} else {
Serialization.generateReadSavepoint(cfg, xcodeml, fctCallAncestor, _claw.getMetadataMap(), inFields, _claw.value(ClawClause.SAVEPOINT), SerializationStep.SER_IN);
}
}
Xnode postHook = fctCallAncestor;
if (_claw.hasClause(ClawClause.UPDATE) && context.isTarget(Target.GPU) && cfg.getBooleanParameter(Configuration.SCA_FORWARD_UPDATE_ENABLED)) {
// Generate update from HOST TO DEVICE
if ((_claw.getUpdateClauseValue() == DataMovement.TWO_WAY || _claw.getUpdateClauseValue() == DataMovement.HOST_TO_DEVICE) && cfg.updateAtInput()) {
List<String> in = _fCall.gatherArguments(xcodeml, _fctType, _mod != null ? _mod : xcodeml, Intent.IN, true, false);
Directive.generateUpdate(xcodeml, fctCallAncestor, in, DataMovement.HOST_TO_DEVICE);
}
// Generate update from DEVICE to HOST
if ((_claw.getUpdateClauseValue() == DataMovement.TWO_WAY || _claw.getUpdateClauseValue() == DataMovement.DEVICE_TO_HOST) && cfg.updateAtOutput()) {
List<String> out = _fCall.gatherArguments(xcodeml, _fctType, _mod != null ? _mod : xcodeml, Intent.OUT, true, false);
if (_fctType.isFunction()) {
String returnValue = XnodeUtil.gatherReturnValue(xcodeml, _fCall);
if (returnValue != null) {
out.add(returnValue);
}
}
postHook = Directive.generateUpdate(xcodeml, fctCallAncestor, out, DataMovement.DEVICE_TO_HOST);
}
}
if (_claw.hasClause(ClawClause.PARALLEL) && context.isTarget(Target.GPU)) {
Directive.generateParallelRegion(xcodeml, fctCallAncestor, fctCallAncestor);
}
// Serialization output
if (_claw.hasClause(ClawClause.SAVEPOINT)) {
List<String> outFields = _fCall.gatherArguments(xcodeml, _fctType, _mod != null ? _mod : xcodeml, Intent.OUT, true, false);
Serialization.insertImports(cfg, xcodeml, _fCall.findParentFunction());
Serialization.generateWriteSavepoint(cfg, xcodeml, postHook, _claw.getMetadataMap(), outFields, _claw.value(ClawClause.SAVEPOINT), SerializationStep.SER_OUT);
}
}
use of claw.tatsu.xcodeml.abstraction.Xblock in project claw-compiler by C2SM-RCM.
the class ExpandNotation method transform.
/**
* Transform an assignment using array notation to a do statement.
*
* @param xcodeml The XcodeML on which the transformations are applied.
* @param translator The translator used to applied the transformations.
* @param other Only for dependent transformation. The other transformation
* part of the transformation.
* @throws Exception If the transformation cannot be applied.
*/
@Override
public void transform(XcodeProgram xcodeml, Translator translator, Transformation other) throws Exception {
final ClawTranslator ct = (ClawTranslator) translator;
final Configuration cfg = ct.cfg();
// 1. Find the function/module declaration TODO handle module/program ?
FfunctionDefinition fctDef = _clawStart.getPragma().findParentFunction();
Xnode from = _clawStart.getPragma();
Xnode to = _clawEnd != null ? _clawEnd.getPragma() : null;
List<String> readArrays = XnodeUtil.getReadArraysInRegion(from, to);
List<String> writtenArrays = XnodeUtil.getWrittenArraysInRegion(from, to);
Set<String> presents = new HashSet<>(readArrays);
presents.addAll(writtenArrays);
Xblock doStmtsBlock = null;
Xblock dataRegionBlock = null;
if (xcodeml.context().isTarget(Target.GPU)) {
Xblock crtBlock;
for (int i = 0; i < _groupedAssignStmts.size(); ++i) {
crtBlock = generateDoStmtNotation(xcodeml, ct, fctDef, _groupIterationRanges.get(i), _groupedAssignStmts.get(i), from);
if (doStmtsBlock == null) {
doStmtsBlock = new Xblock(crtBlock.getStart());
} else {
doStmtsBlock.setEnd(crtBlock.getEnd());
}
}
if (doStmtsBlock == null) {
throw new IllegalTransformationException("Problem occurred during expand transformation", _clawStart.getPragma().lineNo());
}
Xblock parallelRegionBlock;
Xblock updateRegionBlock = null;
if (_clawStart.hasClause(ClawClause.PARALLEL)) {
List<String> privates = Collections.emptyList();
String clauses = _clawStart.hasClause(ClawClause.ACC) ? _clawStart.value(ClawClause.ACC) : "";
parallelRegionBlock = Directive.generateParallelLoopClause(xcodeml, privates, doStmtsBlock.getStart(), doStmtsBlock.getEnd(), clauses, _groupedAssignStmts.size());
if (_clawStart.hasClause(ClawClause.UPDATE) && cfg.getBooleanParameter(Configuration.SCA_FORWARD_UPDATE_ENABLED)) {
updateRegionBlock = generateUpdateClause(cfg, xcodeml, parallelRegionBlock, readArrays, writtenArrays);
}
if (updateRegionBlock == null) {
updateRegionBlock = parallelRegionBlock;
}
List<String> presentLst = new ArrayList<>(presents);
dataRegionBlock = Directive.generateDataRegionClause(xcodeml, presentLst, Collections.emptyList(), updateRegionBlock);
}
} else {
doStmtsBlock = new Xblock(_clawStart.getPragma());
if (_clawEnd != null) {
doStmtsBlock.setEnd(_clawEnd.getPragma());
} else {
doStmtsBlock.setEnd(_clawStart.getPragma().nextSibling());
}
}
if (_clawStart.hasClause(ClawClause.SAVEPOINT) && cfg.getBooleanParameter(Configuration.SCA_SERIALIZATION_ENABLED)) {
if (dataRegionBlock == null) {
dataRegionBlock = doStmtsBlock;
}
generateSavepoint(cfg, xcodeml, dataRegionBlock, readArrays, writtenArrays);
}
removePragma();
transformed();
}
use of claw.tatsu.xcodeml.abstraction.Xblock in project claw-compiler by C2SM-RCM.
the class ExpandNotation method generateUpdateClause.
/**
* Generate update device/host directives to manage data before and after the
* expand block.
*
* @param xcodeml Current XcodeML translation unit.
* @param hook Block around which directives are generated
*/
private Xblock generateUpdateClause(Configuration cfg, XcodeProgram xcodeml, Xblock hook, List<String> readArrays, List<String> writtenArrays) {
Xnode startNode;
Xnode endNode;
// Generate host to device movement
if ((_clawStart.getUpdateClauseValue() == DataMovement.TWO_WAY || _clawStart.getUpdateClauseValue() == DataMovement.HOST_TO_DEVICE) && cfg.updateAtInput()) {
startNode = Directive.generateUpdate(xcodeml, hook.getStart(), readArrays, DataMovement.HOST_TO_DEVICE);
} else {
startNode = hook.getStart();
}
// Generate device to host movement
if ((_clawStart.getUpdateClauseValue() == DataMovement.TWO_WAY || _clawStart.getUpdateClauseValue() == DataMovement.DEVICE_TO_HOST) && cfg.updateAtOutput()) {
endNode = Directive.generateUpdate(xcodeml, hook.getEnd(), writtenArrays, DataMovement.DEVICE_TO_HOST);
} else {
endNode = hook.getEnd();
}
return new Xblock(startNode, endNode);
}
use of claw.tatsu.xcodeml.abstraction.Xblock in project claw-compiler by C2SM-RCM.
the class ExpandNotation method generateDoStmtNotation.
/**
* Generate the corresponding do statements for the array notations. A do
* statement is generated per dimension of the arrays. Iteration index range are
* computed with array dimensions.
*
* @param xcodeml The XcodeML on which the transformations are applied.
* @param translator The translator used to applied the transformations.
* @param fctDef The function definition in which the array notation is
* nested.
* @param ranges The list of iteration ranges to be applied to the created
* do statements.
* @param statements The list of assign statements (array notation) that will be
* included in the nested do statements.
* @param doStmtGrip Grip for the code insertion. Do statements will be inserted
* after the grip element.
* @return Block surrounding the do statements generated.
*/
private Xblock generateDoStmtNotation(XcodeProgram xcodeml, ClawTranslator translator, FfunctionDefinition fctDef, List<Xnode> ranges, List<Xnode> statements, Xnode doStmtGrip) throws IllegalTransformationException {
String[] inductionVars = new String[ranges.size()];
Xnode[] doStmts = new Xnode[ranges.size()];
Xnode var = statements.get(0).matchSeq(Xcode.F_ARRAY_REF, Xcode.VAR_REF, Xcode.VAR);
if (var == null) {
var = statements.get(0).matchSeq(Xcode.F_ARRAY_REF, Xcode.VAR_REF, Xcode.F_MEMBER_REF);
}
// 1. Create do statements with induction variables
for (int i = 0; i < ranges.size(); ++i) {
// 1.1 Create induction variables
if (_clawStart.hasClause(ClawClause.INDUCTION)) {
// Use user names
inductionVars[i] = _clawStart.values(ClawClause.INDUCTION).get(i);
} else {
// generate new names
inductionVars[i] = "claw_induction_" + translator.getNextTransformationCounter();
}
// 2.2 inject a new entry in the symbol table
if (!fctDef.getSymbolTable().contains(inductionVars[i])) {
Xid inductionVarId = xcodeml.createId(FortranType.INTEGER, XstorageClass.F_LOCAL, inductionVars[i]);
fctDef.getSymbolTable().add(inductionVarId, false);
}
// 2.3 inject a new entry in the declaration table
if (!fctDef.getDeclarationTable().contains(inductionVars[i])) {
Xnode inductionVarDecl = xcodeml.createVarDecl(FortranType.INTEGER, inductionVars[i]);
fctDef.getDeclarationTable().add(inductionVarDecl);
}
// 2.4 create do statements
Xnode inductionVar = xcodeml.createVar(FortranType.INTEGER, inductionVars[i], Xscope.LOCAL);
Xnode range;
if (ranges.get(i).getBooleanAttribute(Xattr.IS_ASSUMED_SHAPE)) {
// Allocatable array
// dimension argument of size starts at one
range = xcodeml.createRangeForAssumedShapeArray(var, 1, i + 1);
} else {
range = ranges.get(i).cloneNode();
}
doStmts[i] = xcodeml.createDoStmt(inductionVar, range);
statements.get(0).copyEnhancedInfo(doStmts[i]);
if (i == 0) {
// most outer loop goes after the pragma
doStmtGrip.insertAfter(doStmts[i]);
} else {
// others loop go in the previous one
doStmts[i - 1].body().append(doStmts[i]);
}
}
for (Xnode stmt : statements) {
// 3. Adapt array reference with induction variables
List<Xnode> allArrayRef = stmt.matchAll(Xcode.F_ARRAY_REF);
for (Xnode arrayRef : allArrayRef) {
for (int i = 0; i < arrayRef.children().size() - 1; ++i) {
Xnode el = arrayRef.child(i + 1);
if (Xnode.isOfCode(el, Xcode.INDEX_RANGE) && i < doStmts.length) {
String induction = doStmts[i].matchSeq(Xcode.VAR).value();
Xnode inductionVar = xcodeml.createVar(FortranType.INTEGER, induction, Xscope.LOCAL);
Xnode arrayIdx = xcodeml.createNode(Xcode.ARRAY_INDEX);
arrayIdx.append(inductionVar);
el.insertAfter(arrayIdx);
el.delete();
}
}
}
stmt.matchAll(Xcode.FUNCTION_CALL).stream().map(FunctionCall::new).filter(x -> x.isIntrinsicCall(Xintrinsic.SUM)).forEach(FunctionCall::adaptIntrinsicSumCall);
stmt.matchAll(Xcode.FUNCTION_CALL).stream().map(FunctionCall::new).filter(x -> x.isIntrinsicCall(Xintrinsic.SPREAD)).forEach(FunctionCall::adaptIntrinsicSpreadCall);
// 4. Move assignment statement inside the most inner loop
doStmts[ranges.size() - 1].body().append(stmt, true);
stmt.delete();
}
// Add any additional transformation defined in the directive clauses
translator.generateAdditionalTransformation(_clawStart, xcodeml, doStmts[0]);
return new Xblock(doStmts[0]);
}
use of claw.tatsu.xcodeml.abstraction.Xblock in project claw-compiler by C2SM-RCM.
the class ExpandNotation method generateSavepoint.
/**
* Generate serialization savepoints before and after the expand block.
*
* @param xcodeml Current XcodeML translation unit.
* @param hook Block around which serialization are generated
*/
private Xblock generateSavepoint(Configuration cfg, XcodeProgram xcodeml, Xblock hook, List<String> readArrays, List<String> writtenArrays) {
final Context context = xcodeml.context();
Serialization.insertImports(cfg, xcodeml, hook.getStart().findParentFunction());
Xnode start = null;
Xnode end;
if (context.isTarget(Target.GPU)) {
// Read inputs
start = Serialization.generateReadSavepoint(cfg, xcodeml, hook.getStart(), _clawStart.getMetadataMap(), readArrays, _clawStart.value(ClawClause.SAVEPOINT), SerializationStep.SER_IN);
} else if (context.isTarget(Target.CPU)) {
// Write inputs
start = Serialization.generateWriteSavepoint(cfg, xcodeml, hook.getStart(), _clawStart.getMetadataMap(), readArrays, _clawStart.value(ClawClause.SAVEPOINT), SerializationStep.SER_IN);
}
// Write outputs
end = Serialization.generateWriteSavepoint(cfg, xcodeml, hook.getEnd(), _clawStart.getMetadataMap(), writtenArrays, _clawStart.value(ClawClause.SAVEPOINT), SerializationStep.SER_OUT);
return new Xblock(start, end);
}
Aggregations