2012-05-05 04:18:50 +08:00
|
|
|
//===-- NVPTXTargetMachine.cpp - Define TargetMachine for NVPTX -----------===//
|
|
|
|
//
|
|
|
|
// 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 NVPTX target.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "NVPTXTargetMachine.h"
|
|
|
|
#include "MCTargetDesc/NVPTXMCAsmInfo.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "NVPTX.h"
|
2012-05-05 04:18:50 +08:00
|
|
|
#include "NVPTXAllocaHoisting.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "NVPTXLowerAggrCopies.h"
|
2014-11-13 17:26:31 +08:00
|
|
|
#include "NVPTXTargetObjectFile.h"
|
2015-01-31 19:17:59 +08:00
|
|
|
#include "NVPTXTargetTransformInfo.h"
|
2012-05-05 04:18:50 +08:00
|
|
|
#include "llvm/Analysis/Passes.h"
|
|
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
|
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
|
|
#include "llvm/CodeGen/Passes.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
2014-01-12 19:10:32 +08:00
|
|
|
#include "llvm/IR/IRPrintingPasses.h"
|
2015-02-13 18:01:29 +08:00
|
|
|
#include "llvm/IR/LegacyPassManager.h"
|
2014-01-13 17:26:24 +08:00
|
|
|
#include "llvm/IR/Verifier.h"
|
2012-05-05 04:18:50 +08:00
|
|
|
#include "llvm/MC/MCAsmInfo.h"
|
|
|
|
#include "llvm/MC/MCInstrInfo.h"
|
|
|
|
#include "llvm/MC/MCStreamer.h"
|
|
|
|
#include "llvm/MC/MCSubtargetInfo.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/FormattedStream.h"
|
|
|
|
#include "llvm/Support/TargetRegistry.h"
|
2012-05-05 04:18:50 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
|
|
|
#include "llvm/Target/TargetLowering.h"
|
|
|
|
#include "llvm/Target/TargetLoweringObjectFile.h"
|
|
|
|
#include "llvm/Target/TargetMachine.h"
|
|
|
|
#include "llvm/Target/TargetOptions.h"
|
|
|
|
#include "llvm/Target/TargetRegisterInfo.h"
|
|
|
|
#include "llvm/Target/TargetSubtargetInfo.h"
|
|
|
|
#include "llvm/Transforms/Scalar.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2013-03-30 22:29:25 +08:00
|
|
|
namespace llvm {
|
|
|
|
void initializeNVVMReflectPass(PassRegistry&);
|
2013-05-20 20:13:32 +08:00
|
|
|
void initializeGenericToNVVMPass(PassRegistry&);
|
2014-03-31 23:56:26 +08:00
|
|
|
void initializeNVPTXAssignValidGlobalNamesPass(PassRegistry&);
|
2014-04-04 05:18:25 +08:00
|
|
|
void initializeNVPTXFavorNonGenericAddrSpacesPass(PassRegistry &);
|
2014-11-06 02:19:30 +08:00
|
|
|
void initializeNVPTXLowerStructArgsPass(PassRegistry &);
|
2013-03-30 22:29:25 +08:00
|
|
|
}
|
|
|
|
|
2012-05-05 04:18:50 +08:00
|
|
|
extern "C" void LLVMInitializeNVPTXTarget() {
|
|
|
|
// Register the target.
|
|
|
|
RegisterTargetMachine<NVPTXTargetMachine32> X(TheNVPTXTarget32);
|
|
|
|
RegisterTargetMachine<NVPTXTargetMachine64> Y(TheNVPTXTarget64);
|
|
|
|
|
2013-03-30 22:29:25 +08:00
|
|
|
// FIXME: This pass is really intended to be invoked during IR optimization,
|
|
|
|
// but it's very NVPTX-specific.
|
|
|
|
initializeNVVMReflectPass(*PassRegistry::getPassRegistry());
|
2013-05-20 20:13:32 +08:00
|
|
|
initializeGenericToNVVMPass(*PassRegistry::getPassRegistry());
|
2014-03-31 23:56:26 +08:00
|
|
|
initializeNVPTXAssignValidGlobalNamesPass(*PassRegistry::getPassRegistry());
|
2014-04-04 05:18:25 +08:00
|
|
|
initializeNVPTXFavorNonGenericAddrSpacesPass(
|
|
|
|
*PassRegistry::getPassRegistry());
|
2014-11-06 02:19:30 +08:00
|
|
|
initializeNVPTXLowerStructArgsPass(*PassRegistry::getPassRegistry());
|
2012-05-05 04:18:50 +08:00
|
|
|
}
|
|
|
|
|
2015-01-27 03:03:15 +08:00
|
|
|
static std::string computeDataLayout(bool is64Bit) {
|
|
|
|
std::string Ret = "e";
|
|
|
|
|
|
|
|
if (!is64Bit)
|
|
|
|
Ret += "-p:32:32";
|
|
|
|
|
|
|
|
Ret += "-i64:64-v16:16-v32:32-n16:32:64";
|
|
|
|
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
2014-06-27 09:27:06 +08:00
|
|
|
NVPTXTargetMachine::NVPTXTargetMachine(const Target &T, StringRef TT,
|
|
|
|
StringRef CPU, StringRef FS,
|
|
|
|
const TargetOptions &Options,
|
|
|
|
Reloc::Model RM, CodeModel::Model CM,
|
|
|
|
CodeGenOpt::Level OL, bool is64bit)
|
2013-03-30 22:29:21 +08:00
|
|
|
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
|
2014-11-13 17:26:31 +08:00
|
|
|
TLOF(make_unique<NVPTXTargetObjectFile>()),
|
2015-01-27 03:03:15 +08:00
|
|
|
DL(computeDataLayout(is64bit)),
|
2014-06-27 12:33:14 +08:00
|
|
|
Subtarget(TT, CPU, FS, *this, is64bit) {
|
2013-05-13 09:16:13 +08:00
|
|
|
initAsmInfo();
|
|
|
|
}
|
2012-05-05 04:18:50 +08:00
|
|
|
|
2014-11-21 07:37:18 +08:00
|
|
|
NVPTXTargetMachine::~NVPTXTargetMachine() {}
|
|
|
|
|
2012-05-05 04:18:50 +08:00
|
|
|
void NVPTXTargetMachine32::anchor() {}
|
|
|
|
|
2013-03-30 22:29:21 +08:00
|
|
|
NVPTXTargetMachine32::NVPTXTargetMachine32(
|
|
|
|
const Target &T, StringRef TT, StringRef CPU, StringRef FS,
|
|
|
|
const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
|
|
|
|
CodeGenOpt::Level OL)
|
|
|
|
: NVPTXTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
|
2012-05-05 04:18:50 +08:00
|
|
|
|
|
|
|
void NVPTXTargetMachine64::anchor() {}
|
|
|
|
|
2013-03-30 22:29:21 +08:00
|
|
|
NVPTXTargetMachine64::NVPTXTargetMachine64(
|
|
|
|
const Target &T, StringRef TT, StringRef CPU, StringRef FS,
|
|
|
|
const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM,
|
|
|
|
CodeGenOpt::Level OL)
|
|
|
|
: NVPTXTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
|
2012-05-05 04:18:50 +08:00
|
|
|
|
2013-05-24 01:10:37 +08:00
|
|
|
namespace {
|
2012-05-05 04:18:50 +08:00
|
|
|
class NVPTXPassConfig : public TargetPassConfig {
|
|
|
|
public:
|
|
|
|
NVPTXPassConfig(NVPTXTargetMachine *TM, PassManagerBase &PM)
|
2013-03-30 22:29:21 +08:00
|
|
|
: TargetPassConfig(TM, PM) {}
|
2012-05-05 04:18:50 +08:00
|
|
|
|
|
|
|
NVPTXTargetMachine &getNVPTXTargetMachine() const {
|
|
|
|
return getTM<NVPTXTargetMachine>();
|
|
|
|
}
|
|
|
|
|
2014-04-29 15:57:44 +08:00
|
|
|
void addIRPasses() override;
|
|
|
|
bool addInstSelector() override;
|
2014-12-12 05:26:47 +08:00
|
|
|
void addPostRegAlloc() override;
|
2014-06-28 02:35:14 +08:00
|
|
|
void addMachineSSAOptimization() override;
|
2014-04-29 15:57:44 +08:00
|
|
|
|
|
|
|
FunctionPass *createTargetRegisterAllocator(bool) override;
|
|
|
|
void addFastRegAlloc(FunctionPass *RegAllocPass) override;
|
|
|
|
void addOptimizedRegAlloc(FunctionPass *RegAllocPass) override;
|
2012-05-05 04:18:50 +08:00
|
|
|
};
|
2013-05-24 01:10:37 +08:00
|
|
|
} // end anonymous namespace
|
2012-05-05 04:18:50 +08:00
|
|
|
|
|
|
|
TargetPassConfig *NVPTXTargetMachine::createPassConfig(PassManagerBase &PM) {
|
|
|
|
NVPTXPassConfig *PassConfig = new NVPTXPassConfig(this, PM);
|
|
|
|
return PassConfig;
|
|
|
|
}
|
|
|
|
|
2015-02-01 21:20:00 +08:00
|
|
|
TargetIRAnalysis NVPTXTargetMachine::getTargetIRAnalysis() {
|
|
|
|
return TargetIRAnalysis(
|
|
|
|
[this](Function &) { return TargetTransformInfo(NVPTXTTIImpl(this)); });
|
2014-11-11 02:38:25 +08:00
|
|
|
}
|
|
|
|
|
2013-05-20 20:13:32 +08:00
|
|
|
void NVPTXPassConfig::addIRPasses() {
|
2013-05-31 20:14:49 +08:00
|
|
|
// The following passes are known to not play well with virtual regs hanging
|
|
|
|
// around after register allocation (which in our case, is *all* registers).
|
|
|
|
// We explicitly disable them here. We do, however, need some functionality
|
|
|
|
// of the PrologEpilogCodeInserter pass, so we emulate that behavior in the
|
|
|
|
// NVPTXPrologEpilog pass (see NVPTXPrologEpilogPass.cpp).
|
|
|
|
disablePass(&PrologEpilogCodeInserterID);
|
|
|
|
disablePass(&MachineCopyPropagationID);
|
|
|
|
disablePass(&BranchFolderPassID);
|
2013-11-11 20:58:14 +08:00
|
|
|
disablePass(&TailDuplicateID);
|
2013-05-31 20:14:49 +08:00
|
|
|
|
2014-04-09 23:39:15 +08:00
|
|
|
addPass(createNVPTXImageOptimizerPass());
|
2013-05-20 20:13:32 +08:00
|
|
|
TargetPassConfig::addIRPasses();
|
2014-03-31 23:56:26 +08:00
|
|
|
addPass(createNVPTXAssignValidGlobalNamesPass());
|
2013-05-20 20:13:32 +08:00
|
|
|
addPass(createGenericToNVVMPass());
|
2014-04-04 05:18:25 +08:00
|
|
|
addPass(createNVPTXFavorNonGenericAddrSpacesPass());
|
Add straight-line strength reduction to LLVM
Summary:
Straight-line strength reduction (SLSR) is implemented in GCC but not yet in
LLVM. It has proven to effectively simplify statements derived from an unrolled
loop, and can potentially benefit many other cases too. For example,
LLVM unrolls
#pragma unroll
foo (int i = 0; i < 3; ++i) {
sum += foo((b + i) * s);
}
into
sum += foo(b * s);
sum += foo((b + 1) * s);
sum += foo((b + 2) * s);
However, no optimizations yet reduce the internal redundancy of the three
expressions:
b * s
(b + 1) * s
(b + 2) * s
With SLSR, LLVM can optimize these three expressions into:
t1 = b * s
t2 = t1 + s
t3 = t2 + s
This commit is only an initial step towards implementing a series of such
optimizations. I will implement more (see TODO in the file commentary) in the
near future. This optimization is enabled for the NVPTX backend for now.
However, I am more than happy to push it to the standard optimization pipeline
after more thorough performance tests.
Test Plan: test/StraightLineStrengthReduce/slsr.ll
Reviewers: eliben, HaoLiu, meheff, hfinkel, jholewinski, atrick
Reviewed By: jholewinski, atrick
Subscribers: karthikthecool, jholewinski, llvm-commits
Differential Revision: http://reviews.llvm.org/D7310
llvm-svn: 228016
2015-02-04 03:37:06 +08:00
|
|
|
addPass(createStraightLineStrengthReducePass());
|
2014-05-02 02:38:36 +08:00
|
|
|
addPass(createSeparateConstOffsetFromGEPPass());
|
|
|
|
// The SeparateConstOffsetFromGEP pass creates variadic bases that can be used
|
|
|
|
// by multiple GEPs. Run GVN or EarlyCSE to really reuse them. GVN generates
|
|
|
|
// significantly better code than EarlyCSE for some of our benchmarks.
|
|
|
|
if (getOptLevel() == CodeGenOpt::Aggressive)
|
|
|
|
addPass(createGVNPass());
|
|
|
|
else
|
|
|
|
addPass(createEarlyCSEPass());
|
|
|
|
// Both FavorNonGenericAddrSpaces and SeparateConstOffsetFromGEP may leave
|
|
|
|
// some dead code. We could remove dead code in an ad-hoc manner, but that
|
|
|
|
// requires manual work and might be error-prone.
|
|
|
|
//
|
|
|
|
// The FavorNonGenericAddrSpaces pass shortcuts unnecessary addrspacecasts,
|
|
|
|
// and leave them unused.
|
|
|
|
//
|
|
|
|
// SeparateConstOffsetFromGEP rebuilds a new index from the old index, and the
|
|
|
|
// old index and some of its intermediate results may become unused.
|
2014-04-04 05:18:25 +08:00
|
|
|
addPass(createDeadCodeEliminationPass());
|
2013-05-20 20:13:32 +08:00
|
|
|
}
|
|
|
|
|
2012-05-05 04:18:50 +08:00
|
|
|
bool NVPTXPassConfig::addInstSelector() {
|
2014-04-09 23:39:15 +08:00
|
|
|
const NVPTXSubtarget &ST =
|
|
|
|
getTM<NVPTXTargetMachine>().getSubtarget<NVPTXSubtarget>();
|
|
|
|
|
2012-07-03 03:48:31 +08:00
|
|
|
addPass(createLowerAggrCopies());
|
|
|
|
addPass(createAllocaHoisting());
|
|
|
|
addPass(createNVPTXISelDag(getNVPTXTargetMachine(), getOptLevel()));
|
2014-04-09 23:39:15 +08:00
|
|
|
|
|
|
|
if (!ST.hasImageHandles())
|
|
|
|
addPass(createNVPTXReplaceImageHandlesPass());
|
|
|
|
|
2012-05-05 04:18:50 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-12-12 05:26:47 +08:00
|
|
|
void NVPTXPassConfig::addPostRegAlloc() {
|
|
|
|
addPass(createNVPTXPrologEpilogPass(), false);
|
2013-05-31 20:14:49 +08:00
|
|
|
}
|
|
|
|
|
2013-06-01 03:21:58 +08:00
|
|
|
FunctionPass *NVPTXPassConfig::createTargetRegisterAllocator(bool) {
|
2014-04-25 13:30:21 +08:00
|
|
|
return nullptr; // No reg alloc
|
2013-06-01 03:21:58 +08:00
|
|
|
}
|
|
|
|
|
2013-05-31 20:14:49 +08:00
|
|
|
void NVPTXPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) {
|
2013-06-01 03:21:58 +08:00
|
|
|
assert(!RegAllocPass && "NVPTX uses no regalloc!");
|
2013-10-11 20:39:39 +08:00
|
|
|
addPass(&PHIEliminationID);
|
|
|
|
addPass(&TwoAddressInstructionPassID);
|
2013-05-31 20:14:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void NVPTXPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
|
2013-06-01 03:21:58 +08:00
|
|
|
assert(!RegAllocPass && "NVPTX uses no regalloc!");
|
2013-10-11 20:39:39 +08:00
|
|
|
|
|
|
|
addPass(&ProcessImplicitDefsID);
|
|
|
|
addPass(&LiveVariablesID);
|
|
|
|
addPass(&MachineLoopInfoID);
|
|
|
|
addPass(&PHIEliminationID);
|
|
|
|
|
|
|
|
addPass(&TwoAddressInstructionPassID);
|
|
|
|
addPass(&RegisterCoalescerID);
|
|
|
|
|
|
|
|
// PreRA instruction scheduling.
|
|
|
|
if (addPass(&MachineSchedulerID))
|
|
|
|
printAndVerify("After Machine Scheduling");
|
|
|
|
|
|
|
|
|
|
|
|
addPass(&StackSlotColoringID);
|
|
|
|
|
|
|
|
// FIXME: Needs physical registers
|
|
|
|
//addPass(&PostRAMachineLICMID);
|
|
|
|
|
|
|
|
printAndVerify("After StackSlotColoring");
|
2013-05-31 20:14:49 +08:00
|
|
|
}
|
2014-06-28 02:35:14 +08:00
|
|
|
|
|
|
|
void NVPTXPassConfig::addMachineSSAOptimization() {
|
|
|
|
// Pre-ra tail duplication.
|
|
|
|
if (addPass(&EarlyTailDuplicateID))
|
|
|
|
printAndVerify("After Pre-RegAlloc TailDuplicate");
|
|
|
|
|
|
|
|
// Optimize PHIs before DCE: removing dead PHI cycles may make more
|
|
|
|
// instructions dead.
|
|
|
|
addPass(&OptimizePHIsID);
|
|
|
|
|
|
|
|
// This pass merges large allocas. StackSlotColoring is a different pass
|
|
|
|
// which merges spill slots.
|
|
|
|
addPass(&StackColoringID);
|
|
|
|
|
|
|
|
// If the target requests it, assign local variables to stack slots relative
|
|
|
|
// to one another and simplify frame index references where possible.
|
|
|
|
addPass(&LocalStackSlotAllocationID);
|
|
|
|
|
|
|
|
// With optimization, dead code should already be eliminated. However
|
|
|
|
// there is one known exception: lowered code for arguments that are only
|
|
|
|
// used by tail calls, where the tail calls reuse the incoming stack
|
|
|
|
// arguments directly (see t11 in test/CodeGen/X86/sibcall.ll).
|
|
|
|
addPass(&DeadMachineInstructionElimID);
|
|
|
|
printAndVerify("After codegen DCE pass");
|
|
|
|
|
|
|
|
// Allow targets to insert passes that improve instruction level parallelism,
|
|
|
|
// like if-conversion. Such passes will typically need dominator trees and
|
|
|
|
// loop info, just like LICM and CSE below.
|
|
|
|
if (addILPOpts())
|
|
|
|
printAndVerify("After ILP optimizations");
|
|
|
|
|
|
|
|
addPass(&MachineLICMID);
|
|
|
|
addPass(&MachineCSEID);
|
|
|
|
|
|
|
|
addPass(&MachineSinkingID);
|
|
|
|
printAndVerify("After Machine LICM, CSE and Sinking passes");
|
|
|
|
|
|
|
|
addPass(&PeepholeOptimizerID);
|
|
|
|
printAndVerify("After codegen peephole optimization pass");
|
|
|
|
}
|