From 1799921672835c49f6a29fc27d1840b7c36beabd Mon Sep 17 00:00:00 2001 From: Venkatraman Govindaraju Date: Sat, 8 Jun 2013 15:32:59 +0000 Subject: [PATCH] [Sparc] Delete FPMover Pass and remove Fp* Pseudo-instructions from Sparc backend. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183613 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Sparc/CMakeLists.txt | 1 - lib/Target/Sparc/FPMover.cpp | 141 ------------------------ lib/Target/Sparc/Sparc.h | 1 - lib/Target/Sparc/SparcISelLowering.cpp | 40 ++++++- lib/Target/Sparc/SparcInstrInfo.cpp | 26 ++++- lib/Target/Sparc/SparcInstrInfo.td | 13 --- lib/Target/Sparc/SparcTargetMachine.cpp | 1 - test/CodeGen/SPARC/float.ll | 47 ++++++++ 8 files changed, 108 insertions(+), 162 deletions(-) delete mode 100644 lib/Target/Sparc/FPMover.cpp create mode 100644 test/CodeGen/SPARC/float.ll diff --git a/lib/Target/Sparc/CMakeLists.txt b/lib/Target/Sparc/CMakeLists.txt index efb10db4c0a..0ab7a1c88e0 100644 --- a/lib/Target/Sparc/CMakeLists.txt +++ b/lib/Target/Sparc/CMakeLists.txt @@ -10,7 +10,6 @@ add_public_tablegen_target(SparcCommonTableGen) add_llvm_target(SparcCodeGen DelaySlotFiller.cpp - FPMover.cpp SparcAsmPrinter.cpp SparcInstrInfo.cpp SparcISelDAGToDAG.cpp diff --git a/lib/Target/Sparc/FPMover.cpp b/lib/Target/Sparc/FPMover.cpp deleted file mode 100644 index 5592668952b..00000000000 --- a/lib/Target/Sparc/FPMover.cpp +++ /dev/null @@ -1,141 +0,0 @@ -//===-- FPMover.cpp - Sparc double-precision floating point move fixer ----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Expand FpMOVD/FpABSD/FpNEGD instructions into their single-precision pieces. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "fpmover" -#include "Sparc.h" -#include "SparcSubtarget.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -using namespace llvm; - -STATISTIC(NumFpDs , "Number of instructions translated"); -STATISTIC(NoopFpDs, "Number of noop instructions removed"); - -namespace { - struct FPMover : public MachineFunctionPass { - /// Target machine description which we query for reg. names, data - /// layout, etc. - /// - TargetMachine &TM; - - static char ID; - explicit FPMover(TargetMachine &tm) - : MachineFunctionPass(ID), TM(tm) { } - - virtual const char *getPassName() const { - return "Sparc Double-FP Move Fixer"; - } - - bool runOnMachineBasicBlock(MachineBasicBlock &MBB); - bool runOnMachineFunction(MachineFunction &F); - }; - char FPMover::ID = 0; -} // end of anonymous namespace - -/// createSparcFPMoverPass - Returns a pass that turns FpMOVD -/// instructions into FMOVS instructions -/// -FunctionPass *llvm::createSparcFPMoverPass(TargetMachine &tm) { - return new FPMover(tm); -} - -/// getDoubleRegPair - Given a DFP register, return the even and odd FP -/// registers that correspond to it. -static void getDoubleRegPair(unsigned DoubleReg, unsigned &EvenReg, - unsigned &OddReg) { - static const uint16_t EvenHalvesOfPairs[] = { - SP::F0, SP::F2, SP::F4, SP::F6, SP::F8, SP::F10, SP::F12, SP::F14, - SP::F16, SP::F18, SP::F20, SP::F22, SP::F24, SP::F26, SP::F28, SP::F30 - }; - static const uint16_t OddHalvesOfPairs[] = { - SP::F1, SP::F3, SP::F5, SP::F7, SP::F9, SP::F11, SP::F13, SP::F15, - SP::F17, SP::F19, SP::F21, SP::F23, SP::F25, SP::F27, SP::F29, SP::F31 - }; - static const uint16_t DoubleRegsInOrder[] = { - SP::D0, SP::D1, SP::D2, SP::D3, SP::D4, SP::D5, SP::D6, SP::D7, SP::D8, - SP::D9, SP::D10, SP::D11, SP::D12, SP::D13, SP::D14, SP::D15 - }; - for (unsigned i = 0; i < array_lengthof(DoubleRegsInOrder); ++i) - if (DoubleRegsInOrder[i] == DoubleReg) { - EvenReg = EvenHalvesOfPairs[i]; - OddReg = OddHalvesOfPairs[i]; - return; - } - llvm_unreachable("Can't find reg"); -} - -/// runOnMachineBasicBlock - Fixup FpMOVD instructions in this MBB. -/// -bool FPMover::runOnMachineBasicBlock(MachineBasicBlock &MBB) { - bool Changed = false; - for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) { - MachineInstr *MI = I++; - DebugLoc dl = MI->getDebugLoc(); - if (MI->getOpcode() == SP::FpMOVD || MI->getOpcode() == SP::FpABSD || - MI->getOpcode() == SP::FpNEGD) { - Changed = true; - unsigned DestDReg = MI->getOperand(0).getReg(); - unsigned SrcDReg = MI->getOperand(1).getReg(); - if (DestDReg == SrcDReg && MI->getOpcode() == SP::FpMOVD) { - MBB.erase(MI); // Eliminate the noop copy. - ++NoopFpDs; - continue; - } - - unsigned EvenSrcReg = 0, OddSrcReg = 0, EvenDestReg = 0, OddDestReg = 0; - getDoubleRegPair(DestDReg, EvenDestReg, OddDestReg); - getDoubleRegPair(SrcDReg, EvenSrcReg, OddSrcReg); - - const TargetInstrInfo *TII = TM.getInstrInfo(); - if (MI->getOpcode() == SP::FpMOVD) - MI->setDesc(TII->get(SP::FMOVS)); - else if (MI->getOpcode() == SP::FpNEGD) - MI->setDesc(TII->get(SP::FNEGS)); - else if (MI->getOpcode() == SP::FpABSD) - MI->setDesc(TII->get(SP::FABSS)); - else - llvm_unreachable("Unknown opcode!"); - - MI->getOperand(0).setReg(EvenDestReg); - MI->getOperand(1).setReg(EvenSrcReg); - DEBUG(errs() << "FPMover: the modified instr is: " << *MI); - // Insert copy for the other half of the double. - if (DestDReg != SrcDReg) { - MI = BuildMI(MBB, I, dl, TM.getInstrInfo()->get(SP::FMOVS), OddDestReg) - .addReg(OddSrcReg); - DEBUG(errs() << "FPMover: the inserted instr is: " << *MI); - } - ++NumFpDs; - } - } - return Changed; -} - -bool FPMover::runOnMachineFunction(MachineFunction &F) { - // If the target has V9 instructions, the fp-mover pseudos will never be - // emitted. Avoid a scan of the instructions to improve compile time. - if (TM.getSubtarget().isV9()) - return false; - - bool Changed = false; - for (MachineFunction::iterator FI = F.begin(), FE = F.end(); - FI != FE; ++FI) - Changed |= runOnMachineBasicBlock(*FI); - return Changed; -} diff --git a/lib/Target/Sparc/Sparc.h b/lib/Target/Sparc/Sparc.h index 90ba27358ce..98563db4b9e 100644 --- a/lib/Target/Sparc/Sparc.h +++ b/lib/Target/Sparc/Sparc.h @@ -26,7 +26,6 @@ namespace llvm { FunctionPass *createSparcISelDag(SparcTargetMachine &TM); FunctionPass *createSparcDelaySlotFillerPass(TargetMachine &TM); - FunctionPass *createSparcFPMoverPass(TargetMachine &TM); } // end namespace llvm; diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index 3cd9a74bdee..1d765f24def 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -1315,6 +1315,12 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) // on SparcV8 and later. setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); + if (!Subtarget->isV9()) { + // SparcV8 does not have FNEGD and FABSD. + setOperationAction(ISD::FNEG, MVT::f64, Custom); + setOperationAction(ISD::FABS, MVT::f64, Custom); + } + setOperationAction(ISD::FSIN , MVT::f64, Expand); setOperationAction(ISD::FCOS , MVT::f64, Expand); setOperationAction(ISD::FSINCOS, MVT::f64, Expand); @@ -1365,7 +1371,7 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM) setStackPointerRegisterToSaveRestore(SP::O6); - if (TM.getSubtarget().isV9()) + if (Subtarget->isV9()) setOperationAction(ISD::CTPOP, MVT::i32, Legal); setMinFunctionAlignment(2); @@ -1751,10 +1757,42 @@ static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) { return RetAddr; } +static SDValue LowerF64Op(SDValue Op, SelectionDAG &DAG) +{ + SDLoc dl(Op); + + assert(Op.getValueType() == MVT::f64 && "LowerF64Op called on non-double!"); + assert(Op.getOpcode() == ISD::FNEG || Op.getOpcode() == 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); + 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(Op.getOpcode(), dl, MVT::f32, Hi32); + + SDValue DstReg64 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, + dl, MVT::f64), 0); + DstReg64 = DAG.getTargetInsertSubreg(SP::sub_even, dl, MVT::f64, + DstReg64, Hi32); + DstReg64 = DAG.getTargetInsertSubreg(SP::sub_odd, dl, MVT::f64, + DstReg64, Lo32); + return DstReg64; +} + SDValue SparcTargetLowering:: LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { default: llvm_unreachable("Should not custom lower this!"); + + case ISD::FNEG: + case ISD::FABS: return LowerF64Op(Op, DAG); + case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); case ISD::GlobalTLSAddress: diff --git a/lib/Target/Sparc/SparcInstrInfo.cpp b/lib/Target/Sparc/SparcInstrInfo.cpp index 2ccbdf85bde..626bc40adbc 100644 --- a/lib/Target/Sparc/SparcInstrInfo.cpp +++ b/lib/Target/Sparc/SparcInstrInfo.cpp @@ -289,10 +289,28 @@ void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB, else if (SP::FPRegsRegClass.contains(DestReg, SrcReg)) BuildMI(MBB, I, DL, get(SP::FMOVS), DestReg) .addReg(SrcReg, getKillRegState(KillSrc)); - else if (SP::DFPRegsRegClass.contains(DestReg, SrcReg)) - BuildMI(MBB, I, DL, get(Subtarget.isV9() ? SP::FMOVD : SP::FpMOVD), DestReg) - .addReg(SrcReg, getKillRegState(KillSrc)); - else + else if (SP::DFPRegsRegClass.contains(DestReg, SrcReg)) { + if (Subtarget.isV9()) { + BuildMI(MBB, I, DL, get(SP::FMOVD), DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + } else { + // Use two FMOVS instructions. + const TargetRegisterInfo *TRI = &getRegisterInfo(); + MachineInstr *MovMI = 0; + unsigned subRegIdx[] = {SP::sub_even, SP::sub_odd}; + for (unsigned i = 0; i != 2; ++i) { + unsigned Dst = TRI->getSubReg(DestReg, subRegIdx[i]); + unsigned Src = TRI->getSubReg(SrcReg, subRegIdx[i]); + assert(Dst && Src && "Bad sub-register"); + + MovMI = BuildMI(MBB, I, DL, get(SP::FMOVS), Dst).addReg(Src); + } + // Add implicit super-register defs and kills to the last MovMI. + MovMI->addRegisterDefined(DestReg, TRI); + if (KillSrc) + MovMI->addRegisterKilled(SrcReg, TRI); + } + } else llvm_unreachable("Impossible reg-to-reg copy"); } diff --git a/lib/Target/Sparc/SparcInstrInfo.td b/lib/Target/Sparc/SparcInstrInfo.td index 663947cbe6c..d4cac4d3bac 100644 --- a/lib/Target/Sparc/SparcInstrInfo.td +++ b/lib/Target/Sparc/SparcInstrInfo.td @@ -245,19 +245,6 @@ let hasSideEffects = 1, mayStore = 1 in { def UNIMP : F2_1<0b000, (outs), (ins i32imm:$val), "unimp $val", []>; -// FpMOVD/FpNEGD/FpABSD - These are lowered to single-precision ops by the -// fpmover pass. -let Predicates = [HasNoV9] in { // Only emit these in V8 mode. - def FpMOVD : Pseudo<(outs DFPRegs:$dst), (ins DFPRegs:$src), - "!FpMOVD $src, $dst", []>; - def FpNEGD : Pseudo<(outs DFPRegs:$dst), (ins DFPRegs:$src), - "!FpNEGD $src, $dst", - [(set f64:$dst, (fneg f64:$src))]>; - def FpABSD : Pseudo<(outs DFPRegs:$dst), (ins DFPRegs:$src), - "!FpABSD $src, $dst", - [(set f64:$dst, (fabs f64:$src))]>; -} - // SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded after // instruction selection into a branch sequence. This has to handle all // permutations of selection between i32/f32/f64 on ICC and FCC. diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp index 3e7a24aecf4..a7355f49fae 100644 --- a/lib/Target/Sparc/SparcTargetMachine.cpp +++ b/lib/Target/Sparc/SparcTargetMachine.cpp @@ -69,7 +69,6 @@ bool SparcPassConfig::addInstSelector() { /// passes immediately before machine code is emitted. This should return /// true if -print-machineinstrs should print out the code after the passes. bool SparcPassConfig::addPreEmitPass(){ - addPass(createSparcFPMoverPass(getSparcTargetMachine())); addPass(createSparcDelaySlotFillerPass(getSparcTargetMachine())); return true; } diff --git a/test/CodeGen/SPARC/float.ll b/test/CodeGen/SPARC/float.ll new file mode 100644 index 00000000000..ab46fb301e3 --- /dev/null +++ b/test/CodeGen/SPARC/float.ll @@ -0,0 +1,47 @@ +; RUN: llc -march=sparc < %s | FileCheck %s -check-prefix=V8 +; RUN: llc -march=sparc -O0 < %s | FileCheck %s -check-prefix=V8-UNOPT +; RUN: llc -march=sparc -mattr=v9 < %s | FileCheck %s -check-prefix=V9 + + +; V8: test_neg: +; V8: call get_double +; V8: fnegs %f0, %f0 + +; V8-UNOPT: test_neg: +; V8-UNOPT: fnegs +; V8-UNOPT: ! implicit-def +; V8-UNOPT: fmovs {{.+}}, %f0 +; V8-UNOPT: fmovs {{.+}}, %f1 + +; V9: test_neg: +; V9: fnegd %f0, %f0 + +define double @test_neg() { +entry: + %0 = tail call double @get_double() + %1 = fsub double -0.000000e+00, %0 + ret double %1 +} + +; V8: test_abs: +; V8: fabss %f0, %f0 + +; V8-UNOPT: test_abs: +; V8-UNOPT: fabss +; V8-UNOPT: ! implicit-def +; V8-UNOPT: fmovs {{.+}}, %f0 +; V8-UNOPT: fmovs {{.+}}, %f1 + +; V9: test_abs: +; V9: fabsd %f0, %f0 + +define double @test_abs() { +entry: + %0 = tail call double @get_double() + %1 = tail call double @llvm.fabs.f64(double %0) + ret double %1 +} + +declare double @get_double() +declare double @llvm.fabs.f64(double) nounwind readonly +