Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -3981,6 +3981,29 @@ return {SPF_SMIN, SPNB_NA, false}; } } + + // An unsigned min/max can be written with a signed compare. + if ((CmpLHS == TrueVal && match(FalseVal, m_APInt(C2))) || + (CmpLHS == FalseVal && match(TrueVal, m_APInt(C2)))) { + // Is the sign bit set? + // (X (X >u MAXVAL) ? X : MAXVAL ==> UMAX + // (X (X >u MAXVAL) ? MAXVAL : X ==> UMIN + if (Pred == CmpInst::ICMP_SLT && *C1 == 0 && C2->isMaxSignedValue()) { + LHS = TrueVal; + RHS = FalseVal; + return {TrueVal == CmpLHS ? SPF_UMAX : SPF_UMIN, SPNB_NA, false}; + } + + // Is the sign bit clear? + // (X >s -1) ? X : MINVAL ==> (X UMIN + // (X >s -1) ? MINVAL : X ==> (X UMAX + if (Pred == CmpInst::ICMP_SGT && C1->isAllOnesValue() && + C2->isMinSignedValue()) { + LHS = TrueVal; + RHS = FalseVal; + return {TrueVal == CmpLHS ? SPF_UMIN : SPF_UMAX, SPNB_NA, false}; + } + } } // TODO: (X > 4) ? X : 5 --> (X >= 5) ? X : 5 --> MAX(X, 5) Index: test/CodeGen/X86/vec_umin_umax.ll =================================================================== --- test/CodeGen/X86/vec_umin_umax.ll +++ test/CodeGen/X86/vec_umin_umax.ll @@ -1,15 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+avx | FileCheck %s -; FIXME: These are unsigned min/max ops. - define <4 x i32> @umax_vec1(<4 x i32> %x) { ; CHECK-LABEL: umax_vec1: ; CHECK: # BB#0: -; CHECK-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; CHECK-NEXT: vpcmpgtd %xmm0, %xmm1, %xmm1 -; CHECK-NEXT: vmovaps {{.*#+}} xmm2 = [2147483647,2147483647,2147483647,2147483647] -; CHECK-NEXT: vblendvps %xmm1, %xmm0, %xmm2, %xmm0 +; CHECK-NEXT: vpmaxud {{.*}}(%rip), %xmm0, %xmm0 ; CHECK-NEXT: retq ; %cmp = icmp slt <4 x i32> %x, zeroinitializer @@ -20,9 +15,7 @@ define <4 x i32> @umax_vec2(<4 x i32> %x) { ; CHECK-LABEL: umax_vec2: ; CHECK: # BB#0: -; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 -; CHECK-NEXT: vpcmpgtd %xmm1, %xmm0, %xmm1 -; CHECK-NEXT: vblendvps %xmm1, {{.*}}(%rip), %xmm0, %xmm0 +; CHECK-NEXT: vpmaxud {{.*}}(%rip), %xmm0, %xmm0 ; CHECK-NEXT: retq ; %cmp = icmp sgt <4 x i32> %x, @@ -33,9 +26,7 @@ define <4 x i32> @umin_vec1(<4 x i32> %x) { ; CHECK-LABEL: umin_vec1: ; CHECK: # BB#0: -; CHECK-NEXT: vpxor %xmm1, %xmm1, %xmm1 -; CHECK-NEXT: vpcmpgtd %xmm0, %xmm1, %xmm1 -; CHECK-NEXT: vblendvps %xmm1, {{.*}}(%rip), %xmm0, %xmm0 +; CHECK-NEXT: vpminud {{.*}}(%rip), %xmm0, %xmm0 ; CHECK-NEXT: retq ; %cmp = icmp slt <4 x i32> %x, zeroinitializer @@ -46,10 +37,7 @@ define <4 x i32> @umin_vec2(<4 x i32> %x) { ; CHECK-LABEL: umin_vec2: ; CHECK: # BB#0: -; CHECK-NEXT: vpcmpeqd %xmm1, %xmm1, %xmm1 -; CHECK-NEXT: vpcmpgtd %xmm1, %xmm0, %xmm1 -; CHECK-NEXT: vmovaps {{.*#+}} xmm2 = [2147483648,2147483648,2147483648,2147483648] -; CHECK-NEXT: vblendvps %xmm1, %xmm0, %xmm2, %xmm0 +; CHECK-NEXT: vpminud {{.*}}(%rip), %xmm0, %xmm0 ; CHECK-NEXT: retq ; %cmp = icmp sgt <4 x i32> %x,