Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2454,6 +2454,11 @@ if (isNullConstantOrNullSplatConstant(N1)) return DAG.getUNDEF(VT); + // If any element of a constant divisor vector is zero, the whole op is undef. + if (ISD::isBuildVectorOfConstantSDNodes(N1.getNode()) && + any_of(N1->op_values(), isNullConstant)) + return DAG.getUNDEF(VT); + // undef / X -> 0 // undef % X -> 0 if (N0.isUndef()) Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3725,6 +3725,12 @@ assert(BV1->getNumOperands() == BV2->getNumOperands() && "Out of sync!"); + // If any element of a constant divisor vector is zero, the whole op is undef. + if ((Opcode == ISD::SDIV || Opcode == ISD::UDIV || + Opcode == ISD::SREM || Opcode == ISD::UREM) && + any_of(BV2->op_values(), isNullConstant)) + return getUNDEF(VT); + EVT SVT = VT.getScalarType(); SmallVector Outputs; for (unsigned I = 0, E = BV1->getNumOperands(); I != E; ++I) { @@ -3790,6 +3796,12 @@ !all_of(Ops, IsScalarOrSameVectorSize)) return SDValue(); + // If any element of a constant divisor vector is zero, the whole op is undef. + if ((Opcode == ISD::SDIV || Opcode == ISD::UDIV || + Opcode == ISD::SREM || Opcode == ISD::UREM) && + any_of(Ops[1]->op_values(), isNullConstant)) + return getUNDEF(VT); + // If we are comparing vectors, then the result needs to be a i1 boolean // that is then sign-extended back to the legal result type. EVT SVT = (Opcode == ISD::SETCC ? MVT::i1 : VT.getScalarType()); Index: test/CodeGen/X86/div-rem-simplify.ll =================================================================== --- test/CodeGen/X86/div-rem-simplify.ll +++ test/CodeGen/X86/div-rem-simplify.ll @@ -152,7 +152,6 @@ define <4 x i32> @sdiv0elt_vec(<4 x i32> %x) { ; CHECK-LABEL: sdiv0elt_vec: ; CHECK: # BB#0: -; CHECK-NEXT: movaps {{.*#+}} xmm0 = ; CHECK-NEXT: retq %zero = and <4 x i32> %x, %some_ones = or <4 x i32> %zero, @@ -163,7 +162,6 @@ define <4 x i32> @udiv0elt_vec(<4 x i32> %x) { ; CHECK-LABEL: udiv0elt_vec: ; CHECK: # BB#0: -; CHECK-NEXT: movaps {{.*#+}} xmm0 = ; CHECK-NEXT: retq %div = udiv <4 x i32> , ret <4 x i32> %div @@ -172,7 +170,6 @@ define <4 x i32> @urem0elt_vec(<4 x i32> %x) { ; CHECK-LABEL: urem0elt_vec: ; CHECK: # BB#0: -; CHECK-NEXT: movaps {{.*#+}} xmm0 = ; CHECK-NEXT: retq %zero = and <4 x i32> %x, %some_ones = or <4 x i32> %zero, @@ -183,8 +180,6 @@ define <4 x i32> @srem0elt_vec(<4 x i32> %x) { ; CHECK-LABEL: srem0elt_vec: ; CHECK: # BB#0: -; CHECK-NEXT: movl $-2, %eax -; CHECK-NEXT: movd %eax, %xmm0 ; CHECK-NEXT: retq %rem = srem <4 x i32> , ret <4 x i32> %rem Index: test/CodeGen/X86/vec_sdiv_to_shift.ll =================================================================== --- test/CodeGen/X86/vec_sdiv_to_shift.ll +++ test/CodeGen/X86/vec_sdiv_to_shift.ll @@ -184,27 +184,15 @@ ret <16 x i16> %a0 } -; TODO: The div-by-0 lanes are folded away, so we use scalar ops. Would it be better to keep this in the vector unit? +; Div-by-0 in any lane is UB. define <4 x i32> @sdiv_non_splat(<4 x i32> %x) { ; SSE-LABEL: sdiv_non_splat: ; SSE: # BB#0: -; SSE-NEXT: movd %xmm0, %eax -; SSE-NEXT: movl %eax, %ecx -; SSE-NEXT: shrl $31, %ecx -; SSE-NEXT: addl %eax, %ecx -; SSE-NEXT: sarl %ecx -; SSE-NEXT: movd %ecx, %xmm0 ; SSE-NEXT: retq ; ; AVX-LABEL: sdiv_non_splat: ; AVX: # BB#0: -; AVX-NEXT: vmovd %xmm0, %eax -; AVX-NEXT: movl %eax, %ecx -; AVX-NEXT: shrl $31, %ecx -; AVX-NEXT: addl %eax, %ecx -; AVX-NEXT: sarl %ecx -; AVX-NEXT: vmovd %ecx, %xmm0 ; AVX-NEXT: retq %y = sdiv <4 x i32> %x, ret <4 x i32> %y