Skip to content

Commit ed2318f

Browse files
eecksteinatrick
authored andcommitted
AliasAnalysis: better handling of init_enum_data_addr and init_existential_addr.
Look "through" those instructions when trying to find the underlying objects. (cherry picked from commit c7c2c13)
1 parent 9e57fbf commit ed2318f

File tree

2 files changed

+109
-3
lines changed

2 files changed

+109
-3
lines changed

lib/SILOptimizer/Analysis/AliasAnalysis.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,15 @@ AliasResult AliasAnalysis::alias(SILValue V1, SILValue V2,
569569
return Result;
570570
}
571571

572+
/// Get the underlying object, looking through init_enum_data_addr and
573+
/// init_existential_addr.
574+
static SILValue stripInitEnumAndExistentialAddr(SILValue v) {
575+
while (isa<InitEnumDataAddrInst>(v) || isa<InitExistentialAddrInst>(v)) {
576+
v = getUnderlyingObject(cast<SingleValueInstruction>(v)->getOperand(0));
577+
}
578+
return v;
579+
}
580+
572581
/// The main AA entry point. Performs various analyses on V1, V2 in an attempt
573582
/// to disambiguate the two values.
574583
AliasResult AliasAnalysis::aliasInner(SILValue V1, SILValue V2,
@@ -614,9 +623,12 @@ AliasResult AliasAnalysis::aliasInner(SILValue V1, SILValue V2,
614623
LLVM_DEBUG(llvm::dbgs() << " Underlying V1:" << *O1);
615624
LLVM_DEBUG(llvm::dbgs() << " Underlying V2:" << *O2);
616625

617-
// If O1 and O2 do not equal, see if we can prove that they cannot be the
618-
// same object. If we can, return No Alias.
619-
if (O1 != O2 && aliasUnequalObjects(O1, O2))
626+
// If the underlying objects are not equal, see if we can prove that they
627+
// cannot be the same object. If we can, return No Alias.
628+
// For this we even look through init_enum_data_addr and init_existential_addr.
629+
SILValue StrippedO1 = stripInitEnumAndExistentialAddr(O1);
630+
SILValue StrippedO2 = stripInitEnumAndExistentialAddr(O2);
631+
if (StrippedO1 != StrippedO2 && aliasUnequalObjects(StrippedO1, StrippedO2))
620632
return AliasResult::NoAlias;
621633

622634
// Ok, either O1, O2 are the same or we could not prove anything based off of

test/SILOptimizer/basic-aa.sil

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,3 +579,97 @@ bb0:
579579
%2 = tuple()
580580
return %2 : $()
581581
}
582+
583+
struct TwoInts {
584+
var a: Int
585+
var b: Int
586+
}
587+
588+
struct StructWithOptional {
589+
var i: Optional<TwoInts>
590+
}
591+
592+
// CHECK-LABEL: @init_enum_data_addr
593+
// CHECK: PAIR #3.
594+
// CHECK-NEXT: %0 = argument of bb0 : $*StructWithOptional
595+
// CHECK-NEXT: %3 = init_enum_data_addr %2 : $*Optional<TwoInts>, #Optional.some!enumelt
596+
// CHECK-NEXT: NoAlias
597+
// CHECK: PAIR #4.
598+
// CHECK-NEXT: %0 = argument of bb0 : $*StructWithOptional
599+
// CHECK-NEXT: %4 = struct_element_addr %3 : $*TwoInts, #TwoInts.a
600+
// CHECK-NEXT: NoAlias
601+
// CHECK: PAIR #5.
602+
// CHECK-NEXT: %0 = argument of bb0 : $*StructWithOptional
603+
// CHECK-NEXT: %5 = struct_element_addr %3 : $*TwoInts, #TwoInts.b
604+
// CHECK-NEXT: NoAlias
605+
// CHECK: PAIR #14.
606+
// CHECK-NEXT: %2 = struct_element_addr %1 : $*StructWithOptional, #StructWithOptional.i
607+
// CHECK-NEXT: %3 = init_enum_data_addr %2 : $*Optional<TwoInts>, #Optional.some!enumelt
608+
// CHECK-NEXT: MayAlias
609+
// CHECK: PAIR #15.
610+
// CHECK-NEXT: %2 = struct_element_addr %1 : $*StructWithOptional, #StructWithOptional.i
611+
// CHECK-NEXT: %4 = struct_element_addr %3 : $*TwoInts, #TwoInts.a
612+
// CHECK-NEXT: MayAlias
613+
// CHECK: PAIR #16.
614+
// CHECK-NEXT: %2 = struct_element_addr %1 : $*StructWithOptional, #StructWithOptional.i
615+
// CHECK-NEXT: %5 = struct_element_addr %3 : $*TwoInts, #TwoInts.b
616+
// CHECK-NEXT: MayAlias
617+
// CHECK: PAIR #19.
618+
// CHECK-NEXT: %3 = init_enum_data_addr %2 : $*Optional<TwoInts>, #Optional.some!enumelt
619+
// CHECK-NEXT: %4 = struct_element_addr %3 : $*TwoInts, #TwoInts.a
620+
// CHECK-NEXT: PartialAlias
621+
// CHECK: PAIR #20.
622+
// CHECK-NEXT: %3 = init_enum_data_addr %2 : $*Optional<TwoInts>, #Optional.some!enumelt
623+
// CHECK-NEXT: %5 = struct_element_addr %3 : $*TwoInts, #TwoInts.b
624+
// CHECK-NEXT: PartialAlias
625+
// CHECK: PAIR #23.
626+
// CHECK-NEXT: %4 = struct_element_addr %3 : $*TwoInts, #TwoInts.a
627+
// CHECK-NEXT: %5 = struct_element_addr %3 : $*TwoInts, #TwoInts.b
628+
// CHECK-NEXT: NoAlias
629+
sil @init_enum_data_addr : $@convention(thin) (@in_guaranteed StructWithOptional) -> () {
630+
bb0(%0 : $*StructWithOptional):
631+
%1 = alloc_stack $StructWithOptional
632+
%2 = struct_element_addr %1 : $*StructWithOptional, #StructWithOptional.i
633+
%3 = init_enum_data_addr %2 : $*Optional<TwoInts>, #Optional.some!enumelt
634+
%4 = struct_element_addr %3 : $*TwoInts, #TwoInts.a
635+
%5 = struct_element_addr %3 : $*TwoInts, #TwoInts.b
636+
dealloc_stack %1 : $*StructWithOptional
637+
%6 = tuple ()
638+
return %6 : $()
639+
}
640+
641+
protocol P {}
642+
643+
struct S : P {
644+
var i: Int
645+
}
646+
647+
// CHECK-LABEL: @init_existential_addr
648+
// CHECK: PAIR #3.
649+
// CHECK-NEXT: %0 = argument of bb0 : $P
650+
// CHECK-NEXT: %3 = init_existential_addr %2 : $*P, $S
651+
// CHECK-NEXT: NoAlias
652+
// CHECK: PAIR #12.
653+
// CHECK-NEXT: %2 = alloc_stack $P
654+
// CHECK-NEXT: %3 = init_existential_addr %2 : $*P, $S
655+
// CHECK-NEXT: MayAlias
656+
// CHECK: PAIR #13.
657+
// CHECK-NEXT: %2 = alloc_stack $P
658+
// CHECK-NEXT: %4 = struct_element_addr %3 : $*S, #S.i
659+
// CHECK-NEXT: MayAlias
660+
// CHECK: PAIR #16.
661+
// CHECK-NEXT: %3 = init_existential_addr %2 : $*P, $S
662+
// CHECK-NEXT: %4 = struct_element_addr %3 : $*S, #S.i
663+
// CHECK-NEXT: PartialAlias
664+
sil @init_existential_addr : $@convention(thin) (P) -> () {
665+
bb0(%0 : $P):
666+
%1 = alloc_stack $S
667+
%2 = alloc_stack $P
668+
%3 = init_existential_addr %2 : $*P, $S
669+
%4 = struct_element_addr %3 : $*S, #S.i
670+
dealloc_stack %2 : $*P
671+
dealloc_stack %1 : $*S
672+
%6 = tuple ()
673+
return %6 : $()
674+
}
675+

0 commit comments

Comments
 (0)