diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-12-02 13:48:42 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-12-02 13:48:42 +0000 |
commit | b205606d3e52324827d94025df5a8427b3163f0a (patch) | |
tree | 22228d79defd2653c0c9fc85c9032f3d55d2c863 | |
parent | 2daceedf9279621bb4942b0dc583542c260d7d19 (diff) | |
download | bcm5719-llvm-b205606d3e52324827d94025df5a8427b3163f0a.tar.gz bcm5719-llvm-b205606d3e52324827d94025df5a8427b3163f0a.zip |
[SelectionDAG] fold constant with undef vector per element
This makes the SDAG behavior consistent with the way we do this in IR.
It's possible that we were getting the wrong answer before. For example,
'xor undef, undef --> 0' but 'xor undef, C' --> undef.
But the most practical improvement is likely as shown in the tests here -
for FP, we were overconstraining undef lanes to NaN, and that can prevent
vector simplifications/narrowing (see D51553).
llvm-svn: 348090
-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 |