[InstCombine] Fold icmp of select with implied condition

When threading the icmp over the select, check whether the
condition can be folded when taking into account the select
condition.
This commit is contained in:
Nikita Popov 2022-05-06 16:48:02 +02:00
parent a94589d52f
commit 82190f917a
3 changed files with 28 additions and 19 deletions

View File

@ -3450,12 +3450,21 @@ Instruction *InstCombinerImpl::foldSelectICmp(ICmpInst::Predicate Pred,
const ICmpInst &I) {
// Try to fold the comparison into the select arms, which will cause the
// select to be converted into a logical and/or.
auto SimplifyOp = [&](Value *Op, bool SelectCondIsTrue) -> Value * {
if (Value *Res = SimplifyICmpInst(Pred, Op, RHS, SQ))
return Res;
if (Optional<bool> Impl = isImpliedCondition(SI->getCondition(), Pred, Op,
RHS, DL, SelectCondIsTrue))
return ConstantInt::get(I.getType(), *Impl);
return nullptr;
};
ConstantInt *CI = nullptr;
Value *Op1 = SimplifyICmpInst(Pred, SI->getOperand(1), RHS, SQ);
Value *Op1 = SimplifyOp(SI->getOperand(1), true);
if (Op1)
CI = dyn_cast<ConstantInt>(Op1);
Value *Op2 = SimplifyICmpInst(Pred, SI->getOperand(2), RHS, SQ);
Value *Op2 = SimplifyOp(SI->getOperand(2), false);
if (Op2)
CI = dyn_cast<ConstantInt>(Op2);

View File

@ -166,8 +166,8 @@ define i1 @icmp_select_var_pred_uge_commuted(i8 %x, i8 %y, i8 %z) {
define i1 @icmp_select_implied_cond(i8 %x, i8 %y) {
; CHECK-LABEL: @icmp_select_implied_cond(
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 0, i8 [[Y:%.*]]
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[SEL]], [[X]]
; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]]
; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp eq i8 %x, 0
@ -178,9 +178,9 @@ define i1 @icmp_select_implied_cond(i8 %x, i8 %y) {
define i1 @icmp_select_implied_cond_ne(i8 %x, i8 %y) {
; CHECK-LABEL: @icmp_select_implied_cond_ne(
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 0, i8 [[Y:%.*]]
; CHECK-NEXT: [[CMP2:%.*]] = icmp ne i8 [[SEL]], [[X]]
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
; CHECK-NEXT: [[CMP21:%.*]] = icmp ne i8 [[Y:%.*]], [[X]]
; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp eq i8 %x, 0
@ -192,8 +192,8 @@ define i1 @icmp_select_implied_cond_ne(i8 %x, i8 %y) {
define i1 @icmp_select_implied_cond_swapped_select(i8 %x, i8 %y) {
; CHECK-LABEL: @icmp_select_implied_cond_swapped_select(
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 [[Y:%.*]], i8 0
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[SEL]], [[X]]
; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], 0
; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp eq i8 %x, 0
@ -206,8 +206,9 @@ define i1 @icmp_select_implied_cond_swapped_select_with_inv_cond(i8 %x, i8 %y) {
; CHECK-LABEL: @icmp_select_implied_cond_swapped_select_with_inv_cond(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0
; CHECK-NEXT: call void @use.i1(i1 [[CMP1]])
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 [[Y:%.*]], i8 0
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[SEL]], [[X]]
; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]]
; CHECK-NEXT: [[NOT_CMP1:%.*]] = xor i1 [[CMP1]], true
; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[NOT_CMP1]], i1 true, i1 [[CMP21]]
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp ne i8 %x, 0
@ -220,8 +221,8 @@ define i1 @icmp_select_implied_cond_swapped_select_with_inv_cond(i8 %x, i8 %y) {
define i1 @icmp_select_implied_cond_relational(i8 %x, i8 %y) {
; CHECK-LABEL: @icmp_select_implied_cond_relational(
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[X:%.*]], 10
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 10, i8 [[Y:%.*]]
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[SEL]], [[X]]
; CHECK-NEXT: [[CMP21:%.*]] = icmp ult i8 [[Y:%.*]], [[X]]
; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
; CHECK-NEXT: ret i1 [[CMP2]]
;
%cmp1 = icmp ugt i8 %x, 10
@ -247,10 +248,9 @@ define i1 @icmp_select_implied_cond_relational_off_by_one(i8 %x, i8 %y) {
define i1 @umin_seq_comparison(i8 %x, i8 %y) {
; CHECK-LABEL: @umin_seq_comparison(
; CHECK-NEXT: [[MIN:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 [[Y:%.*]])
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X]], 0
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 0, i8 [[MIN]]
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[SEL]], [[X]]
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0
; CHECK-NEXT: [[CMP21:%.*]] = icmp ule i8 [[X]], [[Y:%.*]]
; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]]
; CHECK-NEXT: ret i1 [[CMP2]]
;
%min = call i8 @llvm.umin.i8(i8 %x, i8 %y)

View File

@ -99,8 +99,8 @@ define i32 @t8(i64 %a, i32 %b) {
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @llvm.smin.i64(i64 [[A:%.*]], i64 -32767)
; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[B:%.*]], 42
; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP3]], i32 42, i32 [[TMP2]]
; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i32 [[TMP4]], [[B]]
; CHECK-NEXT: [[TMP4:%.*]] = icmp ne i32 [[TMP2]], [[B]]
; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i1 true, i1 [[TMP4]]
; CHECK-NEXT: [[TMP6:%.*]] = zext i1 [[TMP5]] to i32
; CHECK-NEXT: ret i32 [[TMP6]]
;