diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1137,6 +1137,51 @@ return nullptr; } +/// Reduce logic-of-compares with equality to a constant by substituting a +/// 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, + BinaryOperator &Logic, + InstCombiner::BuilderTy &Builder, + const SimplifyQuery &Q) { + bool IsAnd = Logic.getOpcode() == Instruction::And; + assert(IsAnd || Logic.getOpcode() == Instruction::Or && "Wrong logic op"); + + // Match an equality compare with a non-poison constant as Cmp0. + ICmpInst::Predicate Pred0; + Value *X; + Constant *C; + if (!match(Cmp0, m_ICmp(Pred0, m_Value(X), m_Constant(C))) || + !isGuaranteedNotToBeUndefOrPoison(C)) + return nullptr; + if ((IsAnd && Pred0 != ICmpInst::ICMP_EQ) || + (!IsAnd && Pred0 != ICmpInst::ICMP_NE)) + return nullptr; + + // The other compare must include a common operand (X). Canonicalize the + // common operand as operand 1 (Pred1 is swapped if the common operand was + // operand 0). + Value *Y; + ICmpInst::Predicate Pred1; + if (!match(Cmp1, m_c_ICmp(Pred1, m_Value(Y), m_Deferred(X)))) + return nullptr; + + // Replace variable with constant value equivalence to remove a variable use: + // (X == C) && (Y Pred1 X) --> (X == C) && (Y Pred1 C) + // (X != C) || (Y Pred1 X) --> (X != C) || (Y Pred1 C) + // Can think of the 'or' substitution with the 'and' bool equivalent: + // A || B --> A || (!A && B) + Value *SubstituteCmp = SimplifyICmpInst(Pred1, Y, C, Q); + if (!SubstituteCmp) { + // If we need to create a new instruction, require that the old compare can + // be removed. + if (!Cmp1->hasOneUse()) + return nullptr; + SubstituteCmp = Builder.CreateICmp(Pred1, Y, C); + } + return Builder.CreateBinOp(Logic.getOpcode(), Cmp0, SubstituteCmp); +} + /// Fold (icmp)&(icmp) if possible. Value *InstCombiner::foldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS, BinaryOperator &And) { @@ -1167,6 +1212,11 @@ if (Value *V = foldLogOpOfMaskedICmps(LHS, RHS, true, Builder)) return V; + if (Value *V = foldAndOrOfICmpsWithConstEq(LHS, RHS, And, Builder, Q)) + return V; + if (Value *V = foldAndOrOfICmpsWithConstEq(RHS, LHS, And, Builder, Q)) + return V; + // E.g. (icmp sge x, 0) & (icmp slt x, n) --> icmp ult x, n if (Value *V = simplifyRangeCheck(LHS, RHS, /*Inverted=*/false)) return V; @@ -2295,6 +2345,11 @@ Builder.CreateAdd(B, ConstantInt::getSigned(B->getType(), -1)), A); } + if (Value *V = foldAndOrOfICmpsWithConstEq(LHS, RHS, Or, Builder, Q)) + return V; + if (Value *V = foldAndOrOfICmpsWithConstEq(RHS, LHS, Or, Builder, Q)) + return V; + // E.g. (icmp slt x, 0) | (icmp sgt x, n) --> icmp ugt x, n if (Value *V = simplifyRangeCheck(LHS, RHS, /*Inverted=*/true)) return V; diff --git a/llvm/test/Transforms/InstCombine/and-or-icmp-min-max.ll b/llvm/test/Transforms/InstCombine/and-or-icmp-min-max.ll --- a/llvm/test/Transforms/InstCombine/and-or-icmp-min-max.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmp-min-max.ll @@ -15,10 +15,7 @@ define i1 @slt_and_max(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_and_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp slt i8 %x, %y %cmpeq = icmp eq i8 %x, 127 @@ -28,10 +25,7 @@ define <2 x i1> @slt_and_max_commute(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @slt_and_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq <2 x i8> [[X]], -; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %cmp = icmp slt <2 x i8> %x, %y %cmpeq = icmp eq <2 x i8> %x, @@ -41,10 +35,7 @@ define i1 @slt_swap_and_max(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_swap_and_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp sgt i8 %y, %x %cmpeq = icmp eq i8 %x, 127 @@ -54,10 +45,7 @@ define i1 @slt_swap_and_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_swap_and_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp sgt i8 %y, %x %cmpeq = icmp eq i8 %x, 127 @@ -67,10 +55,7 @@ define i1 @ult_and_max(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_and_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp ult i8 %x, %y %cmpeq = icmp eq i8 %x, 255 @@ -80,10 +65,7 @@ define i1 @ult_and_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_and_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp ult i8 %x, %y %cmpeq = icmp eq i8 %x, 255 @@ -93,10 +75,7 @@ define i1 @ult_swap_and_max(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_swap_and_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp ugt i8 %y, %x %cmpeq = icmp eq i8 %x, 255 @@ -106,10 +85,7 @@ define i1 @ult_swap_and_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_swap_and_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp ugt i8 %y, %x %cmpeq = icmp eq i8 %x, 255 @@ -125,10 +101,7 @@ define i1 @sgt_and_min(i9 %x, i9 %y) { ; CHECK-LABEL: @sgt_and_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i9 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i9 [[X]], -256 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp sgt i9 %x, %y %cmpeq = icmp eq i9 %x, 256 @@ -138,10 +111,7 @@ define i1 @sgt_and_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_and_min_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp sgt i8 %x, %y %cmpeq = icmp eq i8 %x, 128 @@ -151,10 +121,7 @@ define i1 @sgt_swap_and_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_swap_and_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp slt i8 %y, %x %cmpeq = icmp eq i8 %x, 128 @@ -164,10 +131,7 @@ define i1 @sgt_swap_and_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_swap_and_min_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %cmp = icmp slt i8 %y, %x %cmpeq = icmp eq i8 %x, 128 @@ -223,10 +187,7 @@ define i1 @sge_or_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_or_not_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp sge i8 %x, %y %cmpeq = icmp ne i8 %x, 127 @@ -236,10 +197,7 @@ define i1 @sge_or_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_or_not_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp sge i8 %x, %y %cmpeq = icmp ne i8 %x, 127 @@ -249,10 +207,7 @@ define i1 @sge_swap_or_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_swap_or_not_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp sle i8 %y, %x %cmpeq = icmp ne i8 %x, 127 @@ -262,10 +217,7 @@ define i1 @sge_swap_or_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_swap_or_not_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp sle i8 %y, %x %cmpeq = icmp ne i8 %x, 127 @@ -275,10 +227,7 @@ define i1 @uge_or_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_or_not_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp uge i8 %x, %y %cmpeq = icmp ne i8 %x, 255 @@ -288,10 +237,7 @@ define i1 @uge_or_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_or_not_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp uge i8 %x, %y %cmpeq = icmp ne i8 %x, 255 @@ -301,10 +247,7 @@ define i1 @uge_swap_or_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_swap_or_not_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp ule i8 %y, %x %cmpeq = icmp ne i8 %x, 255 @@ -314,10 +257,7 @@ define i1 @uge_swap_or_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_swap_or_not_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp ule i8 %y, %x %cmpeq = icmp ne i8 %x, 255 @@ -333,10 +273,7 @@ define i1 @sle_or_not_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_or_not_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp sle i8 %x, %y %cmpeq = icmp ne i8 %x, 128 @@ -346,10 +283,7 @@ define i1 @sle_or_not_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_or_not_min_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp sle i8 %x, %y %cmpeq = icmp ne i8 %x, 128 @@ -359,10 +293,7 @@ define i1 @sle_swap_or_not_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_swap_or_not_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp sge i8 %y, %x %cmpeq = icmp ne i8 %x, 128 @@ -372,10 +303,7 @@ define i1 @sle_swap_or_not_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_swap_or_not_min_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %cmp = icmp sge i8 %y, %x %cmpeq = icmp ne i8 %x, 128 @@ -431,10 +359,8 @@ define i1 @sge_and_max(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_and_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], 127 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sge i8 %x, %y %cmpeq = icmp eq i8 %x, 127 @@ -444,10 +370,8 @@ define i1 @sge_and_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_and_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], 127 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sge i8 %x, %y %cmpeq = icmp eq i8 %x, 127 @@ -457,10 +381,8 @@ define i1 @sge_swap_and_max(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_swap_and_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], 127 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sle i8 %y, %x %cmpeq = icmp eq i8 %x, 127 @@ -470,10 +392,8 @@ define i1 @sge_swap_and_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sge_swap_and_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], 127 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sle i8 %y, %x %cmpeq = icmp eq i8 %x, 127 @@ -483,10 +403,8 @@ define i1 @uge_and_max(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_and_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp uge i8 %x, %y %cmpeq = icmp eq i8 %x, 255 @@ -496,10 +414,8 @@ define i1 @uge_and_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_and_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp uge i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp uge i8 %x, %y %cmpeq = icmp eq i8 %x, 255 @@ -509,10 +425,8 @@ define i1 @uge_swap_and_max(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_swap_and_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp ule i8 %y, %x %cmpeq = icmp eq i8 %x, 255 @@ -522,10 +436,8 @@ define i1 @uge_swap_and_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @uge_swap_and_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp ule i8 %y, %x %cmpeq = icmp eq i8 %x, 255 @@ -541,10 +453,8 @@ define i1 @sle_and_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_and_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], -128 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sle i8 %x, %y %cmpeq = icmp eq i8 %x, 128 @@ -554,10 +464,8 @@ define i1 @sle_and_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_and_min_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], -128 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sle i8 %x, %y %cmpeq = icmp eq i8 %x, 128 @@ -567,10 +475,8 @@ define i1 @sle_swap_and_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_swap_and_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], -128 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sge i8 %y, %x %cmpeq = icmp eq i8 %x, 128 @@ -580,10 +486,8 @@ define i1 @sle_swap_and_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sle_swap_and_min_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sge i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8 [[X:%.*]], -128 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sge i8 %y, %x %cmpeq = icmp eq i8 %x, 128 @@ -1019,10 +923,8 @@ define i1 @slt_or_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_or_not_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], 127 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp slt i8 %x, %y %cmpeq = icmp ne i8 %x, 127 @@ -1032,10 +934,8 @@ define i1 @slt_or_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_or_not_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], 127 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp slt i8 %x, %y %cmpeq = icmp ne i8 %x, 127 @@ -1045,10 +945,8 @@ define i1 @slt_swap_or_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_swap_or_not_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], 127 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sgt i8 %y, %x %cmpeq = icmp ne i8 %x, 127 @@ -1058,10 +956,8 @@ define i1 @slt_swap_or_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_swap_or_not_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], 127 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], 127 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sgt i8 %y, %x %cmpeq = icmp ne i8 %x, 127 @@ -1071,10 +967,8 @@ define i1 @ult_or_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_or_not_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp ult i8 %x, %y %cmpeq = icmp ne i8 %x, 255 @@ -1084,10 +978,8 @@ define i1 @ult_or_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_or_not_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp ult i8 %x, %y %cmpeq = icmp ne i8 %x, 255 @@ -1097,10 +989,8 @@ define i1 @ult_swap_or_not_max(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_swap_or_not_max( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp ugt i8 %y, %x %cmpeq = icmp ne i8 %x, 255 @@ -1110,10 +1000,8 @@ define i1 @ult_swap_or_not_max_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @ult_swap_or_not_max_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -1 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], -1 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp ugt i8 %y, %x %cmpeq = icmp ne i8 %x, 255 @@ -1129,10 +1017,8 @@ define i1 @sgt_or_not_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_or_not_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], -128 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sgt i8 %x, %y %cmpeq = icmp ne i8 %x, 128 @@ -1142,10 +1028,8 @@ define i1 @sgt_or_not_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_or_not_min_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], -128 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp sgt i8 %x, %y %cmpeq = icmp ne i8 %x, 128 @@ -1155,10 +1039,8 @@ define i1 @sgt_swap_or_not_min(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_swap_or_not_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], -128 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp slt i8 %y, %x %cmpeq = icmp ne i8 %x, 128 @@ -1168,10 +1050,8 @@ define i1 @sgt_swap_or_not_min_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @sgt_swap_or_not_min_commute( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[Y:%.*]], [[X:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X]], -128 -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8 [[X:%.*]], -128 +; CHECK-NEXT: ret i1 [[CMPEQ]] ; %cmp = icmp slt i8 %y, %x %cmpeq = icmp ne i8 %x, 128 diff --git a/llvm/test/Transforms/InstCombine/and-or-icmp-nullptr.ll b/llvm/test/Transforms/InstCombine/and-or-icmp-nullptr.ll --- a/llvm/test/Transforms/InstCombine/and-or-icmp-nullptr.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmp-nullptr.ll @@ -304,10 +304,10 @@ define i1 @sgt_and_min(i9* %x, i9* %y) { ; CHECK-LABEL: @sgt_and_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i9* [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i9* [[X]], null -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i9* [[X:%.*]], null +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i9* [[Y:%.*]], null +; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[CMPEQ]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %cmp = icmp sgt i9* %x, %y %cmpeq = icmp eq i9* %x, null @@ -317,10 +317,10 @@ define i1 @sle_or_not_min(i427* %x, i427* %y) { ; CHECK-LABEL: @sle_or_not_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i427* [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i427* [[X]], null -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i427* [[X:%.*]], null +; CHECK-NEXT: [[TMP1:%.*]] = icmp sge i427* [[Y:%.*]], null +; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[CMPEQ]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %cmp = icmp sle i427* %x, %y %cmpeq = icmp ne i427* %x, null @@ -330,10 +330,10 @@ define i1 @sle_and_min(i8* %x, i8* %y) { ; CHECK-LABEL: @sle_and_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i8* [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8* [[X]], null -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8* [[X:%.*]], null +; CHECK-NEXT: [[TMP1:%.*]] = icmp sge i8* [[Y:%.*]], null +; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[CMPEQ]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %cmp = icmp sle i8* %x, %y %cmpeq = icmp eq i8* %x, null @@ -356,10 +356,10 @@ define i1 @sgt_or_not_min(i8* %x, i8* %y) { ; CHECK-LABEL: @sgt_or_not_min( -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8* [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8* [[X]], null -; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP]], [[CMPEQ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[CMPEQ:%.*]] = icmp ne i8* [[X:%.*]], null +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8* [[Y:%.*]], null +; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[CMPEQ]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %cmp = icmp sgt i8* %x, %y %cmpeq = icmp ne i8* %x, null @@ -370,9 +370,9 @@ define i1 @slt_and_min(i8* %a, i8* %b) { ; CHECK-LABEL: @slt_and_min( ; CHECK-NEXT: [[CMPEQ:%.*]] = icmp eq i8* [[A:%.*]], null -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8* [[A]], [[B:%.*]] -; CHECK-NEXT: [[R:%.*]] = and i1 [[CMPEQ]], [[CMP]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8* [[B:%.*]], null +; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[CMPEQ]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %cmpeq = icmp eq i8* %a, null %cmp = icmp slt i8* %a, %b diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -382,9 +382,9 @@ define i1 @substitute_constant_and_eq_eq(i8 %x, i8 %y) { ; CHECK-LABEL: @substitute_constant_and_eq_eq( ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X:%.*]], 42 -; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = and i1 [[C1]], [[C2]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[Y:%.*]], 42 +; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[C1]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %c1 = icmp eq i8 %x, 42 %c2 = icmp eq i8 %x, %y @@ -395,9 +395,9 @@ define i1 @substitute_constant_and_eq_eq_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @substitute_constant_and_eq_eq_commute( ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X:%.*]], 42 -; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = and i1 [[C2]], [[C1]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[Y:%.*]], 42 +; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[C1]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %c1 = icmp eq i8 %x, 42 %c2 = icmp eq i8 %x, %y @@ -408,9 +408,9 @@ define i1 @substitute_constant_and_eq_ugt_swap(i8 %x, i8 %y) { ; CHECK-LABEL: @substitute_constant_and_eq_ugt_swap( ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X:%.*]], 42 -; CHECK-NEXT: [[C2:%.*]] = icmp ugt i8 [[Y:%.*]], [[X]] -; CHECK-NEXT: [[R:%.*]] = and i1 [[C2]], [[C1]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i8 [[Y:%.*]], 42 +; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[C1]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %c1 = icmp eq i8 %x, 42 %c2 = icmp ugt i8 %y, %x @@ -421,9 +421,9 @@ define <2 x i1> @substitute_constant_and_eq_ne_vec(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @substitute_constant_and_eq_ne_vec( ; CHECK-NEXT: [[C1:%.*]] = icmp eq <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[C2:%.*]] = icmp ne <2 x i8> [[X]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[C1]], [[C2]] -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i8> [[Y:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i1> [[C1]], [[TMP1]] +; CHECK-NEXT: ret <2 x i1> [[TMP2]] ; %c1 = icmp eq <2 x i8> %x, %c2 = icmp ne <2 x i8> %x, %y @@ -435,9 +435,9 @@ ; CHECK-LABEL: @substitute_constant_and_eq_sgt_use( ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X:%.*]], 42 ; CHECK-NEXT: call void @use(i1 [[C1]]) -; CHECK-NEXT: [[C2:%.*]] = icmp sgt i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = and i1 [[C2]], [[C1]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[Y:%.*]], 42 +; CHECK-NEXT: [[TMP2:%.*]] = and i1 [[C1]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %c1 = icmp eq i8 %x, 42 call void @use(i1 %c1) @@ -446,6 +446,8 @@ ret i1 %r } +; Negative test - extra use + define i1 @substitute_constant_and_eq_sgt_use2(i8 %x, i8 %y) { ; CHECK-LABEL: @substitute_constant_and_eq_sgt_use2( ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X:%.*]], 42 @@ -461,15 +463,14 @@ ret i1 %r } +; Extra use does not prevent transform if the expression simplifies: ; X == MAX && X < Y --> false define i1 @slt_and_max(i8 %x, i8 %y) { ; CHECK-LABEL: @slt_and_max( -; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X:%.*]], 127 -; CHECK-NEXT: [[C2:%.*]] = icmp slt i8 [[X]], [[Y:%.*]] +; CHECK-NEXT: [[C2:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @use(i1 [[C2]]) -; CHECK-NEXT: [[R:%.*]] = and i1 [[C2]], [[C1]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %c1 = icmp eq i8 %x, 127 %c2 = icmp slt i8 %x, %y @@ -478,6 +479,7 @@ ret i1 %r } +; Extra use does not prevent transform if the expression simplifies: ; X == MAX && X >= Y --> X == MAX define i1 @sge_and_max(i8 %x, i8 %y) { @@ -485,8 +487,7 @@ ; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[X:%.*]], 127 ; CHECK-NEXT: [[C2:%.*]] = icmp sge i8 [[X]], [[Y:%.*]] ; CHECK-NEXT: call void @use(i1 [[C2]]) -; CHECK-NEXT: [[R:%.*]] = and i1 [[C2]], [[C1]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 [[C1]] ; %c1 = icmp eq i8 %x, 127 %c2 = icmp sge i8 %x, %y @@ -511,9 +512,9 @@ define i1 @substitute_constant_or_ne_swap_sle(i8 %x, i8 %y) { ; CHECK-LABEL: @substitute_constant_or_ne_swap_sle( ; CHECK-NEXT: [[C1:%.*]] = icmp ne i8 [[X:%.*]], 42 -; CHECK-NEXT: [[C2:%.*]] = icmp sle i8 [[Y:%.*]], [[X]] -; CHECK-NEXT: [[R:%.*]] = or i1 [[C1]], [[C2]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[Y:%.*]], 43 +; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[C1]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %c1 = icmp ne i8 %x, 42 %c2 = icmp sle i8 %y, %x @@ -524,9 +525,9 @@ define i1 @substitute_constant_or_ne_uge_commute(i8 %x, i8 %y) { ; CHECK-LABEL: @substitute_constant_or_ne_uge_commute( ; CHECK-NEXT: [[C1:%.*]] = icmp ne i8 [[X:%.*]], 42 -; CHECK-NEXT: [[C2:%.*]] = icmp uge i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = or i1 [[C2]], [[C1]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[Y:%.*]], 43 +; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[C1]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %c1 = icmp ne i8 %x, 42 %c2 = icmp uge i8 %x, %y @@ -534,6 +535,8 @@ ret i1 %r } +; Negative test - not safe to substitute vector constant with undef element + define <2 x i1> @substitute_constant_or_ne_slt_swap_vec(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @substitute_constant_or_ne_slt_swap_vec( ; CHECK-NEXT: [[C1:%.*]] = icmp ne <2 x i8> [[X:%.*]], @@ -564,9 +567,9 @@ ; CHECK-LABEL: @substitute_constant_or_ne_sge_use( ; CHECK-NEXT: [[C1:%.*]] = icmp ne i8 [[X:%.*]], 42 ; CHECK-NEXT: call void @use(i1 [[C1]]) -; CHECK-NEXT: [[C2:%.*]] = icmp sge i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = or i1 [[C2]], [[C1]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[Y:%.*]], 43 +; CHECK-NEXT: [[TMP2:%.*]] = or i1 [[C1]], [[TMP1]] +; CHECK-NEXT: ret i1 [[TMP2]] ; %c1 = icmp ne i8 %x, 42 call void @use(i1 %c1) @@ -575,6 +578,8 @@ ret i1 %r } +; Negative test - extra use + define i1 @substitute_constant_or_ne_ule_use2(i8 %x, i8 %y) { ; CHECK-LABEL: @substitute_constant_or_ne_ule_use2( ; CHECK-NEXT: [[C1:%.*]] = icmp ne i8 [[X:%.*]], 42