[llvm] f6bb156 - [InstCombine] Fold icmp(X) ? f(X) : C
Alexander Shaposhnikov via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 11 18:33:07 PDT 2022
Author: Alexander Shaposhnikov
Date: 2022-04-12T01:32:55Z
New Revision: f6bb156fb10cd83953a34f75b78835cdf399ee8b
URL: https://github.com/llvm/llvm-project/commit/f6bb156fb10cd83953a34f75b78835cdf399ee8b
DIFF: https://github.com/llvm/llvm-project/commit/f6bb156fb10cd83953a34f75b78835cdf399ee8b.diff
LOG: [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 https://github.com/llvm/llvm-project/issues/54089.
Differential revision: https://reviews.llvm.org/D123159
Test plan: make check-all
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
llvm/test/Transforms/InstCombine/select-binop-cmp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 1cf6e43991c5c..7fc3f5cfe69a6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -22,6 +22,7 @@
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
+#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/IRBuilder.h"
@@ -1529,6 +1530,36 @@ static Instruction *foldSelectZeroOrOnes(ICmpInst *Cmp, Value *TVal,
return nullptr;
}
+static Value *foldSelectInstWithICmpConst(SelectInst &SI, ICmpInst *ICI) {
+ const APInt *CmpC;
+ Value *V;
+ CmpInst::Predicate Pred;
+ if (!match(ICI, m_ICmp(Pred, m_Value(V), m_APInt(CmpC))))
+ return nullptr;
+
+ BinaryOperator *BO;
+ const APInt *C;
+ CmpInst::Predicate CPred;
+ if (match(&SI, m_Select(m_Specific(ICI), m_APInt(C), m_BinOp(BO))))
+ CPred = ICI->getPredicate();
+ else if (match(&SI, m_Select(m_Specific(ICI), m_BinOp(BO), m_APInt(C))))
+ CPred = ICI->getInversePredicate();
+ else
+ return nullptr;
+
+ const APInt *BinOpC;
+ if (!match(BO, m_BinOp(m_Specific(V), m_APInt(BinOpC))))
+ return nullptr;
+
+ ConstantRange R = ConstantRange::makeExactICmpRegion(CPred, *CmpC)
+ .binaryOp(BO->getOpcode(), *BinOpC);
+ if (R == *C) {
+ BO->dropPoisonGeneratingFlags();
+ return BO;
+ }
+ return nullptr;
+}
+
/// Visit a SelectInst that has an ICmpInst as its first operand.
Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
ICmpInst *ICI) {
@@ -1538,6 +1569,9 @@ Instruction *InstCombinerImpl::foldSelectInstWithICmp(SelectInst &SI,
if (Instruction *NewSPF = canonicalizeSPF(SI, *ICI, *this))
return NewSPF;
+ if (Value *V = foldSelectInstWithICmpConst(SI, ICI))
+ return replaceInstUsesWith(SI, V);
+
if (Value *V = canonicalizeClampLike(SI, *ICI, Builder))
return replaceInstUsesWith(SI, V);
diff --git a/llvm/test/Transforms/InstCombine/select-binop-cmp.ll b/llvm/test/Transforms/InstCombine/select-binop-cmp.ll
index 848d55abd4434..f9a708b2ee8c4 100644
--- a/llvm/test/Transforms/InstCombine/select-binop-cmp.ll
+++ b/llvm/test/Transforms/InstCombine/select-binop-cmp.ll
@@ -648,10 +648,8 @@ define i32 @select_or_icmp_bad(i32 %x, i32 %y, i32 %z) {
define i32 @select_lshr_icmp_const(i32 %x) {
; CHECK-LABEL: @select_lshr_icmp_const(
-; CHECK-NEXT: [[A:%.*]] = icmp ugt i32 %x, 31
; CHECK-NEXT: [[B:%.*]] = lshr i32 %x, 5
-; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 0
-; CHECK-NEXT: ret i32 [[C]]
+; CHECK-NEXT: ret i32 [[B]]
;
%A = icmp ugt i32 %x, 31
%B = lshr i32 %x, 5
@@ -661,10 +659,8 @@ define i32 @select_lshr_icmp_const(i32 %x) {
define i32 @select_lshr_icmp_const_reordered(i32 %x) {
; CHECK-LABEL: @select_lshr_icmp_const_reordered(
-; CHECK-NEXT: [[A:%.*]] = icmp ult i32 %x, 32
; CHECK-NEXT: [[B:%.*]] = lshr i32 %x, 5
-; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 0, i32 [[B]]
-; CHECK-NEXT: ret i32 [[C]]
+; CHECK-NEXT: ret i32 [[B]]
;
%A = icmp ult i32 %x, 32
%B = lshr i32 %x, 5
@@ -674,10 +670,8 @@ define i32 @select_lshr_icmp_const_reordered(i32 %x) {
define i32 @select_exact_lshr_icmp_const(i32 %x) {
; CHECK-LABEL: @select_exact_lshr_icmp_const(
-; CHECK-NEXT: [[A:%.*]] = icmp ugt i32 %x, 31
-; CHECK-NEXT: [[B:%.*]] = lshr exact i32 %x, 5
-; CHECK-NEXT: [[C:%.*]] = select i1 [[A]], i32 [[B]], i32 0
-; CHECK-NEXT: ret i32 [[C]]
+; CHECK-NEXT: [[B:%.*]] = lshr i32 %x, 5
+; CHECK-NEXT: ret i32 [[B]]
;
%A = icmp ugt i32 %x, 31
%B = lshr exact i32 %x, 5
More information about the llvm-commits
mailing list