diff options
-rw-r--r-- | llvm/lib/Target/Sparc/SparcISelLowering.cpp | 40 | ||||
-rw-r--r-- | llvm/test/CodeGen/SPARC/float.ll | 9 | ||||
-rw-r--r-- | llvm/test/CodeGen/SPARC/fp128.ll | 117 |
3 files changed, 77 insertions, 89 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); diff --git a/llvm/test/CodeGen/SPARC/float.ll b/llvm/test/CodeGen/SPARC/float.ll index c4cc04420ad..248e98549c9 100644 --- a/llvm/test/CodeGen/SPARC/float.ll +++ b/llvm/test/CodeGen/SPARC/float.ll @@ -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 diff --git a/llvm/test/CodeGen/SPARC/fp128.ll b/llvm/test/CodeGen/SPARC/fp128.ll index e0eaf93a733..bcc013b7357 100644 --- a/llvm/test/CodeGen/SPARC/fp128.ll +++ b/llvm/test/CodeGen/SPARC/fp128.ll @@ -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: |