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 @@ -3090,6 +3090,27 @@ return &SI; } } + + // Fold two-way clamps: + // s1 = (n < C1) ? n : C1 + // s2 = (s1 > C1 - 1) ? s1 : C1 - 1 + // into: + // s2 = n > C1 - 1 ? C1 : C1 - 1 + if (auto *C1 = dyn_cast(TrueSI->getFalseValue())) + if (auto *C2 = dyn_cast(FalseVal)) { + Value *Inner, *N, *InnerC; + auto OuterFlavor = matchSelectPattern(&SI, Inner, FalseVal).Flavor; + auto InnerFlavor = matchSelectPattern(TrueVal, N, InnerC).Flavor; + Pred = cast(SI.getCondition())->getPredicate(); + if ((OuterFlavor == SelectPatternFlavor::SPF_SMAX && + InnerFlavor == SelectPatternFlavor::SPF_SMIN && + C2->getValue() == C1->getValue() - 1) || + (OuterFlavor == SelectPatternFlavor::SPF_SMIN && + InnerFlavor == SelectPatternFlavor::SPF_SMAX && + C2->getValue() == C1->getValue() + 1)) + return SelectInst::Create( + Builder.CreateICmp(Pred, TrueSI->getTrueValue(), C2), C1, C2); + } } if (SelectInst *FalseSI = dyn_cast(FalseVal)) { if (FalseSI->getCondition()->getType() == CondVal->getType()) { diff --git a/llvm/test/Transforms/InstCombine/icmp-dom.ll b/llvm/test/Transforms/InstCombine/icmp-dom.ll --- a/llvm/test/Transforms/InstCombine/icmp-dom.ll +++ b/llvm/test/Transforms/InstCombine/icmp-dom.ll @@ -9,8 +9,8 @@ ; CHECK: land.lhs.true: ; CHECK-NEXT: br label [[LOR_END:%.*]] ; CHECK: lor.rhs: -; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i64 [[A]], 0 -; CHECK-NEXT: br i1 [[CMP2]], label [[LOR_END]], label [[LAND_RHS:%.*]] +; CHECK-NEXT: [[CMP2_NOT:%.*]] = icmp eq i64 [[A]], 0 +; CHECK-NEXT: br i1 [[CMP2_NOT]], label [[LOR_END]], label [[LAND_RHS:%.*]] ; CHECK: land.rhs: ; CHECK-NEXT: br label [[LOR_END]] ; CHECK: lor.end: @@ -393,13 +393,13 @@ define i8 @PR48900_alt(i8 %i, i1* %p) { ; CHECK-LABEL: @PR48900_alt( -; CHECK-NEXT: [[MAXCMP:%.*]] = icmp sgt i8 [[I:%.*]], -127 -; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[MAXCMP]], i8 [[I]], i8 -127 -; CHECK-NEXT: [[I4:%.*]] = icmp ugt i8 [[SMAX]], -128 +; CHECK-NEXT: [[MAXCMP:%.*]] = icmp slt i8 [[I:%.*]], -126 +; CHECK-NEXT: [[I41:%.*]] = icmp ugt i8 [[I]], -128 +; CHECK-NEXT: [[I4:%.*]] = or i1 [[MAXCMP]], [[I41]] ; CHECK-NEXT: br i1 [[I4]], label [[TRUELABEL:%.*]], label [[FALSELABEL:%.*]] ; CHECK: truelabel: -; CHECK-NEXT: [[MINCMP:%.*]] = icmp slt i8 [[SMAX]], -126 -; CHECK-NEXT: [[UMIN:%.*]] = select i1 [[MINCMP]], i8 [[SMAX]], i8 -126 +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[I]], -126 +; CHECK-NEXT: [[UMIN:%.*]] = select i1 [[TMP1]], i8 -127, i8 -126 ; CHECK-NEXT: ret i8 [[UMIN]] ; CHECK: falselabel: ; CHECK-NEXT: ret i8 0 diff --git a/llvm/test/Transforms/InstCombine/minmax-fold.ll b/llvm/test/Transforms/InstCombine/minmax-fold.ll --- a/llvm/test/Transforms/InstCombine/minmax-fold.ll +++ b/llvm/test/Transforms/InstCombine/minmax-fold.ll @@ -537,14 +537,11 @@ ; (icmp slt smax(PositiveA, B) 2) -> (icmp eq B 1) define i32 @clamp_check_for_no_infinite_loop3(i32 %i) { ; CHECK-LABEL: @clamp_check_for_no_infinite_loop3( -; CHECK-NEXT: [[I2:%.*]] = icmp sgt i32 [[I:%.*]], 1 -; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i32 [[I]], i32 1 ; CHECK-NEXT: br i1 true, label [[TRUELABEL:%.*]], label [[FALSELABEL:%.*]] ; CHECK: truelabel: -; CHECK-NEXT: [[I5:%.*]] = icmp slt i32 [[I3]], 2 -; CHECK-NEXT: [[I6:%.*]] = select i1 [[I5]], i32 [[I3]], i32 2 -; CHECK-NEXT: [[I7:%.*]] = shl nuw nsw i32 [[I6]], 2 -; CHECK-NEXT: ret i32 [[I7]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[I:%.*]], 2 +; CHECK-NEXT: [[I6:%.*]] = select i1 [[TMP1]], i32 4, i32 8 +; CHECK-NEXT: ret i32 [[I6]] ; CHECK: falselabel: ; CHECK-NEXT: ret i32 0 ; @@ -1080,8 +1077,8 @@ define i37 @add_umax_simplify(i37 %x) { ; CHECK-LABEL: @add_umax_simplify( -; CHECK-NEXT: [[A:%.*]] = add nuw i37 [[X:%.*]], 42 -; CHECK-NEXT: ret i37 [[A]] +; CHECK-NEXT: [[R:%.*]] = add nuw i37 [[X:%.*]], 42 +; CHECK-NEXT: ret i37 [[R]] ; %a = add nuw i37 %x, 42 %c = icmp ugt i37 %a, 42 @@ -1467,10 +1464,8 @@ define i32 @twoway_clamp_lt(i32 %num) { ; CHECK-LABEL: @twoway_clamp_lt( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[NUM:%.*]], 13768 -; CHECK-NEXT: [[S1:%.*]] = select i1 [[CMP1]], i32 [[NUM]], i32 13768 -; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[S1]], 13767 -; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP2]], i32 [[S1]], i32 13767 +; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i32 [[NUM:%.*]], 13767 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP0]], i32 13768, i32 13767 ; CHECK-NEXT: ret i32 [[R]] ; entry: @@ -1484,10 +1479,8 @@ define i32 @twoway_clamp_gt(i32 %num) { ; CHECK-LABEL: @twoway_clamp_gt( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[NUM:%.*]], 13767 -; CHECK-NEXT: [[S1:%.*]] = select i1 [[CMP1]], i32 [[NUM]], i32 13767 -; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[S1]], 13768 -; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP2]], i32 [[S1]], i32 13768 +; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[NUM:%.*]], 13768 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP0]], i32 13767, i32 13768 ; CHECK-NEXT: ret i32 [[R]] ; entry: