mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 20:29:48 +00:00
6a0f060f64
The VSX instruction set has two types of FMA instructions: A-type (where the addend is taken from the output register) and M-type (where one of the product operands is taken from the output register). This adds a small pass that runs just after MI scheduling (and, thus, just before register allocation) that mutates A-type instructions (that are created during isel) into M-type instructions when: 1. This will eliminate an otherwise-necessary copy of the addend 2. One of the product operands is killed by the instruction The "right" moment to make this decision is in between scheduling and register allocation, because only there do we know whether or not one of the product operands is killed by any particular instruction. Unfortunately, this also makes the implementation somewhat complicated, because the MIs are not in SSA form and we need to preserve the LiveIntervals analysis. As a simple example, if we have: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9 %vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16, %RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16 ... %vreg9<def,tied1> = XSMADDADP %vreg9<tied0>, %vreg17, %vreg19, %RM<imp-use>; VSLRC:%vreg9,%vreg17,%vreg19 ... We can eliminate the copy by changing from the A-type to the M-type instruction. This means: %vreg5<def,tied1> = XSMADDADP %vreg5<tied0>, %vreg17, %vreg16, %RM<imp-use>; VSLRC:%vreg5,%vreg17,%vreg16 is replaced by: %vreg16<def,tied1> = XSMADDMDP %vreg16<tied0>, %vreg18, %vreg9, %RM<imp-use>; VSLRC:%vreg16,%vreg18,%vreg9 and we remove: %vreg5<def> = COPY %vreg9; VSLRC:%vreg5,%vreg9 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204768 91177308-0d34-0410-b5e6-96231b3b80d8
219 lines
6.7 KiB
C++
219 lines
6.7 KiB
C++
//===-- PPCTargetMachine.cpp - Define TargetMachine for PowerPC -----------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Top-level implementation for the PowerPC target.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "PPCTargetMachine.h"
|
|
#include "PPC.h"
|
|
#include "llvm/CodeGen/Passes.h"
|
|
#include "llvm/MC/MCStreamer.h"
|
|
#include "llvm/PassManager.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/FormattedStream.h"
|
|
#include "llvm/Support/TargetRegistry.h"
|
|
#include "llvm/Target/TargetOptions.h"
|
|
using namespace llvm;
|
|
|
|
static cl::
|
|
opt<bool> DisableCTRLoops("disable-ppc-ctrloops", cl::Hidden,
|
|
cl::desc("Disable CTR loops for PPC"));
|
|
|
|
static cl::opt<bool>
|
|
VSXFMAMutateEarly("schedule-ppc-vsx-fma-mutation-early",
|
|
cl::Hidden, cl::desc("Schedule VSX FMA instruction mutation early"));
|
|
|
|
extern "C" void LLVMInitializePowerPCTarget() {
|
|
// Register the targets
|
|
RegisterTargetMachine<PPC32TargetMachine> A(ThePPC32Target);
|
|
RegisterTargetMachine<PPC64TargetMachine> B(ThePPC64Target);
|
|
RegisterTargetMachine<PPC64TargetMachine> C(ThePPC64LETarget);
|
|
}
|
|
|
|
/// Return the datalayout string of a subtarget.
|
|
static std::string getDataLayoutString(const PPCSubtarget &ST) {
|
|
const Triple &T = ST.getTargetTriple();
|
|
|
|
std::string Ret;
|
|
|
|
// Most PPC* platforms are big endian, PPC64LE is little endian.
|
|
if (ST.isLittleEndian())
|
|
Ret = "e";
|
|
else
|
|
Ret = "E";
|
|
|
|
Ret += DataLayout::getManglingComponent(T);
|
|
|
|
// PPC32 has 32 bit pointers. The PS3 (OS Lv2) is a PPC64 machine with 32 bit
|
|
// pointers.
|
|
if (!ST.isPPC64() || T.getOS() == Triple::Lv2)
|
|
Ret += "-p:32:32";
|
|
|
|
// Note, the alignment values for f64 and i64 on ppc64 in Darwin
|
|
// documentation are wrong; these are correct (i.e. "what gcc does").
|
|
if (ST.isPPC64() || ST.isSVR4ABI())
|
|
Ret += "-i64:64";
|
|
else
|
|
Ret += "-f64:32:64";
|
|
|
|
// PPC64 has 32 and 64 bit registers, PPC32 has only 32 bit ones.
|
|
if (ST.isPPC64())
|
|
Ret += "-n32:64";
|
|
else
|
|
Ret += "-n32";
|
|
|
|
return Ret;
|
|
}
|
|
|
|
PPCTargetMachine::PPCTargetMachine(const Target &T, StringRef TT,
|
|
StringRef CPU, StringRef FS,
|
|
const TargetOptions &Options,
|
|
Reloc::Model RM, CodeModel::Model CM,
|
|
CodeGenOpt::Level OL,
|
|
bool is64Bit)
|
|
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
|
|
Subtarget(TT, CPU, FS, is64Bit, OL),
|
|
DL(getDataLayoutString(Subtarget)), InstrInfo(*this),
|
|
FrameLowering(Subtarget), JITInfo(*this, is64Bit),
|
|
TLInfo(*this), TSInfo(*this),
|
|
InstrItins(Subtarget.getInstrItineraryData()) {
|
|
initAsmInfo();
|
|
}
|
|
|
|
void PPC32TargetMachine::anchor() { }
|
|
|
|
PPC32TargetMachine::PPC32TargetMachine(const Target &T, StringRef TT,
|
|
StringRef CPU, StringRef FS,
|
|
const TargetOptions &Options,
|
|
Reloc::Model RM, CodeModel::Model CM,
|
|
CodeGenOpt::Level OL)
|
|
: PPCTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {
|
|
}
|
|
|
|
void PPC64TargetMachine::anchor() { }
|
|
|
|
PPC64TargetMachine::PPC64TargetMachine(const Target &T, StringRef TT,
|
|
StringRef CPU, StringRef FS,
|
|
const TargetOptions &Options,
|
|
Reloc::Model RM, CodeModel::Model CM,
|
|
CodeGenOpt::Level OL)
|
|
: PPCTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Pass Pipeline Configuration
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
namespace {
|
|
/// PPC Code Generator Pass Configuration Options.
|
|
class PPCPassConfig : public TargetPassConfig {
|
|
public:
|
|
PPCPassConfig(PPCTargetMachine *TM, PassManagerBase &PM)
|
|
: TargetPassConfig(TM, PM) {}
|
|
|
|
PPCTargetMachine &getPPCTargetMachine() const {
|
|
return getTM<PPCTargetMachine>();
|
|
}
|
|
|
|
const PPCSubtarget &getPPCSubtarget() const {
|
|
return *getPPCTargetMachine().getSubtargetImpl();
|
|
}
|
|
|
|
virtual bool addPreISel();
|
|
virtual bool addILPOpts();
|
|
virtual bool addInstSelector();
|
|
virtual bool addPreRegAlloc();
|
|
virtual bool addPreSched2();
|
|
virtual bool addPreEmitPass();
|
|
};
|
|
} // namespace
|
|
|
|
TargetPassConfig *PPCTargetMachine::createPassConfig(PassManagerBase &PM) {
|
|
return new PPCPassConfig(this, PM);
|
|
}
|
|
|
|
bool PPCPassConfig::addPreISel() {
|
|
if (!DisableCTRLoops && getOptLevel() != CodeGenOpt::None)
|
|
addPass(createPPCCTRLoops(getPPCTargetMachine()));
|
|
|
|
return false;
|
|
}
|
|
|
|
bool PPCPassConfig::addILPOpts() {
|
|
if (getPPCSubtarget().hasISEL()) {
|
|
addPass(&EarlyIfConverterID);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool PPCPassConfig::addInstSelector() {
|
|
// Install an instruction selector.
|
|
addPass(createPPCISelDag(getPPCTargetMachine()));
|
|
|
|
#ifndef NDEBUG
|
|
if (!DisableCTRLoops && getOptLevel() != CodeGenOpt::None)
|
|
addPass(createPPCCTRLoopsVerify());
|
|
#endif
|
|
|
|
if (getPPCSubtarget().hasVSX())
|
|
addPass(createPPCVSXCopyPass());
|
|
|
|
return false;
|
|
}
|
|
|
|
bool PPCPassConfig::addPreRegAlloc() {
|
|
if (getPPCSubtarget().hasVSX()) {
|
|
initializePPCVSXFMAMutatePass(*PassRegistry::getPassRegistry());
|
|
insertPass(VSXFMAMutateEarly ? &RegisterCoalescerID : &MachineSchedulerID,
|
|
&PPCVSXFMAMutateID);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool PPCPassConfig::addPreSched2() {
|
|
if (getOptLevel() != CodeGenOpt::None)
|
|
addPass(&IfConverterID);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PPCPassConfig::addPreEmitPass() {
|
|
if (getOptLevel() != CodeGenOpt::None)
|
|
addPass(createPPCEarlyReturnPass());
|
|
// Must run branch selection immediately preceding the asm printer.
|
|
addPass(createPPCBranchSelectionPass());
|
|
return false;
|
|
}
|
|
|
|
bool PPCTargetMachine::addCodeEmitter(PassManagerBase &PM,
|
|
JITCodeEmitter &JCE) {
|
|
// Inform the subtarget that we are in JIT mode. FIXME: does this break macho
|
|
// writing?
|
|
Subtarget.SetJITMode();
|
|
|
|
// Machine code emitter pass for PowerPC.
|
|
PM.add(createPPCJITCodeEmitterPass(*this, JCE));
|
|
|
|
return false;
|
|
}
|
|
|
|
void PPCTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
|
|
// Add first the target-independent BasicTTI pass, then our PPC pass. This
|
|
// allows the PPC pass to delegate to the target independent layer when
|
|
// appropriate.
|
|
PM.add(createBasicTargetTransformInfoPass(this));
|
|
PM.add(createPPCTargetTransformInfoPass(this));
|
|
}
|
|
|