Skip to content

Commit e854101

Browse files
committed
add stripNullTest and update isKnownNonZero
1 parent 32cf848 commit e854101

File tree

4 files changed

+67
-16
lines changed

4 files changed

+67
-16
lines changed

llvm/include/llvm/Analysis/ValueTracking.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,11 @@ LLVM_ABI void
999999
findValuesAffectedByCondition(Value *Cond, bool IsAssume,
10001000
function_ref<void(Value *)> InsertAffected);
10011001

1002+
/// Returns the inner value X if the expression has the form f(X)
1003+
/// where f(X) == 0 if and only if X == 0, otherwise returns nullptr.
1004+
LLVM_ABI Value *stripNullTest(Value *V);
1005+
LLVM_ABI const Value *stripNullTest(const Value *V);
1006+
10021007
} // end namespace llvm
10031008

10041009
#endif // LLVM_ANALYSIS_VALUETRACKING_H

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3521,6 +3521,9 @@ bool isKnownNonZero(const Value *V, const APInt &DemandedElts,
35213521
isKnownNonNullFromDominatingCondition(V, Q.CxtI, Q.DT))
35223522
return true;
35233523

3524+
if (const Value *Stripped = stripNullTest(V))
3525+
return isKnownNonZero(Stripped, DemandedElts, Q, Depth);
3526+
35243527
return false;
35253528
}
35263529

@@ -10170,3 +10173,26 @@ void llvm::findValuesAffectedByCondition(
1017010173
}
1017110174
}
1017210175
}
10176+
10177+
const Value *llvm::stripNullTest(const Value *V) {
10178+
// (X >> C) or/add (X & mask(C) != 0)
10179+
if (const auto *BO = dyn_cast<BinaryOperator>(V)) {
10180+
if (BO->getOpcode() == Instruction::Add ||
10181+
BO->getOpcode() == Instruction::Or) {
10182+
const Value *X;
10183+
const APInt *C1, *C2;
10184+
if (match(BO, m_c_BinOp(m_LShr(m_Value(X), m_APInt(C1)),
10185+
m_ZExt(m_SpecificICmp(
10186+
ICmpInst::ICMP_NE,
10187+
m_And(m_Deferred(X), m_LowBitMask(C2)),
10188+
m_Zero())))) &&
10189+
C2->popcount() == C1->getZExtValue())
10190+
return X;
10191+
}
10192+
}
10193+
return nullptr;
10194+
}
10195+
10196+
Value *llvm::stripNullTest(Value *V) {
10197+
return const_cast<Value *>(stripNullTest(const_cast<const Value *>(V)));
10198+
}

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,22 +1299,11 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
12991299
// will fold to a constant elsewhere.
13001300
}
13011301

1302-
// icmp eq/ne ((X >> C) or/add (X & mask(C) != 0)), 0 -> icmp eq/ne X, 0
1303-
if (ICmpInst::isEquality(Pred)) {
1304-
auto *BO = dyn_cast<BinaryOperator>(Cmp.getOperand(0));
1305-
Value *X;
1306-
const APInt *C1, *C2;
1307-
if (BO &&
1308-
(BO->getOpcode() == Instruction::Add ||
1309-
BO->getOpcode() == Instruction::Or) &&
1310-
match(BO, m_c_BinOp(m_LShr(m_Value(X), m_APInt(C1)),
1311-
m_ZExt(m_SpecificICmp(
1312-
ICmpInst::ICMP_NE,
1313-
m_And(m_Deferred(X), m_LowBitMask(C2)),
1314-
m_Zero())))) &&
1315-
C2->popcount() == C1->getZExtValue())
1316-
return new ICmpInst(Pred, X, ConstantInt::getNullValue(X->getType()));
1317-
}
1302+
// (icmp eq/ne f(X), 0) -> (icmp eq/ne X, 0)
1303+
// where f(X) == 0 if and only if X == 0
1304+
if (ICmpInst::isEquality(Pred))
1305+
if (Value *Stripped = stripNullTest(Cmp.getOperand(0)))
1306+
return new ICmpInst(Pred, Stripped, Cmp.getOperand(1));
13181307

13191308
return nullptr;
13201309
}

llvm/test/Transforms/InstCombine/ceil-shift.ll

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,34 @@ define i1 @ceil_shift_not_add_or(i32 %arg0) {
275275
%res = icmp eq i32 %quot_and_rem, 0
276276
ret i1 %res
277277
}
278+
279+
define i32 @ceil_shift_should_infer_ge_zero(i32 %x) {
280+
; CHECK-LABEL: define i32 @ceil_shift_should_infer_ge_zero(
281+
; CHECK-SAME: i32 [[X:%.*]]) {
282+
; CHECK-NEXT: [[COND_NOT:%.*]] = icmp eq i32 [[X]], 0
283+
; CHECK-NEXT: br i1 [[COND_NOT]], label %[[IF_ELSE:.*]], label %[[IF_THEN:.*]]
284+
; CHECK: [[IF_THEN]]:
285+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 20
286+
; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[X]], 1048575
287+
; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0
288+
; CHECK-NEXT: [[TMP4:%.*]] = zext i1 [[TMP3]] to i32
289+
; CHECK-NEXT: [[TMP5:%.*]] = add nuw nsw i32 [[TMP1]], [[TMP4]]
290+
; CHECK-NEXT: ret i32 [[TMP5]]
291+
; CHECK: [[IF_ELSE]]:
292+
; CHECK-NEXT: ret i32 0
293+
;
294+
%cond = icmp ne i32 %x, 0
295+
br i1 %cond, label %if.then, label %if.else
296+
297+
if.then:
298+
%quot = lshr i32 %x, 20
299+
%rem = and i32 %x, 1048575
300+
%has_rem = icmp ne i32 %rem, 0
301+
%zext_has_rem = zext i1 %has_rem to i32
302+
%ceil = add nuw nsw i32 %quot, %zext_has_rem
303+
%max = call i32 @llvm.umax.i32(i32 %ceil, i32 1)
304+
ret i32 %max
305+
306+
if.else:
307+
ret i32 0
308+
}

0 commit comments

Comments
 (0)