Index: llvm/trunk/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp +++ llvm/trunk/lib/Analysis/ValueTracking.cpp @@ -3969,9 +3969,33 @@ } } + // An unsigned min/max can be written with a signed compare. + const APInt *C2; + 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 {CmpLHS == TrueVal ? SPF_UMAX : SPF_UMIN, SPNB_NA, false}; + } + + // Is the sign bit clear? + // (X >s -1) ? MINVAL : X ==> (X UMAX + // (X >s -1) ? X : MINVAL ==> (X UMIN + if (Pred == CmpInst::ICMP_SGT && C1->isAllOnesValue() && + C2->isMinSignedValue()) { + LHS = TrueVal; + RHS = FalseVal; + return {CmpLHS == FalseVal ? SPF_UMAX : SPF_UMIN, SPNB_NA, false}; + } + } + + // Look through 'not' ops to find disguised signed min/max. // (X >s C) ? ~X : ~C ==> (~X SMIN(~X, ~C) // (X (~X >s ~C) ? ~X : ~C ==> SMAX(~X, ~C) - const APInt *C2; if (match(TrueVal, m_Not(m_Specific(CmpLHS))) && match(FalseVal, m_APInt(C2)) && ~(*C1) == *C2 && (Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SLT)) { Index: llvm/trunk/test/CodeGen/X86/vec_minmax_match.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/vec_minmax_match.ll +++ llvm/trunk/test/CodeGen/X86/vec_minmax_match.ll @@ -60,15 +60,10 @@ ret <4 x i32> %sel } -; 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 @@ -79,9 +74,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, @@ -92,9 +85,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 @@ -105,10 +96,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,