11private import internal.ValueNumberingInternal
22private import internal.ValueNumberingImports
3- private import IR
43
54/**
65 * Provides additional information about value numbering in IR dumps.
@@ -10,62 +9,38 @@ class ValueNumberPropertyProvider extends IRPropertyProvider {
109 exists ( ValueNumber vn |
1110 vn = valueNumber ( instr ) and
1211 key = "valnum" and
13- if strictcount ( vn .getAnInstruction ( ) ) > 1 then result = vn .toString ( ) else result = "unique"
12+ if strictcount ( vn .getAnInstruction ( ) ) > 1
13+ then result = vn .getDebugString ( )
14+ else result = "unique"
1415 )
1516 }
1617}
1718
18- newtype TValueNumber =
19- TVariableAddressValueNumber ( IRFunction irFunc , IRVariable var ) {
20- variableAddressValueNumber ( _, irFunc , var )
21- } or
22- TInitializeParameterValueNumber ( IRFunction irFunc , IRVariable var ) {
23- initializeParameterValueNumber ( _, irFunc , var )
24- } or
25- TInitializeThisValueNumber ( IRFunction irFunc ) { initializeThisValueNumber ( _, irFunc ) } or
26- TConstantValueNumber ( IRFunction irFunc , IRType type , string value ) {
27- constantValueNumber ( _, irFunc , type , value )
28- } or
29- TStringConstantValueNumber ( IRFunction irFunc , IRType type , string value ) {
30- stringConstantValueNumber ( _, irFunc , type , value )
31- } or
32- TFieldAddressValueNumber ( IRFunction irFunc , Language:: Field field , ValueNumber objectAddress ) {
33- fieldAddressValueNumber ( _, irFunc , field , objectAddress )
34- } or
35- TBinaryValueNumber (
36- IRFunction irFunc , Opcode opcode , IRType type , ValueNumber leftOperand , ValueNumber rightOperand
37- ) {
38- binaryValueNumber ( _, irFunc , opcode , type , leftOperand , rightOperand )
39- } or
40- TPointerArithmeticValueNumber (
41- IRFunction irFunc , Opcode opcode , IRType type , int elementSize , ValueNumber leftOperand ,
42- ValueNumber rightOperand
43- ) {
44- pointerArithmeticValueNumber ( _, irFunc , opcode , type , elementSize , leftOperand , rightOperand )
45- } or
46- TUnaryValueNumber ( IRFunction irFunc , Opcode opcode , IRType type , ValueNumber operand ) {
47- unaryValueNumber ( _, irFunc , opcode , type , operand )
48- } or
49- TInheritanceConversionValueNumber (
50- IRFunction irFunc , Opcode opcode , Language:: Class baseClass , Language:: Class derivedClass ,
51- ValueNumber operand
52- ) {
53- inheritanceConversionValueNumber ( _, irFunc , opcode , baseClass , derivedClass , operand )
54- } or
55- TLoadTotalOverlapValueNumber (
56- IRFunction irFunc , IRType type , ValueNumber memOperand , ValueNumber operand
57- ) {
58- loadTotalOverlapValueNumber ( _, irFunc , type , memOperand , operand )
59- } or
60- TUniqueValueNumber ( IRFunction irFunc , Instruction instr ) { uniqueValueNumber ( instr , irFunc ) }
61-
6219/**
6320 * The value number assigned to a particular set of instructions that produce equivalent results.
6421 */
6522class ValueNumber extends TValueNumber {
66- final string toString ( ) { result = getExampleInstruction ( ) .getResultId ( ) }
23+ final string toString ( ) { result = "GVN" }
24+
25+ final string getDebugString ( ) { result = strictconcat ( getAnInstruction ( ) .getResultId ( ) , ", " ) }
6726
68- final Language:: Location getLocation ( ) { result = getExampleInstruction ( ) .getLocation ( ) }
27+ final Language:: Location getLocation ( ) {
28+ if
29+ exists ( Instruction i |
30+ i = getAnInstruction ( ) and not i .getLocation ( ) instanceof UnknownLocation
31+ )
32+ then
33+ result =
34+ min ( Language:: Location l |
35+ l = getAnInstruction ( ) .getLocation ( ) and not l instanceof UnknownLocation
36+ |
37+ l
38+ order by
39+ l .getFile ( ) .getAbsolutePath ( ) , l .getStartLine ( ) , l .getStartColumn ( ) , l .getEndLine ( ) ,
40+ l .getEndColumn ( )
41+ )
42+ else result instanceof UnknownDefaultLocation
43+ }
6944
7045 /**
7146 * Gets the instructions that have been assigned this value number. This will always produce at
@@ -90,260 +65,39 @@ class ValueNumber extends TValueNumber {
9065 * Gets an `Operand` whose definition is exact and has this value number.
9166 */
9267 final Operand getAUse ( ) { this = valueNumber ( result .getDef ( ) ) }
93- }
9468
95- /**
96- * A `CopyInstruction` whose source operand's value is congruent to the definition of that source
97- * operand.
98- * For example:
99- * ```
100- * Point p = { 1, 2 };
101- * Point q = p;
102- * int a = p.x;
103- * ```
104- * The use of `p` on line 2 is linked to the definition of `p` on line 1, and is congruent to that
105- * definition because it accesses the exact same memory.
106- * The use of `p.x` on line 3 is linked to the definition of `p` on line 1 as well, but is not
107- * congruent to that definition because `p.x` accesses only a subset of the memory defined by `p`.
108- */
109- class CongruentCopyInstruction extends CopyInstruction {
110- CongruentCopyInstruction ( ) {
111- this .getSourceValueOperand ( ) .getDefinitionOverlap ( ) instanceof MustExactlyOverlap
69+ final string getKind ( ) {
70+ this instanceof TVariableAddressValueNumber and result = "VariableAddress"
71+ or
72+ this instanceof TInitializeParameterValueNumber and result = "InitializeParameter"
73+ or
74+ this instanceof TInitializeThisValueNumber and result = "InitializeThis"
75+ or
76+ this instanceof TStringConstantValueNumber and result = "StringConstant"
77+ or
78+ this instanceof TFieldAddressValueNumber and result = "FieldAddress"
79+ or
80+ this instanceof TBinaryValueNumber and result = "Binary"
81+ or
82+ this instanceof TPointerArithmeticValueNumber and result = "PointerArithmetic"
83+ or
84+ this instanceof TUnaryValueNumber and result = "Unary"
85+ or
86+ this instanceof TInheritanceConversionValueNumber and result = "InheritanceConversion"
87+ or
88+ this instanceof TLoadTotalOverlapValueNumber and result = "LoadTotalOverlap"
89+ or
90+ this instanceof TUniqueValueNumber and result = "Unique"
11291 }
11392}
11493
115- class LoadTotalOverlapInstruction extends LoadInstruction {
116- LoadTotalOverlapInstruction ( ) {
117- this .getSourceValueOperand ( ) .getDefinitionOverlap ( ) instanceof MustTotallyOverlap
118- }
119- }
120-
121- /**
122- * Holds if this library knows how to assign a value number to the specified instruction, other than
123- * a `unique` value number that is never shared by multiple instructions.
124- */
125- private predicate numberableInstruction ( Instruction instr ) {
126- instr instanceof VariableAddressInstruction
127- or
128- instr instanceof InitializeParameterInstruction
129- or
130- instr instanceof InitializeThisInstruction
131- or
132- instr instanceof ConstantInstruction
133- or
134- instr instanceof StringConstantInstruction
135- or
136- instr instanceof FieldAddressInstruction
137- or
138- instr instanceof BinaryInstruction
139- or
140- instr instanceof UnaryInstruction and not instr instanceof CopyInstruction
141- or
142- instr instanceof PointerArithmeticInstruction
143- or
144- instr instanceof CongruentCopyInstruction
145- or
146- instr instanceof LoadTotalOverlapInstruction
147- }
148-
149- private predicate variableAddressValueNumber (
150- VariableAddressInstruction instr , IRFunction irFunc , IRVariable var
151- ) {
152- instr .getEnclosingIRFunction ( ) = irFunc and
153- instr .getIRVariable ( ) = var
154- }
155-
156- private predicate initializeParameterValueNumber (
157- InitializeParameterInstruction instr , IRFunction irFunc , IRVariable var
158- ) {
159- instr .getEnclosingIRFunction ( ) = irFunc and
160- instr .getIRVariable ( ) = var
161- }
162-
163- private predicate initializeThisValueNumber ( InitializeThisInstruction instr , IRFunction irFunc ) {
164- instr .getEnclosingIRFunction ( ) = irFunc
165- }
166-
167- private predicate constantValueNumber (
168- ConstantInstruction instr , IRFunction irFunc , IRType type , string value
169- ) {
170- instr .getEnclosingIRFunction ( ) = irFunc and
171- instr .getResultIRType ( ) = type and
172- instr .getValue ( ) = value
173- }
174-
175- private predicate stringConstantValueNumber (
176- StringConstantInstruction instr , IRFunction irFunc , IRType type , string value
177- ) {
178- instr .getEnclosingIRFunction ( ) = irFunc and
179- instr .getResultIRType ( ) = type and
180- instr .getValue ( ) .getValue ( ) = value
181- }
182-
183- private predicate fieldAddressValueNumber (
184- FieldAddressInstruction instr , IRFunction irFunc , Language:: Field field , ValueNumber objectAddress
185- ) {
186- instr .getEnclosingIRFunction ( ) = irFunc and
187- instr .getField ( ) = field and
188- valueNumber ( instr .getObjectAddress ( ) ) = objectAddress
189- }
190-
191- private predicate binaryValueNumber (
192- BinaryInstruction instr , IRFunction irFunc , Opcode opcode , IRType type , ValueNumber leftOperand ,
193- ValueNumber rightOperand
194- ) {
195- instr .getEnclosingIRFunction ( ) = irFunc and
196- not instr instanceof PointerArithmeticInstruction and
197- instr .getOpcode ( ) = opcode and
198- instr .getResultIRType ( ) = type and
199- valueNumber ( instr .getLeft ( ) ) = leftOperand and
200- valueNumber ( instr .getRight ( ) ) = rightOperand
201- }
202-
203- private predicate pointerArithmeticValueNumber (
204- PointerArithmeticInstruction instr , IRFunction irFunc , Opcode opcode , IRType type ,
205- int elementSize , ValueNumber leftOperand , ValueNumber rightOperand
206- ) {
207- instr .getEnclosingIRFunction ( ) = irFunc and
208- instr .getOpcode ( ) = opcode and
209- instr .getResultIRType ( ) = type and
210- instr .getElementSize ( ) = elementSize and
211- valueNumber ( instr .getLeft ( ) ) = leftOperand and
212- valueNumber ( instr .getRight ( ) ) = rightOperand
213- }
214-
215- private predicate unaryValueNumber (
216- UnaryInstruction instr , IRFunction irFunc , Opcode opcode , IRType type , ValueNumber operand
217- ) {
218- instr .getEnclosingIRFunction ( ) = irFunc and
219- not instr instanceof InheritanceConversionInstruction and
220- not instr instanceof CopyInstruction and
221- not instr instanceof FieldAddressInstruction and
222- instr .getOpcode ( ) = opcode and
223- instr .getResultIRType ( ) = type and
224- valueNumber ( instr .getUnary ( ) ) = operand
225- }
226-
227- private predicate inheritanceConversionValueNumber (
228- InheritanceConversionInstruction instr , IRFunction irFunc , Opcode opcode ,
229- Language:: Class baseClass , Language:: Class derivedClass , ValueNumber operand
230- ) {
231- instr .getEnclosingIRFunction ( ) = irFunc and
232- instr .getOpcode ( ) = opcode and
233- instr .getBaseClass ( ) = baseClass and
234- instr .getDerivedClass ( ) = derivedClass and
235- valueNumber ( instr .getUnary ( ) ) = operand
236- }
237-
238- private predicate loadTotalOverlapValueNumber (
239- LoadTotalOverlapInstruction instr , IRFunction irFunc , IRType type , ValueNumber memOperand ,
240- ValueNumber operand
241- ) {
242- instr .getEnclosingIRFunction ( ) = irFunc and
243- instr .getResultIRType ( ) = type and
244- valueNumber ( instr .getAnOperand ( ) .( MemoryOperand ) .getAnyDef ( ) ) = memOperand and
245- valueNumberOfOperand ( instr .getAnOperand ( ) .( AddressOperand ) ) = operand
246- }
247-
248- /**
249- * Holds if `instr` should be assigned a unique value number because this library does not know how
250- * to determine if two instances of that instruction are equivalent.
251- */
252- private predicate uniqueValueNumber ( Instruction instr , IRFunction irFunc ) {
253- instr .getEnclosingIRFunction ( ) = irFunc and
254- not instr .getResultIRType ( ) instanceof IRVoidType and
255- not numberableInstruction ( instr )
256- }
257-
25894/**
25995 * Gets the value number assigned to `instr`, if any. Returns at most one result.
26096 */
261- cached
262- ValueNumber valueNumber ( Instruction instr ) {
263- result = nonUniqueValueNumber ( instr )
264- or
265- exists ( IRFunction irFunc |
266- uniqueValueNumber ( instr , irFunc ) and
267- result = TUniqueValueNumber ( irFunc , instr )
268- )
269- }
97+ ValueNumber valueNumber ( Instruction instr ) { result = tvalueNumber ( instr ) }
27098
27199/**
272100 * Gets the value number assigned to the exact definition of `op`, if any.
273101 * Returns at most one result.
274102 */
275- ValueNumber valueNumberOfOperand ( Operand op ) { result = valueNumber ( op .getDef ( ) ) }
276-
277- /**
278- * Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
279- * value number.
280- */
281- private ValueNumber nonUniqueValueNumber ( Instruction instr ) {
282- exists ( IRFunction irFunc |
283- irFunc = instr .getEnclosingIRFunction ( ) and
284- (
285- exists ( IRVariable var |
286- variableAddressValueNumber ( instr , irFunc , var ) and
287- result = TVariableAddressValueNumber ( irFunc , var )
288- )
289- or
290- exists ( IRVariable var |
291- initializeParameterValueNumber ( instr , irFunc , var ) and
292- result = TInitializeParameterValueNumber ( irFunc , var )
293- )
294- or
295- initializeThisValueNumber ( instr , irFunc ) and
296- result = TInitializeThisValueNumber ( irFunc )
297- or
298- exists ( IRType type , string value |
299- constantValueNumber ( instr , irFunc , type , value ) and
300- result = TConstantValueNumber ( irFunc , type , value )
301- )
302- or
303- exists ( IRType type , string value |
304- stringConstantValueNumber ( instr , irFunc , type , value ) and
305- result = TStringConstantValueNumber ( irFunc , type , value )
306- )
307- or
308- exists ( Language:: Field field , ValueNumber objectAddress |
309- fieldAddressValueNumber ( instr , irFunc , field , objectAddress ) and
310- result = TFieldAddressValueNumber ( irFunc , field , objectAddress )
311- )
312- or
313- exists ( Opcode opcode , IRType type , ValueNumber leftOperand , ValueNumber rightOperand |
314- binaryValueNumber ( instr , irFunc , opcode , type , leftOperand , rightOperand ) and
315- result = TBinaryValueNumber ( irFunc , opcode , type , leftOperand , rightOperand )
316- )
317- or
318- exists ( Opcode opcode , IRType type , ValueNumber operand |
319- unaryValueNumber ( instr , irFunc , opcode , type , operand ) and
320- result = TUnaryValueNumber ( irFunc , opcode , type , operand )
321- )
322- or
323- exists (
324- Opcode opcode , Language:: Class baseClass , Language:: Class derivedClass , ValueNumber operand
325- |
326- inheritanceConversionValueNumber ( instr , irFunc , opcode , baseClass , derivedClass , operand ) and
327- result = TInheritanceConversionValueNumber ( irFunc , opcode , baseClass , derivedClass , operand )
328- )
329- or
330- exists (
331- Opcode opcode , IRType type , int elementSize , ValueNumber leftOperand ,
332- ValueNumber rightOperand
333- |
334- pointerArithmeticValueNumber ( instr , irFunc , opcode , type , elementSize , leftOperand ,
335- rightOperand ) and
336- result =
337- TPointerArithmeticValueNumber ( irFunc , opcode , type , elementSize , leftOperand , rightOperand )
338- )
339- or
340- exists ( IRType type , ValueNumber memOperand , ValueNumber operand |
341- loadTotalOverlapValueNumber ( instr , irFunc , type , memOperand , operand ) and
342- result = TLoadTotalOverlapValueNumber ( irFunc , type , memOperand , operand )
343- )
344- or
345- // The value number of a copy is just the value number of its source value.
346- result = valueNumber ( instr .( CongruentCopyInstruction ) .getSourceValue ( ) )
347- )
348- )
349- }
103+ ValueNumber valueNumberOfOperand ( Operand op ) { result = tvalueNumberOfOperand ( op ) }
0 commit comments