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:
parent
7fad8e54d1
commit
2986f40e8a
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user