-
Notifications
You must be signed in to change notification settings - Fork 1.7k
C++: Better value numbering support for loading fields in IR #2772
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
687dcb7
54f0b4a
5e5bd92
4f27750
cfcf087
ba395cf
527181b
aaa6233
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,11 @@ newtype TValueNumber = | |
) { | ||
inheritanceConversionValueNumber(_, irFunc, opcode, baseClass, derivedClass, operand) | ||
} or | ||
TLoadTotalOverlapValueNumber( | ||
IRFunction irFunc, IRType type, ValueNumber memOperand, ValueNumber operand | ||
) { | ||
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand) | ||
} or | ||
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) } | ||
|
||
/** | ||
|
@@ -101,12 +106,18 @@ class ValueNumber extends TValueNumber { | |
* The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not | ||
* congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`. | ||
*/ | ||
private class CongruentCopyInstruction extends CopyInstruction { | ||
class CongruentCopyInstruction extends CopyInstruction { | ||
CongruentCopyInstruction() { | ||
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustExactlyOverlap | ||
} | ||
} | ||
|
||
class LoadTotalOverlapInstruction extends LoadInstruction { | ||
LoadTotalOverlapInstruction() { | ||
this.getSourceValueOperand().getDefinitionOverlap() instanceof MustTotallyOverlap | ||
} | ||
} | ||
|
||
/** | ||
* Holds if this library knows how to assign a value number to the specified instruction, other than | ||
* a `unique` value number that is never shared by multiple instructions. | ||
|
@@ -131,6 +142,8 @@ private predicate numberableInstruction(Instruction instr) { | |
instr instanceof PointerArithmeticInstruction | ||
or | ||
instr instanceof CongruentCopyInstruction | ||
or | ||
instr instanceof LoadTotalOverlapInstruction | ||
} | ||
|
||
private predicate variableAddressValueNumber( | ||
|
@@ -205,6 +218,7 @@ private predicate unaryValueNumber( | |
instr.getEnclosingIRFunction() = irFunc and | ||
not instr instanceof InheritanceConversionInstruction and | ||
not instr instanceof CopyInstruction and | ||
not instr instanceof FieldAddressInstruction and | ||
instr.getOpcode() = opcode and | ||
instr.getResultIRType() = type and | ||
valueNumber(instr.getUnary()) = operand | ||
|
@@ -221,6 +235,16 @@ private predicate inheritanceConversionValueNumber( | |
valueNumber(instr.getUnary()) = operand | ||
} | ||
|
||
private predicate loadTotalOverlapValueNumber( | ||
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, ValueNumber memOperand, | ||
ValueNumber operand | ||
) { | ||
instr.getEnclosingIRFunction() = irFunc and | ||
instr.getResultIRType() = type and | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there test cases where the type is required to avoid conflating values? If so, I'd be surprised if those cases can't be tweaked so the type is the same. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Off the top of my head: double foo(void* p, bool b) {
if (b) {
return *(int*)p;
}
else {
return *(float*)p;
}
} I'm not sure we'd treat the results of the two casts as congruent today, but we probably should. However, we would not want the results of the two indirect loads to be congruent, even though their address operands were congruent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I included the type mainly because all the other constructors did so. I will take a further look tomorrow and see if it actually makes a difference |
||
valueNumber(instr.getAnOperand().(MemoryOperand).getAnyDef()) = memOperand and | ||
valueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What
Okay, most of this discussion was just me thinking out loud and confirming that for the way the IR is generated today we're fine. But I think the right thing to do, for future robustness, is to restrict There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've restricted it to extend |
||
} | ||
|
||
/** | ||
* Holds if `instr` should be assigned a unique value number because this library does not know how | ||
* to determine if two instances of that instruction are equivalent. | ||
|
@@ -313,6 +337,11 @@ private ValueNumber nonUniqueValueNumber(Instruction instr) { | |
TPointerArithmeticValueNumber(irFunc, opcode, type, elementSize, leftOperand, rightOperand) | ||
) | ||
or | ||
exists(IRType type, ValueNumber memOperand, ValueNumber operand | | ||
loadTotalOverlapValueNumber(instr, irFunc, type, memOperand, operand) and | ||
result = TLoadTotalOverlapValueNumber(irFunc, type, memOperand, operand) | ||
) | ||
or | ||
// The value number of a copy is just the value number of its source value. | ||
result = valueNumber(instr.(CongruentCopyInstruction).getSourceValue()) | ||
) | ||
|
Uh oh!
There was an error while loading. Please reload this page.