Skip to content

Commit d6f1964

Browse files
committed
[ValueTracking] Handle range assume bundles in isKnownNonZero
1 parent df32fd9 commit d6f1964

File tree

4 files changed

+36
-9
lines changed

4 files changed

+36
-9
lines changed

llvm/include/llvm/Analysis/AssumeBundleQueries.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616

1717
#include "llvm/ADT/DenseMap.h"
1818
#include "llvm/IR/IntrinsicInst.h"
19+
#include <optional>
1920

2021
namespace llvm {
2122
class AssumptionCache;
2223
class DominatorTree;
2324
class Instruction;
25+
class ConstantRange;
2426

2527
/// Index of elements in the operand bundle.
2628
/// If the element exist it is guaranteed to be what is specified in this enum
@@ -170,6 +172,9 @@ RetainedKnowledge getKnowledgeValidInContext(
170172
RetainedKnowledge getKnowledgeFromBundle(AssumeInst &Assume,
171173
const CallBase::BundleOpInfo &BOI);
172174

175+
std::optional<ConstantRange>
176+
getRangeFromBundle(AssumeInst &Assume, const CallBase::BundleOpInfo &BOI);
177+
173178
} // namespace llvm
174179

175180
#endif

llvm/lib/Analysis/AssumeBundleQueries.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "llvm/ADT/Statistic.h"
1111
#include "llvm/Analysis/AssumptionCache.h"
1212
#include "llvm/Analysis/ValueTracking.h"
13+
#include "llvm/IR/ConstantRange.h"
1314
#include "llvm/IR/Instruction.h"
1415
#include "llvm/IR/Instructions.h"
1516
#include "llvm/IR/IntrinsicInst.h"
@@ -214,3 +215,21 @@ RetainedKnowledge llvm::getKnowledgeValidInContext(
214215
return isValidAssumeForContext(I, CtxI, DT);
215216
});
216217
}
218+
219+
std::optional<ConstantRange>
220+
llvm::getRangeFromBundle(AssumeInst &Assume,
221+
const CallBase::BundleOpInfo &BOI) {
222+
if (Attribute::getAttrKindFromName(BOI.Tag->getKey()) != Attribute::Range)
223+
return std::nullopt;
224+
225+
assert(BOI.End - BOI.Begin > ABA_Argument + 1 &&
226+
"range assumptions should have 3 arguments");
227+
228+
if (auto *Lower = dyn_cast<ConstantInt>(
229+
getValueFromBundleOpInfo(Assume, BOI, ABA_Argument)))
230+
if (auto *Upper = dyn_cast<ConstantInt>(
231+
getValueFromBundleOpInfo(Assume, BOI, ABA_Argument + 1)))
232+
if (Lower->getValue() != Upper->getValue())
233+
return ConstantRange(Lower->getValue(), Upper->getValue());
234+
return std::nullopt;
235+
}

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -595,18 +595,25 @@ static bool isKnownNonZeroFromAssume(const Value *V, const SimplifyQuery &Q) {
595595
"Got assumption for the wrong function!");
596596

597597
if (Elem.Index != AssumptionCache::ExprResultIdx) {
598-
if (!V->getType()->isPointerTy())
599-
continue;
598+
if (V->getType()->isPointerTy()) {
600599
if (RetainedKnowledge RK = getKnowledgeFromBundle(
601600
*I, I->bundle_op_info_begin()[Elem.Index])) {
602601
if (RK.WasOn == V &&
603602
(RK.AttrKind == Attribute::NonNull ||
604603
(RK.AttrKind == Attribute::Dereferenceable &&
605-
!NullPointerIsDefined(Q.CxtI->getFunction(),
604+
!NullPointerIsDefined(
605+
Q.CxtI->getFunction(),
606606
V->getType()->getPointerAddressSpace()))) &&
607607
isValidAssumeForContext(I, Q.CxtI, Q.DT))
608608
return true;
609609
}
610+
} else if (V->getType()->isIntOrIntVectorTy()) {
611+
if (std::optional<ConstantRange> Range =
612+
getRangeFromBundle(*I, I->bundle_op_info_begin()[Elem.Index]))
613+
if (!Range->contains(APInt::getZero(Range->getBitWidth())) &&
614+
isValidAssumeForContext(I, Q.CxtI, Q.DT))
615+
return true;
616+
}
610617
continue;
611618
}
612619

llvm/test/Analysis/ValueTracking/known-non-zero.ll

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,9 +1549,7 @@ define i1 @vec_reverse_non_zero_demanded_fail(<4 x i8> %xx) {
15491549
define i1 @range_assume(i8 %x, i8 %y) {
15501550
; CHECK-LABEL: @range_assume(
15511551
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "range"(i8 [[X:%.*]], i8 1, i8 0) ]
1552-
; CHECK-NEXT: [[OR:%.*]] = or i8 [[Y:%.*]], [[X]]
1553-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], 0
1554-
; CHECK-NEXT: ret i1 [[CMP]]
1552+
; CHECK-NEXT: ret i1 false
15551553
;
15561554
call void @llvm.assume(i1 true) ["range"(i8 %x, i8 1, i8 0)]
15571555
%or = or i8 %y, %x
@@ -1575,9 +1573,7 @@ define i1 @neg_range_assum(i8 %x, i8 %y) {
15751573
define <2 x i1> @range_assum_vec(<2 x i8> %x, <2 x i8> %y) {
15761574
; CHECK-LABEL: @range_assum_vec(
15771575
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "range"(<2 x i8> [[X:%.*]], i8 1, i8 0) ]
1578-
; CHECK-NEXT: [[OR:%.*]] = or <2 x i8> [[Y:%.*]], [[X]]
1579-
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[OR]], zeroinitializer
1580-
; CHECK-NEXT: ret <2 x i1> [[CMP]]
1576+
; CHECK-NEXT: ret <2 x i1> <i1 true, i1 true>
15811577
;
15821578
call void @llvm.assume(i1 true) ["range"(<2 x i8> %x, i8 1, i8 0)]
15831579
%or = or <2 x i8> %y, %x

0 commit comments

Comments
 (0)