Index: llvm/include/llvm/IR/Operator.h =================================================================== --- llvm/include/llvm/IR/Operator.h +++ llvm/include/llvm/IR/Operator.h @@ -66,6 +66,7 @@ class OverflowingBinaryOperator : public Operator { public: enum { + AnyWrap = 0, NoUnsignedWrap = (1 << 0), NoSignedWrap = (1 << 1) }; Index: llvm/lib/Analysis/ScalarEvolution.cpp =================================================================== --- llvm/lib/Analysis/ScalarEvolution.cpp +++ llvm/lib/Analysis/ScalarEvolution.cpp @@ -5560,6 +5560,7 @@ unsigned BitWidth = getTypeSizeInBits(S->getType()); ConstantRange ConservativeResult(BitWidth, /*isFullSet=*/true); + using OBO = OverflowingBinaryOperator; // If the value has known zeros, the maximum value will have those known zeros // as well. @@ -5577,8 +5578,14 @@ if (const SCEVAddExpr *Add = dyn_cast(S)) { ConstantRange X = getRangeRef(Add->getOperand(0), SignHint); - for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i) - X = X.add(getRangeRef(Add->getOperand(i), SignHint)); + unsigned WrapType = OBO::AnyWrap; + if (Add->hasNoSignedWrap()) + WrapType |= OBO::NoSignedWrap; + if (Add->hasNoUnsignedWrap()) + WrapType |= OBO::NoUnsignedWrap; + for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i) + X = X.addWithNoWrap(getRangeRef(Add->getOperand(i), SignHint), + WrapType, RangeType); return setRange(Add, SignHint, ConservativeResult.intersectWith(X, RangeType)); } Index: llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll =================================================================== --- llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll +++ llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll @@ -2,7 +2,7 @@ ; copied from flags-from-poison.ll ; CHECK-LABEL: @test-add-nuw -; CHECK: --> {(1 + %offset),+,1}<%loop> U: full-set S: full-set +; CHECK: --> {(1 + %offset),+,1}<%loop> U: [1,0) S: [1,0) define void @test-add-nuw(float* %input, i32 %offset, i32 %numIterations) { entry: br label %loop Index: llvm/test/Transforms/IRCE/ranges_of_different_types.ll =================================================================== --- llvm/test/Transforms/IRCE/ranges_of_different_types.ll +++ llvm/test/Transforms/IRCE/ranges_of_different_types.ll @@ -84,9 +84,7 @@ ; CHECK-NEXT: [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[LEN_MINUS_SMAX]], i32 -13 ; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 %len, [[SMAX1]] ; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp slt i32 [[SUB1]], 101 -; CHECK-NEXT: [[SMAX2:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB1]], i32 101 -; CHECK-NEXT: [[CMP3:%[^ ]+]] = icmp sgt i32 [[SMAX2]], 0 -; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP3]], i32 [[SMAX2]], i32 0 +; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP2]], i32 [[SUB1]], i32 101 ; CHECK-NEXT: br i1 true, label %loop.preloop.preheader ; CHECK: loop.preloop: ; CHECK-NEXT: %idx.preloop = phi i32 [ %idx.next.preloop, %in.bounds.preloop ], [ 0, %loop.preloop.preheader ] @@ -291,9 +289,7 @@ ; CHECK-NEXT: [[SMAX1:%[^ ]+]] = select i1 [[CMP1]], i32 [[LEN_MINUS_SMAX]], i32 -13 ; CHECK-NEXT: [[SUB1:%[^ ]+]] = sub i32 %len, [[SMAX1]] ; CHECK-NEXT: [[CMP2:%[^ ]+]] = icmp slt i32 [[SUB1]], 101 -; CHECK-NEXT: [[SMAX2:%[^ ]+]] = select i1 [[CMP2]], i32 [[SUB1]], i32 101 -; CHECK-NEXT: [[CMP3:%[^ ]+]] = icmp sgt i32 [[SMAX2]], 0 -; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP3]], i32 [[SMAX2]], i32 0 +; CHECK-NEXT: %exit.mainloop.at = select i1 [[CMP2]], i32 [[SUB1]], i32 101 ; CHECK-NEXT: br i1 true, label %loop.preloop.preheader ; CHECK: in.bounds.preloop: ; CHECK-NEXT: %addr.preloop = getelementptr i32, i32* %arr, i32 %idx.preloop