diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index b3216f8fb78db..6b61a3546e8b7 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -776,7 +776,10 @@ static void computeKnownBitsFromICmpCond(const Value *V, ICmpInst *Cmp, if (match(LHS, m_Trunc(m_Specific(V)))) { KnownBits DstKnown(LHS->getType()->getScalarSizeInBits()); computeKnownBitsFromCmp(LHS, Pred, LHS, RHS, DstKnown, SQ); - Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth())); + if (cast(LHS)->hasNoUnsignedWrap()) + Known = Known.unionWith(DstKnown.zext(Known.getBitWidth())); + else + Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth())); return; } diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index bd6b2f015145e..cbd9737415f1f 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -480,6 +480,55 @@ if.else: ret i64 13 } +define i64 @test_icmp_trunc_nuw(i64 %a) { +; CHECK-LABEL: @test_icmp_trunc_nuw( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CAST:%.*]] = trunc nuw i64 [[A:%.*]] to i32 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CAST]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: ret i64 [[A]] +; CHECK: if.else: +; CHECK-NEXT: ret i64 0 +; +entry: + %cast = trunc nuw i64 %a to i32 + %cmp = icmp sgt i32 %cast, 0 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %b = and i64 %a, 2147483647 + ret i64 %b + +if.else: + ret i64 0 +} + +define i64 @test_icmp_trunc_no_nuw(i64 %a) { +; CHECK-LABEL: @test_icmp_trunc_no_nuw( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CAST:%.*]] = trunc i64 [[A:%.*]] to i32 +; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CAST]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 2147483647 +; CHECK-NEXT: ret i64 [[B]] +; CHECK: if.else: +; CHECK-NEXT: ret i64 0 +; +entry: + %cast = trunc i64 %a to i32 + %cmp = icmp sgt i32 %cast, 0 + br i1 %cmp, label %if.then, label %if.else + +if.then: + %b = and i64 %a, 2147483647 + ret i64 %b + +if.else: + ret i64 0 +} + define i1 @test_icmp_or_distjoint(i8 %n, i1 %other) { ; CHECK-LABEL: @test_icmp_or_distjoint( ; CHECK-NEXT: entry: