Index: llvm/include/llvm/Analysis/Utils/Local.h =================================================================== --- llvm/include/llvm/Analysis/Utils/Local.h +++ llvm/include/llvm/Analysis/Utils/Local.h @@ -27,7 +27,7 @@ /// overflowing is made. template Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP, - bool NoAssumptions = false) { + bool NoAssumptions = false, bool IsNonNegative = false) { GEPOperator *GEPOp = cast(GEP); Type *IntIdxTy = DL.getIndexType(GEP->getType()); Value *Result = Constant::getNullValue(IntIdxTy); @@ -35,6 +35,11 @@ // If the GEP is inbounds, we know that none of the addressing operations will // overflow in a signed sense. bool isInBounds = GEPOp->isInBounds() && !NoAssumptions; + // If we additionally know that the result is non-negative, then operations + // also don't overflow in an unsigned sense. Just IsNonNegative is not + // sufficient here, as we may still overflow while yielding a non-negative + // final result. + bool isNUW = IsNonNegative && isInBounds; // Build a mask for high order bits. unsigned IntPtrWidth = IntIdxTy->getScalarType()->getIntegerBitWidth(); @@ -68,7 +73,7 @@ Constant *Scale = ConstantInt::get(IntIdxTy, Size); Constant *OC = ConstantExpr::getIntegerCast(OpC, IntIdxTy, true /*SExt*/); Scale = - ConstantExpr::getMul(OC, Scale, false /*NUW*/, isInBounds /*NSW*/); + ConstantExpr::getMul(OC, Scale, isNUW /*NUW*/, isInBounds /*NSW*/); // Emit an add instruction. Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs"); continue; @@ -84,7 +89,7 @@ if (Size != 1) { // We'll let instcombine(mul) convert this to a shl if possible. Op = Builder->CreateMul(Op, ConstantInt::get(IntIdxTy, Size), - GEP->getName() + ".idx", false /*NUW*/, + GEP->getName() + ".idx", isNUW /*NUW*/, isInBounds /*NSW*/); } Index: llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1585,7 +1585,7 @@ /// &A[10] - &A[0]: we should compile this to "10". LHS/RHS are the pointer /// operands to the ptrtoint instructions for the LHS/RHS of the subtract. Value *InstCombiner::OptimizePointerDifference(Value *LHS, Value *RHS, - Type *Ty) { + Type *Ty, bool IsNUW) { // If LHS is a gep based on RHS or RHS is a gep based on LHS, we can optimize // this. bool Swapped = false; @@ -1651,7 +1651,8 @@ } // Emit the offset of the GEP and an intptr_t. - Value *Result = EmitGEPOffset(GEP1); + bool IsNonNegative = IsNUW && !GEP2 && !Swapped; + Value *Result = EmitGEPOffset(GEP1, IsNonNegative); // If we had a constant expression GEP on the other side offsetting the // pointer, subtract it from the offset we have. @@ -1983,13 +1984,15 @@ Value *LHSOp, *RHSOp; if (match(Op0, m_PtrToInt(m_Value(LHSOp))) && match(Op1, m_PtrToInt(m_Value(RHSOp)))) - if (Value *Res = OptimizePointerDifference(LHSOp, RHSOp, I.getType())) + if (Value *Res = OptimizePointerDifference(LHSOp, RHSOp, I.getType(), + I.hasNoUnsignedWrap())) return replaceInstUsesWith(I, Res); // trunc(p)-trunc(q) -> trunc(p-q) if (match(Op0, m_Trunc(m_PtrToInt(m_Value(LHSOp)))) && match(Op1, m_Trunc(m_PtrToInt(m_Value(RHSOp))))) - if (Value *Res = OptimizePointerDifference(LHSOp, RHSOp, I.getType())) + if (Value *Res = OptimizePointerDifference(LHSOp, RHSOp, I.getType(), + /* IsNUW */ false)) return replaceInstUsesWith(I, Res); // Canonicalize a shifty way to code absolute value to the common pattern. Index: llvm/lib/Transforms/InstCombine/InstCombineInternal.h =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineInternal.h +++ llvm/lib/Transforms/InstCombine/InstCombineInternal.h @@ -369,7 +369,8 @@ Instruction *visitFNeg(UnaryOperator &I); Instruction *visitAdd(BinaryOperator &I); Instruction *visitFAdd(BinaryOperator &I); - Value *OptimizePointerDifference(Value *LHS, Value *RHS, Type *Ty); + Value *OptimizePointerDifference( + Value *LHS, Value *RHS, Type *Ty, bool IsNUW); Instruction *visitSub(BinaryOperator &I); Instruction *visitFSub(BinaryOperator &I); Instruction *visitMul(BinaryOperator &I); @@ -594,7 +595,7 @@ } } - Value *EmitGEPOffset(User *GEP); + Value *EmitGEPOffset(User *GEP, bool IsNonNegative = false); Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN); Instruction *foldCastedBitwiseLogic(BinaryOperator &I); Instruction *narrowBinOp(TruncInst &Trunc); Index: llvm/lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstructionCombining.cpp +++ llvm/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -158,8 +158,9 @@ static cl::opt ShouldLowerDbgDeclare("instcombine-lower-dbg-declare", cl::Hidden, cl::init(true)); -Value *InstCombiner::EmitGEPOffset(User *GEP) { - return llvm::EmitGEPOffset(&Builder, DL, GEP); +Value *InstCombiner::EmitGEPOffset(User *GEP, bool IsNonNegative) { + return llvm::EmitGEPOffset(&Builder, DL, GEP, /* NoAssumptions */ false, + IsNonNegative); } /// Return true if it is desirable to convert an integer computation from a Index: llvm/test/Transforms/InstCombine/sub-gep.ll =================================================================== --- llvm/test/Transforms/InstCombine/sub-gep.ll +++ llvm/test/Transforms/InstCombine/sub-gep.ll @@ -16,7 +16,7 @@ define i64 @test_inbounds_nuw([0 x i32]* %base, i64 %idx) { ; CHECK-LABEL: @test_inbounds_nuw( -; CHECK-NEXT: [[P2_IDX:%.*]] = shl nsw i64 [[IDX:%.*]], 2 +; CHECK-NEXT: [[P2_IDX:%.*]] = shl nuw nsw i64 [[IDX:%.*]], 2 ; CHECK-NEXT: ret i64 [[P2_IDX]] ; %p1 = getelementptr inbounds [0 x i32], [0 x i32]* %base, i64 0, i64 0