/// common operand with the constant. Callers are expected to call this with
/// Cmp0/Cmp1 switched to handle logic op commutativity.
static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
- bool IsAnd,
+ bool IsAnd, bool IsLogical,
InstCombiner::BuilderTy &Builder,
const SimplifyQuery &Q) {
// Match an equality compare with a non-poison constant as Cmp0.
return nullptr;
SubstituteCmp = Builder.CreateICmp(Pred1, Y, C);
}
+ if (IsLogical)
+ return IsAnd ? Builder.CreateLogicalAnd(Cmp0, SubstituteCmp)
+ : Builder.CreateLogicalOr(Cmp0, SubstituteCmp);
return Builder.CreateBinOp(IsAnd ? Instruction::And : Instruction::Or, Cmp0,
SubstituteCmp);
}
/*IsLogical*/ false, Builder))
return V;
- // TODO: Verify whether this is safe for logical and/or.
- if (!IsLogical) {
- if (Value *V = foldAndOrOfICmpsWithConstEq(LHS, RHS, IsAnd, Builder, Q))
- return V;
- if (Value *V = foldAndOrOfICmpsWithConstEq(RHS, LHS, IsAnd, Builder, Q))
- return V;
- }
+ if (Value *V =
+ foldAndOrOfICmpsWithConstEq(LHS, RHS, IsAnd, IsLogical, Builder, Q))
+ return V;
+ // We can convert this case to bitwise and, because both operands are used
+ // on the LHS, and as such poison from both will propagate.
+ if (Value *V = foldAndOrOfICmpsWithConstEq(RHS, LHS, IsAnd,
+ /*IsLogical*/ false, Builder, Q))
+ return V;
if (Value *V = foldIsPowerOf2OrZero(LHS, RHS, IsAnd, Builder))
return V;
define i1 @substitute_constant_and_eq_eq_logical(i8 %x, i8 %y) {
; CHECK-LABEL: @substitute_constant_and_eq_eq_logical(
; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X:%.*]], 42
-; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[Y:%.*]], 42
-; CHECK-NEXT: [[R:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[Y:%.*]], 42
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C1]], i1 [[TMP1]], i1 false
+; CHECK-NEXT: ret i1 [[TMP2]]
;
%c1 = icmp eq i8 %x, 42
%c2 = icmp eq i8 %x, %y
define <2 x i1> @substitute_constant_and_eq_ne_vec_logical(<2 x i8> %x, <2 x i8> %y) {
; CHECK-LABEL: @substitute_constant_and_eq_ne_vec_logical(
; CHECK-NEXT: [[C1:%.*]] = icmp eq <2 x i8> [[X:%.*]], <i8 42, i8 97>
-; CHECK-NEXT: [[C2:%.*]] = icmp ne <2 x i8> [[X]], [[Y:%.*]]
-; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C1]], <2 x i1> [[C2]], <2 x i1> zeroinitializer
-; CHECK-NEXT: ret <2 x i1> [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i8> [[Y:%.*]], <i8 42, i8 97>
+; CHECK-NEXT: [[TMP2:%.*]] = select <2 x i1> [[C1]], <2 x i1> [[TMP1]], <2 x i1> zeroinitializer
+; CHECK-NEXT: ret <2 x i1> [[TMP2]]
;
%c1 = icmp eq <2 x i8> %x, <i8 42, i8 97>
%c2 = icmp ne <2 x i8> %x, %y
define i1 @substitute_constant_or_ne_swap_sle_logical(i8 %x, i8 %y) {
; CHECK-LABEL: @substitute_constant_or_ne_swap_sle_logical(
; CHECK-NEXT: [[C1:%.*]] = icmp ne i8 [[X:%.*]], 42
-; CHECK-NEXT: [[C2:%.*]] = icmp slt i8 [[Y:%.*]], 43
-; CHECK-NEXT: [[R:%.*]] = select i1 [[C1]], i1 true, i1 [[C2]]
-; CHECK-NEXT: ret i1 [[R]]
+; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[Y:%.*]], 43
+; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[C1]], i1 true, i1 [[TMP1]]
+; CHECK-NEXT: ret i1 [[TMP2]]
;
%c1 = icmp ne i8 %x, 42
%c2 = icmp sle i8 %y, %x