use of com.oracle.truffle.llvm.parser.model.blocks.InstructionBlock in project sulong by graalvm.
the class FunctionDefinition method exitLocalScope.
public void exitLocalScope() {
int symbolIndex = 0;
// in K&R style function declarations the parameters are not assigned names
for (final FunctionParameter parameter : parameters) {
if (LLVMIdentifier.UNKNOWN.equals(parameter.getName())) {
parameter.setName(String.valueOf(symbolIndex++));
}
}
final Set<String> explicitBlockNames = Arrays.stream(blocks).map(InstructionBlock::getName).filter(blockName -> !LLVMIdentifier.UNKNOWN.equals(blockName)).collect(Collectors.toSet());
for (final InstructionBlock block : blocks) {
if (block.getName().equals(LLVMIdentifier.UNKNOWN)) {
do {
block.setName(LLVMIdentifier.toImplicitBlockName(symbolIndex++));
// avoid name clashes
} while (explicitBlockNames.contains(block.getName()));
}
for (int i = 0; i < block.getInstructionCount(); i++) {
final Instruction instruction = block.getInstruction(i);
if (instruction instanceof ValueInstruction) {
final ValueInstruction value = (ValueInstruction) instruction;
if (value.getName().equals(LLVMIdentifier.UNKNOWN)) {
value.setName(String.valueOf(symbolIndex++));
}
}
}
}
}
use of com.oracle.truffle.llvm.parser.model.blocks.InstructionBlock in project sulong by graalvm.
the class LLVMLivenessAnalysis method iterateToFixedPoint.
private static int iterateToFixedPoint(List<InstructionBlock> blocks, FrameDescriptor frame, BlockInfo[] blockInfos, ArrayList<InstructionBlock>[] predecessors) {
// by processing the graph bottom-up, we may reach a fixed point more quickly
ArrayDeque<InstructionBlock> workList = new ArrayDeque<>(blocks);
BitSet blockOnWorkList = new BitSet(blocks.size());
blockOnWorkList.set(0, blockOnWorkList.size());
BitSet newPredecessorOut = new BitSet(frame.getSize());
BitSet newIn = new BitSet(frame.getSize());
int processedBlocks = 0;
while (!workList.isEmpty()) {
processedBlocks++;
InstructionBlock block = removeBlockFromWorkList(workList, blockOnWorkList);
BlockInfo blockInfo = blockInfos[block.getBlockIndex()];
newIn.clear();
newIn.or(blockInfo.out);
newIn.andNot(blockInfo.defs);
newIn.or(blockInfo.gen);
newIn.or(blockInfo.phiDefs);
blockInfo.in.clear();
blockInfo.in.or(newIn);
for (InstructionBlock predecessor : predecessors[block.getBlockIndex()]) {
BlockInfo predecessorBlockInfo = blockInfos[predecessor.getBlockIndex()];
newPredecessorOut.clear();
newPredecessorOut.or(blockInfo.in);
newPredecessorOut.andNot(blockInfo.phiDefs);
newPredecessorOut.or(predecessorBlockInfo.phiUses);
boolean changed = or(predecessorBlockInfo.out, newPredecessorOut);
if (changed) {
addBlockToWorkList(workList, blockOnWorkList, predecessor);
}
}
}
return processedBlocks;
}
use of com.oracle.truffle.llvm.parser.model.blocks.InstructionBlock in project sulong by graalvm.
the class LLVMLivenessAnalysis method initializeGenKill.
private static BlockInfo[] initializeGenKill(FrameDescriptor frame, Map<InstructionBlock, List<LLVMPhiManager.Phi>> phis, FunctionDefinition functionDefinition, List<InstructionBlock> blocks) {
BlockInfo[] result = new BlockInfo[blocks.size()];
for (int i = 0; i < blocks.size(); i++) {
InstructionBlock block = blocks.get(i);
BlockInfo blockInfo = result[i] = new BlockInfo(frame.getSize());
if (i == 0) {
// in the first block, the arguments are also always alive
for (FunctionParameter param : functionDefinition.getParameters()) {
processRead(blockInfo, frame.findFrameSlot(param.getName()).getIndex());
}
}
LLVMLivenessReadVisitor readVisitor = new LLVMLivenessReadVisitor(frame, blockInfo);
for (int j = 0; j < block.getInstructionCount(); j++) {
Instruction instruction = block.getInstruction(j);
if (instruction instanceof PhiInstruction) {
processPhiWrite(frame, (PhiInstruction) instruction, blockInfo);
} else {
processReads(readVisitor, instruction);
processWrite(frame, instruction, blockInfo);
}
}
List<LLVMPhiManager.Phi> bbPhis = phis.getOrDefault(block, Collections.emptyList());
for (LLVMPhiManager.Phi phi : bbPhis) {
processValueUsedInPhi(frame, phi.getValue(), blockInfo);
}
}
return result;
}
use of com.oracle.truffle.llvm.parser.model.blocks.InstructionBlock in project sulong by graalvm.
the class LLVMLivenessAnalysis method computeLivenessAnalysisResult.
private static LLVMLivenessAnalysisResult computeLivenessAnalysisResult(FunctionDefinition functionDefinition, List<InstructionBlock> blocks, FrameDescriptor frame, BlockInfo[] blockInfos, ArrayList<InstructionBlock>[] predecessors) {
@SuppressWarnings("unchecked") ArrayList<NullerInformation>[] nullableWithinBlock = new ArrayList[blocks.size()];
BitSet[] nullableBeforeBlock = new BitSet[blocks.size()];
BitSet[] nullableAfterBlock = new BitSet[blocks.size()];
int[] lastInstructionIndexTouchingLocal = new int[frame.getSize()];
LLVMNullerReadVisitor nullerReadVisitor = new LLVMNullerReadVisitor(frame, lastInstructionIndexTouchingLocal);
for (int i = 0; i < blocks.size(); i++) {
ArrayList<NullerInformation> blockNullers = new ArrayList<>();
Arrays.fill(lastInstructionIndexTouchingLocal, -1);
BlockInfo blockInfo = blockInfos[i];
// we destroy the kill and phiDefs bitsets as they are no longer needed anyways
blockInfo.kill.clear();
blockInfo.phiDefs.clear();
if (i == 0) {
// instruction
for (FunctionParameter param : functionDefinition.getParameters()) {
int frameSlotIndex = frame.findFrameSlot(param.getName()).getIndex();
lastInstructionIndexTouchingLocal[frameSlotIndex] = 0;
}
}
InstructionBlock block = blocks.get(i);
for (int j = 0; j < block.getInstructionCount(); j++) {
Instruction instruction = block.getInstruction(j);
if (instruction instanceof PhiInstruction) {
// we need to skip the reads of phi nodes as they belong to a different block
} else {
nullerReadVisitor.setInstructionIndex(j);
instruction.accept(nullerReadVisitor);
}
int frameSlotIndex = resolve(frame, instruction);
if (frameSlotIndex >= 0) {
// the write)
if (lastInstructionIndexTouchingLocal[frameSlotIndex] != -1 && lastInstructionIndexTouchingLocal[frameSlotIndex] != j) {
blockNullers.add(new NullerInformation(frameSlotIndex, lastInstructionIndexTouchingLocal[frameSlotIndex]));
}
lastInstructionIndexTouchingLocal[frameSlotIndex] = j;
}
}
// compute the values that die in this block. we do that in place, i.e., we destroy the
// def bitset that is no longer needed anyways.
blockInfo.defs.or(blockInfo.in);
blockInfo.defs.andNot(blockInfo.out);
int terminatingInstructionIndex = block.getInstructionCount() - 1;
BitSet valuesThatDieInBlock = blockInfo.defs;
int bitIndex = -1;
while ((bitIndex = valuesThatDieInBlock.nextSetBit(bitIndex + 1)) >= 0) {
assert lastInstructionIndexTouchingLocal[bitIndex] >= 0 : "must have a last usage, otherwise the value would not be alive in this block";
if (blockInfo.phiUses.get(bitIndex) || lastInstructionIndexTouchingLocal[bitIndex] == terminatingInstructionIndex) {
// if a value dies that is used in a phi function or in a terminating
// instruction, it dies after the block
blockInfo.phiDefs.set(bitIndex);
} else {
blockNullers.add(new NullerInformation(bitIndex, lastInstructionIndexTouchingLocal[bitIndex]));
}
}
// compute the values that can be nulled out before we enter this block.
for (InstructionBlock predecessor : predecessors[i]) {
BlockInfo predInfo = blockInfos[predecessor.getBlockIndex()];
blockInfo.kill.or(predInfo.out);
}
blockInfo.kill.andNot(blockInfo.in);
// collect the results
Collections.sort(blockNullers);
nullableWithinBlock[i] = blockNullers;
nullableBeforeBlock[i] = blockInfo.kill;
nullableAfterBlock[i] = blockInfo.phiDefs;
}
return new LLVMLivenessAnalysisResult(nullableWithinBlock, nullableBeforeBlock, nullableAfterBlock);
}
Aggregations