summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp26
-rw-r--r--llvm/test/CodeGen/X86/fp-undef.ll20
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
OpenPOWER on IntegriCloud