summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Sparc/SparcISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/Sparc/SparcISelLowering.cpp')
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.cpp40
1 files changed, 28 insertions, 12 deletions
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index 32d88f9be74..304f07f38c9 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -2649,24 +2649,29 @@ static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
return RetAddr;
}
-static SDValue LowerF64Op(SDValue Op, SelectionDAG &DAG, unsigned opcode)
+static SDValue LowerF64Op(SDValue SrcReg64, SDLoc dl, SelectionDAG &DAG, unsigned opcode)
{
- SDLoc dl(Op);
-
- assert(Op.getValueType() == MVT::f64 && "LowerF64Op called on non-double!");
+ assert(SrcReg64.getValueType() == MVT::f64 && "LowerF64Op called on non-double!");
assert(opcode == ISD::FNEG || opcode == ISD::FABS);
// Lower fneg/fabs on f64 to fneg/fabs on f32.
// fneg f64 => fneg f32:sub_even, fmov f32:sub_odd.
// fabs f64 => fabs f32:sub_even, fmov f32:sub_odd.
- SDValue SrcReg64 = Op.getOperand(0);
+ // Note: in little-endian, the floating-point value is stored in the
+ // registers are in the opposite order, so the subreg with the sign
+ // bit is the highest-numbered (odd), rather than the
+ // lowest-numbered (even).
+
SDValue Hi32 = DAG.getTargetExtractSubreg(SP::sub_even, dl, MVT::f32,
SrcReg64);
SDValue Lo32 = DAG.getTargetExtractSubreg(SP::sub_odd, dl, MVT::f32,
SrcReg64);
- Hi32 = DAG.getNode(opcode, dl, MVT::f32, Hi32);
+ if (DAG.getDataLayout().isLittleEndian())
+ Lo32 = DAG.getNode(opcode, dl, MVT::f32, Lo32);
+ else
+ Hi32 = DAG.getNode(opcode, dl, MVT::f32, Hi32);
SDValue DstReg64 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
dl, MVT::f64), 0);
@@ -2810,24 +2815,35 @@ static SDValue LowerFNEGorFABS(SDValue Op, SelectionDAG &DAG, bool isV9) {
assert((Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS)
&& "invalid opcode");
+ SDLoc dl(Op);
+
if (Op.getValueType() == MVT::f64)
- return LowerF64Op(Op, DAG, Op.getOpcode());
+ return LowerF64Op(Op.getOperand(0), dl, DAG, Op.getOpcode());
if (Op.getValueType() != MVT::f128)
return Op;
// Lower fabs/fneg on f128 to fabs/fneg on f64
// fabs/fneg f128 => fabs/fneg f64:sub_even64, fmov f64:sub_odd64
+ // (As with LowerF64Op, on little-endian, we need to negate the odd
+ // subreg)
- SDLoc dl(Op);
SDValue SrcReg128 = Op.getOperand(0);
SDValue Hi64 = DAG.getTargetExtractSubreg(SP::sub_even64, dl, MVT::f64,
SrcReg128);
SDValue Lo64 = DAG.getTargetExtractSubreg(SP::sub_odd64, dl, MVT::f64,
SrcReg128);
- if (isV9)
- Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64);
- else
- Hi64 = LowerF64Op(Hi64, DAG, Op.getOpcode());
+
+ if (DAG.getDataLayout().isLittleEndian()) {
+ if (isV9)
+ Lo64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Lo64);
+ else
+ Lo64 = LowerF64Op(Lo64, dl, DAG, Op.getOpcode());
+ } else {
+ if (isV9)
+ Hi64 = DAG.getNode(Op.getOpcode(), dl, MVT::f64, Hi64);
+ else
+ Hi64 = LowerF64Op(Hi64, dl, DAG, Op.getOpcode());
+ }
SDValue DstReg128 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
dl, MVT::f128), 0);
OpenPOWER on IntegriCloud