forked from OSchip/llvm-project
[BasicAA] Use saturating multiply on range if nsw
If we know that the var * scale multiplication is nsw, we can use a saturating multiplication on the range (as a good approximation of an nsw multiply). This recovers some cases where the fix from D112611 is unnecessarily strict. (This can be further strengthened by using a saturating add, but we currently don't track all the necessary information for that.) This exposes an issue in our NSW tracking for multiplies. The code was assuming that (X +nsw Y) *nsw Z results in (X *nsw Z) +nsw (Y *nsw Z) -- however, it is possible that the distributed multiplications overflow, even if the non-distributed one does not. We should discard the nsw flag if the the offset is non-zero. If we just have (X *nsw Y) *nsw Z then concluding X *nsw (Y *nsw Z) is fine. Differential Revision: https://reviews.llvm.org/D112848
This commit is contained in:
parent
f1d32a521e
commit
51e9f33603
|
@ -360,8 +360,10 @@ struct LinearExpression {
|
||||||
}
|
}
|
||||||
|
|
||||||
LinearExpression mul(const APInt &Other, bool MulIsNSW) const {
|
LinearExpression mul(const APInt &Other, bool MulIsNSW) const {
|
||||||
return LinearExpression(Val, Scale * Other, Offset * Other,
|
// The check for zero offset is necessary, because generally
|
||||||
IsNSW && (Other.isOne() || MulIsNSW));
|
// (X +nsw Y) *nsw Z does not imply (X *nsw Z) +nsw (Y *nsw Z).
|
||||||
|
bool NSW = IsNSW && (Other.isOne() || (MulIsNSW && Offset.isZero()));
|
||||||
|
return LinearExpression(Val, Scale * Other, Offset * Other, NSW);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1249,12 +1251,14 @@ AliasResult BasicAAResult::aliasGEP(
|
||||||
CR = CR.intersectWith(
|
CR = CR.intersectWith(
|
||||||
ConstantRange::fromKnownBits(Known, /* Signed */ true),
|
ConstantRange::fromKnownBits(Known, /* Signed */ true),
|
||||||
ConstantRange::Signed);
|
ConstantRange::Signed);
|
||||||
|
CR = Index.Val.evaluateWith(CR).sextOrTrunc(OffsetRange.getBitWidth());
|
||||||
|
|
||||||
assert(OffsetRange.getBitWidth() == Scale.getBitWidth() &&
|
assert(OffsetRange.getBitWidth() == Scale.getBitWidth() &&
|
||||||
"Bit widths are normalized to MaxPointerSize");
|
"Bit widths are normalized to MaxPointerSize");
|
||||||
OffsetRange = OffsetRange.add(
|
if (Index.IsNSW)
|
||||||
Index.Val.evaluateWith(CR).sextOrTrunc(OffsetRange.getBitWidth())
|
OffsetRange = OffsetRange.add(CR.smul_sat(ConstantRange(Scale)));
|
||||||
.smul_fast(ConstantRange(Scale)));
|
else
|
||||||
|
OffsetRange = OffsetRange.add(CR.smul_fast(ConstantRange(Scale)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We now have accesses at two offsets from the same base:
|
// We now have accesses at two offsets from the same base:
|
||||||
|
|
|
@ -145,12 +145,12 @@ define void @shl_of_non_negative(i8* %ptr, i64 %a) {
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
; TODO: Unlike the previous case, %ptr.neg and %ptr.shl can't alias, because
|
; Unlike the previous case, %ptr.neg and %ptr.shl can't alias, because
|
||||||
; shl nsw of non-negative is non-negative.
|
; shl nsw of non-negative is non-negative.
|
||||||
define void @shl_nsw_of_non_negative(i8* %ptr, i64 %a) {
|
define void @shl_nsw_of_non_negative(i8* %ptr, i64 %a) {
|
||||||
; CHECK-LABEL: Function: shl_nsw_of_non_negative
|
; CHECK-LABEL: Function: shl_nsw_of_non_negative
|
||||||
; CHECK: NoAlias: i8* %ptr.a, i8* %ptr.neg
|
; CHECK: NoAlias: i8* %ptr.a, i8* %ptr.neg
|
||||||
; CHECK: MayAlias: i8* %ptr.neg, i8* %ptr.shl
|
; CHECK: NoAlias: i8* %ptr.neg, i8* %ptr.shl
|
||||||
%a.cmp = icmp sge i64 %a, 0
|
%a.cmp = icmp sge i64 %a, 0
|
||||||
call void @llvm.assume(i1 %a.cmp)
|
call void @llvm.assume(i1 %a.cmp)
|
||||||
%ptr.neg = getelementptr i8, i8* %ptr, i64 -2
|
%ptr.neg = getelementptr i8, i8* %ptr, i64 -2
|
||||||
|
|
Loading…
Reference in New Issue