Skip to content

Commit 3a89d80

Browse files
committed
[SCCP] Relax two-instruction range checks.
1 parent 19c19ca commit 3a89d80

File tree

2 files changed

+50
-2
lines changed

2 files changed

+50
-2
lines changed

llvm/lib/Transforms/Utils/SCCPSolver.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
#include "llvm/Analysis/ValueLattice.h"
2020
#include "llvm/Analysis/ValueLatticeUtils.h"
2121
#include "llvm/Analysis/ValueTracking.h"
22+
#include "llvm/IR/ConstantRange.h"
2223
#include "llvm/IR/IRBuilder.h"
2324
#include "llvm/IR/InstVisitor.h"
25+
#include "llvm/IR/Instructions.h"
2426
#include "llvm/IR/NoFolder.h"
2527
#include "llvm/IR/PatternMatch.h"
2628
#include "llvm/Support/Casting.h"
@@ -284,6 +286,52 @@ static Value *simplifyInstruction(SCCPSolver &Solver,
284286
return Sub;
285287
}
286288

289+
// Relax range checks.
290+
if (auto *ICmp = dyn_cast<ICmpInst>(&Inst)) {
291+
Value *X;
292+
auto MatchTwoInstructionExactRangeCheck =
293+
[&]() -> std::optional<ConstantRange> {
294+
const APInt *RHSC;
295+
if (!match(ICmp->getOperand(1), m_APInt(RHSC)))
296+
return std::nullopt;
297+
298+
Value *LHS = ICmp->getOperand(0);
299+
ICmpInst::Predicate Pred = ICmp->getPredicate();
300+
unsigned BitWidth = RHSC->getBitWidth();
301+
if (Pred == ICmpInst::ICMP_ULT) {
302+
const APInt *Offset;
303+
if (match(LHS, m_AddLike(m_Value(X), m_APInt(Offset))))
304+
return ConstantRange(APInt::getZero(BitWidth), *RHSC).sub(*Offset);
305+
return std::nullopt;
306+
}
307+
// Match icmp eq/ne X & NegPow2, C
308+
if (ICmp->isEquality()) {
309+
const APInt *Mask;
310+
if (match(LHS, m_And(m_Value(X), m_NegatedPower2(Mask))) &&
311+
RHSC->countr_zero() >= Mask->countr_zero()) {
312+
ConstantRange CR(*RHSC, *RHSC - *Mask);
313+
return Pred == ICmpInst::ICMP_EQ ? CR : CR.inverse();
314+
}
315+
}
316+
return std::nullopt;
317+
};
318+
319+
if (auto CR = MatchExactTwoInstructionRangeCheck()) {
320+
ConstantRange LRange = GetRange(X);
321+
if (auto NewCR = CR->exactUnionWith(LRange.inverse())) {
322+
ICmpInst::Predicate Pred;
323+
APInt RHS;
324+
if (NewCR->getEquivalentICmp(Pred, RHS)) {
325+
IRBuilder<NoFolder> Builder(&Inst);
326+
Value *NewICmp =
327+
Builder.CreateICmp(Pred, X, ConstantInt::get(X->getType(), RHS));
328+
InsertedValues.insert(NewICmp);
329+
return NewICmp;
330+
}
331+
}
332+
}
333+
}
334+
287335
return nullptr;
288336
}
289337

llvm/test/Transforms/SCCP/relax-range-checks.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ define i1 @relax_range_check(i8 range(i8 0, 5) %x) {
55
; CHECK-LABEL: define i1 @relax_range_check(
66
; CHECK-SAME: i8 range(i8 0, 5) [[X:%.*]]) {
77
; CHECK-NEXT: [[ADD:%.*]] = add nsw i8 [[X]], -3
8-
; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[ADD]], 2
8+
; CHECK-NEXT: [[RET:%.*]] = icmp uge i8 [[X]], 3
99
; CHECK-NEXT: ret i1 [[RET]]
1010
;
1111
%add = add i8 %x, -3
@@ -17,7 +17,7 @@ define i1 @relax_range_check_highbits_check(i8 range(i8 2, 0) %x) {
1717
; CHECK-LABEL: define i1 @relax_range_check_highbits_check(
1818
; CHECK-SAME: i8 range(i8 2, 0) [[X:%.*]]) {
1919
; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], -2
20-
; CHECK-NEXT: [[RET:%.*]] = icmp eq i8 [[AND]], 2
20+
; CHECK-NEXT: [[RET:%.*]] = icmp ult i8 [[X]], 4
2121
; CHECK-NEXT: ret i1 [[RET]]
2222
;
2323
%and = and i8 %x, -2

0 commit comments

Comments
 (0)