Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,21 +92,39 @@ static bool IsMethodSupported (MethodDefinition method)
return true;
}

static bool HasJumpIntoTargetRange (Collection<Instruction> instructions, int firstInstr, int lastInstr, Func<Instruction, int>? mapping = null)
static bool HasJumpIntoTargetRange (Collection<Instruction> instructions, int firstInstr, int lastInstr, Func<Instruction, int?>? mapping = null)
{
foreach (var instr in instructions) {
switch (instr.OpCode.FlowControl) {
case FlowControl.Branch:
case FlowControl.Cond_Branch:
if (instr.Operand is Instruction target) {
int index = mapping == null ? instructions.IndexOf (target) : mapping (target);
if (index >= firstInstr && index <= lastInstr)
return true;
if (mapping != null && mapping (target) is int index) {
if (index >= firstInstr && index <= lastInstr) {
return true;
}
}
else {
for (int i = firstInstr; i <= lastInstr; i++) {
if (instructions[i] == target) {
return true;
}
}
Comment on lines +108 to +112

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This loop will have maximum of three iterations. This is a lot better than IndexOf which will search through the whole instructions collection which can have thousands of elements.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we even bother with the lookup then?
Can we measure this - if the lookup doesn't bring interesting perf wins I would vote for keeping it simple and just do the linear search over the known possible range (that should be really fast).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vitek-karas I'm not sure about the logic and wanted to avoid potentially changing the meaning of the code, e.g, I have no idea if the dictionary lookup could yield a different result than the loop. So, I wanted to make a change that is clear it doesn't change the code semantics, and at the same time is more performant.

Regarding measuring this, I currently don't have the dotnet/runtime cloned locally to try something (the changes in this PR are done through GitHub UI actually). But I think the performance trace is quite clear this lookup is problematic, and it also the change should hopefully be making sense as a performance improvement. Yet, I understand that measuring would still be a good idea to at least know how much improvement this is. But unfortunately, I'm not able to do it right now. If necessary, would someone from the team be able to do it?

}
} else {
foreach (var rtarget in (Instruction[]) instr.Operand) {
int index = mapping == null ? instructions.IndexOf (rtarget) : mapping (rtarget);
if (index >= firstInstr && index <= lastInstr)
return true;
if (mapping != null && mapping (rtarget) is int index) {
if (index >= firstInstr && index <= lastInstr) {
return true;
}
}
else {
for (int i = firstInstr; i <= lastInstr; i++) {
if (instructions[i] == rtarget) {
return true;
}
}
}
}
}

Expand Down Expand Up @@ -1175,6 +1193,15 @@ int GetInstructionIndex (Instruction instruction)
return idx;
}

int? TryGetInstructionIndex (Instruction instruction)
{
Debug.Assert (mapping != null);
if (mapping.TryGetValue (instruction, out int idx))
return idx;

return null;
}

bool GetOperandsConstantValues (int index, out object? left, out object? right)
{
Debug.Assert (FoldedInstructions != null);
Expand Down Expand Up @@ -1213,7 +1240,7 @@ static bool IsPairedStlocLdloc (Instruction first, Instruction second)
bool IsJumpTargetRange (int firstInstr, int lastInstr)
{
Debug.Assert (FoldedInstructions != null);
return HasJumpIntoTargetRange (FoldedInstructions, firstInstr, lastInstr, GetInstructionIndex);
return HasJumpIntoTargetRange (FoldedInstructions, firstInstr, lastInstr, TryGetInstructionIndex);
}
}

Expand Down