diff options
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 26 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/fp-undef.ll | 20 |
2 files changed, 26 insertions, 20 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index a3661d15a4f..81427e20073 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4400,14 +4400,20 @@ SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Cst2)) return FoldSymbolOffset(Opcode, VT, GA, Cst1); - // For vectors extract each constant element into Inputs so we can constant - // fold them individually. - BuildVectorSDNode *BV1 = dyn_cast<BuildVectorSDNode>(Cst1); - BuildVectorSDNode *BV2 = dyn_cast<BuildVectorSDNode>(Cst2); - if (!BV1 || !BV2) + // For vectors, extract each constant element and fold them individually. + // Either input may be an undef value. + auto *BV1 = dyn_cast<BuildVectorSDNode>(Cst1); + if (!BV1 && !Cst1->isUndef()) + return SDValue(); + auto *BV2 = dyn_cast<BuildVectorSDNode>(Cst2); + if (!BV2 && !Cst2->isUndef()) + return SDValue(); + // If both operands are undef, that's handled the same way as scalars. + if (!BV1 && !BV2) return SDValue(); - assert(BV1->getNumOperands() == BV2->getNumOperands() && "Out of sync!"); + assert((!BV1 || !BV2 || BV1->getNumOperands() == BV2->getNumOperands()) && + "Vector binop with different number of elements in operands?"); EVT SVT = VT.getScalarType(); EVT LegalSVT = SVT; @@ -4417,10 +4423,10 @@ SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL, return SDValue(); } SmallVector<SDValue, 4> Outputs; - for (unsigned I = 0, E = BV1->getNumOperands(); I != E; ++I) { - SDValue V1 = BV1->getOperand(I); - SDValue V2 = BV2->getOperand(I); - + unsigned NumOps = BV1 ? BV1->getNumOperands() : BV2->getNumOperands(); + for (unsigned I = 0; I != NumOps; ++I) { + SDValue V1 = BV1 ? BV1->getOperand(I) : getUNDEF(SVT); + SDValue V2 = BV2 ? BV2->getOperand(I) : getUNDEF(SVT); if (SVT.isInteger()) { if (V1->getValueType(0).bitsGT(SVT)) V1 = getNode(ISD::TRUNCATE, DL, SVT, V1); diff --git a/llvm/test/CodeGen/X86/fp-undef.ll b/llvm/test/CodeGen/X86/fp-undef.ll index 687738f420a..d46bea703fd 100644 --- a/llvm/test/CodeGen/X86/fp-undef.ll +++ b/llvm/test/CodeGen/X86/fp-undef.ll @@ -508,7 +508,7 @@ define double @frem_undef_op1_fast_constant_inf(double %x) { define <2 x double> @fadd_undef_op1_constant_vec(<2 x double> %x) { ; ANY-LABEL: fadd_undef_op1_constant_vec: ; ANY: # %bb.0: -; ANY-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN] +; ANY-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero ; ANY-NEXT: retq %r = fadd <2 x double> <double 42.0, double undef>, undef ret <2 x double> %r @@ -517,7 +517,7 @@ define <2 x double> @fadd_undef_op1_constant_vec(<2 x double> %x) { define <2 x double> @fadd_undef_op0_constant_vec(<2 x double> %x) { ; ANY-LABEL: fadd_undef_op0_constant_vec: ; ANY: # %bb.0: -; ANY-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN] +; ANY-NEXT: movaps {{.*#+}} xmm0 = <u,NaN> ; ANY-NEXT: retq %r = fadd <2 x double> undef, <double undef, double 42.0> ret <2 x double> %r @@ -526,7 +526,7 @@ define <2 x double> @fadd_undef_op0_constant_vec(<2 x double> %x) { define <2 x double> @fsub_undef_op1_constant_vec(<2 x double> %x) { ; ANY-LABEL: fsub_undef_op1_constant_vec: ; ANY: # %bb.0: -; ANY-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN] +; ANY-NEXT: movaps {{.*#+}} xmm0 = <u,NaN> ; ANY-NEXT: retq %r = fsub <2 x double> <double undef, double 42.0>, undef ret <2 x double> %r @@ -535,7 +535,7 @@ define <2 x double> @fsub_undef_op1_constant_vec(<2 x double> %x) { define <2 x double> @fsub_undef_op0_constant_vec(<2 x double> %x) { ; ANY-LABEL: fsub_undef_op0_constant_vec: ; ANY: # %bb.0: -; ANY-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN] +; ANY-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero ; ANY-NEXT: retq %r = fsub <2 x double> undef, <double 42.0, double undef> ret <2 x double> %r @@ -544,7 +544,7 @@ define <2 x double> @fsub_undef_op0_constant_vec(<2 x double> %x) { define <2 x double> @fmul_undef_op1_constant_vec(<2 x double> %x) { ; ANY-LABEL: fmul_undef_op1_constant_vec: ; ANY: # %bb.0: -; ANY-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN] +; ANY-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero ; ANY-NEXT: retq %r = fmul <2 x double> <double 42.0, double undef>, undef ret <2 x double> %r @@ -553,7 +553,7 @@ define <2 x double> @fmul_undef_op1_constant_vec(<2 x double> %x) { define <2 x double> @fmul_undef_op0_constant_vec(<2 x double> %x) { ; ANY-LABEL: fmul_undef_op0_constant_vec: ; ANY: # %bb.0: -; ANY-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN] +; ANY-NEXT: movaps {{.*#+}} xmm0 = <u,NaN> ; ANY-NEXT: retq %r = fmul <2 x double> undef, <double undef, double 42.0> ret <2 x double> %r @@ -562,7 +562,7 @@ define <2 x double> @fmul_undef_op0_constant_vec(<2 x double> %x) { define <2 x double> @fdiv_undef_op1_constant_vec(<2 x double> %x) { ; ANY-LABEL: fdiv_undef_op1_constant_vec: ; ANY: # %bb.0: -; ANY-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN] +; ANY-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero ; ANY-NEXT: retq %r = fdiv <2 x double> <double 42.0, double undef>, undef ret <2 x double> %r @@ -571,7 +571,7 @@ define <2 x double> @fdiv_undef_op1_constant_vec(<2 x double> %x) { define <2 x double> @fdiv_undef_op0_constant_vec(<2 x double> %x) { ; ANY-LABEL: fdiv_undef_op0_constant_vec: ; ANY: # %bb.0: -; ANY-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN] +; ANY-NEXT: movaps {{.*#+}} xmm0 = <u,NaN> ; ANY-NEXT: retq %r = fdiv <2 x double> undef, <double undef, double 42.0> ret <2 x double> %r @@ -580,7 +580,7 @@ define <2 x double> @fdiv_undef_op0_constant_vec(<2 x double> %x) { define <2 x double> @frem_undef_op1_constant_vec(<2 x double> %x) { ; ANY-LABEL: frem_undef_op1_constant_vec: ; ANY: # %bb.0: -; ANY-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN] +; ANY-NEXT: movaps {{.*#+}} xmm0 = <u,NaN> ; ANY-NEXT: retq %r = frem <2 x double> <double undef, double 42.0>, undef ret <2 x double> %r @@ -589,7 +589,7 @@ define <2 x double> @frem_undef_op1_constant_vec(<2 x double> %x) { define <2 x double> @frem_undef_op0_constant_vec(<2 x double> %x) { ; ANY-LABEL: frem_undef_op0_constant_vec: ; ANY: # %bb.0: -; ANY-NEXT: movaps {{.*#+}} xmm0 = [NaN,NaN] +; ANY-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero ; ANY-NEXT: retq %r = frem <2 x double> undef, <double 42.0, double undef> ret <2 x double> %r |