From 82190f917ac4813e22a334b805e84dba8ed4f47d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 6 May 2022 16:48:02 +0200 Subject: [PATCH] [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. --- .../Transforms/InstCombine/InstCombineCompares.cpp | 13 ++++++++-- llvm/test/Transforms/InstCombine/icmp-select.ll | 30 +++++++++++----------- llvm/test/Transforms/InstCombine/minmax-fold.ll | 4 +-- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 06e6f25..4cc377c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -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 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(Op1); - Value *Op2 = SimplifyICmpInst(Pred, SI->getOperand(2), RHS, SQ); + Value *Op2 = SimplifyOp(SI->getOperand(2), false); if (Op2) CI = dyn_cast(Op2); diff --git a/llvm/test/Transforms/InstCombine/icmp-select.ll b/llvm/test/Transforms/InstCombine/icmp-select.ll index 3c6a746..5332ef3 100644 --- a/llvm/test/Transforms/InstCombine/icmp-select.ll +++ b/llvm/test/Transforms/InstCombine/icmp-select.ll @@ -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) diff --git a/llvm/test/Transforms/InstCombine/minmax-fold.ll b/llvm/test/Transforms/InstCombine/minmax-fold.ll index 1f05370..a3119d0 100644 --- a/llvm/test/Transforms/InstCombine/minmax-fold.ll +++ b/llvm/test/Transforms/InstCombine/minmax-fold.ll @@ -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]] ; -- 2.7.4