forked from OSchip/llvm-project
[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:
parent
a94589d52f
commit
82190f917a
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]]
|
||||
;
|
||||
|
|
Loading…
Reference in New Issue