blob: 68080203bcd37bffc8c8f522b70709ae7b3f89ad [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016, 2018 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink - Initial API and implementation
*******************************************************************************/
package org.eclipse.qvtd.compiler.internal.qvts2qvts.merger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.qvtd.compiler.internal.qvtb2qvts.ScheduleManager;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.Concurrency;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.checks.CheckedCondition;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.checks.CheckedConditionAnalysis;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner.AbstractCompositePartitionAnalysis;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner.BasicPartitionAnalysis;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner.MappingPartitionAnalysis;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner.MergedPartitionFactory;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner.PartitionAnalysis;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner.PartitionedTransformationAnalysis;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner.RootPartitionAnalysis;
import org.eclipse.qvtd.compiler.internal.qvts2qvts.partitioner.TransformationPartitioner;
import org.eclipse.qvtd.pivot.qvtschedule.BasicPartition;
import org.eclipse.qvtd.pivot.qvtschedule.CompositePartition;
import org.eclipse.qvtd.pivot.qvtschedule.Connection;
import org.eclipse.qvtd.pivot.qvtschedule.MappingPartition;
import org.eclipse.qvtd.pivot.qvtschedule.Partition;
import org.eclipse.qvtd.pivot.qvtschedule.utilities.QVTscheduleUtil;
import com.google.common.collect.Iterables;
/**
* ConcurrentPartitionMerger replaces one list of MappingRegions by another in which each set of regions that
* share a consumption and can be merged exploiting knowledge of the schedule is replaced by an
* equivalent merged region.
*
* Preconditions:
*
* Late consumer merge must occur at all possible merge sites, or none. That is, a merged region that consumes
* some node and surrounding predicates at its head must merge with all other regions that consume that
* head node with non-conflicting predicates.
*
* Every predicated edge/node of a late merged region must be shared with or satisfied by the other region.
*/
public class SequentialPartitionMerger extends AbstractMerger
{
public static @NonNull List<@NonNull Concurrency> merge(@NonNull PartitionedTransformationAnalysis partitionedTransformationAnalysis, @NonNull List<@NonNull Concurrency> partitionSchedule) {
RootPartitionAnalysis rootPartitionAnalysis = partitionedTransformationAnalysis.getRootPartitionAnalysis();
ScheduleManager scheduleManager = partitionedTransformationAnalysis.getScheduleManager();
for (@NonNull Connection connection : QVTscheduleUtil.getOwnedConnections(rootPartitionAnalysis.getRootRegion())) {
if (connection.isPassed()) {
Iterable<@NonNull Partition> sourcePartitions = connection.getSourcePartitions();
if (Iterables.size(sourcePartitions) == 1) {
Partition sourcePartition = sourcePartitions.iterator().next();
if (sourcePartition instanceof MappingPartition) {
PartitionAnalysis sourcePartitionAnalysis = partitionedTransformationAnalysis.getPartitionAnalysis(sourcePartition);
if (sourcePartitionAnalysis instanceof BasicPartitionAnalysis) {
List<@NonNull BasicPartitionAnalysis> mergeablePartitionAnalyses = null;
CheckedConditionAnalysis sourceCheckedConditionAnalysis = new CheckedConditionAnalysis((MappingPartitionAnalysis<?>)sourcePartitionAnalysis, scheduleManager);
Set<@NonNull CheckedCondition> sourceCheckedConditions = sourceCheckedConditionAnalysis.computeCheckedConditions();
for (@NonNull Partition targetPartition : connection.getTargetPartitions()) {
if ((targetPartition.getHeadNodes().size() == 1) && (sourcePartition.getRegion() == targetPartition.getRegion())) {
PartitionAnalysis targetPartitionAnalysis = partitionedTransformationAnalysis.getPartitionAnalysis(targetPartition);
if (targetPartitionAnalysis instanceof BasicPartitionAnalysis) {
CheckedConditionAnalysis targetCheckedConditionAnalysis = new CheckedConditionAnalysis((MappingPartitionAnalysis<?>)targetPartitionAnalysis, scheduleManager);
Set<@NonNull CheckedCondition> targetCheckedConditions = targetCheckedConditionAnalysis.computeCheckedConditions();
if (sourceCheckedConditions.containsAll(targetCheckedConditions)) {
if (mergeablePartitionAnalyses == null) {
mergeablePartitionAnalyses = new ArrayList<>();
mergeablePartitionAnalyses.add((BasicPartitionAnalysis)sourcePartitionAnalysis);
}
mergeablePartitionAnalyses.add((BasicPartitionAnalysis)targetPartitionAnalysis);
TransformationPartitioner.MERGE_SEQUENTIAL.println(sourcePartition + " => " + connection + " => " + targetPartitionAnalysis);
}
}
}
}
/* if (mergeablePartitionAnalyses != null) {
SequentialPartitionMerger sequentialMerger = new SequentialPartitionMerger(partitionedTransformationAnalysis, mergeablePartitionAnalyses);
Map<@NonNull PartitionAnalysis, @Nullable PartitionAnalysis> old2new = sequentialMerger.merge();
if (old2new != null) {
/* if (newConcurrency == null) {
newConcurrency = Sets.newHashSet(oldConcurrency);
}
for (@NonNull PartitionAnalysis oldPartition : old2new.keySet()) {
newConcurrency.remove(oldPartition);
PartitionAnalysis newPartition = old2new.get(oldPartition);
assert newPartition != null;
newConcurrency.add(newPartition);
}
}
if (newConcurrency != null) {
partitionSchedule.set(i, newConcurrency); * /
}
} */
}
}
}
}
}
return partitionSchedule;
}
protected final @NonNull PartitionedTransformationAnalysis partitionedTransformationAnalysis;
protected final @NonNull List<@NonNull BasicPartitionAnalysis> mergeablePartitionAnalyses;
protected SequentialPartitionMerger(@NonNull PartitionedTransformationAnalysis partitionedTransformationAnalysis,
@NonNull List<@NonNull BasicPartitionAnalysis> mergeablePartitionAnalyses) {
this.partitionedTransformationAnalysis = partitionedTransformationAnalysis;
this.mergeablePartitionAnalyses = mergeablePartitionAnalyses;
}
protected @Nullable Map<@NonNull PartitionAnalysis, @Nullable PartitionAnalysis> merge() {
ScheduleManager scheduleManager = partitionedTransformationAnalysis.getScheduleManager();
Map<@NonNull PartitionAnalysis, @Nullable PartitionAnalysis> old2new = new HashMap<>();
BasicPartition firstPartition = mergeablePartitionAnalyses.get(0).getPartition();
CompositePartition owningCompositePartition = firstPartition.getOwningCompositePartition();
assert owningCompositePartition != null;
AbstractCompositePartitionAnalysis<?> compositePartitionAnalysis = (AbstractCompositePartitionAnalysis<?>)partitionedTransformationAnalysis.getPartitionAnalysis(owningCompositePartition);
List<MappingPartition> ownedMappingPartitions = owningCompositePartition.getOwnedMappingPartitions();
MergedPartitionFactory mergedPartitionFactory = new MergedPartitionFactory(scheduleManager, QVTscheduleUtil.getRegion(firstPartition), mergeablePartitionAnalyses);
BasicPartitionAnalysis mergedPartitionAnalysis = mergedPartitionFactory.createPartitionAnalysis(partitionedTransformationAnalysis);
BasicPartition mergedPartition = mergedPartitionAnalysis.getPartition();
// MappingRegion mappingRegion = (MappingRegion)regionAnalysis.getRegion();
// List<MappingPartition> mappingPartitions = mappingRegion.getMappingPartitions();
for (@NonNull BasicPartitionAnalysis mergeablePartitionAnalysis : mergeablePartitionAnalyses) {
// mergedPartition.getExplicitPredecessors().addAll(oldPartition.getExplicitPredecessors());
// partitionAnalysis.destroy();
// BasicPartition oldPartition = partitionAnalysis.getPartition();
// boolean wasRemoved1 = ownedMappingPartitions.remove(oldPartition);
// assert wasRemoved1;
// boolean wasRemoved2 = mappingPartitions.remove(oldPartition);
// assert wasRemoved2;
// mergedPartition.getExplicitSuccessors().addAll(oldPartition.getExplicitSuccessors());
// oldPartition.getExplicitPredecessors().clear();
// oldPartition.getExplicitSuccessors().clear();
old2new.put(mergeablePartitionAnalysis, mergedPartitionAnalysis);
}
for (int pass : firstPartition.getPasses()) {
mergedPartition.addPass(pass);
}
scheduleManager.writeDebugGraphs(mergedPartition, null);
ownedMappingPartitions.add(mergedPartition);
compositePartitionAnalysis.merge(old2new);
return old2new;
}
}