diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 9ab2bd8f70aa1..1056e75a9fb31 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2985,6 +2985,13 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) { return BinaryOperator::CreateOr(CondVal, FalseVal); } + if (match(CondVal, m_OneUse(m_Select(m_Value(A), m_One(), m_Value(B)))) && + impliesPoison(FalseVal, B)) { + // (A || B) || C --> A || (B | C) + return replaceInstUsesWith( + SI, Builder.CreateLogicalOr(A, Builder.CreateOr(B, FalseVal))); + } + if (auto *LHS = dyn_cast(CondVal)) if (auto *RHS = dyn_cast(FalseVal)) if (Value *V = foldLogicOfFCmps(LHS, RHS, /*IsAnd*/ false, @@ -3026,6 +3033,13 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) { return BinaryOperator::CreateAnd(CondVal, TrueVal); } + if (match(CondVal, m_OneUse(m_Select(m_Value(A), m_Value(B), m_Zero()))) && + impliesPoison(TrueVal, B)) { + // (A && B) && C --> A && (B & C) + return replaceInstUsesWith( + SI, Builder.CreateLogicalAnd(A, Builder.CreateAnd(B, TrueVal))); + } + if (auto *LHS = dyn_cast(CondVal)) if (auto *RHS = dyn_cast(TrueVal)) if (Value *V = foldLogicOfFCmps(LHS, RHS, /*IsAnd*/ true, diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll index c8d348df5f427..63b11d0c0bc08 100644 --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -3038,3 +3038,63 @@ define i32 @icmp_slt_0_or_icmp_add_1_sge_100_i32_fail(i32 %x) { %D = or i32 %C, %B ret i32 %D } + +define i1 @logical_and_icmps1(i32 %a, i1 %other_cond) { +; CHECK-LABEL: @logical_and_icmps1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP3:%.*]] = icmp ult i32 [[A:%.*]], 10086 +; CHECK-NEXT: [[RET2:%.*]] = select i1 [[RET1:%.*]], i1 [[CMP3]], i1 false +; CHECK-NEXT: ret i1 [[RET2]] +; +entry: + %cmp1 = icmp sgt i32 %a, -1 + %logical_and = select i1 %other_cond, i1 %cmp1, i1 false + %cmp2 = icmp slt i32 %a, 10086 + %ret = select i1 %logical_and, i1 %cmp2, i1 false + ret i1 %ret +} + +define i1 @logical_and_icmps2(i32 %a, i1 %other_cond) { +; CHECK-LABEL: @logical_and_icmps2( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i1 false +; +entry: + %cmp1 = icmp slt i32 %a, -1 + %logical_and = select i1 %other_cond, i1 %cmp1, i1 false + %cmp2 = icmp eq i32 %a, 10086 + %ret = select i1 %logical_and, i1 %cmp2, i1 false + ret i1 %ret +} + +define <4 x i1> @logical_and_icmps_vec1(<4 x i32> %a, <4 x i1> %other_cond) { +; CHECK-LABEL: @logical_and_icmps_vec1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP3:%.*]] = icmp ult <4 x i32> [[A:%.*]], +; CHECK-NEXT: [[RET2:%.*]] = select <4 x i1> [[RET1:%.*]], <4 x i1> [[CMP3]], <4 x i1> zeroinitializer +; CHECK-NEXT: ret <4 x i1> [[RET2]] +; +entry: + %cmp1 = icmp sgt <4 x i32> %a, + %logical_and = select <4 x i1> %other_cond, <4 x i1> %cmp1, <4 x i1> zeroinitializer + %cmp2 = icmp slt <4 x i32> %a, + %ret = select <4 x i1> %logical_and, <4 x i1> %cmp2, <4 x i1> zeroinitializer + ret <4 x i1> %ret +} + +define i1 @logical_and_icmps_fail1(i32 %a, i32 %b, i1 %other_cond) { +; CHECK-LABEL: @logical_and_icmps_fail1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[A:%.*]], -1 +; CHECK-NEXT: [[LOGICAL_AND:%.*]] = select i1 [[OTHER_COND:%.*]], i1 [[CMP1]], i1 false +; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], [[B:%.*]] +; CHECK-NEXT: [[RET:%.*]] = select i1 [[LOGICAL_AND]], i1 [[CMP2]], i1 false +; CHECK-NEXT: ret i1 [[RET]] +; +entry: + %cmp1 = icmp sgt i32 %a, -1 + %logical_and = select i1 %other_cond, i1 %cmp1, i1 false + %cmp2 = icmp slt i32 %a, %b + %ret = select i1 %logical_and, i1 %cmp2, i1 false + ret i1 %ret +} diff --git a/llvm/test/Transforms/InstCombine/logical-select.ll b/llvm/test/Transforms/InstCombine/logical-select.ll index f0ea09c088474..c850b87bb2dd4 100644 --- a/llvm/test/Transforms/InstCombine/logical-select.ll +++ b/llvm/test/Transforms/InstCombine/logical-select.ll @@ -1303,3 +1303,221 @@ define i1 @logical_or_and_with_common_not_op_variant5(i1 %a) { %or = select i1 %a, i1 true, i1 %and ret i1 %or } + +define i1 @reduce_logical_and1(i1 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @reduce_logical_and1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[CMP1]], [[CMP]] +; CHECK-NEXT: [[AND2:%.*]] = select i1 [[A:%.*]], i1 [[TMP0]], i1 false +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, %b + %and1 = select i1 %a, i1 %cmp1, i1 false + %and2 = select i1 %and1, i1 %cmp, i1 false + ret i1 %and2 +} + +define i1 @reduce_logical_and2(i1 %a, i1 %b, i1 %c) { +; CHECK-LABEL: @reduce_logical_and2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[C:%.*]], true +; CHECK-NEXT: [[B:%.*]] = and i1 [[TMP0]], [[B1:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = select i1 [[AND2:%.*]], i1 [[B]], i1 false +; CHECK-NEXT: ret i1 [[AND3]] +; +bb: + %or = xor i1 %c, %b + %and1 = select i1 %a, i1 %or, i1 false + %and2 = select i1 %and1, i1 %b, i1 false + ret i1 %and2 +} + +define i1 @reduce_logical_and3(i1 %a, i32 %b, i32 noundef %c) { +; CHECK-LABEL: @reduce_logical_and3( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[TMP0:%.*]] = and i1 [[CMP]], [[CMP1]] +; CHECK-NEXT: [[AND2:%.*]] = select i1 [[A:%.*]], i1 [[TMP0]], i1 false +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, %b + %and1 = select i1 %a, i1 %cmp, i1 false + %and2 = select i1 %and1, i1 %cmp1, i1 false + ret i1 %and2 +} + +define i1 @reduce_logical_or1(i1 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @reduce_logical_or1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[CMP1]], [[CMP]] +; CHECK-NEXT: [[AND2:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP0]] +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, %b + %and1 = select i1 %a, i1 true, i1 %cmp1 + %and2 = select i1 %and1, i1 true, i1 %cmp + ret i1 %and2 +} + +define i1 @reduce_logical_or2(i1 %a, i1 %b, i1 %c) { +; CHECK-LABEL: @reduce_logical_or2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[B:%.*]] = or i1 [[C:%.*]], [[B1:%.*]] +; CHECK-NEXT: [[AND3:%.*]] = select i1 [[AND2:%.*]], i1 true, i1 [[B]] +; CHECK-NEXT: ret i1 [[AND3]] +; +bb: + %or = xor i1 %c, %b + %and1 = select i1 %a, i1 true, i1 %or + %and2 = select i1 %and1, i1 true, i1 %b + ret i1 %and2 +} + +define i1 @reduce_logical_or3(i1 %a, i32 %b, i32 noundef %c) { +; CHECK-LABEL: @reduce_logical_or3( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[TMP0:%.*]] = or i1 [[CMP]], [[CMP1]] +; CHECK-NEXT: [[AND2:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[TMP0]] +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, %b + %and1 = select i1 %a, i1 true, i1 %cmp + %and2 = select i1 %and1, i1 true, i1 %cmp1 + ret i1 %and2 +} + +define i1 @reduce_logical_and_fail1(i1 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @reduce_logical_and_fail1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[AND1:%.*]] = select i1 [[A:%.*]], i1 [[CMP]], i1 false +; CHECK-NEXT: [[AND2:%.*]] = select i1 [[AND1]], i1 [[CMP1]], i1 false +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, %b + %and1 = select i1 %a, i1 %cmp, i1 false + %and2 = select i1 %and1, i1 %cmp1, i1 false + ret i1 %and2 +} + +define i1 @reduce_logical_and_fail2(i1 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @reduce_logical_and_fail2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], 7 +; CHECK-NEXT: [[AND1:%.*]] = select i1 [[A:%.*]], i1 [[CMP]], i1 false +; CHECK-NEXT: [[AND2:%.*]] = select i1 [[AND1]], i1 [[CMP1]], i1 false +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, 7 + %and1 = select i1 %a, i1 %cmp, i1 false + %and2 = select i1 %and1, i1 %cmp1, i1 false + ret i1 %and2 +} + +define i1 @reduce_logical_or_fail1(i1 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @reduce_logical_or_fail1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[AND1:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[CMP]] +; CHECK-NEXT: [[AND2:%.*]] = select i1 [[AND1]], i1 true, i1 [[CMP1]] +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, %b + %and1 = select i1 %a, i1 true, i1 %cmp + %and2 = select i1 %and1, i1 true, i1 %cmp1 + ret i1 %and2 +} + +define i1 @reduce_logical_or_fail2(i1 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @reduce_logical_or_fail2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], 7 +; CHECK-NEXT: [[AND1:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[CMP]] +; CHECK-NEXT: [[AND2:%.*]] = select i1 [[AND1]], i1 true, i1 [[CMP1]] +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, 7 + %and1 = select i1 %a, i1 true, i1 %cmp + %and2 = select i1 %and1, i1 true, i1 %cmp1 + ret i1 %and2 +} + +define i1 @reduce_logical_and_multiuse(i1 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @reduce_logical_and_multiuse( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[AND1:%.*]] = select i1 [[A:%.*]], i1 [[CMP1]], i1 false +; CHECK-NEXT: call void @use1(i1 [[AND1]]) +; CHECK-NEXT: [[AND2:%.*]] = select i1 [[AND1]], i1 [[CMP]], i1 false +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, %b + %and1 = select i1 %a, i1 %cmp1, i1 false + call void @use1(i1 %and1) + %and2 = select i1 %and1, i1 %cmp, i1 false + ret i1 %and2 +} + +define i1 @reduce_bitwise_and1(i1 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @reduce_bitwise_and1( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[AND1:%.*]] = or i1 [[CMP1]], [[A:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = and i1 [[AND1]], [[CMP]] +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, %b + %and1 = or i1 %a, %cmp1 + %and2 = select i1 %and1, i1 %cmp, i1 false + ret i1 %and2 +} + +define i1 @reduce_bitwise_and2(i1 %a, i32 %b, i32 %c) { +; CHECK-LABEL: @reduce_bitwise_and2( +; CHECK-NEXT: bb: +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[B:%.*]], 6 +; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[C:%.*]], [[B]] +; CHECK-NEXT: [[AND1:%.*]] = select i1 [[A:%.*]], i1 [[CMP1]], i1 false +; CHECK-NEXT: [[AND2:%.*]] = or i1 [[AND1]], [[CMP]] +; CHECK-NEXT: ret i1 [[AND2]] +; +bb: + %cmp = icmp slt i32 %b, 6 + %cmp1 = icmp sgt i32 %c, %b + %and1 = select i1 %a, i1 %cmp1, i1 false + %and2 = or i1 %and1, %cmp + ret i1 %and2 +}