mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-01-18 07:30:22 +00:00
separated synthesis from fragment tempaltes.
This commit is contained in:
parent
36936efe80
commit
24049a12c1
@ -1,10 +1,10 @@
|
|||||||
package dk.camelot64.kickc;
|
package dk.camelot64.kickc;
|
||||||
|
|
||||||
import dk.camelot64.kickc.asm.AsmProgram;
|
import dk.camelot64.kickc.asm.AsmProgram;
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
||||||
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentSynthesisResult;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateMasterSynthesizer;
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateMasterSynthesizer;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
|
||||||
import dk.camelot64.kickc.model.*;
|
import dk.camelot64.kickc.model.*;
|
||||||
import dk.camelot64.kickc.model.statements.StatementSource;
|
import dk.camelot64.kickc.model.statements.StatementSource;
|
||||||
import dk.camelot64.kickc.model.symbols.Procedure;
|
import dk.camelot64.kickc.model.symbols.Procedure;
|
||||||
@ -275,8 +275,8 @@ public class KickC implements Callable<Integer> {
|
|||||||
try {
|
try {
|
||||||
final AsmFragmentTemplateMasterSynthesizer masterSynthesizer = compiler.getAsmFragmentMasterSynthesizer();
|
final AsmFragmentTemplateMasterSynthesizer masterSynthesizer = compiler.getAsmFragmentMasterSynthesizer();
|
||||||
final AsmFragmentTemplateSynthesizer cpuSynthesizer = masterSynthesizer.getSynthesizer(program.getTargetCpu());
|
final AsmFragmentTemplateSynthesizer cpuSynthesizer = masterSynthesizer.getSynthesizer(program.getTargetCpu());
|
||||||
Collection<AsmFragmentTemplate> fragmentTemplates = cpuSynthesizer.getBestTemplates(fragment, compiler.getLog());
|
Collection<AsmFragmentSynthesisResult> fragmentTemplates = cpuSynthesizer.getBestTemplates(fragment, compiler.getLog());
|
||||||
for(AsmFragmentTemplate fragmentTemplate : fragmentTemplates) {
|
for(AsmFragmentSynthesisResult fragmentTemplate : fragmentTemplates) {
|
||||||
AsmFragmentTemplateUsages.logTemplate(compiler.getLog(), fragmentTemplate, "");
|
AsmFragmentTemplateUsages.logTemplate(compiler.getLog(), fragmentTemplate, "");
|
||||||
}
|
}
|
||||||
if(fragmentTemplates.size() == 0) {
|
if(fragmentTemplates.size() == 0) {
|
||||||
@ -359,7 +359,7 @@ public class KickC implements Callable<Integer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder CFileNames = new StringBuilder();
|
StringBuilder CFileNames = new StringBuilder();
|
||||||
cFiles.stream().forEach(path -> CFileNames.append(path.toString()).append(" "));
|
cFiles.forEach(path -> CFileNames.append(path.toString()).append(" "));
|
||||||
|
|
||||||
Map<String, String> effectiveDefines = new LinkedHashMap<>();
|
Map<String, String> effectiveDefines = new LinkedHashMap<>();
|
||||||
effectiveDefines.put("__KICKC__", "1");
|
effectiveDefines.put("__KICKC__", "1");
|
||||||
|
@ -2,7 +2,6 @@ package dk.camelot64.kickc.fragment;
|
|||||||
|
|
||||||
import dk.camelot64.cpufamily6502.CpuClobber;
|
import dk.camelot64.cpufamily6502.CpuClobber;
|
||||||
import dk.camelot64.kickc.asm.AsmProgram;
|
import dk.camelot64.kickc.asm.AsmProgram;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesisRule;
|
|
||||||
import dk.camelot64.kickc.model.Program;
|
import dk.camelot64.kickc.model.Program;
|
||||||
import dk.camelot64.kickc.model.Registers;
|
import dk.camelot64.kickc.model.Registers;
|
||||||
import dk.camelot64.kickc.model.TargetCpu;
|
import dk.camelot64.kickc.model.TargetCpu;
|
||||||
@ -19,6 +18,7 @@ import dk.camelot64.kickc.parser.AsmParser;
|
|||||||
import dk.camelot64.kickc.parser.KickCParser;
|
import dk.camelot64.kickc.parser.KickCParser;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An ASM fragment template usable for generating KickAssembler code for different bindings.
|
* An ASM fragment template usable for generating KickAssembler code for different bindings.
|
||||||
@ -26,43 +26,24 @@ import java.util.LinkedHashMap;
|
|||||||
*/
|
*/
|
||||||
public class AsmFragmentTemplate {
|
public class AsmFragmentTemplate {
|
||||||
|
|
||||||
/** true if the fragment was loaded from disk. */
|
|
||||||
private boolean file;
|
|
||||||
/** true if the fragment was loaded from the disk cache. */
|
|
||||||
private boolean cache;
|
|
||||||
/** The fragment template signature name. */
|
/** The fragment template signature name. */
|
||||||
private final String signature;
|
private final String signature;
|
||||||
/** The fragment template body */
|
|
||||||
private String body;
|
|
||||||
/** The synthesis that created the fragment. null if the fragment template was loaded. */
|
|
||||||
private AsmFragmentTemplateSynthesisRule synthesis;
|
|
||||||
/** The sub fragment template that the synthesis modified to create this. null if the fragment template was loaded. */
|
|
||||||
private AsmFragmentTemplate subFragment;
|
|
||||||
/** The target CPU. */
|
/** The target CPU. */
|
||||||
private final TargetCpu targetCpu;
|
private final TargetCpu targetCpu;
|
||||||
/** The parsed ASM lines. Initially null. Will be non-null, is the template is ever used to generate ASM code. */
|
/** The fragment template body */
|
||||||
|
private String body;
|
||||||
|
|
||||||
|
/** The parsed ASM lines. Initially null. Non-null after the template is used to generate ASM code. */
|
||||||
private KickCParser.AsmLinesContext bodyAsm;
|
private KickCParser.AsmLinesContext bodyAsm;
|
||||||
/** The ASM clobber of the fragment. */
|
/** The ASM clobber of the fragment. Initially null. Non-null after the template is used to generate ASM code.*/
|
||||||
private AsmFragmentClobber clobber;
|
private AsmFragmentClobber clobber;
|
||||||
/** The cycles consumed by the ASM of the fragment. */
|
/** The cycles consumed by the ASM of the fragment. Initially null. Non-null after the template is used to generate ASM code.*/
|
||||||
private Double cycles;
|
private Double cycles;
|
||||||
|
|
||||||
public AsmFragmentTemplate(String signature, String body, TargetCpu targetCpu, boolean cache) {
|
public AsmFragmentTemplate(String signature, String body, TargetCpu targetCpu) {
|
||||||
this.signature = signature;
|
this.signature = signature;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.targetCpu = targetCpu;
|
this.targetCpu = targetCpu;
|
||||||
this.file = true;
|
|
||||||
this.cache = cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AsmFragmentTemplate(String signature, String body, AsmFragmentTemplateSynthesisRule synthesis, AsmFragmentTemplate subFragment) {
|
|
||||||
this.signature = signature;
|
|
||||||
this.body = body;
|
|
||||||
this.synthesis = synthesis;
|
|
||||||
this.subFragment = subFragment;
|
|
||||||
this.targetCpu = subFragment.targetCpu;
|
|
||||||
this.file = false;
|
|
||||||
this.cache = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -173,7 +154,7 @@ public class AsmFragmentTemplate {
|
|||||||
this.cycles = asm.getCycles();
|
this.cycles = asm.getCycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getSignature() {
|
public String getSignature() {
|
||||||
return signature;
|
return signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,43 +187,16 @@ public class AsmFragmentTemplate {
|
|||||||
return cycles;
|
return cycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFile() {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCache() {
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
AsmFragmentTemplateSynthesisRule getSynthesis() {
|
|
||||||
return synthesis;
|
|
||||||
}
|
|
||||||
|
|
||||||
AsmFragmentTemplate getSubFragment() {
|
|
||||||
return subFragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
StringBuilder name = new StringBuilder();
|
|
||||||
name.append(signature);
|
|
||||||
if(synthesis != null) {
|
|
||||||
name.append(" < ");
|
|
||||||
name.append(subFragment.getName());
|
|
||||||
}
|
|
||||||
return name.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
AsmFragmentTemplate that = (AsmFragmentTemplate) o;
|
AsmFragmentTemplate that = (AsmFragmentTemplate) o;
|
||||||
return getName().equals(that.getName());
|
return Objects.equals(signature, that.signature) && targetCpu == that.targetCpu && Objects.equals(body, that.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return getName().hashCode();
|
return Objects.hash(signature, targetCpu, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ public class AsmFragmentTemplateCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Special singleton representing that the fragment can not be synthesized or loaded. */
|
/** Special singleton representing that the fragment can not be synthesized or loaded. */
|
||||||
public static AsmFragmentTemplate NO_SYNTHESIS = new AsmFragmentTemplate("NO_SYNTHESIS", "NO_SYNTHESIS", null, false);
|
public static AsmFragmentTemplate NO_SYNTHESIS = new AsmFragmentTemplate("NO_SYNTHESIS", "NO_SYNTHESIS", null);
|
||||||
|
|
||||||
/** Prefix for the fragment hash file header. */
|
/** Prefix for the fragment hash file header. */
|
||||||
public static final String HASH_HEADER = "//KICKC FRAGMENT CACHE ";
|
public static final String HASH_HEADER = "//KICKC FRAGMENT CACHE ";
|
||||||
@ -189,7 +189,7 @@ public class AsmFragmentTemplateCache {
|
|||||||
cache.put(signature, NO_SYNTHESIS);
|
cache.put(signature, NO_SYNTHESIS);
|
||||||
} else {
|
} else {
|
||||||
CharStream fragmentCharStream = CharStreams.fromString(bodyString);
|
CharStream fragmentCharStream = CharStreams.fromString(bodyString);
|
||||||
AsmFragmentTemplate template = new AsmFragmentTemplate(signature, AsmFragmentTemplateSynthesizer.fixNewlines(fragmentCharStream.toString()), targetCpu, true);
|
AsmFragmentTemplate template = new AsmFragmentTemplate(signature, AsmFragmentTemplateSynthesizer.fixNewlines(fragmentCharStream.toString()), targetCpu);
|
||||||
cache.put(signature, template);
|
cache.put(signature, template);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
package dk.camelot64.kickc.fragment;
|
package dk.camelot64.kickc.fragment;
|
||||||
|
|
||||||
import dk.camelot64.kickc.CompileLog;
|
import dk.camelot64.kickc.CompileLog;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesisRule;
|
import dk.camelot64.kickc.fragment.synthesis.*;
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesisRuleManager;
|
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -12,24 +10,25 @@ import java.util.*;
|
|||||||
public class AsmFragmentTemplateUsages {
|
public class AsmFragmentTemplateUsages {
|
||||||
|
|
||||||
/** Usage Statistics for fragment templates. */
|
/** Usage Statistics for fragment templates. */
|
||||||
private static Map<AsmFragmentTemplate, Integer> fragmentTemplateUsage = new HashMap<>();
|
private static Map<AsmFragmentSynthesisResult, Integer> fragmentTemplateUsage = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count one usage of ASM fragment templates - directly or through synthesis
|
* Count one usage of ASM fragment templates - directly or through synthesis
|
||||||
*
|
*
|
||||||
* @param fragmentTemplate The template to increment usage of
|
* @param fragmentTemplate The template to increment usage of
|
||||||
*/
|
*/
|
||||||
public static void incUsage(AsmFragmentTemplate fragmentTemplate) {
|
public static void incUsage(AsmFragmentSynthesisResult fragmentTemplate) {
|
||||||
Integer usage = fragmentTemplateUsage.get(fragmentTemplate);
|
Integer usage = fragmentTemplateUsage.get(fragmentTemplate);
|
||||||
if(usage == null) {
|
if(usage == null) {
|
||||||
usage = 0;
|
usage = 0;
|
||||||
}
|
}
|
||||||
fragmentTemplateUsage.put(fragmentTemplate, usage + 1);
|
fragmentTemplateUsage.put(fragmentTemplate, usage + 1);
|
||||||
AsmFragmentTemplate subFragment = fragmentTemplate.getSubFragment();
|
for (AsmFragmentSynthesisResult subFragment : fragmentTemplate.getSubFragments()) {
|
||||||
if (subFragment != null) {
|
if (subFragment != null) {
|
||||||
incUsage(subFragment);
|
incUsage(subFragment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log the usage of all template fragemnts (both loaded and synthesized).
|
* Log the usage of all template fragemnts (both loaded and synthesized).
|
||||||
@ -38,7 +37,7 @@ public class AsmFragmentTemplateUsages {
|
|||||||
*/
|
*/
|
||||||
public static void logUsages(AsmFragmentTemplateSynthesizer synthesizer, CompileLog log, boolean logRedundantFiles, boolean logUnusedFiles, boolean logUnusedRules, boolean logFileDetails, boolean logAllDetails, boolean logDetailsBody) {
|
public static void logUsages(AsmFragmentTemplateSynthesizer synthesizer, CompileLog log, boolean logRedundantFiles, boolean logUnusedFiles, boolean logUnusedRules, boolean logFileDetails, boolean logAllDetails, boolean logDetailsBody) {
|
||||||
|
|
||||||
Map<String, AsmFragmentTemplateSynthesizer.AsmFragmentSynthesis> synthesisGraph =
|
Map<String, AsmFragmentSynthesis> synthesisGraph =
|
||||||
synthesizer.getSynthesisGraph();
|
synthesizer.getSynthesisGraph();
|
||||||
ArrayList<String> signatures = new ArrayList<>(synthesisGraph.keySet());
|
ArrayList<String> signatures = new ArrayList<>(synthesisGraph.keySet());
|
||||||
Collections.sort(signatures);
|
Collections.sort(signatures);
|
||||||
@ -51,29 +50,21 @@ public class AsmFragmentTemplateUsages {
|
|||||||
String fileName = file.getName();
|
String fileName = file.getName();
|
||||||
String signature = fileName.substring(0, fileName.length() - 4);
|
String signature = fileName.substring(0, fileName.length() - 4);
|
||||||
// Synthesize the fragment - and check if the synthesis is as good as the file body
|
// Synthesize the fragment - and check if the synthesis is as good as the file body
|
||||||
Collection<AsmFragmentTemplate> templates = synthesizer.getBestTemplates(signature, log);
|
Collection<AsmFragmentSynthesisResult> templates = synthesizer.getBestTemplates(signature, log);
|
||||||
boolean isFile = false;
|
boolean isFile = false;
|
||||||
for(AsmFragmentTemplate template : templates) {
|
for(AsmFragmentSynthesisResult template : templates) {
|
||||||
isFile |= template.isFile();
|
isFile |= template.isFile();
|
||||||
}
|
}
|
||||||
if(!isFile) {
|
if(!isFile) {
|
||||||
StringBuilder templateNames = new StringBuilder();
|
StringBuilder templateNames = new StringBuilder();
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for(AsmFragmentTemplate template : templates) {
|
for(AsmFragmentSynthesisResult template : templates) {
|
||||||
templateNames.append(template.getName());
|
templateNames.append(template.getName());
|
||||||
if(first) {
|
if(first) {
|
||||||
first = false;
|
first = false;
|
||||||
} else {
|
} else {
|
||||||
templateNames.append(" / ");
|
templateNames.append(" / ");
|
||||||
}
|
}
|
||||||
// Check if the synthesis uses a file marked as redundant
|
|
||||||
AsmFragmentTemplate sourceFileTemplate = template;
|
|
||||||
while(!sourceFileTemplate.isFile()) {
|
|
||||||
sourceFileTemplate = sourceFileTemplate.getSubFragment();
|
|
||||||
}
|
|
||||||
if(redundantSignatures.contains(sourceFileTemplate.getSignature())) {
|
|
||||||
throw new RuntimeException("Problem in redundancy analysis! " + sourceFileTemplate.getSignature() + ".asm seems redundant but is needed for synthesis of " + signature);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
log.append("rm " + signature + ".asm #synthesized better ASM by " + templateNames);
|
log.append("rm " + signature + ".asm #synthesized better ASM by " + templateNames);
|
||||||
redundantSignatures.add(signature);
|
redundantSignatures.add(signature);
|
||||||
@ -86,13 +77,13 @@ public class AsmFragmentTemplateUsages {
|
|||||||
for(File file : files) {
|
for(File file : files) {
|
||||||
String fileName = file.getName();
|
String fileName = file.getName();
|
||||||
String signature = fileName.substring(0, fileName.length() - 4);
|
String signature = fileName.substring(0, fileName.length() - 4);
|
||||||
AsmFragmentTemplateSynthesizer.AsmFragmentSynthesis asmFragmentSynthesis = synthesisGraph.get(signature);
|
AsmFragmentSynthesis asmFragmentSynthesis = synthesisGraph.get(signature);
|
||||||
Collection<AsmFragmentTemplate> templates = asmFragmentSynthesis.getBestTemplates();
|
Collection<AsmFragmentSynthesisResult> templates = asmFragmentSynthesis.getBestTemplates();
|
||||||
if(templates != null && templates.size() > 0) {
|
if(templates != null && templates.size() > 0) {
|
||||||
// The template has been loaded / synthesized - is the usage count zero?
|
// The template has been loaded / synthesized - is the usage count zero?
|
||||||
boolean allZero = true;
|
boolean allZero = true;
|
||||||
Integer fileUsage = null;
|
Integer fileUsage = null;
|
||||||
for(AsmFragmentTemplate template : templates) {
|
for(AsmFragmentSynthesisResult template : templates) {
|
||||||
Integer usage = fragmentTemplateUsage.get(template);
|
Integer usage = fragmentTemplateUsage.get(template);
|
||||||
if(usage == null) usage = 0;
|
if(usage == null) usage = 0;
|
||||||
if(usage > 0) {
|
if(usage > 0) {
|
||||||
@ -118,16 +109,16 @@ public class AsmFragmentTemplateUsages {
|
|||||||
if(logUnusedRules) {
|
if(logUnusedRules) {
|
||||||
log.append("\nUNUSED ASM FRAGMENT SYNTHESIS RULE ANALYSIS (if found consider removing them)");
|
log.append("\nUNUSED ASM FRAGMENT SYNTHESIS RULE ANALYSIS (if found consider removing them)");
|
||||||
final Collection<AsmFragmentTemplateSynthesisRule> allRules = AsmFragmentTemplateSynthesisRuleManager.getAllSynthesisRules();
|
final Collection<AsmFragmentTemplateSynthesisRule> allRules = AsmFragmentTemplateSynthesisRuleManager.getAllSynthesisRules();
|
||||||
|
|
||||||
for(String signature : signatures) {
|
for(String signature : signatures) {
|
||||||
Collection<AsmFragmentTemplate> templates =
|
LinkedList<AsmFragmentSynthesisResult> templates = new LinkedList<>(synthesizer.getBestTemplates(signature, log));
|
||||||
synthesizer.getBestTemplates(signature, log);
|
while(!templates.isEmpty()) {
|
||||||
for(AsmFragmentTemplate template : templates) {
|
final AsmFragmentSynthesisResult template = templates.pop();
|
||||||
while(template.getSynthesis()!=null) {
|
|
||||||
allRules.remove(template.getSynthesis());
|
allRules.remove(template.getSynthesis());
|
||||||
template = template.getSubFragment();
|
templates.addAll(template.getSubFragments());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(AsmFragmentTemplateSynthesisRule rule : allRules) {
|
for(AsmFragmentTemplateSynthesisRule rule : allRules) {
|
||||||
log.append("Synthesis Rule Unused: - "+rule.toString());
|
log.append("Synthesis Rule Unused: - "+rule.toString());
|
||||||
}
|
}
|
||||||
@ -136,10 +127,10 @@ public class AsmFragmentTemplateUsages {
|
|||||||
if(logFileDetails) {
|
if(logFileDetails) {
|
||||||
log.append("\nDETAILED ASM FILE USAGES");
|
log.append("\nDETAILED ASM FILE USAGES");
|
||||||
// Find all file templates
|
// Find all file templates
|
||||||
List<AsmFragmentTemplate> fileTemplates = new ArrayList<>();
|
List<AsmFragmentSynthesisResult> fileTemplates = new ArrayList<>();
|
||||||
for(String signature : signatures) {
|
for(String signature : signatures) {
|
||||||
Collection<AsmFragmentTemplate> templates = synthesisGraph.get(signature).getBestTemplates();
|
Collection<AsmFragmentSynthesisResult> templates = synthesisGraph.get(signature).getBestTemplates();
|
||||||
for(AsmFragmentTemplate template : templates) {
|
for(AsmFragmentSynthesisResult template : templates) {
|
||||||
if(template.isFile()) {
|
if(template.isFile()) {
|
||||||
fileTemplates.add(template);
|
fileTemplates.add(template);
|
||||||
}
|
}
|
||||||
@ -151,9 +142,9 @@ public class AsmFragmentTemplateUsages {
|
|||||||
|
|
||||||
if(logAllDetails) {
|
if(logAllDetails) {
|
||||||
log.append("\nDETAILED ASM FRAGMENT USAGES");
|
log.append("\nDETAILED ASM FRAGMENT USAGES");
|
||||||
List<AsmFragmentTemplate> allTemplates = new ArrayList<>();
|
List<AsmFragmentSynthesisResult> allTemplates = new ArrayList<>();
|
||||||
for(String signature : signatures) {
|
for(String signature : signatures) {
|
||||||
Collection<AsmFragmentTemplate> templates = synthesisGraph.get(signature).getBestTemplates();
|
Collection<AsmFragmentSynthesisResult> templates = synthesisGraph.get(signature).getBestTemplates();
|
||||||
allTemplates.addAll(templates);
|
allTemplates.addAll(templates);
|
||||||
}
|
}
|
||||||
logTemplatesByUsage(synthesizer, log, allTemplates, logDetailsBody);
|
logTemplatesByUsage(synthesizer, log, allTemplates, logDetailsBody);
|
||||||
@ -162,7 +153,7 @@ public class AsmFragmentTemplateUsages {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void logTemplatesByUsage(AsmFragmentTemplateSynthesizer synthesizer, CompileLog log, List<AsmFragmentTemplate> templates, boolean logBody) {
|
private static void logTemplatesByUsage(AsmFragmentTemplateSynthesizer synthesizer, CompileLog log, List<AsmFragmentSynthesisResult> templates, boolean logBody) {
|
||||||
// Sort by usage
|
// Sort by usage
|
||||||
Collections.sort(templates, (o1, o2) -> {
|
Collections.sort(templates, (o1, o2) -> {
|
||||||
Integer u1 = fragmentTemplateUsage.get(o1);
|
Integer u1 = fragmentTemplateUsage.get(o1);
|
||||||
@ -173,14 +164,14 @@ public class AsmFragmentTemplateUsages {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
// Output
|
// Output
|
||||||
for(AsmFragmentTemplate template : templates) {
|
for(AsmFragmentSynthesisResult template : templates) {
|
||||||
Integer usage = fragmentTemplateUsage.get(template);
|
Integer usage = fragmentTemplateUsage.get(template);
|
||||||
if(usage == null) usage = 0;
|
if(usage == null) usage = 0;
|
||||||
AsmFragmentTemplateSynthesizer.AsmFragmentSynthesis synthesis = synthesizer.getOrCreateSynthesis(template.getSignature(), log);
|
AsmFragmentSynthesis synthesis = synthesizer.getOrCreateSynthesis(template.getSignature(), log);
|
||||||
Collection<AsmFragmentTemplate> bestTemplates = synthesis.getBestTemplates();
|
Collection<AsmFragmentSynthesisResult> bestTemplates = synthesis.getBestTemplates();
|
||||||
log.append(String.format("%8d", usage) + " " + template.getSignature()+" - templates: " + bestTemplates.size());
|
log.append(String.format("%8d", usage) + " " + template.getSignature()+" - templates: " + bestTemplates.size());
|
||||||
if(logBody) {
|
if(logBody) {
|
||||||
for(AsmFragmentTemplate bestTemplate : bestTemplates) {
|
for(AsmFragmentSynthesisResult bestTemplate : bestTemplates) {
|
||||||
logTemplate(log, bestTemplate, " ");
|
logTemplate(log, bestTemplate, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,7 +179,7 @@ public class AsmFragmentTemplateUsages {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void logTemplate(CompileLog log, AsmFragmentTemplate template, String indent) {
|
public static void logTemplate(CompileLog log, AsmFragmentSynthesisResult template, String indent) {
|
||||||
String prefix;
|
String prefix;
|
||||||
if(template.isCache()) {
|
if(template.isCache()) {
|
||||||
prefix = "cached ";
|
prefix = "cached ";
|
||||||
|
@ -0,0 +1,169 @@
|
|||||||
|
package dk.camelot64.kickc.fragment.synthesis;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.fragment.AsmFragmentClobber;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The synthesis is capable of loading the fragment from disk or synthesizing it from other fragments using synthesis rules.
|
||||||
|
* The synthesis caches the best fragments for each clobber profile (loaded or synthesized).
|
||||||
|
* A node in the synthesis graph.
|
||||||
|
*/
|
||||||
|
public class AsmFragmentSynthesis {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signature of the fragment template being synthesized.
|
||||||
|
*/
|
||||||
|
private final String signature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The best template loaded/synthesized so far for each clobber profile
|
||||||
|
*/
|
||||||
|
private final Map<AsmFragmentClobber, AsmFragmentSynthesisResult> bestTemplates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for synthesizing the template from sub-fragments using a specific synthesis rule. Forward edges in the synthesis graph.
|
||||||
|
*/
|
||||||
|
private final Set<AsmFragmentSynthesisOption> synthesisOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for synthesizing the other templates from this template using a specific synthesis rule. Backward edges in the synthesis graph.
|
||||||
|
*/
|
||||||
|
private final Set<AsmFragmentSynthesisOption> parentOptions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The templates loaded from a file. Empty if no file exists for the signature.
|
||||||
|
*/
|
||||||
|
private final List<AsmFragmentSynthesisResult> fileTemplates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new synthesis
|
||||||
|
*
|
||||||
|
* @param signature The signature of the fragment template to load/synthesize
|
||||||
|
*/
|
||||||
|
AsmFragmentSynthesis(String signature) {
|
||||||
|
this.signature = signature;
|
||||||
|
this.bestTemplates = new LinkedHashMap<>();
|
||||||
|
this.synthesisOptions = new LinkedHashSet<>();
|
||||||
|
this.parentOptions = new LinkedHashSet<>();
|
||||||
|
this.fileTemplates = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a synthesis option to the template synthesis.
|
||||||
|
* The synthesis options can be used for synthesizing the template from sub-fragments using a specific synthesis rule.
|
||||||
|
*
|
||||||
|
* @param synthesisOption The option to add
|
||||||
|
*/
|
||||||
|
void addSynthesisOption(AsmFragmentSynthesisOption synthesisOption) {
|
||||||
|
this.synthesisOptions.add(synthesisOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the options for synthesizing the template from sub-fragments using a specific synthesis rule. Forward edges in the synthesis graph.
|
||||||
|
*
|
||||||
|
* @return The options
|
||||||
|
*/
|
||||||
|
Collection<AsmFragmentSynthesisOption> getSynthesisOptions() {
|
||||||
|
return synthesisOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a parent. The parent is an option for synthesizing another fragment template from this one using a specific synthesis rule.
|
||||||
|
*
|
||||||
|
* @param synthesisOption Thew parent option to add
|
||||||
|
*/
|
||||||
|
void addParentOption(AsmFragmentSynthesisOption synthesisOption) {
|
||||||
|
this.parentOptions.add(synthesisOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addFileTemplate(AsmFragmentSynthesisResult fileTemplate) {
|
||||||
|
this.fileTemplates.add(fileTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AsmFragmentSynthesisResult> getFileTemplates() {
|
||||||
|
return fileTemplates;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a candidate for best template.
|
||||||
|
* If the candidate is better than the current best for its clobber profile update the best template
|
||||||
|
*
|
||||||
|
* @param candidate The template candidate to examine
|
||||||
|
* @return true if the best template was updated
|
||||||
|
*/
|
||||||
|
boolean bestTemplateCandidate(AsmFragmentSynthesisResult candidate) {
|
||||||
|
AsmFragmentClobber candidateClobber = candidate.getClobber();
|
||||||
|
double candidateCycles = candidate.getCycles();
|
||||||
|
|
||||||
|
// Check if any current best templates are better
|
||||||
|
Set<AsmFragmentClobber> bestClobbers = new LinkedHashSet<>(bestTemplates.keySet());
|
||||||
|
for (AsmFragmentClobber bestClobber : bestClobbers) {
|
||||||
|
AsmFragmentSynthesisResult bestTemplate = bestTemplates.get(bestClobber);
|
||||||
|
double bestCycles = bestTemplate.getCycles();
|
||||||
|
if (bestClobber.isTrueSubset(candidateClobber) && bestCycles <= candidateCycles) {
|
||||||
|
// A better template already found - don't update
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bestClobber.isSubset(candidateClobber) && bestCycles < candidateCycles) {
|
||||||
|
// A better template already found - don't update
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bestClobber.equals(candidateClobber) && bestCycles == candidateCycles && bestTemplate.getBody().compareTo(candidate.getBody()) <= 0) {
|
||||||
|
// A better template already found - don't update
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// The candidate is better than some of the current best!
|
||||||
|
|
||||||
|
// Remove any current templates that are worse
|
||||||
|
for (AsmFragmentClobber bestClobber : bestClobbers) {
|
||||||
|
AsmFragmentSynthesisResult bestTemplate = bestTemplates.get(bestClobber);
|
||||||
|
double bestCycles = bestTemplate.getCycles();
|
||||||
|
|
||||||
|
if (candidateClobber.isTrueSubset(bestClobber) && candidateCycles <= bestCycles) {
|
||||||
|
// The candidate is better - remove the current template
|
||||||
|
bestTemplates.remove(bestClobber);
|
||||||
|
}
|
||||||
|
if (candidateClobber.isSubset(bestClobber) && candidateCycles < bestCycles) {
|
||||||
|
// The candidate is better - remove the current template
|
||||||
|
bestTemplates.remove(bestClobber);
|
||||||
|
}
|
||||||
|
if (candidateClobber.equals(bestClobber) && candidateCycles == bestCycles && candidate.getBody().compareTo(bestTemplate.getBody()) <= 0) {
|
||||||
|
// The candidate is better - remove the current template
|
||||||
|
bestTemplates.remove(bestClobber);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Update the current best
|
||||||
|
bestTemplates.put(candidateClobber, candidate);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the parent options.
|
||||||
|
* These are options for synthesizing other templates
|
||||||
|
* from this template using a specific synthesis rule. Backward edges in the synthesis graph.
|
||||||
|
*
|
||||||
|
* @return The parent options.
|
||||||
|
*/
|
||||||
|
Set<AsmFragmentSynthesisOption> getParentOptions() {
|
||||||
|
return parentOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the best fragment templates of the synthesis.
|
||||||
|
* Multiple templates are returned if templates with different clobber profiles exist.
|
||||||
|
*
|
||||||
|
* @return The best templates of the synthesis.
|
||||||
|
*/
|
||||||
|
public Collection<AsmFragmentSynthesisResult> getBestTemplates() {
|
||||||
|
return bestTemplates.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignature() {
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package dk.camelot64.kickc.fragment.synthesis;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An option for synthesizing a fragment template from a sub-template using a specific synthesis rule. An edge in the synthesis graph.
|
||||||
|
*/
|
||||||
|
public class AsmFragmentSynthesisOption {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signature of the fragment template being synthesized. The from-node in the graph.
|
||||||
|
*/
|
||||||
|
private final String signature;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signatures of the sub-fragment templates to synthesize from. The to-nodes in the graph.
|
||||||
|
*/
|
||||||
|
private final List<String> subSignatures;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The synthesis rule capable of synthesizing this template from the sub-fragments.
|
||||||
|
*/
|
||||||
|
private final AsmFragmentTemplateSynthesisRule rule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a synthesis option
|
||||||
|
*
|
||||||
|
* @param signature the signature of the fragment template being synthesized.
|
||||||
|
* @param rule The synthesis rule capable of synthesizing this template from the sub-fragment.
|
||||||
|
*/
|
||||||
|
AsmFragmentSynthesisOption(String signature, AsmFragmentTemplateSynthesisRule rule) {
|
||||||
|
this.signature = signature;
|
||||||
|
this.rule = rule;
|
||||||
|
this.subSignatures = rule.getSubSignatures(signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignature() {
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> getSubSignatures() {
|
||||||
|
return subSignatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsmFragmentTemplateSynthesisRule getRule() {
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
AsmFragmentSynthesisOption that = (AsmFragmentSynthesisOption) o;
|
||||||
|
return Objects.equals(signature, that.signature) &&
|
||||||
|
Objects.equals(subSignatures, that.subSignatures) &&
|
||||||
|
Objects.equals(rule, that.rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(signature, subSignatures, rule);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package dk.camelot64.kickc.fragment.synthesis;
|
||||||
|
|
||||||
|
import dk.camelot64.kickc.fragment.AsmFragmentClobber;
|
||||||
|
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A successfully synthesized or loaded fragment.
|
||||||
|
*/
|
||||||
|
public class AsmFragmentSynthesisResult {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ASM fragment template.
|
||||||
|
*/
|
||||||
|
final AsmFragmentTemplate fragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* true if the fragment was loaded from disk.
|
||||||
|
*/
|
||||||
|
private boolean file;
|
||||||
|
/**
|
||||||
|
* true if the fragment was loaded from the disk cache.
|
||||||
|
*/
|
||||||
|
private boolean cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The synthesis that created the fragment. null if the fragment template was loaded.
|
||||||
|
*/
|
||||||
|
private AsmFragmentTemplateSynthesisRule synthesis;
|
||||||
|
/**
|
||||||
|
* The sub fragment template that the synthesis used to create this.
|
||||||
|
*/
|
||||||
|
private List<AsmFragmentSynthesisResult> subFragments;
|
||||||
|
|
||||||
|
public AsmFragmentSynthesisResult(AsmFragmentTemplate fragment, boolean file, boolean cache, AsmFragmentTemplateSynthesisRule synthesis, List<AsmFragmentSynthesisResult> subFragments) {
|
||||||
|
this.fragment = fragment;
|
||||||
|
this.file = file;
|
||||||
|
this.cache = cache;
|
||||||
|
this.synthesis = synthesis;
|
||||||
|
this.subFragments = subFragments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCache() {
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsmFragmentTemplateSynthesisRule getSynthesis() {
|
||||||
|
return synthesis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsmFragmentTemplate getFragment() {
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AsmFragmentSynthesisResult> getSubFragments() {
|
||||||
|
return subFragments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
StringBuilder name = new StringBuilder();
|
||||||
|
name.append(fragment.getSignature());
|
||||||
|
if (synthesis != null) {
|
||||||
|
name.append(" < ");
|
||||||
|
if (subFragments.size() == 1) {
|
||||||
|
name.append(subFragments.get(0).getName());
|
||||||
|
} else {
|
||||||
|
for (AsmFragmentSynthesisResult subFragment : subFragments) {
|
||||||
|
name.append("(");
|
||||||
|
name.append(subFragment.getName());
|
||||||
|
name.append(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return name.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AsmFragmentClobber getClobber() {
|
||||||
|
return fragment.getClobber();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getCycles() {
|
||||||
|
return fragment.getCycles();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBody() {
|
||||||
|
return fragment.getBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignature() {
|
||||||
|
return fragment.getSignature();
|
||||||
|
}
|
||||||
|
}
|
@ -97,7 +97,7 @@ class AsmFragmentTemplateSynthesisRuleRegex implements AsmFragmentTemplateSynthe
|
|||||||
subSignature = subSignature.replace(bound, bindMappings.get(bound));
|
subSignature = subSignature.replace(bound, bindMappings.get(bound));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Arrays.asList(subSignature);
|
return Collections.singletonList(subSignature);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ class AsmFragmentTemplateSynthesisRuleRegex implements AsmFragmentTemplateSynthe
|
|||||||
if(newFragment.length() > 0 && newFragment.charAt(newFragment.length() - 1) == '\n') {
|
if(newFragment.length() > 0 && newFragment.charAt(newFragment.length() - 1) == '\n') {
|
||||||
newFragment = new StringBuilder(newFragment.substring(0, newFragment.length() - 1));
|
newFragment = new StringBuilder(newFragment.substring(0, newFragment.length() - 1));
|
||||||
}
|
}
|
||||||
return new AsmFragmentTemplate(signature, newFragment.toString(), this, subTemplate);
|
return new AsmFragmentTemplate(signature, newFragment.toString(), subTemplate.getTargetCpu());
|
||||||
}
|
}
|
||||||
|
|
||||||
static String regexpRewriteSignature(String signature, String match, String replace) {
|
static String regexpRewriteSignature(String signature, String match, String replace) {
|
||||||
|
@ -12,6 +12,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides fragment templates from their signature.
|
* Provides fragment templates from their signature.
|
||||||
@ -99,9 +100,14 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
}
|
}
|
||||||
throw new UnknownFragmentException(signature);
|
throw new UnknownFragmentException(signature);
|
||||||
}
|
}
|
||||||
if(bestTemplate == null) {
|
if (bestTemplate != null) {
|
||||||
|
AsmFragmentTemplateUsages.incUsage(new AsmFragmentSynthesisResult(bestTemplate, false, true, null, new ArrayList<>()));
|
||||||
|
return bestTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
AsmFragmentSynthesisResult bestResult = null;
|
||||||
// Attempt to synthesize or load in main fragment folder
|
// Attempt to synthesize or load in main fragment folder
|
||||||
Collection<AsmFragmentTemplate> candidates = getBestTemplates(signature, log);
|
Collection<AsmFragmentSynthesisResult> candidates = getBestTemplates(signature, log);
|
||||||
if (candidates.size() == 0) {
|
if (candidates.size() == 0) {
|
||||||
if (log.isVerboseFragmentLog()) {
|
if (log.isVerboseFragmentLog()) {
|
||||||
log.append("Unknown fragment " + signature);
|
log.append("Unknown fragment " + signature);
|
||||||
@ -110,7 +116,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
throw new UnknownFragmentException(signature);
|
throw new UnknownFragmentException(signature);
|
||||||
}
|
}
|
||||||
double minScore = Double.MAX_VALUE;
|
double minScore = Double.MAX_VALUE;
|
||||||
for(AsmFragmentTemplate candidateTemplate : candidates) {
|
for (AsmFragmentSynthesisResult candidateTemplate : candidates) {
|
||||||
double score = candidateTemplate.getCycles();
|
double score = candidateTemplate.getCycles();
|
||||||
if (candidateTemplate.getClobber().isClobberZ()) score += 0.25;
|
if (candidateTemplate.getClobber().isClobberZ()) score += 0.25;
|
||||||
if (candidateTemplate.getClobber().isClobberA()) score += 0.5;
|
if (candidateTemplate.getClobber().isClobberA()) score += 0.5;
|
||||||
@ -118,17 +124,15 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
if (candidateTemplate.getClobber().isClobberX()) score += 1.5;
|
if (candidateTemplate.getClobber().isClobberX()) score += 1.5;
|
||||||
if (score < minScore) {
|
if (score < minScore) {
|
||||||
minScore = score;
|
minScore = score;
|
||||||
bestTemplate = candidateTemplate;
|
bestResult = candidateTemplate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (log.isVerboseFragmentLog()) {
|
if (log.isVerboseFragmentLog()) {
|
||||||
log.append("Found best fragment " + bestTemplate.getName() + " score: " + minScore);
|
log.append("Found best fragment " + bestResult.getName() + " score: " + minScore);
|
||||||
}
|
}
|
||||||
fragmentCache.put(signature, bestTemplate);
|
fragmentCache.put(signature, bestResult.getFragment());
|
||||||
}
|
AsmFragmentTemplateUsages.incUsage(bestResult);
|
||||||
// Count usages
|
return bestResult.getFragment();
|
||||||
AsmFragmentTemplateUsages.incUsage(bestTemplate);
|
|
||||||
return bestTemplate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -140,7 +144,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
* @param log The compile log
|
* @param log The compile log
|
||||||
* @return The best templates for the passed signature
|
* @return The best templates for the passed signature
|
||||||
*/
|
*/
|
||||||
public Collection<AsmFragmentTemplate> getBestTemplates(String signature, CompileLog log) {
|
public Collection<AsmFragmentSynthesisResult> getBestTemplates(String signature, CompileLog log) {
|
||||||
getOrCreateSynthesis(signature, log);
|
getOrCreateSynthesis(signature, log);
|
||||||
updateBestTemplates(log);
|
updateBestTemplates(log);
|
||||||
AsmFragmentSynthesis synthesis = getSynthesis(signature);
|
AsmFragmentSynthesis synthesis = getSynthesis(signature);
|
||||||
@ -150,212 +154,6 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
return synthesis.getBestTemplates();
|
return synthesis.getBestTemplates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The synthesis is capable of loading the fragment from disk or synthesizing it from other fragments using synthesis rules.
|
|
||||||
* The synthesis caches the best fragments for each clobber profile (loaded or synthesized).
|
|
||||||
* A node in the synthesis graph.
|
|
||||||
*/
|
|
||||||
public static class AsmFragmentSynthesis {
|
|
||||||
|
|
||||||
/** The signature of the fragment template being synthesized. */
|
|
||||||
private final String signature;
|
|
||||||
|
|
||||||
/** The best template loaded/synthesized so far for each clobber profile */
|
|
||||||
private final Map<AsmFragmentClobber, AsmFragmentTemplate> bestTemplates;
|
|
||||||
|
|
||||||
/** Options for synthesizing the template from sub-fragments using a specific synthesis rule. Forward edges in the synthesis graph. */
|
|
||||||
private final Set<AsmFragmentSynthesisOption> synthesisOptions;
|
|
||||||
|
|
||||||
/** Options for synthesizing the other templates from this template using a specific synthesis rule. Backward edges in the synthesis graph. */
|
|
||||||
private final Set<AsmFragmentSynthesisOption> parentOptions;
|
|
||||||
|
|
||||||
/** The templates loaded from a file. Empty if no file exists for the signature. */
|
|
||||||
private final List<AsmFragmentTemplate> fileTemplates;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new synthesis
|
|
||||||
*
|
|
||||||
* @param signature The signature of the fragment template to load/synthesize
|
|
||||||
*/
|
|
||||||
AsmFragmentSynthesis(String signature) {
|
|
||||||
this.signature = signature;
|
|
||||||
this.bestTemplates = new LinkedHashMap<>();
|
|
||||||
this.synthesisOptions = new LinkedHashSet<>();
|
|
||||||
this.parentOptions = new LinkedHashSet<>();
|
|
||||||
this.fileTemplates = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a synthesis option to the template synthesis.
|
|
||||||
* The synthesis options can be used for synthesizing the template from sub-fragments using a specific synthesis rule.
|
|
||||||
*
|
|
||||||
* @param synthesisOption The option to add
|
|
||||||
*/
|
|
||||||
void addSynthesisOption(AsmFragmentSynthesisOption synthesisOption) {
|
|
||||||
this.synthesisOptions.add(synthesisOption);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the options for synthesizing the template from sub-fragments using a specific synthesis rule. Forward edges in the synthesis graph.
|
|
||||||
*
|
|
||||||
* @return The options
|
|
||||||
*/
|
|
||||||
Collection<AsmFragmentSynthesisOption> getSynthesisOptions() {
|
|
||||||
return synthesisOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a parent. The parent is an option for synthesizing another fragment template from this one using a specific synthesis rule.
|
|
||||||
*
|
|
||||||
* @param synthesisOption Thew parent option to add
|
|
||||||
*/
|
|
||||||
void addParentOption(AsmFragmentSynthesisOption synthesisOption) {
|
|
||||||
this.parentOptions.add(synthesisOption);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addFileTemplate(AsmFragmentTemplate fileTemplate) {
|
|
||||||
this.fileTemplates.add(fileTemplate);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<AsmFragmentTemplate> getFileTemplates() {
|
|
||||||
return fileTemplates;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle a candidate for best template.
|
|
||||||
* If the candidate is better than the current best for its clobber profile update the best template
|
|
||||||
*
|
|
||||||
* @param candidate The template candidate to examine
|
|
||||||
* @return true if the best template was updated
|
|
||||||
*/
|
|
||||||
boolean bestTemplateCandidate(AsmFragmentTemplate candidate) {
|
|
||||||
AsmFragmentClobber candidateClobber = candidate.getClobber();
|
|
||||||
double candidateCycles = candidate.getCycles();
|
|
||||||
|
|
||||||
// Check if any current best templates are better
|
|
||||||
Set<AsmFragmentClobber> bestClobbers = new LinkedHashSet<>(bestTemplates.keySet());
|
|
||||||
for(AsmFragmentClobber bestClobber : bestClobbers) {
|
|
||||||
AsmFragmentTemplate bestTemplate = bestTemplates.get(bestClobber);
|
|
||||||
double bestCycles = bestTemplate.getCycles();
|
|
||||||
if(bestClobber.isTrueSubset(candidateClobber) && bestCycles <= candidateCycles) {
|
|
||||||
// A better template already found - don't update
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(bestClobber.isSubset(candidateClobber) && bestCycles < candidateCycles) {
|
|
||||||
// A better template already found - don't update
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(bestClobber.equals(candidateClobber) && bestCycles == candidateCycles && bestTemplate.getBody().compareTo(candidate.getBody()) <= 0) {
|
|
||||||
// A better template already found - don't update
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// The candidate is better than some of the current best!
|
|
||||||
|
|
||||||
// Remove any current templates that are worse
|
|
||||||
for(AsmFragmentClobber bestClobber : bestClobbers) {
|
|
||||||
AsmFragmentTemplate bestTemplate = bestTemplates.get(bestClobber);
|
|
||||||
double bestCycles = bestTemplate.getCycles();
|
|
||||||
|
|
||||||
if(candidateClobber.isTrueSubset(bestClobber) && candidateCycles <= bestCycles) {
|
|
||||||
// The candidate is better - remove the current template
|
|
||||||
bestTemplates.remove(bestClobber);
|
|
||||||
}
|
|
||||||
if(candidateClobber.isSubset(bestClobber) && candidateCycles < bestCycles) {
|
|
||||||
// The candidate is better - remove the current template
|
|
||||||
bestTemplates.remove(bestClobber);
|
|
||||||
}
|
|
||||||
if(candidateClobber.equals(bestClobber) && candidateCycles == bestCycles && candidate.getBody().compareTo(bestTemplate.getBody()) < 0) {
|
|
||||||
// The candidate is better - remove the current template
|
|
||||||
bestTemplates.remove(bestClobber);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// Update the current best
|
|
||||||
bestTemplates.put(candidateClobber, candidate);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the parent options.
|
|
||||||
* These are options for synthesizing other templates
|
|
||||||
* from this template using a specific synthesis rule. Backward edges in the synthesis graph.
|
|
||||||
*
|
|
||||||
* @return The parent options.
|
|
||||||
*/
|
|
||||||
Set<AsmFragmentSynthesisOption> getParentOptions() {
|
|
||||||
return parentOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the best fragment templates of the synthesis.
|
|
||||||
* Multiple templates are returned if templates with different clobber profiles exist.
|
|
||||||
*
|
|
||||||
* @return The best templates of the synthesis.
|
|
||||||
*/
|
|
||||||
public Collection<AsmFragmentTemplate> getBestTemplates() {
|
|
||||||
return bestTemplates.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSignature() {
|
|
||||||
return signature;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An option for synthesizing a fragment template from a sub-template using a specific synthesis rule. An edge in the synthesis graph. */
|
|
||||||
public static class AsmFragmentSynthesisOption {
|
|
||||||
|
|
||||||
/** The signature of the fragment template being synthesized. The from-node in the graph. */
|
|
||||||
private final String signature;
|
|
||||||
|
|
||||||
/** The signatures of the sub-fragment templates to synthesize from. The to-nodes in the graph. */
|
|
||||||
private final List<String> subSignatures;
|
|
||||||
|
|
||||||
/** The synthesis rule capable of synthesizing this template from the sub-fragments. */
|
|
||||||
private final AsmFragmentTemplateSynthesisRule rule;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a synthesis option
|
|
||||||
*
|
|
||||||
* @param signature he signature of the fragment template being synthesized.
|
|
||||||
* @param rule The synthesis rule capable of synthesizing this template from the sub-fragment.
|
|
||||||
*/
|
|
||||||
AsmFragmentSynthesisOption(String signature, AsmFragmentTemplateSynthesisRule rule) {
|
|
||||||
this.signature = signature;
|
|
||||||
this.rule = rule;
|
|
||||||
this.subSignatures = rule.getSubSignatures(signature);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSignature() {
|
|
||||||
return signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> getSubSignatures() {
|
|
||||||
return subSignatures;
|
|
||||||
}
|
|
||||||
|
|
||||||
AsmFragmentTemplateSynthesisRule getRule() {
|
|
||||||
return rule;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if(this == o) return true;
|
|
||||||
if(o == null || getClass() != o.getClass()) return false;
|
|
||||||
AsmFragmentSynthesisOption that = (AsmFragmentSynthesisOption) o;
|
|
||||||
return Objects.equals(signature, that.signature) &&
|
|
||||||
Objects.equals(subSignatures, that.subSignatures) &&
|
|
||||||
Objects.equals(rule, that.rule);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(signature, subSignatures, rule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the entire synthesis graph. Called by the usage statistics.
|
* Get the entire synthesis graph. Called by the usage statistics.
|
||||||
*
|
*
|
||||||
@ -399,8 +197,8 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
synthesisGraph.put(signature, synthesis);
|
synthesisGraph.put(signature, synthesis);
|
||||||
queueUpdateBestTemplate(synthesis);
|
queueUpdateBestTemplate(synthesis);
|
||||||
// Load the template from file - if it exists
|
// Load the template from file - if it exists
|
||||||
List<AsmFragmentTemplate> fileTemplates = loadFragmentTemplates(signature);
|
List<AsmFragmentSynthesisResult> fileTemplates = loadFragmentTemplates(signature);
|
||||||
for(AsmFragmentTemplate fileTemplate : fileTemplates) {
|
for (AsmFragmentSynthesisResult fileTemplate : fileTemplates) {
|
||||||
synthesis.addFileTemplate(fileTemplate);
|
synthesis.addFileTemplate(fileTemplate);
|
||||||
if (log.isVerboseFragmentLog()) {
|
if (log.isVerboseFragmentLog()) {
|
||||||
log.append("New fragment synthesis " + signature + " - Successfully loaded " + signature + ".asm");
|
log.append("New fragment synthesis " + signature + " - Successfully loaded " + signature + ".asm");
|
||||||
@ -450,35 +248,37 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
AsmFragmentSynthesis synthesis = bestTemplateUpdate.pop();
|
AsmFragmentSynthesis synthesis = bestTemplateUpdate.pop();
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
// Check if the file template is best in class
|
// Check if the file template is best in class
|
||||||
List<AsmFragmentTemplate> fileTemplates = synthesis.getFileTemplates();
|
List<AsmFragmentSynthesisResult> fileTemplates = synthesis.getFileTemplates();
|
||||||
for(AsmFragmentTemplate fileTemplate : fileTemplates) {
|
for (AsmFragmentSynthesisResult fileTemplate : fileTemplates) {
|
||||||
modified |= synthesis.bestTemplateCandidate(fileTemplate);
|
modified |= synthesis.bestTemplateCandidate(fileTemplate);
|
||||||
}
|
}
|
||||||
Collection<AsmFragmentSynthesisOption> synthesisOptions = synthesis.getSynthesisOptions();
|
Collection<AsmFragmentSynthesisOption> synthesisOptions = synthesis.getSynthesisOptions();
|
||||||
for (AsmFragmentSynthesisOption synthesisOption : synthesisOptions) {
|
for (AsmFragmentSynthesisOption synthesisOption : synthesisOptions) {
|
||||||
// for each sub-signature find the best templates
|
// for each sub-signature find the best templates
|
||||||
List<Collection<AsmFragmentTemplate>> subSignatureTemplates = new ArrayList<>();
|
List<Collection<AsmFragmentSynthesisResult>> subSignatureTemplates = new ArrayList<>();
|
||||||
for (String subSignature : synthesisOption.getSubSignatures()) {
|
for (String subSignature : synthesisOption.getSubSignatures()) {
|
||||||
AsmFragmentSynthesis subSynthesis = getSynthesis(subSignature);
|
AsmFragmentSynthesis subSynthesis = getSynthesis(subSignature);
|
||||||
if (subSynthesis == null) {
|
if (subSynthesis == null) {
|
||||||
throw new RuntimeException("Synthesis Graph Error! Sub-synthesis not found in graph " + subSignature);
|
throw new RuntimeException("Synthesis Graph Error! Sub-synthesis not found in graph " + subSignature);
|
||||||
}
|
}
|
||||||
Collection<AsmFragmentTemplate> subTemplates = subSynthesis.getBestTemplates();
|
Collection<AsmFragmentSynthesisResult> subTemplates = subSynthesis.getBestTemplates();
|
||||||
subSignatureTemplates.add(subTemplates);
|
subSignatureTemplates.add(subTemplates);
|
||||||
}
|
}
|
||||||
AsmFragmentTemplateSynthesisRule rule = synthesisOption.getRule();
|
AsmFragmentTemplateSynthesisRule rule = synthesisOption.getRule();
|
||||||
// Create all combinations of the best sub-templates
|
// Create all combinations of the best sub-templates
|
||||||
List<List<AsmFragmentTemplate>> combinations = combinations(subSignatureTemplates);
|
List<List<AsmFragmentSynthesisResult>> combinations = combinations(subSignatureTemplates);
|
||||||
for (List<AsmFragmentTemplate> subTemplateCombination : combinations) {
|
for (List<AsmFragmentSynthesisResult> subFragmentCombination : combinations) {
|
||||||
AsmFragmentTemplate synthesized = rule.synthesize(synthesis.getSignature(), subTemplateCombination);
|
final List<AsmFragmentTemplate> subFragments = subFragmentCombination.stream().map(AsmFragmentSynthesisResult::getFragment).collect(Collectors.toList());
|
||||||
if (synthesized != null) {
|
final AsmFragmentTemplate synthesize = rule.synthesize(synthesis.getSignature(), subFragments);
|
||||||
|
if (synthesize != null) {
|
||||||
if (log.isVerboseFragmentLog()) {
|
if (log.isVerboseFragmentLog()) {
|
||||||
log.append("Fragment synthesis " + synthesis.getSignature() + " - Successfully synthesized from " + String.join(",", synthesisOption.subSignatures));
|
log.append("Fragment synthesis " + synthesis.getSignature() + " - Successfully synthesized from " + String.join(",", synthesisOption.getSubSignatures()));
|
||||||
}
|
}
|
||||||
modified |= synthesis.bestTemplateCandidate(synthesized);
|
AsmFragmentSynthesisResult synthesisResult = new AsmFragmentSynthesisResult(synthesize, false, false, rule, subFragmentCombination);
|
||||||
|
modified |= synthesis.bestTemplateCandidate(synthesisResult);
|
||||||
} else {
|
} else {
|
||||||
if (log.isVerboseFragmentLog()) {
|
if (log.isVerboseFragmentLog()) {
|
||||||
log.append("Fragment synthesis " + synthesis.getSignature() + " - Sub clobber prevents synthesis from " + String.join(",", synthesisOption.subSignatures));
|
log.append("Fragment synthesis " + synthesis.getSignature() + " - Sub clobber prevents synthesis from " + String.join(",", synthesisOption.getSubSignatures()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -506,6 +306,7 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate all possible combinations of a number of options.
|
* Generate all possible combinations of a number of options.
|
||||||
|
*
|
||||||
* @param options A list of the options for each position.
|
* @param options A list of the options for each position.
|
||||||
* @param <T> The top of an option
|
* @param <T> The top of an option
|
||||||
* @return A list with all combinations of the passed options on each position.
|
* @return A list with all combinations of the passed options on each position.
|
||||||
@ -540,11 +341,11 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
* @param signature The signature
|
* @param signature The signature
|
||||||
* @return The fragment template from a file. null if the template is not found as a file.
|
* @return The fragment template from a file. null if the template is not found as a file.
|
||||||
*/
|
*/
|
||||||
private List<AsmFragmentTemplate> loadFragmentTemplates(String signature) {
|
private List<AsmFragmentSynthesisResult> loadFragmentTemplates(String signature) {
|
||||||
ArrayList<AsmFragmentTemplate> fileTemplates = new ArrayList<>();
|
ArrayList<AsmFragmentSynthesisResult> fileTemplates = new ArrayList<>();
|
||||||
List<TargetCpu.Feature> cpuFeatures = targetCpu.getFeatures();
|
List<TargetCpu.Feature> cpuFeatures = targetCpu.getFeatures();
|
||||||
for (TargetCpu.Feature cpuFeature : cpuFeatures) {
|
for (TargetCpu.Feature cpuFeature : cpuFeatures) {
|
||||||
AsmFragmentTemplate fileFragment = loadFragmentTemplate(signature, baseFragmentFolder.resolve(cpuFeature.getName()));
|
AsmFragmentSynthesisResult fileFragment = loadFragmentTemplate(signature, baseFragmentFolder.resolve(cpuFeature.getName()));
|
||||||
if (fileFragment != null)
|
if (fileFragment != null)
|
||||||
fileTemplates.add(fileFragment);
|
fileTemplates.add(fileFragment);
|
||||||
}
|
}
|
||||||
@ -556,9 +357,9 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
*
|
*
|
||||||
* @param signature The signature to search for
|
* @param signature The signature to search for
|
||||||
* @param fragmentFolder The folder to look in
|
* @param fragmentFolder The folder to look in
|
||||||
* @return any fragment with the gicen signature found in the folder. null if not found.
|
* @return any fragment with the given signature found in the folder. null if not found.
|
||||||
*/
|
*/
|
||||||
private AsmFragmentTemplate loadFragmentTemplate(String signature, Path fragmentFolder) {
|
private AsmFragmentSynthesisResult loadFragmentTemplate(String signature, Path fragmentFolder) {
|
||||||
try {
|
try {
|
||||||
File fragmentFile = fragmentFolder.resolve(signature + ".asm").toFile();
|
File fragmentFile = fragmentFolder.resolve(signature + ".asm").toFile();
|
||||||
if (!fragmentFile.exists()) {
|
if (!fragmentFile.exists()) {
|
||||||
@ -572,7 +373,8 @@ public class AsmFragmentTemplateSynthesizer {
|
|||||||
CharStream fragmentCharStream = CharStreams.fromStream(fragmentStream);
|
CharStream fragmentCharStream = CharStreams.fromStream(fragmentStream);
|
||||||
body = fixNewlines(fragmentCharStream.toString());
|
body = fixNewlines(fragmentCharStream.toString());
|
||||||
}
|
}
|
||||||
return new AsmFragmentTemplate(signature, body, targetCpu, false);
|
final AsmFragmentTemplate fragment = new AsmFragmentTemplate(signature, body, targetCpu);
|
||||||
|
return new AsmFragmentSynthesisResult(fragment, true, false, null, new ArrayList<>());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Error loading fragment file " + signature, e);
|
throw new RuntimeException("Error loading fragment file " + signature, e);
|
||||||
} catch (StringIndexOutOfBoundsException e) {
|
} catch (StringIndexOutOfBoundsException e) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package dk.camelot64.kickc.test;
|
package dk.camelot64.kickc.test;
|
||||||
|
|
||||||
import dk.camelot64.kickc.CompileLog;
|
import dk.camelot64.kickc.CompileLog;
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplate;
|
|
||||||
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
|
||||||
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
import dk.camelot64.kickc.fragment.AsmFragmentTemplateUsages;
|
||||||
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentSynthesisResult;
|
||||||
|
import dk.camelot64.kickc.fragment.synthesis.AsmFragmentTemplateSynthesizer;
|
||||||
import dk.camelot64.kickc.model.TargetCpu;
|
import dk.camelot64.kickc.model.TargetCpu;
|
||||||
import dk.camelot64.kickc.model.operators.Operators;
|
import dk.camelot64.kickc.model.operators.Operators;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
@ -196,11 +196,11 @@ public class TestFragments {
|
|||||||
asmFragmentTemplateSynthesizer = new AsmFragmentTemplateSynthesizer(TargetCpu.MOS6502X, new File("src/main/fragment/").toPath(), false, new CompileLog());
|
asmFragmentTemplateSynthesizer = new AsmFragmentTemplateSynthesizer(TargetCpu.MOS6502X, new File("src/main/fragment/").toPath(), false, new CompileLog());
|
||||||
log.setSysOut(true);
|
log.setSysOut(true);
|
||||||
//log.setVerboseFragmentLog(true);
|
//log.setVerboseFragmentLog(true);
|
||||||
List<AsmFragmentTemplate> templates =
|
List<AsmFragmentSynthesisResult> templates =
|
||||||
new ArrayList<>(asmFragmentTemplateSynthesizer.getBestTemplates(signature, log));
|
new ArrayList<>(asmFragmentTemplateSynthesizer.getBestTemplates(signature, log));
|
||||||
if(templates.size() > 0) {
|
if(templates.size() > 0) {
|
||||||
log.append("");
|
log.append("");
|
||||||
for(AsmFragmentTemplate template : templates) {
|
for(AsmFragmentSynthesisResult template : templates) {
|
||||||
AsmFragmentTemplateUsages.logTemplate(log, template, "");
|
AsmFragmentTemplateUsages.logTemplate(log, template, "");
|
||||||
}
|
}
|
||||||
log.append("");
|
log.append("");
|
||||||
@ -227,14 +227,14 @@ public class TestFragments {
|
|||||||
|
|
||||||
String signature = sigs.get(testIdx);
|
String signature = sigs.get(testIdx);
|
||||||
|
|
||||||
List<AsmFragmentTemplate> templates =
|
List<AsmFragmentSynthesisResult> templates =
|
||||||
new ArrayList<>(asmFragmentTemplateSynthesizer.getBestTemplates(signature, log));
|
new ArrayList<>(asmFragmentTemplateSynthesizer.getBestTemplates(signature, log));
|
||||||
Collections.sort(templates, Comparator.comparing(AsmFragmentTemplate::getClobber));
|
Collections.sort(templates, Comparator.comparing(AsmFragmentSynthesisResult::getClobber));
|
||||||
if(templates.size() == 0) {
|
if(templates.size() == 0) {
|
||||||
log.append("CANNOT SYNTHESIZE " + signature);
|
log.append("CANNOT SYNTHESIZE " + signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(AsmFragmentTemplate template : templates) {
|
for(AsmFragmentSynthesisResult template : templates) {
|
||||||
String prefix = "";
|
String prefix = "";
|
||||||
if(template.isCache()) {
|
if(template.isCache()) {
|
||||||
prefix = "cached ";
|
prefix = "cached ";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user