[llvm] r267489 - [Sparc] Fix double-float fabs and fneg on little endian CPUs.
James Y Knight via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 25 15:54:09 PDT 2016
Author: jyknight
Date: Mon Apr 25 17:54:09 2016
New Revision: 267489
URL: http://llvm.org/viewvc/llvm-project?rev=267489&view=rev
Log:
[Sparc] Fix double-float fabs and fneg on little endian CPUs.
The SparcV8 fneg and fabs instructions interestingly come only in a
single-float variant. Since the sign bit is always the topmost bit no
matter what size float it is, you simply operate on the high
subregister, as if it were a single float.
However, the layout of double-floats in the float registers is reversed
on little-endian CPUs, so that the high bits are in the second
subregister, rather than the first.
Thus, this expansion must check the endianness to use the correct
subregister.
Modified:
llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp
llvm/trunk/test/CodeGen/SPARC/float.ll
llvm/trunk/test/CodeGen/SPARC/fp128.ll
Modified: llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp?rev=267489&r1=267488&r2=267489&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp Mon Apr 25 17:54:09 2016
@@ -2649,24 +2649,29 @@ static SDValue LowerRETURNADDR(SDValue O
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 O
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);
Modified: llvm/trunk/test/CodeGen/SPARC/float.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/float.ll?rev=267489&r1=267488&r2=267489&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/float.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/float.ll Mon Apr 25 17:54:09 2016
@@ -1,11 +1,13 @@
-; RUN: llc -march=sparc < %s | FileCheck %s -check-prefix=V8
+; RUN: llc -march=sparc < %s | FileCheck %s -check-prefix=V8 -check-prefix=V8-BE
+; RUN: llc -march=sparcel < %s | FileCheck %s -check-prefix=V8 -check-prefix=V8-EL
; RUN: llc -march=sparc -O0 < %s | FileCheck %s -check-prefix=V8-UNOPT
; RUN: llc -march=sparc -mattr=v9 < %s | FileCheck %s -check-prefix=V9
; RUN: llc -mtriple=sparc64-unknown-linux < %s | FileCheck %s -check-prefix=SPARC64
; V8-LABEL: test_neg:
; V8: call get_double
-; V8: fnegs %f0, %f0
+; V8-BE: fnegs %f0, %f0
+; V8-EL: fnegs %f1, %f1
; V8-UNOPT-LABEL: test_neg:
; V8-UNOPT: fnegs
@@ -27,7 +29,8 @@ entry:
}
; V8-LABEL: test_abs:
-; V8: fabss %f0, %f0
+; V8-BE: fabss %f0, %f0
+; V8-EL: fabss %f1, %f1
; V8-UNOPT-LABEL: test_abs:
; V8-UNOPT: fabss
Modified: llvm/trunk/test/CodeGen/SPARC/fp128.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/SPARC/fp128.ll?rev=267489&r1=267488&r2=267489&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/SPARC/fp128.ll (original)
+++ llvm/trunk/test/CodeGen/SPARC/fp128.ll Mon Apr 25 17:54:09 2016
@@ -1,30 +1,24 @@
-; RUN: llc < %s -march=sparc -mattr=hard-quad-float | FileCheck %s --check-prefix=HARD
-; RUN: llc < %s -march=sparc -mattr=-hard-quad-float | FileCheck %s --check-prefix=SOFT
+; RUN: llc < %s -march=sparc -mattr=hard-quad-float | FileCheck %s --check-prefix=CHECK --check-prefix=HARD --check-prefix=BE
+; RUN: llc < %s -march=sparcel -mattr=hard-quad-float | FileCheck %s --check-prefix=CHECK --check-prefix=HARD --check-prefix=EL
+; RUN: llc < %s -march=sparc -mattr=-hard-quad-float | FileCheck %s --check-prefix=CHECK --check-prefix=SOFT --check-prefix=BE
+; RUN: llc < %s -march=sparcel -mattr=-hard-quad-float | FileCheck %s --check-prefix=CHECK --check-prefix=SOFT --check-prefix=EL
-; HARD-LABEL: f128_ops
-; HARD: ldd
-; HARD: ldd
-; HARD: ldd
-; HARD: ldd
+; CHECK-LABEL: f128_ops:
+; CHECK: ldd
+; CHECK: ldd
+; CHECK: ldd
+; CHECK: ldd
; HARD: faddq [[R0:.+]], [[R1:.+]], [[R2:.+]]
; HARD: fsubq [[R2]], [[R3:.+]], [[R4:.+]]
; HARD: fmulq [[R4]], [[R5:.+]], [[R6:.+]]
; HARD: fdivq [[R6]], [[R2]]
-; HARD: std
-; HARD: std
-
-; SOFT-LABEL: f128_ops
-; SOFT: ldd
-; SOFT: ldd
-; SOFT: ldd
-; SOFT: ldd
; SOFT: call _Q_add
; SOFT: call _Q_sub
; SOFT: call _Q_mul
; SOFT: call _Q_div
-; SOFT: std
-; SOFT: std
+; CHECK: std
+; CHECK: std
define void @f128_ops(fp128* noalias sret %scalar.result, fp128* byval %a, fp128* byval %b, fp128* byval %c, fp128* byval %d) {
entry:
@@ -40,19 +34,12 @@ entry:
ret void
}
-; HARD-LABEL: f128_spill
-; HARD: std %f{{.+}}, [%[[S0:.+]]]
-; HARD: std %f{{.+}}, [%[[S1:.+]]]
-; HARD-DAG: ldd [%[[S0]]], %f{{.+}}
-; HARD-DAG: ldd [%[[S1]]], %f{{.+}}
-; HARD: jmp {{%[oi]7}}+12
-
-; SOFT-LABEL: f128_spill
-; SOFT: std %f{{.+}}, [%[[S0:.+]]]
-; SOFT: std %f{{.+}}, [%[[S1:.+]]]
-; SOFT-DAG: ldd [%[[S0]]], %f{{.+}}
-; SOFT-DAG: ldd [%[[S1]]], %f{{.+}}
-; SOFT: jmp {{%[oi]7}}+12
+; CHECK-LABEL: f128_spill:
+; CHECK: std %f{{.+}}, [%[[S0:.+]]]
+; CHECK: std %f{{.+}}, [%[[S1:.+]]]
+; CHECK-DAG: ldd [%[[S0]]], %f{{.+}}
+; CHECK-DAG: ldd [%[[S1]]], %f{{.+}}
+; CHECK: jmp {{%[oi]7}}+12
define void @f128_spill(fp128* noalias sret %scalar.result, fp128* byval %a) {
entry:
@@ -62,11 +49,9 @@ entry:
ret void
}
-; HARD-LABEL: f128_compare
+; CHECK-LABEL: f128_compare:
; HARD: fcmpq
; HARD-NEXT: nop
-
-; SOFT-LABEL: f128_compare
; SOFT: _Q_cmp
define i32 @f128_compare(fp128* byval %f0, fp128* byval %f1, i32 %a, i32 %b) {
@@ -78,11 +63,9 @@ entry:
ret i32 %ret
}
-; HARD-LABEL: f128_compare2
-; HARD: fcmpq
-; HARD: fb{{ule|g}}
-
-; SOFT-LABEL: f128_compare2
+; CHECK-LABEL: f128_compare2:
+; HARD: fcmpq
+; HARD: fb{{ule|g}}
; SOFT: _Q_cmp
; SOFT: cmp
@@ -99,11 +82,11 @@ entry:
}
-; HARD-LABEL: f128_abs
-; HARD: fabss
-
-; SOFT-LABEL: f128_abs
-; SOFT: fabss
+; CHECK-LABEL: f128_abs:
+; CHECK: ldd [%o0], %f0
+; CHECK: ldd [%o0+8], %f2
+; BE: fabss %f0, %f0
+; EL: fabss %f3, %f3
define void @f128_abs(fp128* noalias sret %scalar.result, fp128* byval %a) {
entry:
@@ -115,10 +98,8 @@ entry:
declare fp128 @llvm.fabs.f128(fp128) nounwind readonly
-; HARD-LABEL: int_to_f128
+; CHECK-LABEL: int_to_f128:
; HARD: fitoq
-
-; SOFT-LABEL: int_to_f128
; SOFT: _Q_itoq
define void @int_to_f128(fp128* noalias sret %scalar.result, i32 %i) {
@@ -128,17 +109,12 @@ entry:
ret void
}
-; HARD-LABEL: fp128_unaligned
-; HARD: ldub
-; HARD: faddq
-; HARD: stb
-; HARD: ret
-
-; SOFT-LABEL: fp128_unaligned
-; SOFT: ldub
+; CHECK-LABEL: fp128_unaligned:
+; CHECK: ldub
+; HARD: faddq
; SOFT: call _Q_add
-; SOFT: stb
-; SOFT: ret
+; CHECK: stb
+; CHECK: ret
define void @fp128_unaligned(fp128* %a, fp128* %b, fp128* %c) {
entry:
@@ -149,10 +125,8 @@ entry:
ret void
}
-; HARD-LABEL: uint_to_f128
+; CHECK-LABEL: uint_to_f128:
; HARD: fdtoq
-
-; SOFT-LABEL: uint_to_f128
; SOFT: _Q_utoq
define void @uint_to_f128(fp128* noalias sret %scalar.result, i32 %i) {
@@ -162,11 +136,9 @@ entry:
ret void
}
-; HARD-LABEL: f128_to_i32
+; CHECK-LABEL: f128_to_i32:
; HARD: fqtoi
; HARD: fqtoi
-
-; SOFT-LABEL: f128_to_i32
; SOFT: call _Q_qtou
; SOFT: call _Q_qtoi
@@ -181,13 +153,11 @@ entry:
ret i32 %4
}
-; HARD-LABEL: test_itoq_qtoi
+; CHECK-LABEL: test_itoq_qtoi
; HARD-DAG: call _Q_lltoq
; HARD-DAG: call _Q_qtoll
; HARD-DAG: fitoq
; HARD-DAG: fqtoi
-
-; SOFT-LABEL: test_itoq_qtoi
; SOFT-DAG: call _Q_lltoq
; SOFT-DAG: call _Q_qtoll
; SOFT-DAG: call _Q_itoq
@@ -209,15 +179,11 @@ entry:
ret void
}
-; HARD-LABEL: test_utoq_qtou
-; HARD-DAG: call _Q_ulltoq
-; HARD-DAG: call _Q_qtoull
+; CHECK-LABEL: test_utoq_qtou:
+; CHECK-DAG: call _Q_ulltoq
+; CHECK-DAG: call _Q_qtoull
; HARD-DAG: fdtoq
; HARD-DAG: fqtoi
-
-; SOFT-LABEL: test_utoq_qtou
-; SOFT-DAG: call _Q_ulltoq
-; SOFT-DAG: call _Q_qtoull
; SOFT-DAG: call _Q_utoq
; SOFT-DAG: call _Q_qtou
@@ -237,8 +203,11 @@ entry:
ret void
}
-; SOFT-LABEL: f128_neg
-; SOFT: fnegs
+; CHECK-LABEL: f128_neg:
+; CHECK: ldd [%o0], %f0
+; CHECK: ldd [%o0+8], %f2
+; BE: fnegs %f0, %f0
+; EL: fnegs %f3, %f3
define void @f128_neg(fp128* noalias sret %scalar.result, fp128* byval %a) {
entry:
More information about the llvm-commits
mailing list