}
SmallVector<Value *, 4> V1Srcs;
- // For a recursive phi, that recurses through a contant gep, we can perform
- // aliasing calculations using the other phi operands with an unknown size to
- // specify that an unknown number of elements after the initial value are
- // potentially accessed.
+ // If a phi operand recurses back to the phi, we can still determine NoAlias
+ // if we don't alias the underlying objects of the other phi operands, as we
+ // know that the recursive phi needs to be based on them in some way.
bool isRecursive = false;
auto CheckForRecPhi = [&](Value *PV) {
if (!EnableRecPhiAnalysis)
return false;
- if (GEPOperator *PVGEP = dyn_cast<GEPOperator>(PV)) {
- // Check whether the incoming value is a GEP that advances the pointer
- // result of this PHI node (e.g. in a loop). If this is the case, we
- // would recurse and always get a MayAlias. Handle this case specially
- // below. We need to ensure that the phi is inbounds and has a constant
- // positive operand so that we can check for alias with the initial value
- // and an unknown but positive size.
- if (PVGEP->getPointerOperand() == PN && PVGEP->isInBounds() &&
- PVGEP->getNumIndices() == 1 && isa<ConstantInt>(PVGEP->idx_begin()) &&
- !cast<ConstantInt>(PVGEP->idx_begin())->isNegative()) {
- isRecursive = true;
- return true;
- }
+ if (getUnderlyingObject(PV) == PN) {
+ isRecursive = true;
+ return true;
}
return false;
};
if (V1Srcs.empty())
return MayAlias;
- // If this PHI node is recursive, set the size of the accessed memory to
- // unknown to represent all the possible values the GEP could advance the
- // pointer to.
+ // If this PHI node is recursive, indicate that the pointer may be moved
+ // across iterations. We can only prove NoAlias if different underlying
+ // objects are involved.
if (isRecursive)
- // TODO: We are checking above that the addrec GEP has a positive offset
- // and can thus assume that all accesses happen after the base pointer.
- // It might be better to drop the offset requirement and use
- // beforeOrAfterPointer().
- PNSize = LocationSize::afterPointer();
+ PNSize = LocationSize::beforeOrAfterPointer();
// In the recursive alias queries below, we may compare values from two
// different loop iterations. Keep track of visited phi blocks, which will
; CHECK: NoAlias: [3 x i16]* %int_arr.10, i16** %argv.6.par
; CHECK: NoAlias: i16* %_tmp1, i16** %argv.6.par
; CHECK: PartialAlias: [3 x i16]* %int_arr.10, i16* %_tmp1
-; CHECK: MayAlias: i16* %ls1.9.0, i16** %argv.6.par
+; CHECK: NoAlias: i16* %ls1.9.0, i16** %argv.6.par
; CHECK: MayAlias: [3 x i16]* %int_arr.10, i16* %ls1.9.0
; CHECK: MayAlias: i16* %_tmp1, i16* %ls1.9.0
-; CHECK: MayAlias: i16* %_tmp7, i16** %argv.6.par
+; CHECK: NoAlias: i16* %_tmp7, i16** %argv.6.par
; CHECK: MayAlias: [3 x i16]* %int_arr.10, i16* %_tmp7
; CHECK: MayAlias: i16* %_tmp1, i16* %_tmp7
; CHECK: NoAlias: i16* %_tmp7, i16* %ls1.9.0
; CHECK-LABEL: Function: dynamic_offset
; CHECK: NoAlias: i8* %a, i8* %p.base
; CHECK: MayAlias: i8* %p, i8* %p.base
-; CHECK: MayAlias: i8* %a, i8* %p
+; CHECK: NoAlias: i8* %a, i8* %p
; CHECK: MayAlias: i8* %p.base, i8* %p.next
-; CHECK: MayAlias: i8* %a, i8* %p.next
+; CHECK: NoAlias: i8* %a, i8* %p.next
; CHECK: MayAlias: i8* %p, i8* %p.next
define void @dynamic_offset(i1 %c, i8* noalias %p.base) {
entry:
; CHECK-NEXT: @ => This Inner Loop Header: Depth=2
; CHECK-NEXT: vldrw.u32 q4, [r1, q0, uxtw #2]
; CHECK-NEXT: vldrw.u32 q5, [r4, q0, uxtw #2]
+; CHECK-NEXT: vldrw.u32 q3, [sp, #8]
; CHECK-NEXT: adds r1, #8
; CHECK-NEXT: vfma.f32 q5, q4, r5
+; CHECK-NEXT: vfma.f32 q3, q5, q2
; CHECK-NEXT: vstmia r7, {s20, s21}
; CHECK-NEXT: adds r7, #8
-; CHECK-NEXT: vldrw.u32 q3, [sp, #8]
-; CHECK-NEXT: vfma.f32 q3, q5, q2
; CHECK-NEXT: vfma.f32 q3, q4, q1
; CHECK-NEXT: vstrw.32 q3, [r4]
; CHECK-NEXT: le lr, .LBB17_3