@@ -15,6 +15,43 @@ private class OldInstruction = Reachability::ReachableInstruction;
15
15
16
16
import Cached
17
17
18
+ /**
19
+ * Holds if `instruction` is the first instruction that may be followed by
20
+ * an `InitializeGroup` instruction, and the enclosing function of
21
+ * `instruction` is `func`.
22
+ */
23
+ private predicate isFirstInstructionBeforeInitializeGroup ( Instruction instruction , IRFunction func ) {
24
+ instruction = getChi ( any ( OldIR:: InitializeNonLocalInstruction init ) ) and
25
+ func = instruction .getEnclosingIRFunction ( )
26
+ }
27
+
28
+ /** Gets the `i`'th `InitializeGroup` instruction in `func`. */
29
+ private InitializeGroupInstruction getInitGroupInstruction ( int i , IRFunction func ) {
30
+ exists ( Alias:: VariableGroup vg |
31
+ vg .getIRFunction ( ) = func and
32
+ vg .getInitializationOrder ( ) = i and
33
+ result = initializeGroup ( vg )
34
+ )
35
+ }
36
+
37
+ /**
38
+ * Holds if `instruction` is the last instruction in the chain of `InitializeGroup`
39
+ * instructions in `func`. The chain of instructions may be empty in which case
40
+ * `instruction` satisfies
41
+ * ```
42
+ * isFirstInstructionBeforeInitializeGroup(instruction, func)
43
+ * ```
44
+ */
45
+ predicate isLastInstructionForInitializeGroups ( Instruction instruction , IRFunction func ) {
46
+ exists ( int i |
47
+ instruction = getInitGroupInstruction ( i , func ) and
48
+ not exists ( getInitGroupInstruction ( i + 1 , func ) )
49
+ )
50
+ or
51
+ isFirstInstructionBeforeInitializeGroup ( instruction , func ) and
52
+ not exists ( getInitGroupInstruction ( 0 , func ) )
53
+ }
54
+
18
55
cached
19
56
private module Cached {
20
57
cached
@@ -45,7 +82,8 @@ private module Cached {
45
82
}
46
83
47
84
class TStageInstruction =
48
- TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction ;
85
+ TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction or
86
+ TInitializeGroupInstruction ;
49
87
50
88
/**
51
89
* If `oldInstruction` is a `Phi` instruction that has exactly one reachable predecessor block,
@@ -78,6 +116,8 @@ private module Cached {
78
116
or
79
117
instr instanceof TChiInstruction
80
118
or
119
+ instr instanceof TInitializeGroupInstruction
120
+ or
81
121
instr instanceof TUnreachedInstruction
82
122
}
83
123
@@ -123,7 +163,8 @@ private module Cached {
123
163
predicate hasModeledMemoryResult ( Instruction instruction ) {
124
164
canModelResultForOldInstruction ( getOldInstruction ( instruction ) ) or
125
165
instruction instanceof PhiInstruction or // Phis always have modeled results
126
- instruction instanceof ChiInstruction // Chis always have modeled results
166
+ instruction instanceof ChiInstruction or // Chis always have modeled results
167
+ instruction instanceof InitializeGroupInstruction // Group initializers always have modeled results
127
168
}
128
169
129
170
cached
@@ -143,7 +184,7 @@ private module Cached {
143
184
// conflated if it's associated with a conflated location.
144
185
exists ( Alias:: MemoryLocation location |
145
186
instruction = getPhi ( _, location ) and
146
- not exists ( location .getAllocation ( ) )
187
+ not exists ( location .getAnAllocation ( ) )
147
188
)
148
189
}
149
190
@@ -264,7 +305,12 @@ private module Cached {
264
305
}
265
306
266
307
cached
267
- IRVariable getAnInitializeGroupVariable ( InitializeGroupInstruction instr ) { none ( ) }
308
+ IRVariable getAnInitializeGroupVariable ( InitializeGroupInstruction init ) {
309
+ exists ( Alias:: VariableGroup vg |
310
+ init = initializeGroup ( vg ) and
311
+ result = vg .getAnAllocation ( ) .getABaseInstruction ( ) .( VariableInstruction ) .getIRVariable ( )
312
+ )
313
+ }
268
314
269
315
/**
270
316
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
@@ -347,14 +393,28 @@ private module Cached {
347
393
)
348
394
}
349
395
350
- /*
351
- * This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
352
- * that node is its successor in the new successor relation, and the Chi node's successors are
353
- * the new instructions generated from the successors of the old instruction
354
- */
396
+ private InitializeGroupInstruction firstInstructionToInitializeGroup (
397
+ Instruction instruction , EdgeKind kind
398
+ ) {
399
+ exists ( IRFunction func |
400
+ isFirstInstructionBeforeInitializeGroup ( instruction , func ) and
401
+ result = getInitGroupInstruction ( 0 , func ) and
402
+ kind instanceof GotoEdge
403
+ )
404
+ }
355
405
356
- cached
357
- Instruction getInstructionSuccessor ( Instruction instruction , EdgeKind kind ) {
406
+ private Instruction getNextInitializeGroupInstruction ( Instruction instruction , EdgeKind kind ) {
407
+ exists ( int i , IRFunction func |
408
+ func = instruction .getEnclosingIRFunction ( ) and
409
+ instruction = getInitGroupInstruction ( i , func ) and
410
+ result = getInitGroupInstruction ( i + 1 , func ) and
411
+ kind instanceof GotoEdge
412
+ )
413
+ }
414
+
415
+ private Instruction getInstructionSuccessorAfterInitializeGroup0 (
416
+ Instruction instruction , EdgeKind kind
417
+ ) {
358
418
if hasChiNode ( _, getOldInstruction ( instruction ) )
359
419
then
360
420
result = getChi ( getOldInstruction ( instruction ) ) and
@@ -374,6 +434,35 @@ private module Cached {
374
434
)
375
435
}
376
436
437
+ private Instruction getInstructionSuccessorAfterInitializeGroup (
438
+ Instruction instruction , EdgeKind kind
439
+ ) {
440
+ exists ( IRFunction func , Instruction firstBeforeInitializeGroup |
441
+ isLastInstructionForInitializeGroups ( instruction , func ) and
442
+ isFirstInstructionBeforeInitializeGroup ( firstBeforeInitializeGroup , func ) and
443
+ result = getInstructionSuccessorAfterInitializeGroup0 ( firstBeforeInitializeGroup , kind )
444
+ )
445
+ }
446
+
447
+ /**
448
+ * This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
449
+ * that node is its successor in the new successor relation, and the Chi node's successors are
450
+ * the new instructions generated from the successors of the old instruction.
451
+ *
452
+ * Furthermore, the entry block is augmented with `InitializeGroup` instructions.
453
+ */
454
+ cached
455
+ Instruction getInstructionSuccessor ( Instruction instruction , EdgeKind kind ) {
456
+ result = firstInstructionToInitializeGroup ( instruction , kind )
457
+ or
458
+ result = getNextInitializeGroupInstruction ( instruction , kind )
459
+ or
460
+ result = getInstructionSuccessorAfterInitializeGroup ( instruction , kind )
461
+ or
462
+ not isFirstInstructionBeforeInitializeGroup ( instruction , _) and
463
+ result = getInstructionSuccessorAfterInitializeGroup0 ( instruction , kind )
464
+ }
465
+
377
466
cached
378
467
Instruction getInstructionBackEdgeSuccessor ( Instruction instruction , EdgeKind kind ) {
379
468
exists ( OldInstruction oldInstruction |
@@ -409,6 +498,11 @@ private module Cached {
409
498
exists ( IRFunctionBase irFunc |
410
499
instr = unreachedInstruction ( irFunc ) and result = irFunc .getFunction ( )
411
500
)
501
+ or
502
+ exists ( Alias:: VariableGroup vg |
503
+ instr = initializeGroup ( vg ) and
504
+ result = vg .getIRFunction ( ) .getFunction ( )
505
+ )
412
506
}
413
507
414
508
cached
@@ -426,6 +520,11 @@ private module Cached {
426
520
result = vvar .getType ( )
427
521
)
428
522
or
523
+ exists ( Alias:: VariableGroup vg |
524
+ instr = initializeGroup ( vg ) and
525
+ result = vg .getType ( )
526
+ )
527
+ or
429
528
instr = reusedPhiInstruction ( _) and
430
529
result = instr .( OldInstruction ) .getResultLanguageType ( )
431
530
or
@@ -451,6 +550,8 @@ private module Cached {
451
550
or
452
551
instr = chiInstruction ( _) and opcode instanceof Opcode:: Chi
453
552
or
553
+ instr = initializeGroup ( _) and opcode instanceof Opcode:: InitializeGroup
554
+ or
454
555
instr = unreachedInstruction ( _) and opcode instanceof Opcode:: Unreached
455
556
}
456
557
@@ -467,6 +568,11 @@ private module Cached {
467
568
instr = chiInstruction ( primaryInstr ) and result = primaryInstr .getEnclosingIRFunction ( )
468
569
)
469
570
or
571
+ exists ( Alias:: VariableGroup vg |
572
+ instr = initializeGroup ( vg ) and
573
+ result = vg .getIRFunction ( )
574
+ )
575
+ or
470
576
instr = unreachedInstruction ( result )
471
577
}
472
578
@@ -671,19 +777,30 @@ private import DefUse
671
777
* potentially very sparse.
672
778
*/
673
779
module DefUse {
780
+ bindingset [ index, block]
781
+ pragma [ inline_late]
782
+ private int getNonChiOffset ( int index , OldBlock block ) {
783
+ exists ( IRFunction func | func = block .getEnclosingIRFunction ( ) |
784
+ if getNewBlock ( block ) = func .getEntryBlock ( )
785
+ then result = 2 * ( index + count ( VariableGroup vg | vg .getIRFunction ( ) = func ) )
786
+ else result = 2 * index
787
+ )
788
+ }
789
+
790
+ bindingset [ index, block]
791
+ pragma [ inline_late]
792
+ private int getChiOffset ( int index , OldBlock block ) { result = getNonChiOffset ( index , block ) + 1 }
793
+
674
794
/**
675
795
* Gets the `Instruction` for the definition at offset `defOffset` in block `defBlock`.
676
796
*/
677
797
Instruction getDefinitionOrChiInstruction (
678
798
OldBlock defBlock , int defOffset , Alias:: MemoryLocation defLocation ,
679
799
Alias:: MemoryLocation actualDefLocation
680
800
) {
681
- exists ( OldInstruction oldInstr , int oldOffset |
682
- oldInstr = defBlock .getInstruction ( oldOffset ) and
683
- oldOffset >= 0
684
- |
801
+ exists ( OldInstruction oldInstr , int oldOffset | oldInstr = defBlock .getInstruction ( oldOffset ) |
685
802
// An odd offset corresponds to the `Chi` instruction.
686
- defOffset = oldOffset * 2 + 1 and
803
+ defOffset = getChiOffset ( oldOffset , defBlock ) and
687
804
result = getChi ( oldInstr ) and
688
805
(
689
806
defLocation = Alias:: getResultMemoryLocation ( oldInstr ) or
@@ -692,7 +809,7 @@ module DefUse {
692
809
actualDefLocation = defLocation .getVirtualVariable ( )
693
810
or
694
811
// An even offset corresponds to the original instruction.
695
- defOffset = oldOffset * 2 and
812
+ defOffset = getNonChiOffset ( oldOffset , defBlock ) and
696
813
result = getNewInstruction ( oldInstr ) and
697
814
(
698
815
defLocation = Alias:: getResultMemoryLocation ( oldInstr ) or
@@ -705,6 +822,26 @@ module DefUse {
705
822
hasDefinition ( _, defLocation , defBlock , defOffset ) and
706
823
result = getPhi ( defBlock , defLocation ) and
707
824
actualDefLocation = defLocation
825
+ or
826
+ exists (
827
+ Alias:: VariableGroup vg , int index , InitializeGroupInstruction initGroup ,
828
+ Alias:: GroupedMemoryLocation gml
829
+ |
830
+ // Add 3 to account for the function prologue:
831
+ // v1(void) = EnterFunction
832
+ // m1(unknown) = AliasedDefinition
833
+ // m2(unknown) = InitializeNonLocal
834
+ index = 3 + vg .getInitializationOrder ( ) and
835
+ not gml .isMayAccess ( ) and
836
+ gml .isSome ( ) and
837
+ gml .getGroup ( ) = vg and
838
+ vg .getIRFunction ( ) .getEntryBlock ( ) = defBlock and
839
+ initGroup = initializeGroup ( vg ) and
840
+ ( defLocation = gml or defLocation = gml .getVirtualVariable ( ) ) and
841
+ result = initGroup and
842
+ defOffset = 2 * index and
843
+ actualDefLocation = defLocation
844
+ )
708
845
}
709
846
710
847
/**
@@ -845,8 +982,18 @@ module DefUse {
845
982
block .getInstruction ( index ) = def and
846
983
overlap = Alias:: getOverlap ( defLocation , useLocation ) and
847
984
if overlap instanceof MayPartiallyOverlap
848
- then offset = ( index * 2 ) + 1 // The use will be connected to the definition on the `Chi` instruction.
849
- else offset = index * 2 // The use will be connected to the definition on the original instruction.
985
+ then offset = getChiOffset ( index , block ) // The use will be connected to the definition on the `Chi` instruction.
986
+ else offset = getNonChiOffset ( index , block ) // The use will be connected to the definition on the original instruction.
987
+ )
988
+ or
989
+ exists ( InitializeGroupInstruction initGroup , int index , VariableGroup vg |
990
+ initGroup .getEnclosingIRFunction ( ) .getEntryBlock ( ) = getNewBlock ( block ) and
991
+ vg = defLocation .( Alias:: GroupedMemoryLocation ) .getGroup ( ) and
992
+ // EnterFunction + AliasedDefinition + InitializeNonLocal + index
993
+ index = 3 + vg .getInitializationOrder ( ) and
994
+ initGroup = initializeGroup ( vg ) and
995
+ exists ( Alias:: getOverlap ( defLocation , useLocation ) ) and
996
+ offset = 2 * index
850
997
)
851
998
}
852
999
@@ -907,10 +1054,11 @@ module DefUse {
907
1054
block .getInstruction ( index ) = use and
908
1055
(
909
1056
// A direct use of the location.
910
- useLocation = Alias:: getOperandMemoryLocation ( use .getAnOperand ( ) ) and offset = index * 2
1057
+ useLocation = Alias:: getOperandMemoryLocation ( use .getAnOperand ( ) ) and
1058
+ offset = getNonChiOffset ( index , block )
911
1059
or
912
1060
// A `Chi` instruction will include a use of the virtual variable.
913
- hasChiNode ( useLocation , use ) and offset = ( index * 2 ) + 1
1061
+ hasChiNode ( useLocation , use ) and offset = getChiOffset ( index , block )
914
1062
)
915
1063
)
916
1064
}
@@ -1061,4 +1209,6 @@ module Ssa {
1061
1209
predicate hasChiInstruction = Cached:: hasChiInstructionCached / 1 ;
1062
1210
1063
1211
predicate hasUnreachedInstruction = Cached:: hasUnreachedInstructionCached / 1 ;
1212
+
1213
+ class VariableGroup = Alias:: VariableGroup ;
1064
1214
}
0 commit comments