@@ -45,6 +45,12 @@ private InitializeGroupInstruction getInitGroupInstruction(int i, IRFunction fun
4545predicate isLastInstructionForInitializeGroups ( Instruction instruction , IRFunction func ) {
4646 exists ( int i |
4747 instruction = getInitGroupInstruction ( i , func ) and
48+ not exists ( getChi ( instruction ) ) and
49+ not exists ( getInitGroupInstruction ( i + 1 , func ) )
50+ )
51+ or
52+ exists ( int i |
53+ instruction = getChi ( getInitGroupInstruction ( i , func ) ) and
4854 not exists ( getInitGroupInstruction ( i + 1 , func ) )
4955 )
5056 or
@@ -69,6 +75,11 @@ private module Cached {
6975 hasChiNode ( _, primaryInstruction )
7076 }
7177
78+ cached
79+ predicate hasChiNodeAfterInitializeGroup ( InitializeGroupInstruction initGroup ) {
80+ hasChiNodeAfterInitializeGroup ( _, initGroup )
81+ }
82+
7283 cached
7384 predicate hasUnreachedInstructionCached ( IRFunction irFunc ) {
7485 exists ( OldIR:: Instruction oldInstruction |
@@ -175,9 +186,18 @@ private module Cached {
175186 or
176187 // Chi instructions track virtual variables, and therefore a chi instruction is
177188 // conflated if it's associated with the aliased virtual variable.
178- exists ( OldInstruction oldInstruction | instruction = getChi ( oldInstruction ) |
179- Alias:: getResultMemoryLocation ( oldInstruction ) .getVirtualVariable ( ) instanceof
189+ exists ( Instruction input | instruction = getChi ( input ) |
190+ instruction = getChi ( input ) and
191+ Alias:: getResultMemoryLocation ( input ) .getVirtualVariable ( ) instanceof
180192 Alias:: AliasedVirtualVariable
193+ or
194+ // A chi following an `InitializeGroupInstruction` only happens when the virtual
195+ // variable of the grouped memory location is `{AllAliasedMemory}`.
196+ exists ( Alias:: GroupedMemoryLocation gml |
197+ instruction = getChi ( input ) and
198+ input = initializeGroup ( gml .getGroup ( ) ) and
199+ gml .getVirtualVariable ( ) instanceof Alias:: AliasedVirtualVariable
200+ )
181201 )
182202 or
183203 // Phi instructions track locations, and therefore a phi instruction is
@@ -246,7 +266,11 @@ private module Cached {
246266 hasMemoryOperandDefinition ( oldInstruction , oldOperand , overlap , result )
247267 )
248268 or
249- instruction = getChi ( getOldInstruction ( result ) ) and
269+ (
270+ instruction = getChi ( getOldInstruction ( result ) )
271+ or
272+ instruction = getChi ( result .( InitializeGroupInstruction ) )
273+ ) and
250274 tag instanceof ChiPartialOperandTag and
251275 overlap instanceof MustExactlyOverlap
252276 or
@@ -365,6 +389,18 @@ private module Cached {
365389 result = getNewPhiOperandDefinitionFromOldSsa ( instr , newPredecessorBlock , overlap )
366390 }
367391
392+ private ChiInstruction getChiAfterInitializeGroup ( int i , IRFunction func ) {
393+ result =
394+ rank [ i + 1 ] ( VariableGroup vg , InitializeGroupInstruction initGroup , ChiInstruction chi , int r |
395+ initGroup .getEnclosingIRFunction ( ) = func and
396+ chi = getChi ( initGroup ) and
397+ initGroup = initializeGroup ( vg ) and
398+ r = vg .getInitializationOrder ( )
399+ |
400+ chi order by r
401+ )
402+ }
403+
368404 cached
369405 Instruction getChiInstructionTotalOperand ( ChiInstruction chiInstr ) {
370406 exists (
@@ -378,6 +414,19 @@ private module Cached {
378414 definitionReachesUse ( vvar , defBlock , defRank , useBlock , useRank ) and
379415 result = getDefinitionOrChiInstruction ( defBlock , defOffset , vvar , _)
380416 )
417+ or
418+ exists ( InitializeGroupInstruction initGroup , IRFunction func |
419+ chiInstr = getChi ( initGroup ) and
420+ func = initGroup .getEnclosingIRFunction ( )
421+ |
422+ chiInstr = getChiAfterInitializeGroup ( 0 , func ) and
423+ isFirstInstructionBeforeInitializeGroup ( result , func )
424+ or
425+ exists ( int i |
426+ chiInstr = getChiAfterInitializeGroup ( i + 1 , func ) and
427+ result = getChiAfterInitializeGroup ( i , func )
428+ )
429+ )
381430 }
382431
383432 cached
@@ -407,8 +456,20 @@ private module Cached {
407456 exists ( int i , IRFunction func |
408457 func = instruction .getEnclosingIRFunction ( ) and
409458 instruction = getInitGroupInstruction ( i , func ) and
410- result = getInitGroupInstruction ( i + 1 , func ) and
411459 kind instanceof GotoEdge
460+ |
461+ if hasChiNodeAfterInitializeGroup ( _, instruction )
462+ then result = getChi ( instruction )
463+ else result = getInitGroupInstruction ( i + 1 , func )
464+ )
465+ or
466+ exists ( int i , IRFunction func , InitializeGroupInstruction initGroup |
467+ func = instruction .getEnclosingIRFunction ( ) and
468+ instruction = getChi ( initGroup ) and
469+ initGroup = getInitGroupInstruction ( i , func ) and
470+ kind instanceof GotoEdge
471+ |
472+ result = getInitGroupInstruction ( i + 1 , func )
412473 )
413474 }
414475
@@ -503,6 +564,11 @@ private module Cached {
503564 instr = initializeGroup ( vg ) and
504565 result = vg .getIRFunction ( ) .getFunction ( )
505566 )
567+ or
568+ exists ( InitializeGroupInstruction initGroup |
569+ instr = chiInstruction ( initGroup ) and
570+ result = getInstructionAst ( initGroup )
571+ )
506572 }
507573
508574 cached
@@ -515,9 +581,11 @@ private module Cached {
515581 )
516582 or
517583 exists ( Instruction primaryInstr , Alias:: VirtualVariable vvar |
518- instr = chiInstruction ( primaryInstr ) and
519- hasChiNode ( vvar , primaryInstr ) and
520- result = vvar .getType ( )
584+ instr = chiInstruction ( primaryInstr ) and result = vvar .getType ( )
585+ |
586+ hasChiNode ( vvar , primaryInstr )
587+ or
588+ hasChiNodeAfterInitializeGroup ( vvar , primaryInstr )
521589 )
522590 or
523591 exists ( Alias:: VariableGroup vg |
@@ -564,7 +632,7 @@ private module Cached {
564632 result = blockStartInstr .getEnclosingIRFunction ( )
565633 )
566634 or
567- exists ( OldInstruction primaryInstr |
635+ exists ( Instruction primaryInstr |
568636 instr = chiInstruction ( primaryInstr ) and result = primaryInstr .getEnclosingIRFunction ( )
569637 )
570638 or
@@ -587,14 +655,16 @@ private module Cached {
587655 instruction = getChi ( oldInstruction ) and
588656 result = getNewInstruction ( oldInstruction )
589657 )
658+ or
659+ instruction = getChi ( result .( InitializeGroupInstruction ) )
590660 }
591661}
592662
593663private Instruction getNewInstruction ( OldInstruction instr ) { getOldInstruction ( result ) = instr }
594664
595665private OldInstruction getOldInstruction ( Instruction instr ) { instr = result }
596666
597- private ChiInstruction getChi ( OldInstruction primaryInstr ) { result = chiInstruction ( primaryInstr ) }
667+ private ChiInstruction getChi ( Instruction primaryInstr ) { result = chiInstruction ( primaryInstr ) }
598668
599669private PhiInstruction getPhi ( OldBlock defBlock , Alias:: MemoryLocation defLocation ) {
600670 result = phiInstruction ( defBlock .getFirstInstruction ( ) , defLocation )
@@ -615,6 +685,16 @@ private predicate hasChiNode(Alias::VirtualVariable vvar, OldInstruction def) {
615685 )
616686}
617687
688+ private predicate hasChiNodeAfterInitializeGroup (
689+ Alias:: AliasedVirtualVariable vvar , InitializeGroupInstruction initGroup
690+ ) {
691+ exists ( Alias:: GroupedMemoryLocation defLocation |
692+ initGroup = initializeGroup ( defLocation .getGroup ( ) ) and
693+ defLocation .getVirtualVariable ( ) = vvar and
694+ Alias:: getOverlap ( defLocation , vvar ) instanceof MayPartiallyOverlap
695+ )
696+ }
697+
618698private import PhiInsertion
619699
620700/**
@@ -781,7 +861,10 @@ module DefUse {
781861 pragma [ inline_late]
782862 private int getNonChiOffset ( int index , OldBlock block ) {
783863 exists ( IRFunction func | func = block .getEnclosingIRFunction ( ) |
784- if getNewBlock ( block ) = func .getEntryBlock ( )
864+ if
865+ getNewBlock ( block ) = func .getEntryBlock ( ) and
866+ not block .getInstruction ( index ) instanceof InitializeNonLocalInstruction and
867+ not block .getInstruction ( index ) instanceof AliasedDefinitionInstruction
785868 then result = 2 * ( index + count ( VariableGroup vg | vg .getIRFunction ( ) = func ) )
786869 else result = 2 * index
787870 )
@@ -794,7 +877,7 @@ module DefUse {
794877 /**
795878 * Gets the `Instruction` for the definition at offset `defOffset` in block `defBlock`.
796879 */
797- Instruction getDefinitionOrChiInstruction (
880+ private Instruction getDefinitionOrChiInstruction0 (
798881 OldBlock defBlock , int defOffset , Alias:: MemoryLocation defLocation ,
799882 Alias:: MemoryLocation actualDefLocation
800883 ) {
@@ -837,10 +920,38 @@ module DefUse {
837920 gml .getGroup ( ) = vg and
838921 vg .getIRFunction ( ) .getEntryBlock ( ) = defBlock and
839922 initGroup = initializeGroup ( vg ) and
840- ( defLocation = gml or defLocation = gml .getVirtualVariable ( ) ) and
923+ ( defLocation = gml or defLocation = gml .getVirtualVariable ( ) )
924+ |
841925 result = initGroup and
842926 defOffset = 2 * index and
843927 actualDefLocation = defLocation
928+ or
929+ result = getChi ( initGroup ) and
930+ defOffset = 2 * index + 1 and
931+ actualDefLocation = defLocation .getVirtualVariable ( )
932+ )
933+ }
934+
935+ private ChiInstruction remapGetDefinitionOrChiInstruction ( Instruction oldResult ) {
936+ exists ( IRFunction func |
937+ isFirstInstructionBeforeInitializeGroup ( oldResult , func ) and
938+ isLastInstructionForInitializeGroups ( result , func )
939+ )
940+ }
941+
942+ Instruction getDefinitionOrChiInstruction (
943+ OldBlock defBlock , int defOffset , Alias:: MemoryLocation defLocation ,
944+ Alias:: MemoryLocation actualDefLocation
945+ ) {
946+ exists ( Instruction oldResult |
947+ oldResult =
948+ getDefinitionOrChiInstruction0 ( defBlock , defOffset , defLocation , actualDefLocation ) and
949+ (
950+ result = remapGetDefinitionOrChiInstruction ( oldResult )
951+ or
952+ not exists ( remapGetDefinitionOrChiInstruction ( oldResult ) ) and
953+ result = oldResult
954+ )
844955 )
845956 }
846957
@@ -986,14 +1097,16 @@ module DefUse {
9861097 else offset = getNonChiOffset ( index , block ) // The use will be connected to the definition on the original instruction.
9871098 )
9881099 or
989- exists ( InitializeGroupInstruction initGroup , int index , VariableGroup vg |
1100+ exists ( InitializeGroupInstruction initGroup , int index , Overlap overlap , VariableGroup vg |
9901101 initGroup .getEnclosingIRFunction ( ) .getEntryBlock ( ) = getNewBlock ( block ) and
9911102 vg = defLocation .( Alias:: GroupedMemoryLocation ) .getGroup ( ) and
9921103 // EnterFunction + AliasedDefinition + InitializeNonLocal + index
9931104 index = 3 + vg .getInitializationOrder ( ) and
9941105 initGroup = initializeGroup ( vg ) and
995- exists ( Alias:: getOverlap ( defLocation , useLocation ) ) and
996- offset = 2 * index
1106+ overlap = Alias:: getOverlap ( defLocation , useLocation ) and
1107+ if overlap instanceof MayPartiallyOverlap and hasChiNodeAfterInitializeGroup ( initGroup )
1108+ then offset = 2 * index + 1 // The use will be connected to the definition on the `Chi` instruction.
1109+ else offset = 2 * index // The use will be connected to the definition on the original instruction.
9971110 )
9981111 }
9991112
@@ -1208,6 +1321,8 @@ module Ssa {
12081321
12091322 predicate hasChiInstruction = Cached:: hasChiInstructionCached / 1 ;
12101323
1324+ predicate hasChiNodeAfterInitializeGroup = Cached:: hasChiNodeAfterInitializeGroup / 1 ;
1325+
12111326 predicate hasUnreachedInstruction = Cached:: hasUnreachedInstructionCached / 1 ;
12121327
12131328 class VariableGroup = Alias:: VariableGroup ;
0 commit comments