Skip to content

Commit f6bb156

Browse files
[InstCombine] Fold icmp(X) ? f(X) : C
This diff extends foldSelectInstWithICmp to handle the case icmp(X) ? f(X) : C when f(X) is guaranteed to be equal to C for all X in the exact range of the inverse predicate. This addresses the issue #54089. Differential revision: https://reviews.llvm.org/D123159 Test plan: make check-all
1 parent e4c4d0d commit f6bb156

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/Analysis/ValueTracking.h"
2323
#include "llvm/IR/BasicBlock.h"
2424
#include "llvm/IR/Constant.h"
25+
#include "llvm/IR/ConstantRange.h"
2526
#include "llvm/IR/Constants.h"
2627
#include "llvm/IR/DerivedTypes.h"
2728
#include "llvm/IR/IRBuilder.h"
@@ -1529,6 +1530,36 @@ static Instruction *foldSelectZeroOrOnes(ICmpInst *Cmp, Value *TVal,
15291530
return nullptr;
15301531
}
15311532

1533+
static Value *foldSelectInstWithICmpConst(SelectInst &SI, ICmpInst *ICI) {
1534+
const APInt *CmpC;
1535+
Value *V;
1536+
CmpInst::Predicate Pred;
1537+
if (!match(ICI, m_ICmp(Pred, m_Value(V), m_APInt(CmpC))))
1538+
return nullptr;
1539+
1540+
BinaryOperator *BO;
1541+
const APInt *C;
1542+
CmpInst::Predicate CPred;
1543+
if (match(&SI, m_Select(m_Specific(ICI), m_APInt(C), m_BinOp(BO))))
1544+
CPred = ICI->getPredicate();
1545+
else if (match(&SI, m_Select(m_Specific(ICI), m_BinOp(BO), m_APInt(C))))
1546+
CPred = ICI->getInversePredicate();
1547+
else
1548+
return nullptr;
1549+
1550+
const APInt *BinOpC;
1551+
if (!match(BO, m_BinOp(m_Specific(V), m_APInt(BinOpC))))
1552+
return nullptr;
1553+
1554+
ConstantRange R = ConstantRange::makeExactICmpRegion(CPred, *CmpC)
1555+
.binaryOp(BO->getOpcode(), *BinOpC);
1556+
if (R == *C) {
1557+
BO->dropPoisonGeneratingFlags();
1558+
return BO;
1559+
}
1560+
return nullptr;
1561+
}
1562+
15321563
/// Visit a SelectInst that has an ICmpInst as its first operand.
15331564
Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
15341565
ICmpInst *ICI) {
@@ -1538,6 +1569,9 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
15381569
if (Instruction *NewSPF = canonicalizeSPF(SI, *ICI, *this))
15391570
return NewSPF;
15401571

1572+
if (Value *V = foldSelectInstWithICmpConst(SI, ICI))
1573+
return replaceInstUsesWith(SI, V);
1574+
15411575
if (Value *V = canonicalizeClampLike(SI, *ICI, Builder))
15421576
return replaceInstUsesWith(SI, V);
15431577

llvm/test/Transforms/InstCombine/select-binop-cmp.ll

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -648,10 +648,8 @@ define i32 @select_or_icmp_bad(i32 %x, i32 %y, i32 %z) {
648648

649649
define i32 @select_lshr_icmp_const(i32 %x) {
650650
; CHECK-LABEL: @select_lshr_icmp_const(
651-
; CHECK-NEXT: [[A:%.*]] = icmp ugt i32 %x, 31
652651
; CHECK-NEXT: [[B:%.*]] = lshr i32 %x, 5
653-
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 0
654-
; CHECK-NEXT: ret i32 [[C]]
652+
; CHECK-NEXT: ret i32 [[B]]
655653
;
656654
%A = icmp ugt i32 %x, 31
657655
%B = lshr i32 %x, 5
@@ -661,10 +659,8 @@ define i32 @select_lshr_icmp_const(i32 %x) {
661659

662660
define i32 @select_lshr_icmp_const_reordered(i32 %x) {
663661
; CHECK-LABEL: @select_lshr_icmp_const_reordered(
664-
; CHECK-NEXT: [[A:%.*]] = icmp ult i32 %x, 32
665662
; CHECK-NEXT: [[B:%.*]] = lshr i32 %x, 5
666-
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 0, i32 [[B]]
667-
; CHECK-NEXT: ret i32 [[C]]
663+
; CHECK-NEXT: ret i32 [[B]]
668664
;
669665
%A = icmp ult i32 %x, 32
670666
%B = lshr i32 %x, 5
@@ -674,10 +670,8 @@ define i32 @select_lshr_icmp_const_reordered(i32 %x) {
674670

675671
define i32 @select_exact_lshr_icmp_const(i32 %x) {
676672
; CHECK-LABEL: @select_exact_lshr_icmp_const(
677-
; CHECK-NEXT: [[A:%.*]] = icmp ugt i32 %x, 31
678-
; CHECK-NEXT: [[B:%.*]] = lshr exact i32 %x, 5
679-
; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 0
680-
; CHECK-NEXT: ret i32 [[C]]
673+
; CHECK-NEXT: [[B:%.*]] = lshr i32 %x, 5
674+
; CHECK-NEXT: ret i32 [[B]]
681675
;
682676
%A = icmp ugt i32 %x, 31
683677
%B = lshr exact i32 %x, 5

0 commit comments

Comments
 (0)