[llvm] r348090 - [SelectionDAG] fold constant with undef vector per element

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 2 05:48:43 PST 2018


Author: spatel
Date: Sun Dec  2 05:48:42 2018
New Revision: 348090

URL: http://llvm.org/viewvc/llvm-project?rev=348090&view=rev
Log:
[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).

Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
    llvm/trunk/test/CodeGen/X86/fp-undef.ll

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=348090&r1=348089&r2=348090&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Sun Dec  2 05:48:42 2018
@@ -4400,14 +4400,20 @@ SDValue SelectionDAG::FoldConstantArithm
     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::FoldConstantArithm
       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);

Modified: llvm/trunk/test/CodeGen/X86/fp-undef.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fp-undef.ll?rev=348090&r1=348089&r2=348090&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/fp-undef.ll (original)
+++ llvm/trunk/test/CodeGen/X86/fp-undef.ll Sun Dec  2 05:48:42 2018
@@ -508,7 +508,7 @@ define double @frem_undef_op1_fast_const
 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_cons
 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_cons
 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_cons
 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_cons
 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_cons
 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_cons
 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_cons
 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_cons
 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_cons
 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




More information about the llvm-commits mailing list