From 953a78084b85ea88cd2b208153a72df70e27133f Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Mon, 19 Aug 2013 05:01:02 +0000 Subject: [PATCH] Add the PPC fcpsgn instruction Modern PPC cores support a floating-point copysign instruction, and we can use this to lower the FCOPYSIGN node (which is created from calls to the libm copysign function). A couple of extra patterns are necessary because the operand types of FCOPYSIGN need not agree. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@188653 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPC.td | 12 +++--- lib/Target/PowerPC/PPCISelLowering.cpp | 9 ++++- lib/Target/PowerPC/PPCInstrInfo.td | 28 ++++++++++++++ lib/Target/PowerPC/PPCSubtarget.cpp | 1 + lib/Target/PowerPC/PPCSubtarget.h | 2 + test/CodeGen/PowerPC/fcpsgn.ll | 52 ++++++++++++++++++++++++++ test/MC/PowerPC/ppc64-encoding-fp.s | 6 ++- 7 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 test/CodeGen/PowerPC/fcpsgn.ll diff --git a/lib/Target/PowerPC/PPC.td b/lib/Target/PowerPC/PPC.td index 806822c2961..0d950ee5a06 100644 --- a/lib/Target/PowerPC/PPC.td +++ b/lib/Target/PowerPC/PPC.td @@ -57,6 +57,8 @@ def FeatureMFOCRF : SubtargetFeature<"mfocrf","HasMFOCRF", "true", "Enable the MFOCRF instruction">; def FeatureFSqrt : SubtargetFeature<"fsqrt","HasFSQRT", "true", "Enable the fsqrt instruction">; +def FeatureFCPSGN : SubtargetFeature<"fcpsgn", "HasFCPSGN", "true", + "Enable the fcpsgn instruction">; def FeatureFRE : SubtargetFeature<"fre", "HasFRE", "true", "Enable the fre instruction">; def FeatureFRES : SubtargetFeature<"fres", "HasFRES", "true", @@ -194,7 +196,7 @@ def : ProcessorModel<"e5500", PPCE5500Model, FeatureSTFIWX, FeatureBookE, FeatureISEL]>; def : ProcessorModel<"a2", PPCA2Model, [DirectiveA2, FeatureBookE, FeatureMFOCRF, - FeatureFSqrt, FeatureFRE, FeatureFRES, + FeatureFCPSGN, FeatureFSqrt, FeatureFRE, FeatureFRES, FeatureFRSQRTE, FeatureFRSQRTES, FeatureRecipPrec, FeatureSTFIWX, FeatureLFIWAX, FeatureFPRND, FeatureFPCVT, FeatureISEL, @@ -202,7 +204,7 @@ def : ProcessorModel<"a2", PPCA2Model, /*, Feature64BitRegs */]>; def : ProcessorModel<"a2q", PPCA2Model, [DirectiveA2, FeatureBookE, FeatureMFOCRF, - FeatureFSqrt, FeatureFRE, FeatureFRES, + FeatureFCPSGN, FeatureFSqrt, FeatureFRE, FeatureFRES, FeatureFRSQRTE, FeatureFRSQRTES, FeatureRecipPrec, FeatureSTFIWX, FeatureLFIWAX, FeatureFPRND, FeatureFPCVT, FeatureISEL, @@ -228,19 +230,19 @@ def : ProcessorModel<"pwr5x", G5Model, FeatureSTFIWX, FeatureFPRND, Feature64Bit]>; def : ProcessorModel<"pwr6", G5Model, [DirectivePwr6, FeatureAltivec, - FeatureMFOCRF, FeatureFSqrt, FeatureFRE, + FeatureMFOCRF, FeatureFCPSGN, FeatureFSqrt, FeatureFRE, FeatureFRES, FeatureFRSQRTE, FeatureFRSQRTES, FeatureRecipPrec, FeatureSTFIWX, FeatureLFIWAX, FeatureFPRND, Feature64Bit /*, Feature64BitRegs */]>; def : ProcessorModel<"pwr6x", G5Model, [DirectivePwr5x, FeatureAltivec, FeatureMFOCRF, - FeatureFSqrt, FeatureFRE, FeatureFRES, + FeatureFCPSGN, FeatureFSqrt, FeatureFRE, FeatureFRES, FeatureFRSQRTE, FeatureFRSQRTES, FeatureRecipPrec, FeatureSTFIWX, FeatureLFIWAX, FeatureFPRND, Feature64Bit]>; def : ProcessorModel<"pwr7", G5Model, [DirectivePwr7, FeatureAltivec, - FeatureMFOCRF, FeatureFSqrt, FeatureFRE, + FeatureMFOCRF, FeatureFCPSGN, FeatureFSqrt, FeatureFRE, FeatureFRES, FeatureFRSQRTE, FeatureFRSQRTES, FeatureRecipPrec, FeatureSTFIWX, FeatureLFIWAX, FeatureFPRND, FeatureFPCVT, FeatureISEL, diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index 2b83a22ac67..bc55d383f1e 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -149,8 +149,13 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) Subtarget->hasFRSQRTES() && Subtarget->hasFRES())) setOperationAction(ISD::FSQRT, MVT::f32, Expand); - setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); - setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); + if (Subtarget->hasFCPSGN()) { + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Legal); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Legal); + } else { + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); + } if (Subtarget->hasFPRND()) { setOperationAction(ISD::FFLOOR, MVT::f64, Legal); diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 84ddb3ffdb7..35e9935f7b7 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -785,6 +785,20 @@ multiclass XForm_26r opcode, bits<10> xo, dag OOL, dag IOL, } } +multiclass XForm_28r opcode, bits<10> xo, dag OOL, dag IOL, + string asmbase, string asmstr, InstrItinClass itin, + list pattern> { + let BaseName = asmbase in { + def NAME : XForm_28, RecFormRel; + let Defs = [CR1] in + def o : XForm_28, isDOT, RecFormRel; + } +} + multiclass AForm_1r opcode, bits<5> xo, dag OOL, dag IOL, string asmbase, string asmstr, InstrItinClass itin, list pattern> { @@ -1762,6 +1776,14 @@ defm FNEGD : XForm_26r<63, 40, (outs f8rc:$frD), (ins f8rc:$frB), "fneg", "$frD, $frB", FPGeneral, [(set f64:$frD, (fneg f64:$frB))]>; +defm FCPSGNS : XForm_28r<63, 8, (outs f4rc:$frD), (ins f4rc:$frA, f4rc:$frB), + "fcpsgn", "$frD, $frA, $frB", FPGeneral, + [(set f32:$frD, (fcopysign f32:$frB, f32:$frA))]>; +let Interpretation64Bit = 1 in +defm FCPSGND : XForm_28r<63, 8, (outs f8rc:$frD), (ins f8rc:$frA, f8rc:$frB), + "fcpsgn", "$frD, $frA, $frB", FPGeneral, + [(set f64:$frD, (fcopysign f64:$frB, f64:$frA))]>; + // Reciprocal estimates. defm FRE : XForm_26r<63, 24, (outs f8rc:$frD), (ins f8rc:$frB), "fre", "$frD, $frB", FPGeneral, @@ -2270,6 +2292,12 @@ def : Pat<(fma (fneg f32:$A), f32:$C, f32:$B), def : Pat<(fma f32:$A, (fneg f32:$C), f32:$B), (FNMSUBS $A, $C, $B)>; +// FCOPYSIGN's operand types need not agree. +def : Pat<(fcopysign f64:$frB, f32:$frA), + (FCPSGND (COPY_TO_REGCLASS $frA, F8RC), $frB)>; +def : Pat<(fcopysign f32:$frB, f64:$frA), + (FCPSGNS (COPY_TO_REGCLASS $frA, F4RC), $frB)>; + include "PPCInstrAltivec.td" include "PPCInstr64Bit.td" diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp b/lib/Target/PowerPC/PPCSubtarget.cpp index 12d0326855c..f975f5539c3 100644 --- a/lib/Target/PowerPC/PPCSubtarget.cpp +++ b/lib/Target/PowerPC/PPCSubtarget.cpp @@ -74,6 +74,7 @@ void PPCSubtarget::initializeEnvironment() { Use64BitRegs = false; HasAltivec = false; HasQPX = false; + HasFCPSGN = false; HasFSQRT = false; HasFRE = false; HasFRES = false; diff --git a/lib/Target/PowerPC/PPCSubtarget.h b/lib/Target/PowerPC/PPCSubtarget.h index 3f3fc0e9cda..a933bf69bbe 100644 --- a/lib/Target/PowerPC/PPCSubtarget.h +++ b/lib/Target/PowerPC/PPCSubtarget.h @@ -76,6 +76,7 @@ protected: bool IsPPC64; bool HasAltivec; bool HasQPX; + bool HasFCPSGN; bool HasFSQRT; bool HasFRE, HasFRES, HasFRSQRTE, HasFRSQRTES; bool HasRecipPrec; @@ -171,6 +172,7 @@ public: bool isLittleEndian() const { return IsLittleEndian; } // Specific obvious features. + bool hasFCPSGN() const { return HasFCPSGN; } bool hasFSQRT() const { return HasFSQRT; } bool hasFRE() const { return HasFRE; } bool hasFRES() const { return HasFRES; } diff --git a/test/CodeGen/PowerPC/fcpsgn.ll b/test/CodeGen/PowerPC/fcpsgn.ll new file mode 100644 index 00000000000..f4699816340 --- /dev/null +++ b/test/CodeGen/PowerPC/fcpsgn.ll @@ -0,0 +1,52 @@ +; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 < %s | FileCheck %s +target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64" +target triple = "powerpc64-unknown-linux-gnu" + +define double @foo_dd(double %a, double %b) #0 { +entry: + %call = tail call double @copysign(double %a, double %b) #0 + ret double %call + +; CHECK-LABEL: @foo_dd +; CHECK: fcpsgn 1, 2, 1 +; CHECK: blr +} + +declare double @copysign(double, double) #0 + +define float @foo_ss(float %a, float %b) #0 { +entry: + %call = tail call float @copysignf(float %a, float %b) #0 + ret float %call + +; CHECK-LABEL: @foo_ss +; CHECK: fcpsgn 1, 2, 1 +; CHECK: blr +} + +declare float @copysignf(float, float) #0 + +define float @foo_sd(float %a, double %b) #0 { +entry: + %conv = fptrunc double %b to float + %call = tail call float @copysignf(float %a, float %conv) #0 + ret float %call + +; CHECK-LABEL: @foo_sd +; CHECK: fcpsgn 1, 2, 1 +; CHECK: blr +} + +define double @foo_ds(double %a, float %b) #0 { +entry: + %conv = fpext float %b to double + %call = tail call double @copysign(double %a, double %conv) #0 + ret double %call + +; CHECK-LABEL: @foo_ds +; CHECK: fcpsgn 1, 2, 1 +; CHECK: blr +} + +attributes #0 = { nounwind readnone } + diff --git a/test/MC/PowerPC/ppc64-encoding-fp.s b/test/MC/PowerPC/ppc64-encoding-fp.s index ae0e2866a26..e288dea89f3 100644 --- a/test/MC/PowerPC/ppc64-encoding-fp.s +++ b/test/MC/PowerPC/ppc64-encoding-fp.s @@ -65,8 +65,10 @@ fnabs 2, 3 # CHECK: fnabs. 2, 3 # encoding: [0xfc,0x40,0x19,0x11] fnabs. 2, 3 -# FIXME: fcpsgn 2, 3 -# FIXME: fcpsgn. 2, 3 +# CHECK: fcpsgn 2, 3, 4 # encoding: [0xfc,0x43,0x20,0x10] + fcpsgn 2, 3, 4 +# CHECK: fcpsgn. 2, 3, 4 # encoding: [0xfc,0x43,0x20,0x11] + fcpsgn. 2, 3, 4 # Floating-point arithmetic instructions -- 2.34.1