Skip to content

Commit 3589cac

Browse files
authored
[ValueTracking] Handle icmp pred (trunc X), C in computeKnownBitsFromCmp (#82803)
This patch handles the pattern `icmp pred (trunc X), C` in `computeKnownBitsFromCmp` to infer low bits of `X` from dominating conditions.
1 parent 0cbbcf1 commit 3589cac

File tree

2 files changed

+162
-6
lines changed

2 files changed

+162
-6
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,25 @@ static void computeKnownBitsFromCmp(const Value *V, CmpInst::Predicate Pred,
708708
}
709709
}
710710

711+
static void computeKnownBitsFromICmpCond(const Value *V, ICmpInst *Cmp,
712+
KnownBits &Known,
713+
const SimplifyQuery &SQ, bool Invert) {
714+
ICmpInst::Predicate Pred =
715+
Invert ? Cmp->getInversePredicate() : Cmp->getPredicate();
716+
Value *LHS = Cmp->getOperand(0);
717+
Value *RHS = Cmp->getOperand(1);
718+
719+
// Handle icmp pred (trunc V), C
720+
if (match(LHS, m_Trunc(m_Specific(V)))) {
721+
KnownBits DstKnown(LHS->getType()->getScalarSizeInBits());
722+
computeKnownBitsFromCmp(LHS, Pred, LHS, RHS, DstKnown, SQ);
723+
Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth()));
724+
return;
725+
}
726+
727+
computeKnownBitsFromCmp(V, Pred, LHS, RHS, Known, SQ);
728+
}
729+
711730
static void computeKnownBitsFromCond(const Value *V, Value *Cond,
712731
KnownBits &Known, unsigned Depth,
713732
const SimplifyQuery &SQ, bool Invert) {
@@ -727,9 +746,7 @@ static void computeKnownBitsFromCond(const Value *V, Value *Cond,
727746
}
728747

729748
if (auto *Cmp = dyn_cast<ICmpInst>(Cond))
730-
computeKnownBitsFromCmp(
731-
V, Invert ? Cmp->getInversePredicate() : Cmp->getPredicate(),
732-
Cmp->getOperand(0), Cmp->getOperand(1), Known, SQ);
749+
computeKnownBitsFromICmpCond(V, Cmp, Known, SQ, Invert);
733750
}
734751

735752
void llvm::computeKnownBitsFromContext(const Value *V, KnownBits &Known,
@@ -815,8 +832,7 @@ void llvm::computeKnownBitsFromContext(const Value *V, KnownBits &Known,
815832
if (!isValidAssumeForContext(I, Q.CxtI, Q.DT))
816833
continue;
817834

818-
computeKnownBitsFromCmp(V, Cmp->getPredicate(), Cmp->getOperand(0),
819-
Cmp->getOperand(1), Known, Q);
835+
computeKnownBitsFromICmpCond(V, Cmp, Known, Q, /*Invert=*/false);
820836
}
821837

822838
// Conflicting assumption: Undefined behavior will occur on this execution
@@ -9133,7 +9149,7 @@ addValueAffectedByCondition(Value *V,
91339149

91349150
// Peek through unary operators to find the source of the condition.
91359151
Value *Op;
9136-
if (match(I, m_PtrToInt(m_Value(Op)))) {
9152+
if (match(I, m_CombineOr(m_PtrToInt(m_Value(Op)), m_Trunc(m_Value(Op))))) {
91379153
if (isa<Instruction>(Op) || isa<Argument>(Op))
91389154
InsertAffected(Op);
91399155
}

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

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,5 +343,145 @@ exit:
343343
ret i8 %or2
344344
}
345345

346+
define i32 @test_icmp_trunc1(i32 %x){
347+
; CHECK-LABEL: @test_icmp_trunc1(
348+
; CHECK-NEXT: entry:
349+
; CHECK-NEXT: [[Y:%.*]] = trunc i32 [[X:%.*]] to i16
350+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[Y]], 7
351+
; CHECK-NEXT: br i1 [[CMP]], label [[THEN:%.*]], label [[ELSE:%.*]]
352+
; CHECK: then:
353+
; CHECK-NEXT: ret i32 7
354+
; CHECK: else:
355+
; CHECK-NEXT: ret i32 0
356+
;
357+
entry:
358+
%y = trunc i32 %x to i16
359+
%cmp = icmp eq i16 %y, 7
360+
br i1 %cmp, label %then, label %else
361+
then:
362+
%z = and i32 %x, 15
363+
ret i32 %z
364+
else:
365+
ret i32 0
366+
}
367+
368+
define i32 @test_icmp_trunc_assume(i32 %x){
369+
; CHECK-LABEL: @test_icmp_trunc_assume(
370+
; CHECK-NEXT: entry:
371+
; CHECK-NEXT: [[Y:%.*]] = trunc i32 [[X:%.*]] to i16
372+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[Y]], 7
373+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
374+
; CHECK-NEXT: ret i32 7
375+
;
376+
entry:
377+
%y = trunc i32 %x to i16
378+
%cmp = icmp eq i16 %y, 7
379+
call void @llvm.assume(i1 %cmp)
380+
%z = and i32 %x, 15
381+
ret i32 %z
382+
}
383+
384+
define i64 @test_icmp_trunc2(i64 %x) {
385+
; CHECK-LABEL: @test_icmp_trunc2(
386+
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[X:%.*]] to i32
387+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CONV]], 12
388+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
389+
; CHECK: if.then:
390+
; CHECK-NEXT: [[SEXT:%.*]] = and i64 [[X]], 2147483647
391+
; CHECK-NEXT: ret i64 [[SEXT]]
392+
; CHECK: if.else:
393+
; CHECK-NEXT: ret i64 0
394+
;
395+
%conv = trunc i64 %x to i32
396+
%cmp = icmp sgt i32 %conv, 12
397+
br i1 %cmp, label %if.then, label %if.else
398+
399+
if.then:
400+
%sext = shl i64 %x, 32
401+
%ret = ashr exact i64 %sext, 32
402+
ret i64 %ret
403+
if.else:
404+
ret i64 0
405+
}
406+
407+
define i64 @test_icmp_trunc3(i64 %n) {
408+
; CHECK-LABEL: @test_icmp_trunc3(
409+
; CHECK-NEXT: entry:
410+
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[N:%.*]] to i32
411+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[CONV]], 96
412+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
413+
; CHECK: if.then:
414+
; CHECK-NEXT: [[RET:%.*]] = and i64 [[N]], 127
415+
; CHECK-NEXT: ret i64 [[RET]]
416+
; CHECK: if.else:
417+
; CHECK-NEXT: ret i64 0
418+
;
419+
entry:
420+
%conv = trunc i64 %n to i32
421+
%cmp = icmp ult i32 %conv, 96
422+
br i1 %cmp, label %if.then, label %if.else
423+
424+
if.then:
425+
%ret = and i64 %n, 4294967295
426+
ret i64 %ret
427+
428+
if.else:
429+
ret i64 0
430+
}
431+
432+
define i8 @test_icmp_trunc4(i64 %n) {
433+
; CHECK-LABEL: @test_icmp_trunc4(
434+
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[N:%.*]] to i32
435+
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[CONV]], 10
436+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
437+
; CHECK: if.then:
438+
; CHECK-NEXT: [[CONV2:%.*]] = trunc i64 [[N]] to i8
439+
; CHECK-NEXT: [[ADD:%.*]] = or disjoint i8 [[CONV2]], 48
440+
; CHECK-NEXT: ret i8 [[ADD]]
441+
; CHECK: if.else:
442+
; CHECK-NEXT: ret i8 0
443+
;
444+
%conv = trunc i64 %n to i32
445+
%cmp = icmp ult i32 %conv, 10
446+
br i1 %cmp, label %if.then, label %if.else
447+
448+
if.then:
449+
%conv2 = trunc i64 %n to i8
450+
%add = add i8 %conv2, 48
451+
ret i8 %add
452+
453+
if.else:
454+
ret i8 0
455+
}
456+
457+
define i64 @test_icmp_trunc5(i64 %n) {
458+
; CHECK-LABEL: @test_icmp_trunc5(
459+
; CHECK-NEXT: entry:
460+
; CHECK-NEXT: [[SHR:%.*]] = ashr i64 [[N:%.*]], 47
461+
; CHECK-NEXT: [[CONV1:%.*]] = trunc i64 [[SHR]] to i32
462+
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[CONV1]], -13
463+
; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
464+
; CHECK: if.then:
465+
; CHECK-NEXT: [[TMP0:%.*]] = and i64 [[SHR]], 15
466+
; CHECK-NEXT: [[NOT:%.*]] = xor i64 [[TMP0]], 15
467+
; CHECK-NEXT: ret i64 [[NOT]]
468+
; CHECK: if.else:
469+
; CHECK-NEXT: ret i64 13
470+
;
471+
entry:
472+
%shr = ashr i64 %n, 47
473+
%conv1 = trunc i64 %shr to i32
474+
%cmp = icmp ugt i32 %conv1, -13
475+
br i1 %cmp, label %if.then, label %if.else
476+
477+
if.then:
478+
%and = and i64 %shr, 4294967295
479+
%not = xor i64 %and, 4294967295
480+
ret i64 %not
481+
482+
if.else:
483+
ret i64 13
484+
}
485+
346486
declare void @use(i1)
347487
declare void @sink(i8)

0 commit comments

Comments
 (0)