Skip to content

Commit 711fcae

Browse files
authored
[ValueTracking] Handle trunc nuw in computeKnownBitsFromICmpCond (#125414)
This patch extends #82803 to further infer high bits when `nuw` is set. It will save some and instructions on induction variables. No real-world benefit is observed for `trunc nsw`. Alive2: https://alive2.llvm.org/ce/z/j-YFvt
1 parent 046dd4b commit 711fcae

File tree

2 files changed

+53
-1
lines changed

2 files changed

+53
-1
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,10 @@ static void computeKnownBitsFromICmpCond(const Value *V, ICmpInst *Cmp,
776776
if (match(LHS, m_Trunc(m_Specific(V)))) {
777777
KnownBits DstKnown(LHS->getType()->getScalarSizeInBits());
778778
computeKnownBitsFromCmp(LHS, Pred, LHS, RHS, DstKnown, SQ);
779-
Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth()));
779+
if (cast<TruncInst>(LHS)->hasNoUnsignedWrap())
780+
Known = Known.unionWith(DstKnown.zext(Known.getBitWidth()));
781+
else
782+
Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth()));
780783
return;
781784
}
782785

llvm/test/Transforms/InstCombine/known-bits.ll

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,55 @@ if.else:
480480
ret i64 13
481481
}
482482

483+
define i64 @test_icmp_trunc_nuw(i64 %a) {
484+
; CHECK-LABEL: @test_icmp_trunc_nuw(
485+
; CHECK-NEXT: entry:
486+
; CHECK-NEXT: [[CAST:%.*]] = trunc nuw i64 [[A:%.*]] to i32
487+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CAST]], 0
488+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
489+
; CHECK: if.then:
490+
; CHECK-NEXT: ret i64 [[A]]
491+
; CHECK: if.else:
492+
; CHECK-NEXT: ret i64 0
493+
;
494+
entry:
495+
%cast = trunc nuw i64 %a to i32
496+
%cmp = icmp sgt i32 %cast, 0
497+
br i1 %cmp, label %if.then, label %if.else
498+
499+
if.then:
500+
%b = and i64 %a, 2147483647
501+
ret i64 %b
502+
503+
if.else:
504+
ret i64 0
505+
}
506+
507+
define i64 @test_icmp_trunc_no_nuw(i64 %a) {
508+
; CHECK-LABEL: @test_icmp_trunc_no_nuw(
509+
; CHECK-NEXT: entry:
510+
; CHECK-NEXT: [[CAST:%.*]] = trunc i64 [[A:%.*]] to i32
511+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CAST]], 0
512+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
513+
; CHECK: if.then:
514+
; CHECK-NEXT: [[B:%.*]] = and i64 [[A]], 2147483647
515+
; CHECK-NEXT: ret i64 [[B]]
516+
; CHECK: if.else:
517+
; CHECK-NEXT: ret i64 0
518+
;
519+
entry:
520+
%cast = trunc i64 %a to i32
521+
%cmp = icmp sgt i32 %cast, 0
522+
br i1 %cmp, label %if.then, label %if.else
523+
524+
if.then:
525+
%b = and i64 %a, 2147483647
526+
ret i64 %b
527+
528+
if.else:
529+
ret i64 0
530+
}
531+
483532
define i1 @test_icmp_or_distjoint(i8 %n, i1 %other) {
484533
; CHECK-LABEL: @test_icmp_or_distjoint(
485534
; CHECK-NEXT: entry:

0 commit comments

Comments
 (0)