Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1717,12 +1717,12 @@ EVT VT = Sel.getValueType(); SDLoc DL(Sel); SDValue NewCT = DAG.getNode(BinOpcode, DL, VT, CT, C1); - assert((isConstantOrConstantVector(NewCT) || + assert((NewCT.isUndef() || isConstantOrConstantVector(NewCT) || isConstantFPBuildVectorOrConstantFP(NewCT)) && "Failed to constant fold a binop with constant operands"); SDValue NewCF = DAG.getNode(BinOpcode, DL, VT, CF, C1); - assert((isConstantOrConstantVector(NewCF) || + assert((NewCF.isUndef() || isConstantOrConstantVector(NewCF) || isConstantFPBuildVectorOrConstantFP(NewCF)) && "Failed to constant fold a binop with constant operands"); @@ -2417,6 +2417,9 @@ if (N1C && N1C->isAllOnesValue()) return DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), N0); + if (SDValue V = simplifyDivRem(N, DAG)) + return V; + if (SDValue NewSel = foldBinOpIntoSelect(N)) return NewSel; @@ -2482,9 +2485,6 @@ if (SDValue DivRem = useDivRem(N)) return DivRem; - if (SDValue V = simplifyDivRem(N, DAG)) - return V; - return SDValue(); } @@ -2508,6 +2508,9 @@ N0C, N1C)) return Folded; + if (SDValue V = simplifyDivRem(N, DAG)) + return V; + if (SDValue NewSel = foldBinOpIntoSelect(N)) return NewSel; @@ -2553,9 +2556,6 @@ if (SDValue DivRem = useDivRem(N)) return DivRem; - if (SDValue V = simplifyDivRem(N, DAG)) - return V; - return SDValue(); } @@ -2575,6 +2575,9 @@ if (SDValue Folded = DAG.FoldConstantArithmetic(Opcode, DL, VT, N0C, N1C)) return Folded; + if (SDValue V = simplifyDivRem(N, DAG)) + return V; + if (SDValue NewSel = foldBinOpIntoSelect(N)) return NewSel; @@ -2629,9 +2632,6 @@ if (SDValue DivRem = useDivRem(N)) return DivRem.getValue(1); - if (SDValue V = simplifyDivRem(N, DAG)) - return V; - return SDValue(); } Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3657,6 +3657,12 @@ if (Cst1->isOpaque() || Cst2->isOpaque()) return SDValue(); + // Division/remainder with a zero divisor is undefined behavior. + if ((Opcode == ISD::SDIV || Opcode == ISD::UDIV || + Opcode == ISD::SREM || Opcode == ISD::UREM) && + Cst2->isNullValue()) + return getUNDEF(VT); + std::pair Folded = FoldValue(Opcode, Cst1->getAPIntValue(), Cst2->getAPIntValue()); if (!Folded.second) Index: test/CodeGen/X86/div-rem-simplify.ll =================================================================== --- test/CodeGen/X86/div-rem-simplify.ll +++ test/CodeGen/X86/div-rem-simplify.ll @@ -69,3 +69,81 @@ ret <4 x i32> %div } +; Make sure we handle undef before we try to fold constants from the select with the 0. +; These used to assert because we can't fold div/rem-by-0 into APInt. + +define i32 @sel_urem0(i1 %cond) { +; CHECK-LABEL: sel_urem0: +; CHECK: # BB#0: +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 23, i32 234 + %rem = urem i32 %sel, 0 + ret i32 %rem +} + +define i32 @sel_srem0(i1 %cond) { +; CHECK-LABEL: sel_srem0: +; CHECK: # BB#0: +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 23, i32 234 + %rem = srem i32 %sel, 0 + ret i32 %rem +} + +define i32 @sel_udiv0(i1 %cond) { +; CHECK-LABEL: sel_udiv0: +; CHECK: # BB#0: +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 23, i32 234 + %div = udiv i32 %sel, 0 + ret i32 %div +} + +define i32 @sel_sdiv0(i1 %cond) { +; CHECK-LABEL: sel_sdiv0: +; CHECK: # BB#0: +; CHECK-NEXT: retq + %sel = select i1 %cond, i32 23, i32 234 + %div = sdiv i32 %sel, 0 + ret i32 %div +} + +; Make sure we handle undef before we try to fold constants from the select with the vector 0. +; These used to assert because we can't fold div/rem-by-0 into APInt. + +define <4 x i32> @sel_urem0_vec(i1 %cond) { +; CHECK-LABEL: sel_urem0_vec: +; CHECK: # BB#0: +; CHECK-NEXT: retq + %sel = select i1 %cond, <4 x i32> , <4 x i32> + %rem = urem <4 x i32> %sel, zeroinitializer + ret <4 x i32> %rem +} + +define <4 x i32> @sel_srem0_vec(i1 %cond) { +; CHECK-LABEL: sel_srem0_vec: +; CHECK: # BB#0: +; CHECK-NEXT: retq + %sel = select i1 %cond, <4 x i32> , <4 x i32> + %rem = srem <4 x i32> %sel, zeroinitializer + ret <4 x i32> %rem +} + +define <4 x i32> @sel_udiv0_vec(i1 %cond) { +; CHECK-LABEL: sel_udiv0_vec: +; CHECK: # BB#0: +; CHECK-NEXT: retq + %sel = select i1 %cond, <4 x i32> , <4 x i32> + %div = udiv <4 x i32> %sel, zeroinitializer + ret <4 x i32> %div +} + +define <4 x i32> @sel_sdiv0_vec(i1 %cond) { +; CHECK-LABEL: sel_sdiv0_vec: +; CHECK: # BB#0: +; CHECK-NEXT: retq + %sel = select i1 %cond, <4 x i32> , <4 x i32> + %div = sdiv <4 x i32> %sel, zeroinitializer + ret <4 x i32> %div +} +