diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -1297,8 +1297,31 @@ const VariableGEPIndex &Var = DecompGEP1.VarIndices[0]; if (Var.Val.TruncBits == 0 && isKnownNonZero(Var.Val.V, DL, 0, &AC, Var.CxtI, DT)) { - // If V != 0 then abs(VarIndex) >= abs(Scale). - MinAbsVarIndex = Var.Scale.abs(); + // If V != 0, then abs(VarIndex) > 0. + MinAbsVarIndex = APInt(Var.Scale.getBitWidth(), 1); + + // Check if abs(V*Scale) >= abs(Scale) holds in the presence of + // potentially wrapping math. + auto MultiplyByScaleNoWrap = [](const VariableGEPIndex &Var) { + if (Var.IsNSW) + return true; + + int ValOrigBW = Var.Val.V->getType()->getPrimitiveSizeInBits(); + // If Scale is small enough so that abs(V*Scale) >= abs(Scale) holds. + // The max value of abs(V) is 2^ValOrigBW - 1. Multiplying with a + // constant smaller than 2^(bitwidth(Val) - ValOrigBW) won't wrap. + int MaxScaleValueBW = Var.Val.getBitWidth() - ValOrigBW; + if (MaxScaleValueBW <= 0) + return false; + return Var.Scale.ule( + APInt::getMaxValue(MaxScaleValueBW).zext(Var.Scale.getBitWidth())); + }; + // Refine MinAbsVarIndex, if abs(Scale*V) >= abs(Scale) holds in the + // presence of potentially wrapping math. + if (MultiplyByScaleNoWrap(Var)) { + // If V != 0 then abs(VarIndex) >= abs(Scale). + MinAbsVarIndex = Var.Scale.abs(); + } } } else if (DecompGEP1.VarIndices.size() == 2) { // VarIndex = Scale*V0 + (-Scale)*V1. diff --git a/llvm/test/Analysis/BasicAA/gep-modulo.ll b/llvm/test/Analysis/BasicAA/gep-modulo.ll --- a/llvm/test/Analysis/BasicAA/gep-modulo.ll +++ b/llvm/test/Analysis/BasicAA/gep-modulo.ll @@ -323,9 +323,9 @@ ; If %v == 10581764700698480926, %idx == 917, so %gep.917 and %gep.idx may alias. define i8 @mul_may_overflow_var_nonzero_minabsvarindex_one_index([2000 x i8]* %arr, i8 %x, i64 %v) { ; CHECK-LABEL: Function: mul_may_overflow_var_nonzero_minabsvarindex_one_index: 4 pointers, 0 call sites -; CHECK-NEXT: NoAlias: [2000 x i8]* %arr, i8* %gep.idx +; CHECK-NEXT: MayAlias: [2000 x i8]* %arr, i8* %gep.idx ; CHECK-NEXT: PartialAlias (off 917): [2000 x i8]* %arr, i8* %gep.917 -; CHECK-NEXT: NoAlias: i8* %gep.917, i8* %gep.idx +; CHECK-NEXT: MayAlias: i8* %gep.917, i8* %gep.idx ; CHECK-NEXT: MustAlias: [2000 x i8]* %arr, i8* %gep.0 ; CHECK-NEXT: NoAlias: i8* %gep.0, i8* %gep.idx ; CHECK-NEXT: NoAlias: i8* %gep.0, i8* %gep.917