diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -1118,6 +1118,150 @@ return nullptr; } +// See if this is a pattern like: +// %old_cmp1 = icmp slt i32 %x, C2 +// %old_replacement = select i1 %old_cmp1, i32 %target_low, i32 %target_high +// %old_x_offseted = add i32 %x, C1 +// %old_cmp0 = icmp ult i32 %old_x_offseted, C0 +// %r = select i1 %old_cmp0, i32 %x, i32 %old_replacement +// This can be rewriten as more canonical pattern: +// %new_cmp1 = icmp slt i32 %x, -C1 +// %new_cmp2 = icmp sge i32 %x, C0-C1 +// %new_clamped_low = select i1 %new_cmp1, i32 %target_low, i32 %x +// %r = select i1 %new_cmp2, i32 %target_high, i32 %new_clamped_low +// Iff -C1 s<= C2 s<= C0-C1 +// Also, ULT predicate can also be UGE; or UGT iff C0 != -1 (+invert result) +// Also, SLT predicate can also be SGE; or SGT iff C2 != INT_MAX (+invert res.) +static Instruction *canonicalizeClampLike(SelectInst &Sel0, ICmpInst &Cmp0, + InstCombiner::BuilderTy &Builder) { + Value *X = Sel0.getTrueValue(); + Value *Sel1 = Sel0.getFalseValue(); + + // First match the condition of the outermost select. + // Said condition must be one-use. + if (!Cmp0.hasOneUse()) + return nullptr; + Value *Cmp00 = Cmp0.getOperand(0); + Constant *C0; + if (!match(Cmp0.getOperand(1), + m_CombineAnd(m_AnyIntegralConstant(), m_Constant(C0)))) + return nullptr; + // Canonicalize Cmp0 into the form we expect. + // FIXME: we shouldn't care about lanes that are 'undef' in the end? + switch (Cmp0.getPredicate()) { + case ICmpInst::Predicate::ICMP_ULT: + break; // Great! + case ICmpInst::Predicate::ICMP_ULE: + // We'd have to increment C0 by one, and for that it must not have all-ones + // element, but then it would have been canonicalized to 'ult' before + // we get here. So we can't do anything useful with 'ule'. + return nullptr; + case ICmpInst::Predicate::ICMP_UGT: + // We want to canonicalize it to 'ult', so we'll need to increment C0, + // which again means it must not have any all-ones elements. + if (!match(C0, + m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, + APInt::getAllOnesValue( + C0->getType()->getScalarSizeInBits())))) + return nullptr; // Can't do, have all-ones element[s]. + C0 = AddOne(C0); + LLVM_FALLTHROUGH; + case ICmpInst::Predicate::ICMP_UGE: + // Also non-canonical, but here we don't need to change C0, + // so we don't have any restrictions on C0, so we can just handle it. + // Both the 'ug[te]' predicates mean we need to swap the select hands. + std::swap(X, Sel1); + break; + default: + return nullptr; // Unknown predicate. + } + + // Now that we've canonicalized the ICmp, we know the X we expect; + // the select in other hand shold be one-use. + if (!Sel1->hasOneUse()) + return nullptr; + + // We now can finish matching the condition of the outermost select: + // it should either be the X itself, or an addition of some constant to X. + Constant *C1; + if (Cmp00 == X) + C1 = ConstantInt::getNullValue(Sel0.getType()); + else if (!match(Cmp00, + m_Add(m_Specific(X), + m_CombineAnd(m_AnyIntegralConstant(), m_Constant(C1))))) + return nullptr; + + Value *Cmp1; + ICmpInst::Predicate Pred1; + Constant *C2; + Value *ReplacementLow, *ReplacementHigh; + if (!match(Sel1, m_Select(m_Value(Cmp1), m_Value(ReplacementLow), + m_Value(ReplacementHigh))) || + !match(Cmp1, + m_ICmp(Pred1, m_Specific(X), + m_CombineAnd(m_AnyIntegralConstant(), m_Constant(C2))))) + return nullptr; + + if (!Cmp1->hasOneUse() && (Cmp00 == X || !Cmp00->hasOneUse())) + return nullptr; // Not enough one-use instructions for the fold. :/ + // FIXME: this restriction could be relaxed if Cmp1 can be reused as one of + // two comparisons we'll need to build. + + // Canonicalize Cmp1 into the form we expect. + // FIXME: we shouldn't care about lanes that are 'undef' in the end? + switch (Pred1) { + case ICmpInst::Predicate::ICMP_SLT: + break; + case ICmpInst::Predicate::ICMP_SLE: + // We'd have to increment C2 by one, and for that it must not have signed + // max element, but then it would have been canonicalized to 'slt' before + // we get here. So we can't do anything useful with 'sle'. + return nullptr; + case ICmpInst::Predicate::ICMP_SGT: + // We want to canonicalize it to 'slt', so we'll need to increment C2, + // which again means it must not have any signed max elements. + if (!match(C2, + m_SpecificInt_ICMP(ICmpInst::Predicate::ICMP_NE, + APInt::getSignedMaxValue( + C2->getType()->getScalarSizeInBits())))) + return nullptr; // Can't do, have signed max element[s]. + C2 = AddOne(C2); + LLVM_FALLTHROUGH; + case ICmpInst::Predicate::ICMP_SGE: + // Also non-canonical, but here we don't need to change C2, + // so we don't have any restrictions on C2, so we can just handle it. + std::swap(ReplacementLow, ReplacementHigh); + break; + default: + return nullptr; // Unknown predicate. + } + + // The thresholds of this clamp-like pattern. + auto *ThresholdLowIncl = ConstantExpr::getNeg(C1); + auto *ThresholdHighExcl = ConstantExpr::getSub(C0, C1); + + // The fold has a precondition 1: C2 s>= ThresholdLow + auto *Precond1 = ConstantExpr::getICmp(ICmpInst::Predicate::ICMP_SGE, C2, + ThresholdLowIncl); + if (!match(Precond1, m_One())) + return nullptr; + // The fold has a precondition 2: C2 s<= ThresholdHigh + auto *Precond2 = ConstantExpr::getICmp(ICmpInst::Predicate::ICMP_SLE, C2, + ThresholdHighExcl); + if (!match(Precond2, m_One())) + return nullptr; + + // All good, finally emit the new pattern. + Value *ShouldReplaceLow = Builder.CreateICmpSLT(X, ThresholdLowIncl); + Value *ShouldReplaceHigh = Builder.CreateICmpSGE(X, ThresholdHighExcl); + Value *MaybeReplacedLow = + Builder.CreateSelect(ShouldReplaceLow, ReplacementLow, X); + Instruction *MaybeReplacedHigh = + SelectInst::Create(ShouldReplaceHigh, ReplacementHigh, MaybeReplacedLow); + + return MaybeReplacedHigh; +} + /// Visit a SelectInst that has an ICmpInst as its first operand. Instruction *InstCombiner::foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI) { @@ -1130,6 +1274,9 @@ if (Instruction *NewAbs = canonicalizeAbsNabs(SI, *ICI, Builder)) return NewAbs; + if (Instruction *NewAbs = canonicalizeClampLike(SI, *ICI, Builder)) + return NewAbs; + bool Changed = adjustMinMax(SI, *ICI); if (Value *V = foldSelectICmpAnd(SI, ICI, Builder)) diff --git a/llvm/test/Transforms/InstCombine/canonicalize-clamp-like-pattern-between-negative-and-positive-thresholds.ll b/llvm/test/Transforms/InstCombine/canonicalize-clamp-like-pattern-between-negative-and-positive-thresholds.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-clamp-like-pattern-between-negative-and-positive-thresholds.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-clamp-like-pattern-between-negative-and-positive-thresholds.ll @@ -25,11 +25,10 @@ define i32 @t0_ult_slt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t0_ult_slt_128( -; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 128 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 -; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 128 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp slt i32 %x, 128 @@ -41,11 +40,10 @@ } define i32 @t1_ult_slt_0(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t1_ult_slt_0( -; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], -16 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 -; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 128 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp slt i32 %x, -16 @@ -58,11 +56,10 @@ define i32 @t2_ult_sgt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t2_ult_sgt_128( -; CHECK-NEXT: [[T0:%.*]] = icmp sgt i32 [[X:%.*]], 127 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[REPLACEMENT_LOW:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 -; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 128 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp sgt i32 %x, 127 @@ -74,11 +71,10 @@ } define i32 @t3_ult_sgt_neg1(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t3_ult_sgt_neg1( -; CHECK-NEXT: [[T0:%.*]] = icmp sgt i32 [[X:%.*]], -17 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[REPLACEMENT_LOW:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 -; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 128 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp sgt i32 %x, -17 @@ -91,11 +87,10 @@ define i32 @t4_ugt_slt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t4_ugt_slt_128( -; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 128 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 -; CHECK-NEXT: [[T3:%.*]] = icmp ugt i32 [[T2]], 143 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[T1]], i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 128 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp slt i32 %x, 128 @@ -107,11 +102,10 @@ } define i32 @t5_ugt_slt_0(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t5_ugt_slt_0( -; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], -16 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 -; CHECK-NEXT: [[T3:%.*]] = icmp ugt i32 [[T2]], 143 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[T1]], i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 128 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp slt i32 %x, -16 @@ -124,11 +118,10 @@ define i32 @t6_ugt_sgt_128(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t6_ugt_sgt_128( -; CHECK-NEXT: [[T0:%.*]] = icmp sgt i32 [[X:%.*]], 127 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[REPLACEMENT_LOW:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 -; CHECK-NEXT: [[T3:%.*]] = icmp ugt i32 [[T2]], 143 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[T1]], i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 128 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp sgt i32 %x, 127 @@ -140,11 +133,10 @@ } define i32 @t7_ugt_sgt_neg1(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t7_ugt_sgt_neg1( -; CHECK-NEXT: [[T0:%.*]] = icmp sgt i32 [[X:%.*]], -17 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[REPLACEMENT_LOW:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 -; CHECK-NEXT: [[T3:%.*]] = icmp ugt i32 [[T2]], 143 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[T1]], i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], -16 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 128 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp sgt i32 %x, -17 @@ -205,10 +197,10 @@ ; CHECK-LABEL: @t10_oneuse0( ; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 ; CHECK-NEXT: call void @use1(i1 [[T0]]) -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 -; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X]], -16 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 128 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp slt i32 %x, 64 @@ -241,12 +233,12 @@ ; This one is ok. define i32 @t12_oneuse2(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t12_oneuse2( -; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 64 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add i32 [[X]], 16 +; CHECK-NEXT: [[T2:%.*]] = add i32 [[X:%.*]], 16 ; CHECK-NEXT: call void @use32(i32 [[T2]]) -; CHECK-NEXT: [[T3:%.*]] = icmp ult i32 [[T2]], 144 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T3]], i32 [[X]], i32 [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X]], -16 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 128 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp slt i32 %x, 64 @@ -414,11 +406,10 @@ define <2 x i32> @t20_ult_slt_vec_splat(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) { ; CHECK-LABEL: @t20_ult_slt_vec_splat( -; CHECK-NEXT: [[T0:%.*]] = icmp slt <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = select <2 x i1> [[T0]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[X]], -; CHECK-NEXT: [[T3:%.*]] = icmp ult <2 x i32> [[T2]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T3]], <2 x i32> [[X]], <2 x i32> [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt <2 x i32> [[X]], +; CHECK-NEXT: [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]] +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret <2 x i32> [[R]] ; %t0 = icmp slt <2 x i32> %x, @@ -430,11 +421,10 @@ } define <2 x i32> @t21_ult_slt_vec_nonsplat(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) { ; CHECK-LABEL: @t21_ult_slt_vec_nonsplat( -; CHECK-NEXT: [[T0:%.*]] = icmp slt <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = select <2 x i1> [[T0]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = add <2 x i32> [[X]], -; CHECK-NEXT: [[T3:%.*]] = icmp ult <2 x i32> [[T2]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T3]], <2 x i32> [[X]], <2 x i32> [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt <2 x i32> [[X]], +; CHECK-NEXT: [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]] +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret <2 x i32> [[R]] ; %t0 = icmp slt <2 x i32> %x, diff --git a/llvm/test/Transforms/InstCombine/canonicalize-clamp-like-pattern-between-zero-and-positive-threshold.ll b/llvm/test/Transforms/InstCombine/canonicalize-clamp-like-pattern-between-zero-and-positive-threshold.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-clamp-like-pattern-between-zero-and-positive-threshold.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-clamp-like-pattern-between-zero-and-positive-threshold.ll @@ -25,10 +25,10 @@ define i32 @t0_ult_slt_65536(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t0_ult_slt_65536( -; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 65536 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ult i32 [[X]], 65536 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[X]], i32 [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 65536 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp slt i32 %x, 65536 @@ -39,10 +39,10 @@ } define i32 @t1_ult_slt_0(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t1_ult_slt_0( -; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 0 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ult i32 [[X]], 65536 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[X]], i32 [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 65536 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp slt i32 %x, 0 @@ -54,10 +54,10 @@ define i32 @t2_ult_sgt_65536(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t2_ult_sgt_65536( -; CHECK-NEXT: [[T0:%.*]] = icmp sgt i32 [[X:%.*]], 65535 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[REPLACEMENT_LOW:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ult i32 [[X]], 65536 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[X]], i32 [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 65536 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp sgt i32 %x, 65535 @@ -68,10 +68,10 @@ } define i32 @t3_ult_sgt_neg1(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t3_ult_sgt_neg1( -; CHECK-NEXT: [[T0:%.*]] = icmp sgt i32 [[X:%.*]], -1 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[REPLACEMENT_LOW:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ult i32 [[X]], 65536 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[X]], i32 [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 65536 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp sgt i32 %x, -1 @@ -83,10 +83,10 @@ define i32 @t4_ugt_slt_65536(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t4_ugt_slt_65536( -; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 65536 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ugt i32 [[X]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[T1]], i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 65536 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp slt i32 %x, 65536 @@ -97,10 +97,10 @@ } define i32 @t5_ugt_slt_0(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t5_ugt_slt_0( -; CHECK-NEXT: [[T0:%.*]] = icmp slt i32 [[X:%.*]], 0 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ugt i32 [[X]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[T1]], i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 65536 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp slt i32 %x, 0 @@ -112,10 +112,10 @@ define i32 @t6_ugt_sgt_65536(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t6_ugt_sgt_65536( -; CHECK-NEXT: [[T0:%.*]] = icmp sgt i32 [[X:%.*]], 65535 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[REPLACEMENT_LOW:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ugt i32 [[X]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[T1]], i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 65536 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp sgt i32 %x, 65535 @@ -126,10 +126,10 @@ } define i32 @t7_ugt_sgt_neg1(i32 %x, i32 %replacement_low, i32 %replacement_high) { ; CHECK-LABEL: @t7_ugt_sgt_neg1( -; CHECK-NEXT: [[T0:%.*]] = icmp sgt i32 [[X:%.*]], -1 -; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32 [[REPLACEMENT_HIGH:%.*]], i32 [[REPLACEMENT_LOW:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ugt i32 [[X]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32 [[T1]], i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[X]], 65536 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i32 [[REPLACEMENT_LOW:%.*]], i32 [[X]] +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP2]], i32 [[TMP3]], i32 [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret i32 [[R]] ; %t0 = icmp sgt i32 %x, -1 @@ -311,10 +311,10 @@ define <2 x i32> @t17_ult_slt_vec_splat(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) { ; CHECK-LABEL: @t17_ult_slt_vec_splat( -; CHECK-NEXT: [[T0:%.*]] = icmp slt <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = select <2 x i1> [[T0]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ult <2 x i32> [[X]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T2]], <2 x i32> [[X]], <2 x i32> [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt <2 x i32> [[X]], +; CHECK-NEXT: [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]] +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret <2 x i32> [[R]] ; %t0 = icmp slt <2 x i32> %x, @@ -325,10 +325,10 @@ } define <2 x i32> @t18_ult_slt_vec_nonsplat(<2 x i32> %x, <2 x i32> %replacement_low, <2 x i32> %replacement_high) { ; CHECK-LABEL: @t18_ult_slt_vec_nonsplat( -; CHECK-NEXT: [[T0:%.*]] = icmp slt <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = select <2 x i1> [[T0]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ult <2 x i32> [[X]], -; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[T2]], <2 x i32> [[X]], <2 x i32> [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i32> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt <2 x i32> [[X]], +; CHECK-NEXT: [[TMP3:%.*]] = select <2 x i1> [[TMP1]], <2 x i32> [[REPLACEMENT_LOW:%.*]], <2 x i32> [[X]] +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[TMP2]], <2 x i32> [[TMP3]], <2 x i32> [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret <2 x i32> [[R]] ; %t0 = icmp slt <2 x i32> %x, @@ -340,10 +340,10 @@ define <3 x i32> @t19_ult_slt_vec_undef0(<3 x i32> %x, <3 x i32> %replacement_low, <3 x i32> %replacement_high) { ; CHECK-LABEL: @t19_ult_slt_vec_undef0( -; CHECK-NEXT: [[T0:%.*]] = icmp slt <3 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = select <3 x i1> [[T0]], <3 x i32> [[REPLACEMENT_LOW:%.*]], <3 x i32> [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ult <3 x i32> [[X]], -; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[T2]], <3 x i32> [[X]], <3 x i32> [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <3 x i32> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt <3 x i32> [[X]], +; CHECK-NEXT: [[TMP3:%.*]] = select <3 x i1> [[TMP1]], <3 x i32> [[REPLACEMENT_LOW:%.*]], <3 x i32> [[X]] +; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP2]], <3 x i32> [[TMP3]], <3 x i32> [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret <3 x i32> [[R]] ; %t0 = icmp slt <3 x i32> %x, @@ -354,10 +354,10 @@ } define <3 x i32> @t20_ult_slt_vec_undef1(<3 x i32> %x, <3 x i32> %replacement_low, <3 x i32> %replacement_high) { ; CHECK-LABEL: @t20_ult_slt_vec_undef1( -; CHECK-NEXT: [[T0:%.*]] = icmp slt <3 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = select <3 x i1> [[T0]], <3 x i32> [[REPLACEMENT_LOW:%.*]], <3 x i32> [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ult <3 x i32> [[X]], -; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[T2]], <3 x i32> [[X]], <3 x i32> [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <3 x i32> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt <3 x i32> [[X]], +; CHECK-NEXT: [[TMP3:%.*]] = select <3 x i1> [[TMP1]], <3 x i32> [[REPLACEMENT_LOW:%.*]], <3 x i32> [[X]] +; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP2]], <3 x i32> [[TMP3]], <3 x i32> [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret <3 x i32> [[R]] ; %t0 = icmp slt <3 x i32> %x, @@ -368,10 +368,10 @@ } define <3 x i32> @t21_ult_slt_vec_undef2(<3 x i32> %x, <3 x i32> %replacement_low, <3 x i32> %replacement_high) { ; CHECK-LABEL: @t21_ult_slt_vec_undef2( -; CHECK-NEXT: [[T0:%.*]] = icmp slt <3 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = select <3 x i1> [[T0]], <3 x i32> [[REPLACEMENT_LOW:%.*]], <3 x i32> [[REPLACEMENT_HIGH:%.*]] -; CHECK-NEXT: [[T2:%.*]] = icmp ult <3 x i32> [[X]], -; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[T2]], <3 x i32> [[X]], <3 x i32> [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <3 x i32> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt <3 x i32> [[X]], +; CHECK-NEXT: [[TMP3:%.*]] = select <3 x i1> [[TMP1]], <3 x i32> [[REPLACEMENT_LOW:%.*]], <3 x i32> [[X]] +; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP2]], <3 x i32> [[TMP3]], <3 x i32> [[REPLACEMENT_HIGH:%.*]] ; CHECK-NEXT: ret <3 x i32> [[R]] ; %t0 = icmp slt <3 x i32> %x, @@ -380,3 +380,20 @@ %r = select <3 x i1> %t2, <3 x i32> %x, <3 x i32> %t1 ret <3 x i32> %r } + +;------------------------------------------------------------------------------- + +define i32* @t22_pointers(i32* %x, i32* %replacement_low, i32* %replacement_high) { +; CHECK-LABEL: @t22_pointers( +; CHECK-NEXT: [[T0:%.*]] = icmp slt i32* [[X:%.*]], inttoptr (i64 65536 to i32*) +; CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i32* [[REPLACEMENT_LOW:%.*]], i32* [[REPLACEMENT_HIGH:%.*]] +; CHECK-NEXT: [[T2:%.*]] = icmp ult i32* [[X]], inttoptr (i64 65536 to i32*) +; CHECK-NEXT: [[R:%.*]] = select i1 [[T2]], i32* [[X]], i32* [[T1]] +; CHECK-NEXT: ret i32* [[R]] +; + %t0 = icmp slt i32* %x, inttoptr (i64 65536 to i32*) + %t1 = select i1 %t0, i32* %replacement_low, i32* %replacement_high + %t2 = icmp ult i32* %x, inttoptr (i64 65536 to i32*) + %r = select i1 %t2, i32* %x, i32* %t1 + ret i32* %r +} diff --git a/llvm/test/Transforms/InstCombine/canonicalize-clamp-with-select-of-constant-threshold-pattern.ll b/llvm/test/Transforms/InstCombine/canonicalize-clamp-with-select-of-constant-threshold-pattern.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-clamp-with-select-of-constant-threshold-pattern.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-clamp-with-select-of-constant-threshold-pattern.ll @@ -7,11 +7,10 @@ define i32 @t0_select_cond_and_v0(i32 %X) { ; CHECK-LABEL: @t0_select_cond_and_v0( -; CHECK-NEXT: [[DONT_NEED_TO_CLAMP_POSITIVE:%.*]] = icmp slt i32 [[X:%.*]], 32768 -; CHECK-NEXT: [[CLAMP_LIMIT:%.*]] = select i1 [[DONT_NEED_TO_CLAMP_POSITIVE]], i32 -32768, i32 32767 -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], 32768 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65536 -; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 [[CLAMP_LIMIT]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767 ; CHECK-NEXT: ret i32 [[R]] ; %dont_need_to_clamp_positive = icmp sle i32 %X, 32767 @@ -23,11 +22,10 @@ } define i32 @t1_select_cond_and_v1(i32 %X) { ; CHECK-LABEL: @t1_select_cond_and_v1( -; CHECK-NEXT: [[DONT_NEED_TO_CLAMP_NEGATIVE:%.*]] = icmp sgt i32 [[X:%.*]], -32769 -; CHECK-NEXT: [[CLAMP_LIMIT:%.*]] = select i1 [[DONT_NEED_TO_CLAMP_NEGATIVE]], i32 32767, i32 -32768 -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], 32768 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65536 -; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 [[CLAMP_LIMIT]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767 ; CHECK-NEXT: ret i32 [[R]] ; %dont_need_to_clamp_positive = icmp sle i32 %X, 32767 @@ -42,11 +40,10 @@ define i32 @t2_select_cond_or_v0(i32 %X) { ; CHECK-LABEL: @t2_select_cond_or_v0( -; CHECK-NEXT: [[NEED_TO_CLAMP_POSITIVE:%.*]] = icmp sgt i32 [[X:%.*]], 32767 -; CHECK-NEXT: [[CLAMP_LIMIT:%.*]] = select i1 [[NEED_TO_CLAMP_POSITIVE]], i32 32767, i32 -32768 -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], 32768 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[X_OFF]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[CLAMP_LIMIT]], i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767 ; CHECK-NEXT: ret i32 [[R]] ; %need_to_clamp_positive = icmp sgt i32 %X, 32767 @@ -58,11 +55,10 @@ } define i32 @t3_select_cond_or_v1(i32 %X) { ; CHECK-LABEL: @t3_select_cond_or_v1( -; CHECK-NEXT: [[NEED_TO_CLAMP_NEGATIVE:%.*]] = icmp slt i32 [[X:%.*]], -32768 -; CHECK-NEXT: [[CLAMP_LIMIT:%.*]] = select i1 [[NEED_TO_CLAMP_NEGATIVE]], i32 -32768, i32 32767 -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], 32768 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[X_OFF]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[CLAMP_LIMIT]], i32 [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767 ; CHECK-NEXT: ret i32 [[R]] ; %need_to_clamp_positive = icmp sgt i32 %X, 32767 @@ -77,11 +73,10 @@ define i32 @t4_select_cond_xor_v0(i32 %X) { ; CHECK-LABEL: @t4_select_cond_xor_v0( -; CHECK-NEXT: [[NEED_TO_CLAMP_POSITIVE:%.*]] = icmp slt i32 [[X:%.*]], 32768 -; CHECK-NEXT: [[CLAMP_LIMIT:%.*]] = select i1 [[NEED_TO_CLAMP_POSITIVE]], i32 -32768, i32 32767 -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], 32767 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 [[CLAMP_LIMIT]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767 ; CHECK-NEXT: ret i32 [[R]] ; %need_to_clamp_positive = icmp sgt i32 %X, 32767 @@ -93,11 +88,10 @@ } define i32 @t4_select_cond_xor_v1(i32 %X) { ; CHECK-LABEL: @t4_select_cond_xor_v1( -; CHECK-NEXT: [[DONT_NEED_TO_CLAMP_NEGATIVE:%.*]] = icmp sgt i32 [[X:%.*]], -32768 -; CHECK-NEXT: [[CLAMP_LIMIT:%.*]] = select i1 [[DONT_NEED_TO_CLAMP_NEGATIVE]], i32 32767, i32 -32768 -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], 32767 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 [[CLAMP_LIMIT]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767 ; CHECK-NEXT: ret i32 [[R]] ; %need_to_clamp_positive = icmp sgt i32 %X, 32767 @@ -110,11 +104,10 @@ define i32 @t5_select_cond_xor_v2(i32 %X) { ; CHECK-LABEL: @t5_select_cond_xor_v2( -; CHECK-NEXT: [[NEED_TO_CLAMP_NEGATIVE:%.*]] = icmp sgt i32 [[X:%.*]], -32768 -; CHECK-NEXT: [[CLAMP_LIMIT:%.*]] = select i1 [[NEED_TO_CLAMP_NEGATIVE]], i32 32767, i32 -32768 -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], 32767 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 [[CLAMP_LIMIT]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767 ; CHECK-NEXT: ret i32 [[R]] ; %dont_need_to_clamp_positive = icmp sle i32 %X, 32767 @@ -126,11 +119,10 @@ } define i32 @t5_select_cond_xor_v3(i32 %X) { ; CHECK-LABEL: @t5_select_cond_xor_v3( -; CHECK-NEXT: [[DONT_NEED_TO_CLAMP_POSITIVE:%.*]] = icmp slt i32 [[X:%.*]], 32768 -; CHECK-NEXT: [[CLAMP_LIMIT:%.*]] = select i1 [[DONT_NEED_TO_CLAMP_POSITIVE]], i32 -32768, i32 32767 -; CHECK-NEXT: [[X_OFF:%.*]] = add i32 [[X]], 32767 -; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[X_OFF]], 65535 -; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[X]], i32 [[CLAMP_LIMIT]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[X:%.*]], 32768 +; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[X]], -32768 +; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP2]], i32 [[X]], i32 -32768 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i32 [[TMP3]], i32 32767 ; CHECK-NEXT: ret i32 [[R]] ; %dont_need_to_clamp_positive = icmp sle i32 %X, 32767