diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -5232,6 +5232,16 @@ } } +static ICmpInst::Predicate getMaxMinPredicate(Intrinsic::ID IID) { + switch (IID) { + case Intrinsic::smax: return ICmpInst::ICMP_SGE; + case Intrinsic::smin: return ICmpInst::ICMP_SLE; + case Intrinsic::umax: return ICmpInst::ICMP_UGE; + case Intrinsic::umin: return ICmpInst::ICMP_ULE; + default: llvm_unreachable("Unexpected intrinsic"); + } +} + /// Given a min/max intrinsic, see if it can be removed based on having an /// operand that is another min/max intrinsic with shared operand(s). The caller /// is expected to swap the operand arguments to handle commutation. @@ -5324,6 +5334,12 @@ if (Value *V = foldMinMaxSharedOp(IID, Op1, Op0)) return V; + ICmpInst::Predicate Pred = getMaxMinPredicate(IID); + if (isICmpTrue(Pred, Op0, Op1, Q.getWithoutUndef(), RecursionLimit)) + return Op0; + if (isICmpTrue(Pred, Op1, Op0, Q.getWithoutUndef(), RecursionLimit)) + return Op1; + break; } case Intrinsic::usub_with_overflow: diff --git a/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll b/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll --- a/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll +++ b/llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll @@ -1895,8 +1895,7 @@ ; CHECK-LABEL: @umin_assume_uge( ; CHECK-NEXT: [[C:%.*]] = icmp uge i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[Y]] ; %c = icmp uge i8 %x, %y call void @llvm.assume(i1 %c) @@ -1908,8 +1907,7 @@ ; CHECK-LABEL: @umin_assume_ugt( ; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[Y]] ; %c = icmp ugt i8 %x, %y call void @llvm.assume(i1 %c) @@ -1921,8 +1919,7 @@ ; CHECK-LABEL: @umin_assume_ule( ; CHECK-NEXT: [[C:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[X]] ; %c = icmp ule i8 %x, %y call void @llvm.assume(i1 %c) @@ -1934,8 +1931,7 @@ ; CHECK-LABEL: @umin_assume_ult( ; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[X]] ; %c = icmp ult i8 %x, %y call void @llvm.assume(i1 %c) @@ -1947,8 +1943,7 @@ ; CHECK-LABEL: @umax_assume_uge( ; CHECK-NEXT: [[C:%.*]] = icmp uge i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[X]] ; %c = icmp uge i8 %x, %y call void @llvm.assume(i1 %c) @@ -1960,8 +1955,7 @@ ; CHECK-LABEL: @umax_assume_ugt( ; CHECK-NEXT: [[C:%.*]] = icmp ugt i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[X]] ; %c = icmp ugt i8 %x, %y call void @llvm.assume(i1 %c) @@ -1973,8 +1967,7 @@ ; CHECK-LABEL: @umax_assume_ule( ; CHECK-NEXT: [[C:%.*]] = icmp ule i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[Y]] ; %c = icmp ule i8 %x, %y call void @llvm.assume(i1 %c) @@ -1986,8 +1979,7 @@ ; CHECK-LABEL: @umax_assume_ult( ; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[Y]] ; %c = icmp ult i8 %x, %y call void @llvm.assume(i1 %c) @@ -1999,8 +1991,7 @@ ; CHECK-LABEL: @smin_assume_sge( ; CHECK-NEXT: [[C:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[Y]] ; %c = icmp sge i8 %x, %y call void @llvm.assume(i1 %c) @@ -2012,8 +2003,7 @@ ; CHECK-LABEL: @smin_assume_sgt( ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[Y]] ; %c = icmp sgt i8 %x, %y call void @llvm.assume(i1 %c) @@ -2025,8 +2015,7 @@ ; CHECK-LABEL: @smin_assume_sle( ; CHECK-NEXT: [[C:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[X]] ; %c = icmp sle i8 %x, %y call void @llvm.assume(i1 %c) @@ -2038,8 +2027,7 @@ ; CHECK-LABEL: @smin_assume_slt( ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smin.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[X]] ; %c = icmp slt i8 %x, %y call void @llvm.assume(i1 %c) @@ -2051,8 +2039,7 @@ ; CHECK-LABEL: @smax_assume_sge( ; CHECK-NEXT: [[C:%.*]] = icmp sge i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[X]] ; %c = icmp sge i8 %x, %y call void @llvm.assume(i1 %c) @@ -2064,8 +2051,7 @@ ; CHECK-LABEL: @smax_assume_sgt( ; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[X]] ; %c = icmp sgt i8 %x, %y call void @llvm.assume(i1 %c) @@ -2077,8 +2063,7 @@ ; CHECK-LABEL: @smax_assume_sle( ; CHECK-NEXT: [[C:%.*]] = icmp sle i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[Y]] ; %c = icmp sle i8 %x, %y call void @llvm.assume(i1 %c) @@ -2090,8 +2075,7 @@ ; CHECK-LABEL: @smax_assume_slt( ; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: call void @llvm.assume(i1 [[C]]) -; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.smax.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[M]] +; CHECK-NEXT: ret i8 [[Y]] ; %c = icmp slt i8 %x, %y call void @llvm.assume(i1 %c) @@ -2102,8 +2086,7 @@ define i8 @umax_add_nuw_1(i8 %x) { ; CHECK-LABEL: @umax_add_nuw_1( ; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X:%.*]], 1 -; CHECK-NEXT: [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD]], i8 [[X]]) -; CHECK-NEXT: ret i8 [[MAX]] +; CHECK-NEXT: ret i8 [[ADD]] ; %add = add nuw i8 %x, 1 %max = call i8 @llvm.umax.i8(i8 %add, i8 %x) @@ -2113,8 +2096,7 @@ define i8 @umax_add_nuw_2(i8 %x) { ; CHECK-LABEL: @umax_add_nuw_2( ; CHECK-NEXT: [[ADD:%.*]] = add nuw i8 [[X:%.*]], 42 -; CHECK-NEXT: [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ADD]], i8 42) -; CHECK-NEXT: ret i8 [[MAX]] +; CHECK-NEXT: ret i8 [[ADD]] ; %add = add nuw i8 %x, 42 %max = call i8 @llvm.umax.i8(i8 %add, i8 42) @@ -2123,10 +2105,8 @@ define i8 @umax_range_metadata(i8* %p1, i8* %p2) { ; CHECK-LABEL: @umax_range_metadata( -; CHECK-NEXT: [[X:%.*]] = load i8, i8* [[P1:%.*]], align 1, [[RNG0:!range !.*]] -; CHECK-NEXT: [[Y:%.*]] = load i8, i8* [[P2:%.*]], align 1, [[RNG1:!range !.*]] -; CHECK-NEXT: [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[Y]]) -; CHECK-NEXT: ret i8 [[MAX]] +; CHECK-NEXT: [[Y:%.*]] = load i8, i8* [[P2:%.*]], align 1, [[RNG0:!range !.*]] +; CHECK-NEXT: ret i8 [[Y]] ; %x = load i8, i8* %p1, !range !{i8 0, i8 10} %y = load i8, i8* %p2, !range !{i8 20, i8 30} @@ -2136,10 +2116,8 @@ define i8 @umax_zext_sext(i4 %x) { ; CHECK-LABEL: @umax_zext_sext( -; CHECK-NEXT: [[ZEXT:%.*]] = zext i4 [[X:%.*]] to i8 -; CHECK-NEXT: [[SEXT:%.*]] = sext i4 [[X]] to i8 -; CHECK-NEXT: [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[ZEXT]], i8 [[SEXT]]) -; CHECK-NEXT: ret i8 [[MAX]] +; CHECK-NEXT: [[SEXT:%.*]] = sext i4 [[X:%.*]] to i8 +; CHECK-NEXT: ret i8 [[SEXT]] ; %zext = zext i4 %x to i8 %sext = sext i4 %x to i8 @@ -2149,9 +2127,7 @@ define i8 @umax_lshr(i8 %x, i8 %y) { ; CHECK-LABEL: @umax_lshr( -; CHECK-NEXT: [[SHR:%.*]] = lshr i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[MAX:%.*]] = call i8 @llvm.umax.i8(i8 [[X]], i8 [[SHR]]) -; CHECK-NEXT: ret i8 [[MAX]] +; CHECK-NEXT: ret i8 [[X:%.*]] ; %shr = lshr i8 %x, %y %max = call i8 @llvm.umax.i8(i8 %x, i8 %shr)