Index: llvm/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/lib/Analysis/InstructionSimplify.cpp +++ 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: Index: llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll =================================================================== --- llvm/test/Transforms/InstSimplify/maxmin_intrinsics.ll +++ 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)