Skip to content

Commit 92dadc0

Browse files
committed
[Sparc] Custom bitcast between f64 and v2i32
Summary: Currently bitcasting constants from f64 to v2i32 is done by storing the value to the stack and then loading it again. This is not necessary, but seems to happen because v2i32 is a valid type for Sparc V8. If it had not been legal, we would have gotten help from the type legalizer. This patch tries to do the same work as the legalizer would have done by bitcasting the floating point constant and splitting the value up into a vector of two i32 values. Reviewers: venkatra, jyknight Reviewed By: jyknight Subscribers: glaubitz, fedor.sergeev, jrtc27, llvm-commits Differential Revision: https://reviews.llvm.org/D49219 llvm-svn: 340723
1 parent fe28217 commit 92dadc0

File tree

3 files changed

+64
-15
lines changed

3 files changed

+64
-15
lines changed

llvm/lib/Target/Sparc/SparcISelLowering.cpp

+42-6
Original file line numberDiff line numberDiff line change
@@ -852,12 +852,10 @@ SparcTargetLowering::LowerCall_32(TargetLowering::CallLoweringInfo &CLI,
852852
if (VA.getLocVT() == MVT::f64) {
853853
// Move from the float value from float registers into the
854854
// integer registers.
855-
856-
// TODO: The f64 -> v2i32 conversion is super-inefficient for
857-
// constants: it sticks them in the constant pool, then loads
858-
// to a fp register, then stores to temp memory, then loads to
859-
// integer registers.
860-
Arg = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, Arg);
855+
if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Arg))
856+
Arg = bitcastConstantFPToInt(C, dl, DAG);
857+
else
858+
Arg = DAG.getNode(ISD::BITCAST, dl, MVT::v2i32, Arg);
861859
}
862860

863861
SDValue Part0 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::i32,
@@ -1801,6 +1799,10 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
18011799
setOperationAction(ISD::FMUL, MVT::f32, Promote);
18021800
}
18031801

1802+
// Custom combine bitcast between f64 and v2i32
1803+
if (!Subtarget->is64Bit())
1804+
setTargetDAGCombine(ISD::BITCAST);
1805+
18041806
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
18051807

18061808
setMinFunctionAlignment(2);
@@ -3075,6 +3077,40 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const {
30753077
}
30763078
}
30773079

3080+
SDValue SparcTargetLowering::bitcastConstantFPToInt(ConstantFPSDNode *C,
3081+
const SDLoc &DL,
3082+
SelectionDAG &DAG) const {
3083+
APInt V = C->getValueAPF().bitcastToAPInt();
3084+
SDValue Lo = DAG.getConstant(V.zextOrTrunc(32), DL, MVT::i32);
3085+
SDValue Hi = DAG.getConstant(V.lshr(32).zextOrTrunc(32), DL, MVT::i32);
3086+
if (DAG.getDataLayout().isLittleEndian())
3087+
std::swap(Lo, Hi);
3088+
return DAG.getBuildVector(MVT::v2i32, DL, {Hi, Lo});
3089+
}
3090+
3091+
SDValue SparcTargetLowering::PerformBITCASTCombine(SDNode *N,
3092+
DAGCombinerInfo &DCI) const {
3093+
SDLoc dl(N);
3094+
SDValue Src = N->getOperand(0);
3095+
3096+
if (isa<ConstantFPSDNode>(Src) && N->getSimpleValueType(0) == MVT::v2i32 &&
3097+
Src.getSimpleValueType() == MVT::f64)
3098+
return bitcastConstantFPToInt(cast<ConstantFPSDNode>(Src), dl, DCI.DAG);
3099+
3100+
return SDValue();
3101+
}
3102+
3103+
SDValue SparcTargetLowering::PerformDAGCombine(SDNode *N,
3104+
DAGCombinerInfo &DCI) const {
3105+
switch (N->getOpcode()) {
3106+
default:
3107+
break;
3108+
case ISD::BITCAST:
3109+
return PerformBITCASTCombine(N, DCI);
3110+
}
3111+
return SDValue();
3112+
}
3113+
30783114
MachineBasicBlock *
30793115
SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
30803116
MachineBasicBlock *BB) const {

llvm/lib/Target/Sparc/SparcISelLowering.h

+7
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,13 @@ namespace llvm {
191191

192192
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
193193

194+
SDValue PerformBITCASTCombine(SDNode *N, DAGCombinerInfo &DCI) const;
195+
196+
SDValue bitcastConstantFPToInt(ConstantFPSDNode *C, const SDLoc &DL,
197+
SelectionDAG &DAG) const;
198+
199+
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
200+
194201
bool ShouldShrinkFPConstant(EVT VT) const override {
195202
// Do not shrink FP constpool if VT == MVT::f128.
196203
// (ldd, call _Q_fdtoq) is more expensive than two ldds.

llvm/test/CodeGen/SPARC/float-constants.ll

+15-9
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
; RUN: llc < %s -march=sparc | FileCheck %s
2-
3-
; TODO: actually fix the codegen to be optimal. At least we don't
4-
; crash for now, though...
2+
; RUN: llc < %s -march=sparcel | FileCheck %s --check-prefix=CHECK-LE
53

64
;; Bitcast should not do a runtime conversion, but rather emit a
75
;; constant into integer registers directly.
86

97
; CHECK-LABEL: bitcast:
10-
; TODO-CHECK: sethi 1049856, %o0
11-
; TODO-CHECK: sethi 0, %o1
8+
; CHECK: sethi 1049856, %o0
9+
; CHECK: mov %g0, %o1
10+
; CHECK-LE: mov %g0, %o0
11+
; CHECK-LE: sethi 1049856, %o1
1212
define <2 x i32> @bitcast() {
1313
%1 = bitcast double 5.0 to <2 x i32>
1414
ret <2 x i32> %1
@@ -18,8 +18,10 @@ define <2 x i32> @bitcast() {
1818
;; registers)
1919

2020
; CHECK-LABEL: test_call
21-
; TODO-CHECK: sethi 1049856, %o0
22-
; TODO-CHECK: sethi 0, %o1
21+
; CHECK: sethi 1049856, %o0
22+
; CHECK: mov %g0, %o1
23+
; CHECK-LE: mov %g0, %o0
24+
; CHECK-LE: sethi 1049856, %o1
2325
declare void @a(double)
2426
define void @test_call() {
2527
call void @a(double 5.0)
@@ -32,8 +34,12 @@ define void @test_call() {
3234
;; due to an earlier broken workaround for this issue.)
3335

3436
; CHECK-LABEL: test_intrins_call
35-
; TODO-CHECK: sethi 1049856, %o0
36-
; TODO-CHECK: sethi 0, %o1
37+
; CHECK: sethi 1048576, %o0
38+
; CHECK: mov %g0, %o1
39+
; CHECK: mov %o0, %o2
40+
; CHECK: mov %o1, %o3
41+
; CHECK-LE: mov %g0, %o0
42+
; CHECK-LE: sethi 1048576, %o1
3743
declare double @llvm.pow.f64(double, double)
3844
define double @test_intrins_call() {
3945
%1 = call double @llvm.pow.f64(double 2.0, double 2.0)

0 commit comments

Comments
 (0)