Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -540,6 +540,7 @@ SDValue convertSelectOfFPConstantsToLoadOffset( const SDLoc &DL, SDValue N0, SDValue N1, SDValue N2, SDValue N3, ISD::CondCode CC); + SDValue foldSignChangeInBitcast(SDNode *N); SDValue foldSelectCCToShiftAnd(const SDLoc &DL, SDValue N0, SDValue N1, SDValue N2, SDValue N3, ISD::CondCode CC); SDValue foldLogicOfSetCCs(bool IsAnd, SDValue N0, SDValue N1, @@ -13966,7 +13967,6 @@ return SDValue(); } -// FIXME: FNEG and FABS have a lot in common; refactor. SDValue DAGCombiner::visitFNEG(SDNode *N) { SDValue N0 = N->getOperand(0); EVT VT = N->getValueType(0); @@ -13990,31 +13990,8 @@ N0.getOperand(0), N->getFlags()); } - // Transform fneg(bitconvert(x)) -> bitconvert(x ^ sign) to avoid loading - // constant pool values. - if (!TLI.isFNegFree(VT) && - N0.getOpcode() == ISD::BITCAST && - N0.getNode()->hasOneUse()) { - SDValue Int = N0.getOperand(0); - EVT IntVT = Int.getValueType(); - if (IntVT.isInteger() && !IntVT.isVector()) { - APInt SignMask; - if (N0.getValueType().isVector()) { - // For a vector, get a mask such as 0x80... per scalar element - // and splat it. - SignMask = APInt::getSignMask(N0.getScalarValueSizeInBits()); - SignMask = APInt::getSplat(IntVT.getSizeInBits(), SignMask); - } else { - // For a scalar, just generate 0x80... - SignMask = APInt::getSignMask(IntVT.getSizeInBits()); - } - SDLoc DL0(N0); - Int = DAG.getNode(ISD::XOR, DL0, IntVT, Int, - DAG.getConstant(SignMask, DL0, IntVT)); - AddToWorklist(Int.getNode()); - return DAG.getBitcast(VT, Int); - } - } + if (SDValue Cast = foldSignChangeInBitcast(N)) + return Cast; // (fneg (fmul c, x)) -> (fmul -c, x) if (N0.getOpcode() == ISD::FMUL && @@ -14090,28 +14067,8 @@ if (N0.getOpcode() == ISD::FNEG || N0.getOpcode() == ISD::FCOPYSIGN) return DAG.getNode(ISD::FABS, SDLoc(N), VT, N0.getOperand(0)); - // fabs(bitcast(x)) -> bitcast(x & ~sign) to avoid constant pool loads. - if (!TLI.isFAbsFree(VT) && N0.getOpcode() == ISD::BITCAST && N0.hasOneUse()) { - SDValue Int = N0.getOperand(0); - EVT IntVT = Int.getValueType(); - if (IntVT.isInteger() && !IntVT.isVector()) { - APInt SignMask; - if (N0.getValueType().isVector()) { - // For a vector, get a mask such as 0x7f... per scalar element - // and splat it. - SignMask = ~APInt::getSignMask(N0.getScalarValueSizeInBits()); - SignMask = APInt::getSplat(IntVT.getSizeInBits(), SignMask); - } else { - // For a scalar, just generate 0x7f... - SignMask = ~APInt::getSignMask(IntVT.getSizeInBits()); - } - SDLoc DL(N0); - Int = DAG.getNode(ISD::AND, DL, IntVT, Int, - DAG.getConstant(SignMask, DL, IntVT)); - AddToWorklist(Int.getNode()); - return DAG.getBitcast(N->getValueType(0), Int); - } - } + if (SDValue Cast = foldSignChangeInBitcast(N)) + return Cast; return SDValue(); } @@ -21318,6 +21275,44 @@ return DAG.getNode(ISD::AND, DL, AType, Shift, N2); } +// Transform (fneg/fabs (bitconvert x)) to avoid loading constant pool values. +SDValue DAGCombiner::foldSignChangeInBitcast(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + bool isFNeg = N->getOpcode() == ISD::FNEG; + bool Free = isFNeg ? TLI.isFNegFree(VT) : TLI.isFAbsFree(VT); + + // (fneg (bitconvert x)) -> (bitconvert (xor x sign)) + // (fabs (bitconvert x)) -> (bitconvert (and x ~sign)) + if (!Free && N0.getOpcode() == ISD::BITCAST && N0.hasOneUse()) { + SDValue Int = N0.getOperand(0); + EVT IntVT = Int.getValueType(); + if (IntVT.isInteger() && !IntVT.isVector()) { + APInt SignMask; + if (N0.getValueType().isVector()) { + // For a vector, get a mask such as 0x7f... per scalar element + // and splat it. + SignMask = APInt::getSignMask(N0.getScalarValueSizeInBits()); + if (!isFNeg) + SignMask = ~SignMask; + SignMask = APInt::getSplat(IntVT.getSizeInBits(), SignMask); + } else { + // For a scalar, just generate 0x7f... + SignMask = APInt::getSignMask(IntVT.getSizeInBits()); + if (!isFNeg) + SignMask = ~SignMask; + } + SDLoc DL(N0); + Int = DAG.getNode(isFNeg ? ISD::XOR : ISD::AND, DL, IntVT, Int, + DAG.getConstant(SignMask, DL, IntVT)); + AddToWorklist(Int.getNode()); + return DAG.getBitcast(VT, Int); + } + } + + return SDValue(); +} + /// Turn "(a cond b) ? 1.0f : 2.0f" into "load (tmp + ((a cond b) ? 0 : 4)" /// where "tmp" is a constant pool entry containing an array with 1.0 and 2.0 /// in it. This may be a win when the constant is not otherwise available