1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[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
This commit is contained in:
Sanjay Patel 2018-12-02 13:48:42 +00:00
parent 7fad8e54d1
commit 2986f40e8a
2 changed files with 26 additions and 20 deletions

View File

@ -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);

View File

@ -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