mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-02 08:45:55 +00:00
- FCOPYSIGN custom lowering bug. Clear the sign bit of operand 0 first before
or'ing in the sign bit of operand 1. - Tweaking: rather than left shift the sign bit, fp_extend operand 1 first before taking its sign bit if its type is smaller than that of operand 0. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@32932 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5cf0fe40d0
commit
73d6cf12ad
@ -4127,9 +4127,18 @@ SDOperand X86TargetLowering::LowerFNEG(SDOperand Op, SelectionDAG &DAG) {
|
||||
}
|
||||
|
||||
SDOperand X86TargetLowering::LowerFCOPYSIGN(SDOperand Op, SelectionDAG &DAG) {
|
||||
SDOperand Op0 = Op.getOperand(0);
|
||||
SDOperand Op1 = Op.getOperand(1);
|
||||
MVT::ValueType VT = Op.getValueType();
|
||||
MVT::ValueType SrcVT = Op.getOperand(1).getValueType();
|
||||
MVT::ValueType SrcVT = Op1.getValueType();
|
||||
const Type *SrcTy = MVT::getTypeForValueType(SrcVT);
|
||||
|
||||
// If second operand is smaller, extend it first.
|
||||
if (MVT::getSizeInBits(SrcVT) < MVT::getSizeInBits(VT)) {
|
||||
Op1 = DAG.getNode(ISD::FP_EXTEND, VT, Op1);
|
||||
SrcVT = VT;
|
||||
}
|
||||
|
||||
// First get the sign bit of second operand.
|
||||
std::vector<Constant*> CV;
|
||||
if (SrcVT == MVT::f64) {
|
||||
@ -4150,8 +4159,8 @@ SDOperand X86TargetLowering::LowerFCOPYSIGN(SDOperand Op, SelectionDAG &DAG) {
|
||||
Ops.push_back(DAG.getEntryNode());
|
||||
Ops.push_back(CPIdx);
|
||||
Ops.push_back(DAG.getSrcValue(NULL));
|
||||
SDOperand Mask = DAG.getNode(X86ISD::LOAD_PACK, Tys, &Ops[0], Ops.size());
|
||||
SDOperand SignBit = DAG.getNode(X86ISD::FAND, SrcVT, Op.getOperand(1), Mask);
|
||||
SDOperand Mask1 = DAG.getNode(X86ISD::LOAD_PACK, Tys, &Ops[0], Ops.size());
|
||||
SDOperand SignBit = DAG.getNode(X86ISD::FAND, SrcVT, Op1, Mask1);
|
||||
|
||||
// Shift sign bit right or left if the two operands have different types.
|
||||
if (MVT::getSizeInBits(SrcVT) > MVT::getSizeInBits(VT)) {
|
||||
@ -4162,18 +4171,33 @@ SDOperand X86TargetLowering::LowerFCOPYSIGN(SDOperand Op, SelectionDAG &DAG) {
|
||||
SignBit = DAG.getNode(ISD::BIT_CONVERT, MVT::v4f32, SignBit);
|
||||
SignBit = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::f32, SignBit,
|
||||
DAG.getConstant(0, getPointerTy()));
|
||||
} else if (MVT::getSizeInBits(SrcVT) < MVT::getSizeInBits(VT)) {
|
||||
// Op0 is MVT::f64, Op1 is MVT::f32.
|
||||
SignBit = DAG.getNode(ISD::SCALAR_TO_VECTOR, MVT::v4f32, SignBit);
|
||||
SignBit = DAG.getNode(X86ISD::FSHL, MVT::v4f32, SignBit,
|
||||
DAG.getConstant(32, MVT::i32));
|
||||
SignBit = DAG.getNode(ISD::BIT_CONVERT, MVT::v2f64, SignBit);
|
||||
SignBit = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::f64, SignBit,
|
||||
DAG.getConstant(0, getPointerTy()));
|
||||
}
|
||||
|
||||
// Or the first operand with the sign bit.
|
||||
return DAG.getNode(X86ISD::FOR, VT, Op.getOperand(0), SignBit);
|
||||
// Clear first operand sign bit.
|
||||
CV.clear();
|
||||
if (VT == MVT::f64) {
|
||||
CV.push_back(ConstantFP::get(SrcTy, BitsToDouble(~(1ULL << 63))));
|
||||
CV.push_back(ConstantFP::get(SrcTy, 0.0));
|
||||
} else {
|
||||
CV.push_back(ConstantFP::get(SrcTy, BitsToFloat(~(1U << 31))));
|
||||
CV.push_back(ConstantFP::get(SrcTy, 0.0));
|
||||
CV.push_back(ConstantFP::get(SrcTy, 0.0));
|
||||
CV.push_back(ConstantFP::get(SrcTy, 0.0));
|
||||
}
|
||||
CS = ConstantStruct::get(CV);
|
||||
CPIdx = DAG.getConstantPool(CS, getPointerTy(), 4);
|
||||
Tys.clear();
|
||||
Tys.push_back(VT);
|
||||
Tys.push_back(MVT::Other);
|
||||
Ops.clear();
|
||||
Ops.push_back(DAG.getEntryNode());
|
||||
Ops.push_back(CPIdx);
|
||||
Ops.push_back(DAG.getSrcValue(NULL));
|
||||
SDOperand Mask2 = DAG.getNode(X86ISD::LOAD_PACK, Tys, &Ops[0], Ops.size());
|
||||
SDOperand Val = DAG.getNode(X86ISD::FAND, VT, Op0, Mask2);
|
||||
|
||||
// Or the value with the sign bit.
|
||||
return DAG.getNode(X86ISD::FOR, VT, Val, SignBit);
|
||||
}
|
||||
|
||||
SDOperand X86TargetLowering::LowerSETCC(SDOperand Op, SelectionDAG &DAG,
|
||||
@ -5032,7 +5056,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::FAND: return "X86ISD::FAND";
|
||||
case X86ISD::FOR: return "X86ISD::FOR";
|
||||
case X86ISD::FXOR: return "X86ISD::FXOR";
|
||||
case X86ISD::FSHL: return "X86ISD::FSHL";
|
||||
case X86ISD::FSRL: return "X86ISD::FSRL";
|
||||
case X86ISD::FILD: return "X86ISD::FILD";
|
||||
case X86ISD::FILD_FLAG: return "X86ISD::FILD_FLAG";
|
||||
|
@ -43,10 +43,8 @@ namespace llvm {
|
||||
/// to X86::XORPS or X86::XORPD.
|
||||
FXOR,
|
||||
|
||||
/// FSHL, FSRL - Shift a floating point value (in SSE register) by n bits
|
||||
/// while shifting in 0's. These corresponds to X86::PSLLDQ or
|
||||
/// X86::PSRLDQ.
|
||||
FSHL,
|
||||
/// FSRL - Bitwise logical right shift of floating point values. These
|
||||
/// corresponds to X86::PSRLDQ.
|
||||
FSRL,
|
||||
|
||||
/// FILD, FILD_FLAG - This instruction implements SINT_TO_FP with the
|
||||
|
@ -31,7 +31,6 @@ def X86for : SDNode<"X86ISD::FOR", SDTFPBinOp,
|
||||
[SDNPCommutative, SDNPAssociative]>;
|
||||
def X86fxor : SDNode<"X86ISD::FXOR", SDTFPBinOp,
|
||||
[SDNPCommutative, SDNPAssociative]>;
|
||||
def X86fshl : SDNode<"X86ISD::FSHL", SDTX86FPShiftOp>;
|
||||
def X86fsrl : SDNode<"X86ISD::FSRL", SDTX86FPShiftOp>;
|
||||
def X86comi : SDNode<"X86ISD::COMI", SDTX86CmpTest,
|
||||
[SDNPHasChain, SDNPOutFlag]>;
|
||||
@ -1377,8 +1376,6 @@ let Predicates = [HasSSE2] in {
|
||||
(v2i64 (PSLLDQri VR128:$src1, (PSxLDQ_imm imm:$src2)))>;
|
||||
def : Pat<(int_x86_sse2_psrl_dq VR128:$src1, imm:$src2),
|
||||
(v2i64 (PSRLDQri VR128:$src1, (PSxLDQ_imm imm:$src2)))>;
|
||||
def : Pat<(v4f32 (X86fshl VR128:$src1, i32immSExt8:$src2)),
|
||||
(v4f32 (PSLLDQri VR128:$src1, (PSxLDQ_imm imm:$src2)))>;
|
||||
def : Pat<(v2f64 (X86fsrl VR128:$src1, i32immSExt8:$src2)),
|
||||
(v2f64 (PSRLDQri VR128:$src1, (PSxLDQ_imm imm:$src2)))>;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user