llvm_unreachable("Unknown OverflowResult");
}
+/// Combine constant ranges from computeConstantRange() and computeKnownBits().
+static ConstantRange computeConstantRangeIncludingKnownBits(
+ const Value *V, bool ForSigned, const DataLayout &DL, unsigned Depth,
+ AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT,
+ OptimizationRemarkEmitter *ORE = nullptr, bool UseInstrInfo = true) {
+ KnownBits Known = computeKnownBits(
+ V, DL, Depth, AC, CxtI, DT, ORE, UseInstrInfo);
+ ConstantRange CR = computeConstantRange(V, UseInstrInfo);
+ return ConstantRange::fromKnownBits(Known, ForSigned).intersectWith(CR);
+}
+
OverflowResult llvm::computeOverflowForUnsignedAdd(
const Value *LHS, const Value *RHS, const DataLayout &DL,
AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT,
bool UseInstrInfo) {
- KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT,
- nullptr, UseInstrInfo);
- KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT,
- nullptr, UseInstrInfo);
- ConstantRange LHSRange =
- ConstantRange::fromKnownBits(LHSKnown, /*signed*/ false);
- ConstantRange RHSRange =
- ConstantRange::fromKnownBits(RHSKnown, /*signed*/ false);
+ ConstantRange LHSRange = computeConstantRangeIncludingKnownBits(
+ LHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT,
+ nullptr, UseInstrInfo);
+ ConstantRange RHSRange = computeConstantRangeIncludingKnownBits(
+ RHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT,
+ nullptr, UseInstrInfo);
return mapOverflowResult(LHSRange.unsignedAddMayOverflow(RHSRange));
}
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT) {
- KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT);
- KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT);
- ConstantRange LHSRange =
- ConstantRange::fromKnownBits(LHSKnown, /*signed*/ false);
- ConstantRange RHSRange =
- ConstantRange::fromKnownBits(RHSKnown, /*signed*/ false);
+ ConstantRange LHSRange = computeConstantRangeIncludingKnownBits(
+ LHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT);
+ ConstantRange RHSRange = computeConstantRangeIncludingKnownBits(
+ RHS, /*ForSigned=*/false, DL, /*Depth=*/0, AC, CxtI, DT);
return mapOverflowResult(LHSRange.unsignedSubMayOverflow(RHSRange));
}
ConstantRange llvm::computeConstantRange(const Value *V, bool UseInstrInfo) {
assert(V->getType()->isIntOrIntVectorTy() && "Expected integer instruction");
+ const APInt *C;
+ if (match(V, m_APInt(C)))
+ return ConstantRange(*C);
+
InstrInfoQuery IIQ(UseInstrInfo);
unsigned BitWidth = V->getType()->getScalarSizeInBits();
APInt Lower = APInt(BitWidth, 0);
; CHECK-LABEL: @and1_lshr1_is_cmp_eq_0_multiuse(
; CHECK-NEXT: [[SH:%.*]] = lshr i8 1, %x
; CHECK-NEXT: [[AND:%.*]] = and i8 [[SH]], 1
-; CHECK-NEXT: [[ADD:%.*]] = add i8 [[SH]], [[AND]]
+; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[SH]], [[AND]]
; CHECK-NEXT: ret i8 [[ADD]]
;
%sh = lshr i8 1, %x
define i8 @test_scalar_uadd_urem_no_ov(i8 %a) {
; CHECK-LABEL: @test_scalar_uadd_urem_no_ov(
; CHECK-NEXT: [[B:%.*]] = urem i8 [[A:%.*]], 100
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[B]], i8 -100)
+; CHECK-NEXT: [[R:%.*]] = add nuw nsw i8 [[B]], -100
; CHECK-NEXT: ret i8 [[R]]
;
%b = urem i8 %a, 100
; CHECK-LABEL: @test_scalar_uadd_urem_known_bits(
; CHECK-NEXT: [[AA:%.*]] = udiv i8 -66, [[A:%.*]]
; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 63
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[AA]], i8 [[BB]])
+; CHECK-NEXT: [[R:%.*]] = add nuw i8 [[AA]], [[BB]]
; CHECK-NEXT: ret i8 [[R]]
;
%aa = udiv i8 190, %a
define i8 @test_scalar_usub_add_nuw_no_ov(i8 %a) {
; CHECK-LABEL: @test_scalar_usub_add_nuw_no_ov(
-; CHECK-NEXT: [[B:%.*]] = add nuw i8 [[A:%.*]], 10
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[B]], i8 9)
+; CHECK-NEXT: [[R:%.*]] = add i8 [[A:%.*]], 1
; CHECK-NEXT: ret i8 [[R]]
;
%b = add nuw i8 %a, 10
define i8 @test_scalar_usub_add_nuw_eq(i8 %a) {
; CHECK-LABEL: @test_scalar_usub_add_nuw_eq(
-; CHECK-NEXT: [[B:%.*]] = add nuw i8 [[A:%.*]], 10
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[B]], i8 10)
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: ret i8 [[A:%.*]]
;
%b = add nuw i8 %a, 10
%r = call i8 @llvm.usub.sat.i8(i8 %b, i8 10)
define i8 @test_scalar_usub_urem_must_ov(i8 %a) {
; CHECK-LABEL: @test_scalar_usub_urem_must_ov(
-; CHECK-NEXT: [[B:%.*]] = urem i8 [[A:%.*]], 10
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[B]], i8 10)
-; CHECK-NEXT: ret i8 [[R]]
+; CHECK-NEXT: ret i8 0
;
%b = urem i8 %a, 10
%r = call i8 @llvm.usub.sat.i8(i8 %b, i8 10)
; CHECK-LABEL: @test_scalar_usub_add_nuw_known_bits(
; CHECK-NEXT: [[AA:%.*]] = add nuw i8 [[A:%.*]], 10
; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 7
-; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[AA]], i8 [[BB]])
+; CHECK-NEXT: [[R:%.*]] = sub nuw i8 [[AA]], [[BB]]
; CHECK-NEXT: ret i8 [[R]]
;
%aa = add nuw i8 %a, 10
define i8 @test_scalar_usub_add_nuw_inferred(i8 %a) {
; CHECK-LABEL: @test_scalar_usub_add_nuw_inferred(
; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 10)
-; CHECK-NEXT: [[R:%.*]] = add i8 [[B]], 9
+; CHECK-NEXT: [[R:%.*]] = add nuw i8 [[B]], 9
; CHECK-NEXT: ret i8 [[R]]
;
%b = call i8 @llvm.usub.sat.i8(i8 %a, i8 10)
define <2 x i8> @test_vector_usub_add_nuw_no_ov(<2 x i8> %a) {
; CHECK-LABEL: @test_vector_usub_add_nuw_no_ov(
-; CHECK-NEXT: [[B:%.*]] = add nuw <2 x i8> [[A:%.*]], <i8 10, i8 10>
-; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[B]], <2 x i8> <i8 9, i8 9>)
+; CHECK-NEXT: [[R:%.*]] = add <2 x i8> [[A:%.*]], <i8 1, i8 1>
; CHECK-NEXT: ret <2 x i8> [[R]]
;
%b = add nuw <2 x i8> %a, <i8 10, i8 10>
define { i8, i1 } @no_fold_on_constant_add_overflow(i8 %x) {
; CHECK-LABEL: @no_fold_on_constant_add_overflow(
-; CHECK-NEXT: [[A:%.*]] = add nuw i8 [[X:%.*]], -56
-; CHECK-NEXT: [[B:%.*]] = tail call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 [[A]], i8 56)
-; CHECK-NEXT: ret { i8, i1 } [[B]]
+; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 undef, i1 true }, i8 [[X:%.*]], 0
+; CHECK-NEXT: ret { i8, i1 } [[TMP1]]
;
%a = add nuw i8 %x, 200
%b = tail call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %a, i8 56)
; CHECK-NEXT: [[N_RND_UP:%.*]] = add nuw nsw i64 [[TMP3]], 4
; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP2]], 3
; CHECK-NEXT: [[N_MOD_VF:%.*]] = zext i32 [[TMP4]] to i64
-; CHECK-NEXT: [[N_VEC:%.*]] = sub nsw i64 [[N_RND_UP]], [[N_MOD_VF]]
+; CHECK-NEXT: [[N_VEC:%.*]] = sub nuw nsw i64 [[N_RND_UP]], [[N_MOD_VF]]
; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <4 x i64> undef, i64 [[TMP3]], i32 0
; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <4 x i64> [[BROADCAST_SPLATINSERT1]], <4 x i64> undef, <4 x i32> zeroinitializer
; CHECK-NEXT: br label [[VECTOR_BODY:%.*]]