diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index a75580a5c4c65..52de05117b124 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10813,28 +10813,29 @@ SDValue DAGCombiner::foldSextSetcc(SDNode *N) { } // Try to eliminate the sext of a setcc by zexting the compare operands. - // TODO: Handle signed compare by sexting the ops. - if (!ISD::isSignedIntSetCC(CC) && N0.hasOneUse() && - TLI.isOperationLegalOrCustom(ISD::SETCC, VT) && + if (N0.hasOneUse() && TLI.isOperationLegalOrCustom(ISD::SETCC, VT) && !TLI.isOperationLegalOrCustom(ISD::SETCC, SVT)) { + bool IsSignedCmp = ISD::isSignedIntSetCC(CC); + unsigned LoadOpcode = IsSignedCmp ? ISD::SEXTLOAD : ISD::ZEXTLOAD; + unsigned ExtOpcode = IsSignedCmp ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; + // We have an unsupported narrow vector compare op that would be legal // if extended to the destination type. See if the compare operands // can be freely extended to the destination type. - auto IsFreeToZext = [&](SDValue V) { + auto IsFreeToExtend = [&](SDValue V) { if (isConstantOrConstantVector(V, /*NoOpaques*/ true)) return true; - // Match a simple, non-extended load that can be converted to a - // legal zext-load. - // TODO: Allow widening of an existing zext-load? + // legal {z/s}ext-load. + // TODO: Allow widening of an existing {z/s}ext-load? if (!(ISD::isNON_EXTLoad(V.getNode()) && ISD::isUNINDEXEDLoad(V.getNode()) && cast(V)->isSimple() && - TLI.isLoadExtLegal(ISD::ZEXTLOAD, VT, V.getValueType()))) + TLI.isLoadExtLegal(LoadOpcode, VT, V.getValueType()))) return false; // Non-chain users of this value must either be the setcc in this - // sequence or zexts that can be folded into the new zext-load. + // sequence or extends that can be folded into the new {z/s}ext-load. for (SDNode::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE; ++UI) { // Skip uses of the chain and the setcc. @@ -10844,16 +10845,15 @@ SDValue DAGCombiner::foldSextSetcc(SDNode *N) { // Extra users must have exactly the same cast we are about to create. // TODO: This restriction could be eased if ExtendUsesToFormExtLoad() // is enhanced similarly. - if (User->getOpcode() != ISD::ZERO_EXTEND || - User->getValueType(0) != VT) + if (User->getOpcode() != ExtOpcode || User->getValueType(0) != VT) return false; } return true; }; - if (IsFreeToZext(N00) && IsFreeToZext(N01)) { - SDValue Ext0 = DAG.getZExtOrTrunc(N00, DL, VT); - SDValue Ext1 = DAG.getZExtOrTrunc(N01, DL, VT); + if (IsFreeToExtend(N00) && IsFreeToExtend(N01)) { + SDValue Ext0 = DAG.getNode(ExtOpcode, DL, VT, N00); + SDValue Ext1 = DAG.getNode(ExtOpcode, DL, VT, N01); return DAG.getSetCC(DL, VT, Ext0, Ext1, CC); } } diff --git a/llvm/test/CodeGen/X86/sext-vsetcc.ll b/llvm/test/CodeGen/X86/sext-vsetcc.ll index e78d7356d89d9..579939a356846 100644 --- a/llvm/test/CodeGen/X86/sext-vsetcc.ll +++ b/llvm/test/CodeGen/X86/sext-vsetcc.ll @@ -283,7 +283,7 @@ define <3 x i32> @cmp_ult_load_const_bad_type(<3 x i8>* %x) nounwind { ret <3 x i32> %sext } -; negative test - signed cmp (TODO) +; Signed compare needs signed extend. define <4 x i32> @cmp_slt_load_const(<4 x i8>* %x) nounwind { ; SSE-LABEL: cmp_slt_load_const: @@ -298,10 +298,9 @@ define <4 x i32> @cmp_slt_load_const(<4 x i8>* %x) nounwind { ; ; AVX-LABEL: cmp_slt_load_const: ; AVX: # %bb.0: -; AVX-NEXT: vmovd {{.*#+}} xmm0 = mem[0],zero,zero,zero -; AVX-NEXT: vmovdqa {{.*#+}} xmm1 = <42,214,0,255,u,u,u,u,u,u,u,u,u,u,u,u> -; AVX-NEXT: vpcmpgtb %xmm0, %xmm1, %xmm0 -; AVX-NEXT: vpmovsxbd %xmm0, %xmm0 +; AVX-NEXT: vpmovsxbd (%rdi), %xmm0 +; AVX-NEXT: vmovdqa {{.*#+}} xmm1 = [42,4294967254,0,4294967295] +; AVX-NEXT: vpcmpgtd %xmm0, %xmm1, %xmm0 ; AVX-NEXT: retq %loadx = load <4 x i8>, <4 x i8>* %x %icmp = icmp slt <4 x i8> %loadx, @@ -373,7 +372,7 @@ define <8 x i16> @cmp_ugt_zextload(<8 x i8>* %x, <8 x i8>* %y) nounwind { ret <8 x i16> %sext } -; negative test - signed cmp (TODO) +; Signed compare needs signed extends. define <8 x i16> @cmp_sgt_zextload(<8 x i8>* %x, <8 x i8>* %y) nounwind { ; SSE-LABEL: cmp_sgt_zextload: @@ -387,10 +386,9 @@ define <8 x i16> @cmp_sgt_zextload(<8 x i8>* %x, <8 x i8>* %y) nounwind { ; ; AVX-LABEL: cmp_sgt_zextload: ; AVX: # %bb.0: -; AVX-NEXT: vmovq {{.*#+}} xmm0 = mem[0],zero -; AVX-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero -; AVX-NEXT: vpcmpgtb %xmm1, %xmm0, %xmm0 -; AVX-NEXT: vpmovsxbw %xmm0, %xmm0 +; AVX-NEXT: vpmovsxbw (%rdi), %xmm0 +; AVX-NEXT: vpmovsxbw (%rsi), %xmm1 +; AVX-NEXT: vpcmpgtw %xmm1, %xmm0, %xmm0 ; AVX-NEXT: retq %loadx = load <8 x i8>, <8 x i8>* %x %loady = load <8 x i8>, <8 x i8>* %y @@ -571,11 +569,9 @@ define <4 x i64> @PR50055_signed(<2 x i64>* %src, <4 x i64>* %dst) { ; ; AVX-LABEL: PR50055_signed: ; AVX: # %bb.0: -; AVX-NEXT: vmovq {{.*#+}} xmm1 = mem[0],zero -; AVX-NEXT: vpmovsxbd %xmm1, %ymm0 -; AVX-NEXT: vpxor %xmm2, %xmm2, %xmm2 -; AVX-NEXT: vpcmpgtb %xmm2, %xmm1, %xmm1 -; AVX-NEXT: vpmovsxbd %xmm1, %ymm1 +; AVX-NEXT: vpmovsxbd (%rdi), %ymm0 +; AVX-NEXT: vpxor %xmm1, %xmm1, %xmm1 +; AVX-NEXT: vpcmpgtd %ymm1, %ymm0, %ymm1 ; AVX-NEXT: vmovdqa %ymm1, (%rsi) ; AVX-NEXT: retq %t0 = bitcast <2 x i64>* %src to <8 x i8>*