use of cx2x.translator.language.common.ClawDimension in project claw-compiler by C2SM-RCM.
the class ClawLanguageTest method parallelizeTest.
/**
* Test various input for the CLAW parallelize directive.
*/
@Test
public void parallelizeTest() {
// Valid directives
ClawDimension d1 = new ClawDimension("i", "1", "nx");
List<String> data1 = Arrays.asList("t", "qc", "qv");
List<List<String>> dataLst1 = Collections.singletonList(data1);
List<String> ijc = Arrays.asList("i", "j", ":");
List<String> icj = Arrays.asList("i", ":", "j");
List<String> cij = Arrays.asList(":", "i", "j");
List<List<String>> over1 = Collections.singletonList(ijc);
List<List<String>> over2 = Collections.singletonList(icj);
List<List<String>> over3 = Collections.singletonList(cij);
analyzeValidParallelize("claw define dimension i(1:nx)" + " parallelize data(t,qc,qv) over (i,j,:)", dataLst1, over1, Collections.singletonList(d1), null, null);
ClawDimension d2 = new ClawDimension("j", "1", "ny");
analyzeValidParallelize("claw define dimension j(1:ny)" + "parallelize data(t,qc,qv) over (i,j,:)", dataLst1, over1, Collections.singletonList(d2), null, null);
ClawDimension d3 = new ClawDimension("j", "1", "10");
analyzeValidParallelize("claw define dimension j(1:10) " + "parallelize data(t,qc,qv) over (i,j,:)", dataLst1, over1, Collections.singletonList(d3), null, null);
ClawDimension d4 = new ClawDimension("j", "jstart", "10");
analyzeValidParallelize("claw define dimension j(jstart:10) " + "parallelize data(t,qc,qv) over (i,j,:)", dataLst1, over1, Collections.singletonList(d4), null, null);
ClawDimension d5 = new ClawDimension("j", "jstart", "ny");
analyzeValidParallelize("claw define dimension j(jstart:ny) " + "parallelize data(t,qc,qv) over (i,j,:)", dataLst1, over1, Collections.singletonList(d5), null, null);
ClawDimension d6 = new ClawDimension("j", "jstart", "ny");
analyzeValidParallelize("claw define dimension j(jstart:ny) parallelize", null, null, Collections.singletonList(d6), null, null);
analyzeValidParallelize("claw parallelize forward", null, null, null, null, null);
analyzeValidParallelize("claw parallelize data(t,qc,qv) over (i,j,:)", dataLst1, over1, null, null, null);
analyzeValidParallelize("claw parallelize data(t,qc,qv) over (:,i,j)", dataLst1, over3, null, null, null);
analyzeValidParallelize("claw parallelize data(t,qc,qv) over (i,:,j)", dataLst1, over2, null, null, null);
analyzeValidParallelize("claw parallelize data(t , qc , qv) over (i,:,j)", dataLst1, over2, null, null, null);
analyzeValidParallelize("claw parallelize data(t , qc , qv) over (i,:,j) " + "copy", dataLst1, over2, null, ClawDMD.BOTH, null);
analyzeValidParallelize("claw parallelize data(t , qc , qv) over (i,:,j) " + "copy(in)", dataLst1, over2, null, ClawDMD.IN, null);
analyzeValidParallelize("claw parallelize data(t , qc , qv) over (i,:,j) " + "copy(out)", dataLst1, over2, null, ClawDMD.OUT, null);
ClawDimension d7 = new ClawDimension("c", "1", "nc");
analyzeValidParallelize("claw define dimension c(1:nc) parallelize copy", null, null, Collections.singletonList(d7), ClawDMD.BOTH, null);
analyzeValidParallelize("claw define dimension c(1:nc) " + "parallelize copy(in)", null, null, Collections.singletonList(d7), ClawDMD.IN, null);
analyzeValidParallelize("claw define dimension c(1:nc) " + "parallelize copy(out)", null, null, Collections.singletonList(d7), ClawDMD.OUT, null);
analyzeValidParallelize("claw parallelize data(t , qc , qv) over (i,:,j) " + "update", dataLst1, over2, null, null, ClawDMD.BOTH);
analyzeValidParallelize("claw parallelize data(t , qc , qv) over (i,:,j) " + "update(in)", dataLst1, over2, null, null, ClawDMD.IN);
analyzeValidParallelize("claw parallelize data(t , qc , qv) over (i,:,j) " + "update(out)", dataLst1, over2, null, null, ClawDMD.OUT);
analyzeValidParallelize("claw define dimension c(1:nc) parallelize update", null, null, Collections.singletonList(d7), null, ClawDMD.BOTH);
analyzeValidParallelize("claw define dimension c(1:nc) " + "parallelize update(in)", null, null, Collections.singletonList(d7), null, ClawDMD.IN);
analyzeValidParallelize("claw define dimension c(1:nc) " + "parallelize update(out)", null, null, Collections.singletonList(d7), null, ClawDMD.OUT);
analyzeValidParallelize("claw parallelize forward copy", null, null, null, ClawDMD.BOTH, null);
analyzeValidParallelize("claw parallelize forward copy(in)", null, null, null, ClawDMD.IN, null);
analyzeValidParallelize("claw parallelize forward copy(out)", null, null, null, ClawDMD.OUT, null);
analyzeValidParallelize("claw parallelize forward update", null, null, null, null, ClawDMD.BOTH);
analyzeValidParallelize("claw parallelize forward update(in)", null, null, null, null, ClawDMD.IN);
analyzeValidParallelize("claw parallelize forward update(out)", null, null, null, null, ClawDMD.OUT);
List<String> data2 = Collections.singletonList("t");
List<String> data3 = Collections.singletonList("q");
List<List<String>> dataLst2 = Arrays.asList(data2, data3);
List<String> ic = Arrays.asList("i", ":");
List<String> ci = Arrays.asList(":", "i");
List<List<String>> over4 = Arrays.asList(ic, ci);
analyzeValidParallelize("claw parallelize data(t) over (i,:) data(q) " + "over(:,i)", dataLst2, over4, null, null, null);
// Unvalid directives
analyzeUnvalidClawLanguage("claw parallelize data over ");
analyzeUnvalidClawLanguage("claw parallelize data");
analyzeUnvalidClawLanguage("claw parallelize over");
analyzeUnvalidClawLanguage("claw parallelite data() over ()");
}
use of cx2x.translator.language.common.ClawDimension in project claw-compiler by C2SM-RCM.
the class ParallelizeForward 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 transformer Current transformer.
* @throws Exception If something goes wrong.
*/
private void transformStd(XcodeProgram xcodeml, Transformer transformer) throws Exception {
XfunctionDefinition fDef = XnodeUtil.findParentFunction(_claw.getPragma());
if (fDef == null) {
throw new IllegalTransformationException("Parallelize directive is not " + "nested in a function/subroutine.", _claw.getPragma().lineNo());
}
_parentFctType = (XfunctionType) xcodeml.getTypeTable().get(fDef.getName().getAttribute(Xattr.TYPE));
List<Xnode> params = _fctType.getParams().getAll();
/* 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.get(0).getAttribute(Xattr.TYPE).startsWith(Xtype.PREFIX_STRUCT) && _fctCall.firstChild().opcode().equals(Xcode.FMEMBERREF)) {
argOffset = 1;
}
// 1. Adapt function call with potential new arguments
for (int i = 0; i < params.size(); i++) {
Xnode p = params.get(i);
String var = p.value();
String type;
XbasicType paramType = (XbasicType) xcodeml.getTypeTable().get(p.getAttribute(Xattr.TYPE));
if (!p.getBooleanAttribute(ClawAttr.IS_CLAW.toString())) {
continue;
}
if (!fDef.getSymbolTable().contains(var)) {
if (_flatten && !paramType.getBooleanAttribute(Xattr.IS_OPTIONAL)) {
throw new IllegalTransformationException("Variable " + var + " must" + " be locally defined where the last call to parallelize if made.", _claw.getPragma().lineNo());
}
// Size variable have to be declared
XbasicType intTypeIntentIn = xcodeml.createBasicType(xcodeml.getTypeTable().generateIntegerTypeHash(), Xname.TYPE_F_INT, Xintent.IN);
xcodeml.getTypeTable().add(intTypeIntentIn);
xcodeml.createIdAndDecl(var, intTypeIntentIn.getType(), Xname.SCLASS_F_PARAM, fDef);
type = intTypeIntentIn.getType();
Xnode param = xcodeml.createAndAddParam(var, type, _parentFctType);
param.setAttribute(ClawAttr.IS_CLAW.toString(), Xname.TRUE);
} else {
// Var exists already. Add to the parameters if not here.
type = fDef.getSymbolTable().get(var).getType();
/* If flatten mode, we do not add extra parameters to the function
* definition */
if (!_flatten) {
Xnode param = xcodeml.createAndAddParamIfNotExists(var, type, _parentFctType);
if (param != null) {
param.setAttribute(ClawAttr.IS_CLAW.toString(), Xname.TRUE);
}
}
}
// Add variable in the function call before the optional parameters
Xnode arg = xcodeml.createNamedValue(var);
Xnode namedValVar = xcodeml.createVar(type, var, Xscope.LOCAL);
arg.append(namedValVar, false);
Xnode arguments = _fctCall.matchSeq(Xcode.ARGUMENTS);
Xnode hook = arguments.child((i - 1) - argOffset);
hook.insertAfter(arg);
}
// In flatten mode, arguments are demoted if needed.
if (_flatten) {
Xnode arguments = _fctCall.matchSeq(Xcode.ARGUMENTS);
for (Xnode arg : arguments.children()) {
if (arg.opcode() == Xcode.FARRAYREF && arg.matchDirectDescendant(Arrays.asList(Xcode.INDEXRANGE, Xcode.ARRAYINDEX)) != null) {
Xnode var = arg.matchSeq(Xcode.VARREF, Xcode.VAR);
if (var != null) {
arg.insertAfter(var.cloneNode());
arg.delete();
}
}
}
} else {
// 2. Adapt function/subroutine in which the function call is nested
for (Xnode pBase : _fctType.getParams().getAll()) {
String original_param = pBase.value();
if (_fctCallMapping.containsKey(original_param)) {
original_param = _fctCallMapping.get(original_param);
}
Xnode pUpdate = null;
for (Xnode param : _parentFctType.getParams().getAll()) {
if (original_param.equals(param.value())) {
pUpdate = param;
}
}
if (pUpdate == null) {
// field is not a parameter but maybe out field
Xdecl d = fDef.getDeclarationTable().get(original_param);
if (d != null) {
pUpdate = d.matchSeq(Xcode.NAME);
}
// TODO handle deferred shape
}
if (pUpdate != null) {
if (pUpdate.getAttribute(Xattr.TYPE) == null || XnodeUtil.isBuiltInType(pUpdate.getAttribute(Xattr.TYPE))) {
continue;
}
XbasicType typeBase = (_localFct) ? (XbasicType) xcodeml.getTypeTable().get(pBase.getAttribute(Xattr.TYPE)) : (XbasicType) _mod.getTypeTable().get(pBase.getAttribute(Xattr.TYPE));
XbasicType typeToUpdate = (XbasicType) xcodeml.getTypeTable().get(pUpdate.getAttribute(Xattr.TYPE));
int targetDim = typeBase.getDimensions();
int baseDim = typeToUpdate.getDimensions();
// Types have different dimensions
if (typeBase.getDimensions() > typeToUpdate.getDimensions()) {
// TODO check intent rules
/*if(!isParam && typeToUpdate.getIntent() != Xintent.OUT){
continue;
}*/
List<ClawDimension> dimensions = TransformationHelper.findDimensions(_fctType);
OverPosition overPos = OverPosition.fromString(pBase.getAttribute(ClawAttr.OVER.toString()));
String type = _localFct ? TransformationHelper.duplicateWithDimension(typeBase, typeToUpdate, xcodeml, xcodeml, overPos, dimensions) : TransformationHelper.duplicateWithDimension(typeBase, typeToUpdate, xcodeml, _mod, overPos, dimensions);
pUpdate.setAttribute(Xattr.TYPE, type);
Xid id = fDef.getSymbolTable().get(original_param);
if (id != null) {
id.setAttribute(Xattr.TYPE, type);
}
Xdecl varDecl = fDef.getDeclarationTable().get(original_param);
if (varDecl != null) {
varDecl.matchSeq(Xcode.NAME).setAttribute(Xattr.TYPE, type);
}
_promotedVar.add(original_param);
addPromotedVar(original_param, overPos);
_promotions.put(original_param, new PromotionInfo(pBase.value(), baseDim, targetDim, type));
}
}
}
if (!_parentFctType.getBooleanAttribute(Xattr.IS_PRIVATE)) {
// 3. Replicate the change in a potential module file
XmoduleDefinition modDef = fDef.findParentModule();
TransformationHelper.updateModuleSignature(xcodeml, fDef, _parentFctType, modDef, _claw, transformer, false);
} else if (_fctCall.matchSeq(Xcode.NAME).hasAttribute(Xattr.DATAREF)) {
/* 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. */
XmoduleDefinition modDef = fDef.findParentModule();
TransformationHelper.updateModuleSignature(xcodeml, fDef, _parentFctType, modDef, _claw, transformer, true);
}
}
updateResultVar(xcodeml);
propagatePromotion(xcodeml, (ClawTransformer) transformer);
}
use of cx2x.translator.language.common.ClawDimension in project claw-compiler by C2SM-RCM.
the class ParallelizeForward method propagatePromotion.
/**
* Propagate possible promotion in assignments statements in the parent
* subroutine of the function call.
*
* @param xcodeml Current XcodeML program unit.
* @param transformer Current transformer to store information between
* transformation.
*/
private void propagatePromotion(XcodeProgram xcodeml, ClawTransformer transformer) throws IllegalTransformationException {
// Get all the assignment statements in the function definition
XfunctionDefinition parentFctDef = XnodeUtil.findParentFunction(_fctCall);
// Retrieve information of previous forward transformation in the same fct
List<String> previouslyPromoted = Utility.convertToList(transformer.hasElement(parentFctDef));
List<Xnode> assignments = parentFctDef.matchAll(Xcode.FASSIGNSTATEMENT);
List<ClawDimension> dimensions = TransformationHelper.findDimensions(_parentFctType);
// Prepare the array index to be inserted in array references.
List<Xnode> crt = new ArrayList<>();
List<Xnode> empty = Collections.emptyList();
for (ClawDimension dim : dimensions) {
crt.add(dim.generateArrayIndex(xcodeml));
}
Collections.reverse(crt);
List<List<Xnode>> induction = new ArrayList<>();
List<List<Xnode>> emptyInd = new ArrayList<>();
induction.add(crt);
emptyInd.add(empty);
for (Xnode assignment : assignments) {
Xnode lhs = assignment.child(0);
Xnode rhs = assignment.child(1);
List<Xnode> varsInRhs = rhs.matchAll(Xcode.VAR);
for (Xnode var : varsInRhs) {
// Check if the assignment statement uses a promoted variable
if (_promotedVar.contains(var.value()) && var.matchAncestor(Xcode.FUNCTIONCALL) == null && lhs.opcode() == Xcode.FARRAYREF) {
Xnode varInLhs = lhs.matchDescendant(Xcode.VAR);
if (varInLhs == null) {
throw new IllegalTransformationException("Unable to propagate " + "promotion. Internal error.", _claw.getPragma().lineNo());
}
XbasicType varType = (XbasicType) xcodeml.getTypeTable().get(varInLhs.getAttribute(Xattr.TYPE));
// Declare the induction variable if they are not present
TransformationHelper.declareInductionVariables(dimensions, parentFctDef, xcodeml);
// Generate the do statements and move the assignment statement in
NestedDoStatement doStmt = new NestedDoStatement(dimensions, xcodeml);
assignment.insertAfter(doStmt.getOuterStatement());
doStmt.getInnerStatement().body().append(assignment, false);
PromotionInfo promotionInfo;
if (!previouslyPromoted.contains(varInLhs.value().toLowerCase())) {
// Perform the promotion on the variable
promotionInfo = TransformationHelper.promoteField(varInLhs.value(), true, true, 0, 0, parentFctDef, _parentFctType, dimensions, _claw, xcodeml, null);
_promotions.put(varInLhs.value(), promotionInfo);
// TODO if #38 is implemented, the variable has to be put either in
// TODO _promotedWithBeforeOver or _promotedWithAfterOver
_promotedWithBeforeOver.add(varInLhs.value());
} else {
promotionInfo = _promotions.get(varInLhs.value());
}
// Adapt the reference in the assignment statement
TransformationHelper.adaptArrayReferences(_promotedWithBeforeOver, 0, assignment, _promotions, induction, emptyInd, emptyInd, xcodeml);
TransformationHelper.adaptArrayReferences(_promotedWithMiddleOver, 0, assignment, _promotions, emptyInd, induction, emptyInd, xcodeml);
TransformationHelper.adaptArrayReferences(_promotedWithAfterOver, 0, assignment, _promotions, emptyInd, emptyInd, induction, xcodeml);
// If the array is a target, check if we have to promote a pointer
if (!previouslyPromoted.contains(varInLhs.value().toLowerCase())) {
adaptPointer(varType, varInLhs.value(), parentFctDef, xcodeml, promotionInfo, dimensions);
// TODO centralized info
previouslyPromoted.add(varInLhs.value().toLowerCase());
}
break;
/* if one var in the rhs of the assignment statement was
* promoted it's enough and we can switch to the next assignment
* statement. */
}
}
}
transformer.storeElement(parentFctDef, previouslyPromoted);
}
use of cx2x.translator.language.common.ClawDimension in project claw-compiler by C2SM-RCM.
the class Parallelize method prepareArrayIndexes.
/**
* Prepare the arrayIndex elements that will be inserted before and after the
* current indexes in the array references.
*
* @param xcodeml Current XcodeML program unit in which new elements are
* created.
*/
private void prepareArrayIndexes(XcodeProgram xcodeml) {
_beforeCrt = new ArrayList<>();
_afterCrt = new ArrayList<>();
_inMiddle = new ArrayList<>();
if (_claw.hasOverClause()) {
for (List<String> over : _claw.getOverClauseValues()) {
List<Xnode> beforeCrt = new ArrayList<>();
List<Xnode> afterCrt = new ArrayList<>();
List<Xnode> inMiddle = new ArrayList<>();
List<Xnode> crt = beforeCrt;
// In middle insertion
if (TransformationHelper.baseDimensionNb(over) == 2) {
for (String dim : over) {
if (!dim.equals(ClawDimension.BASE_DIM)) {
ClawDimension d = _dimensions.get(dim);
inMiddle.add(d.generateArrayIndex(xcodeml));
}
}
} else {
for (String dim : over) {
if (dim.equals(ClawDimension.BASE_DIM)) {
crt = afterCrt;
} else {
ClawDimension d = _dimensions.get(dim);
crt.add(d.generateArrayIndex(xcodeml));
}
}
}
Collections.reverse(beforeCrt);
_beforeCrt.add(beforeCrt);
_afterCrt.add(afterCrt);
_inMiddle.add(inMiddle);
}
} else {
/* If no over clause, the indexes are inserted in order from the first
* defined dimensions from left to right. Everything is inserted on the
* left of current indexes. */
List<Xnode> crt = new ArrayList<>();
List<Xnode> empty = Collections.emptyList();
for (ClawDimension dim : _claw.getDimensionValues()) {
crt.add(dim.generateArrayIndex(xcodeml));
}
Collections.reverse(crt);
_beforeCrt.add(crt);
_afterCrt.add(empty);
_inMiddle.add(empty);
}
}
use of cx2x.translator.language.common.ClawDimension in project claw-compiler by C2SM-RCM.
the class ParallelizeForward method updateResultVar.
/**
* Apply promotion to the result return variable of a forward call.
*
* @param xcodeml Current XcodeML program unit.
* @throws IllegalTransformationException If XcodeML transformation cannot be
* done.
*/
private void updateResultVar(XcodeProgram xcodeml) throws IllegalTransformationException {
if (_isNestedInAssignment) {
Xnode assignment = _claw.getPragma().nextSibling();
if (assignment == null || !_fctType.hasAttribute(ClawAttr.OVER.toString())) {
return;
}
OverPosition overPos = OverPosition.fromString(_fctType.getAttribute(ClawAttr.OVER.toString()));
Xnode lhs = assignment.child(0);
// TODO handle the case when the array ref is a var directly
Xnode varInLhs = lhs.matchDescendant(Xcode.VAR);
List<ClawDimension> dimensions = TransformationHelper.findDimensions(_parentFctType);
XfunctionDefinition parentFctDef = XnodeUtil.findParentFunction(_fctCall);
XbasicType varType = (XbasicType) xcodeml.getTypeTable().get(varInLhs.getAttribute(Xattr.TYPE));
PromotionInfo promotionInfo;
if (!_promotions.containsKey(varInLhs.value())) {
// Perform the promotion on the variable
promotionInfo = TransformationHelper.promoteField(varInLhs.value(), true, true, 0, 0, parentFctDef, _parentFctType, dimensions, _claw, xcodeml, overPos);
_promotions.put(varInLhs.value(), promotionInfo);
addPromotedVar(varInLhs.value(), overPos);
} else {
promotionInfo = _promotions.get(varInLhs.value());
}
// Adapt array index to reflect the new return type
if (lhs.opcode() == Xcode.FARRAYREF) {
for (int i = 0; i < promotionInfo.diffDimension(); ++i) {
Xnode indexRange = xcodeml.createEmptyAssumedShaped();
lhs.append(indexRange, false);
}
/*} else if(lhs.opcode() == Xcode.VAR) {
// TODO avoid array var without colon notation
/* throw new IllegalTransformationException("Use the colon notation "
+ "for the return variable. This notation is not supported." +
_claw.getPragma().value()); */
} else {
throw new IllegalTransformationException("Unsupported return " + "variable for promotion.", _claw.getPragma().lineNo());
}
// If the array is a target, check if we have to promote a pointer
adaptPointer(varType, varInLhs.value(), parentFctDef, xcodeml, promotionInfo, dimensions);
}
}
Aggregations