summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorChris Dewhurst <chris.dewhurst@lero.ie>2016-05-23 10:56:36 +0000
committerChris Dewhurst <chris.dewhurst@lero.ie>2016-05-23 10:56:36 +0000
commit4f7cac3674d5f06e2acf2694db86e0a37de6f47c (patch)
tree8429654217184fb6e4cc42fa1eb935ceeae3b094 /llvm/lib
parent25227fe7b0b78b1377a00c0205c8d66cbfa4c1fa (diff)
downloadbcm5719-llvm-4f7cac3674d5f06e2acf2694db86e0a37de6f47c.tar.gz
bcm5719-llvm-4f7cac3674d5f06e2acf2694db86e0a37de6f47c.zip
[Sparc][LEON] LEON Erratum fix. Insert NOP after LD or LDF instruction.
Due to an erratum in some versions of LEON, we must insert a NOP after any LD or LDF instruction to ensure the processor has time to load the value correctly before using it. This pass will implement that erratum fix. The code will have no effect for other Sparc, but non-LEON processors. Differential Review: http://reviews.llvm.org/D20353 llvm-svn: 270417
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/Sparc/CMakeLists.txt1
-rwxr-xr-xllvm/lib/Target/Sparc/LeonFeatures.td8
-rwxr-xr-xllvm/lib/Target/Sparc/LeonPasses.cpp79
-rwxr-xr-xllvm/lib/Target/Sparc/LeonPasses.h46
-rw-r--r--llvm/lib/Target/Sparc/Sparc.td8
-rw-r--r--llvm/lib/Target/Sparc/SparcISelLowering.cpp4
-rw-r--r--llvm/lib/Target/Sparc/SparcSubtarget.cpp1
-rw-r--r--llvm/lib/Target/Sparc/SparcSubtarget.h2
-rw-r--r--llvm/lib/Target/Sparc/SparcTargetMachine.cpp10
-rw-r--r--llvm/lib/Target/Sparc/SparcTargetMachine.h2
10 files changed, 152 insertions, 9 deletions
diff --git a/llvm/lib/Target/Sparc/CMakeLists.txt b/llvm/lib/Target/Sparc/CMakeLists.txt
index 5b7bfdd2802..312215cf6cd 100644
--- a/llvm/lib/Target/Sparc/CMakeLists.txt
+++ b/llvm/lib/Target/Sparc/CMakeLists.txt
@@ -13,6 +13,7 @@ add_public_tablegen_target(SparcCommonTableGen)
add_llvm_target(SparcCodeGen
DelaySlotFiller.cpp
+ LeonPasses.cpp
SparcAsmPrinter.cpp
SparcInstrInfo.cpp
SparcISelDAGToDAG.cpp
diff --git a/llvm/lib/Target/Sparc/LeonFeatures.td b/llvm/lib/Target/Sparc/LeonFeatures.td
index 5e62891c3ff..7de98407dac 100755
--- a/llvm/lib/Target/Sparc/LeonFeatures.td
+++ b/llvm/lib/Target/Sparc/LeonFeatures.td
@@ -36,4 +36,10 @@ def LeonCASA : SubtargetFeature<
"true",
"Enable CASA instruction for LEON3 and LEON4 processors"
>;
- \ No newline at end of file
+
+def InsertNOPLoad: SubtargetFeature<
+ "insertnopload",
+ "InsertNOPLoad",
+ "true",
+ "LEON3 erratum fix: Insert a NOP instruction after every single-cycle load instruction when the next instruction is another load/store instruction"
+>;
diff --git a/llvm/lib/Target/Sparc/LeonPasses.cpp b/llvm/lib/Target/Sparc/LeonPasses.cpp
new file mode 100755
index 00000000000..0a99a9825f1
--- /dev/null
+++ b/llvm/lib/Target/Sparc/LeonPasses.cpp
@@ -0,0 +1,79 @@
+//===------ LeonPasses.cpp - Define passes specific to LEON ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "LeonPasses.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+
+LEONMachineFunctionPass::LEONMachineFunctionPass(TargetMachine &tm, char& ID) :
+ MachineFunctionPass(ID)
+{
+}
+
+LEONMachineFunctionPass::LEONMachineFunctionPass(char& ID) :
+ MachineFunctionPass(ID)
+{
+}
+
+//*****************************************************************************
+//**** InsertNOPLoad pass
+//*****************************************************************************
+//This pass inserts a NOP after any LD or LDF instruction.
+//
+char InsertNOPLoad::ID = 0;
+
+InsertNOPLoad::InsertNOPLoad(TargetMachine &tm) :
+ LEONMachineFunctionPass(tm, ID)
+{
+}
+
+bool InsertNOPLoad::runOnMachineFunction(MachineFunction& MF)
+{
+ Subtarget = &MF.getSubtarget<SparcSubtarget>();
+ const TargetInstrInfo& TII = *Subtarget->getInstrInfo();
+ DebugLoc DL = DebugLoc();
+
+ bool Modified = false;
+ for (auto MFI = MF.begin(), E = MF.end(); MFI != E; ++MFI) {
+ MachineBasicBlock &MBB = *MFI;
+ for (auto MBBI = MBB.begin(), E = MBB.end(); MBBI != E; ++ MBBI) {
+ MachineInstr &MI = *MBBI;
+ unsigned Opcode = MI.getOpcode();
+ if (Opcode >= SP::LDDArr && Opcode <= SP::LDrr) {
+ //errs() << "Inserting NOP after LD instruction\n";
+ MachineBasicBlock::iterator NMBBI = std::next(MBBI);
+ BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
+ Modified = true;
+ }
+ else if (MI.isInlineAsm()) {
+ std::string AsmString (MI.getOperand(InlineAsm::MIOp_AsmString)
+ .getSymbolName());
+ std::string LDOpCoode ("ld");
+ std::transform(AsmString.begin(), AsmString.end(), AsmString.begin(),
+ ::tolower);
+ if (AsmString.find(LDOpCoode) == 0) { // an inline ld or ldf instruction
+ //errs() << "Inserting NOP after LD instruction\n";
+ MachineBasicBlock::iterator NMBBI = std::next(MBBI);
+ BuildMI(MBB, NMBBI, DL, TII.get(SP::NOP));
+ Modified = true;
+ }
+ }
+ }
+ }
+
+ return Modified;
+}
diff --git a/llvm/lib/Target/Sparc/LeonPasses.h b/llvm/lib/Target/Sparc/LeonPasses.h
new file mode 100755
index 00000000000..ea17b55bef3
--- /dev/null
+++ b/llvm/lib/Target/Sparc/LeonPasses.h
@@ -0,0 +1,46 @@
+//===------- LeonPasses.h - Define passes specific to LEON ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_SPARC_LEON_PASSES_H
+#define LLVM_LIB_TARGET_SPARC_LEON_PASSES_H
+
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
+
+#include "Sparc.h"
+#include "SparcSubtarget.h"
+
+using namespace llvm;
+
+class LEONMachineFunctionPass : public MachineFunctionPass {
+protected:
+ const SparcSubtarget *Subtarget;
+
+protected:
+ LEONMachineFunctionPass(TargetMachine &tm, char& ID);
+ LEONMachineFunctionPass(char& ID);
+};
+
+class InsertNOPLoad : public LEONMachineFunctionPass {
+public:
+ static char ID;
+
+ InsertNOPLoad(TargetMachine &tm);
+ bool runOnMachineFunction(MachineFunction& MF) override;
+
+ const char *getPassName() const override {
+ return "InsertNOPLoad: Erratum Fix LBR35: insert a NOP instruction after every single-cycle load instruction when the next instruction is another load/store instruction";
+ }
+};
+
+#endif
diff --git a/llvm/lib/Target/Sparc/Sparc.td b/llvm/lib/Target/Sparc/Sparc.td
index 51e0b9acdb0..4fb82ff5c74 100644
--- a/llvm/lib/Target/Sparc/Sparc.td
+++ b/llvm/lib/Target/Sparc/Sparc.td
@@ -107,12 +107,12 @@ def : Processor<"leon2", LEON2Itineraries,
// LEON 2 FT (AT697E)
// TO DO: Place-holder: Processor specific features will be added *very* soon here.
def : Processor<"at697e", LEON2Itineraries,
- [FeatureLeon]>;
+ [FeatureLeon, InsertNOPLoad]>;
// LEON 2 FT (AT697F)
// TO DO: Place-holder: Processor specific features will be added *very* soon here.
def : Processor<"at697f", LEON2Itineraries,
- [FeatureLeon]>;
+ [FeatureLeon, InsertNOPLoad]>;
// LEON 3 FT generic
@@ -122,12 +122,12 @@ def : Processor<"leon3", LEON3Itineraries,
// LEON 3 FT (UT699). Provides features for the UT699 processor
// - covers all the erratum fixes for LEON3, but does not support the CASA instruction.
def : Processor<"ut699", LEON3Itineraries,
- [FeatureLeon, UMACSMACSupport]>;
+ [FeatureLeon, InsertNOPLoad]>;
// LEON3 FT (GR712RC). Provides features for the GR712RC processor.
// - covers all the erratum fixed for LEON3 and support for the CASA instruction.
def : Processor<"gr712rc", LEON3Itineraries,
- [FeatureLeon, UMACSMACSupport, LeonCASA]>;
+ [FeatureLeon, LeonCASA]>;
// LEON 4 FT generic
def : Processor<"leon4", LEON4Itineraries,
diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
index e5fbc477c06..23385a92579 100644
--- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp
+++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp
@@ -1642,8 +1642,8 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
if (Subtarget->isV9())
setMaxAtomicSizeInBitsSupported(64);
else if (false && Subtarget->hasLeonCasa())
- // Test made to fail pending completion of AtomicExpandPass,
- // as this will cause a regression until that work is completed.
+ // Test made to fail pending completion of AtomicExpandPass,
+ // as this will cause a regression until that work is completed.
setMaxAtomicSizeInBitsSupported(32);
else
setMaxAtomicSizeInBitsSupported(0);
diff --git a/llvm/lib/Target/Sparc/SparcSubtarget.cpp b/llvm/lib/Target/Sparc/SparcSubtarget.cpp
index f3b50d40323..3dd8a84ba47 100644
--- a/llvm/lib/Target/Sparc/SparcSubtarget.cpp
+++ b/llvm/lib/Target/Sparc/SparcSubtarget.cpp
@@ -39,6 +39,7 @@ SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(StringRef CPU,
// Leon features
HasLeonCasa = false;
HasUmacSmac = false;
+ InsertNOPLoad = false;
// Determine default and user specified characteristics
std::string CPUName = CPU;
diff --git a/llvm/lib/Target/Sparc/SparcSubtarget.h b/llvm/lib/Target/Sparc/SparcSubtarget.h
index 4ad963e31d8..a69c2efd913 100644
--- a/llvm/lib/Target/Sparc/SparcSubtarget.h
+++ b/llvm/lib/Target/Sparc/SparcSubtarget.h
@@ -44,6 +44,7 @@ class SparcSubtarget : public SparcGenSubtargetInfo {
// LEON features
bool HasUmacSmac;
bool HasLeonCasa;
+ bool InsertNOPLoad;
SparcInstrInfo InstrInfo;
SparcTargetLowering TLInfo;
@@ -83,6 +84,7 @@ public:
// Leon options
bool hasUmacSmac() const { return HasUmacSmac; }
bool hasLeonCasa() const { return HasLeonCasa; }
+ bool insertNOPLoad() const { return InsertNOPLoad; }
/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
diff --git a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp
index 80c78514831..cc2be3a9ef0 100644
--- a/llvm/lib/Target/Sparc/SparcTargetMachine.cpp
+++ b/llvm/lib/Target/Sparc/SparcTargetMachine.cpp
@@ -13,6 +13,7 @@
#include "SparcTargetMachine.h"
#include "SparcTargetObjectFile.h"
#include "Sparc.h"
+#include "LeonPasses.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/LegacyPassManager.h"
@@ -68,9 +69,9 @@ SparcTargetMachine::SparcTargetMachine(const Target &T, const Triple &TT,
CodeGenOpt::Level OL, bool is64bit)
: LLVMTargetMachine(T, computeDataLayout(TT, is64bit), TT, CPU, FS, Options,
getEffectiveRelocModel(RM), CM, OL),
- TLOF(make_unique<SparcELFTargetObjectFile>()) {
+ TLOF(make_unique<SparcELFTargetObjectFile>()),
+ Subtarget(TT, CPU, FS, *this, is64bit), is64Bit(is64bit) {
initAsmInfo();
- this->is64Bit = is64bit;
}
SparcTargetMachine::~SparcTargetMachine() {}
@@ -143,6 +144,11 @@ bool SparcPassConfig::addInstSelector() {
void SparcPassConfig::addPreEmitPass(){
addPass(createSparcDelaySlotFillerPass(getSparcTargetMachine()));
+
+ if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad())
+ {
+ addPass(new InsertNOPLoad(getSparcTargetMachine()));
+ }
}
void SparcV8TargetMachine::anchor() { }
diff --git a/llvm/lib/Target/Sparc/SparcTargetMachine.h b/llvm/lib/Target/Sparc/SparcTargetMachine.h
index 8c056b3c361..48193fe095b 100644
--- a/llvm/lib/Target/Sparc/SparcTargetMachine.h
+++ b/llvm/lib/Target/Sparc/SparcTargetMachine.h
@@ -22,6 +22,7 @@ namespace llvm {
class SparcTargetMachine : public LLVMTargetMachine {
std::unique_ptr<TargetLoweringObjectFile> TLOF;
+ SparcSubtarget Subtarget;
bool is64Bit;
mutable StringMap<std::unique_ptr<SparcSubtarget>> SubtargetMap;
public:
@@ -31,6 +32,7 @@ public:
CodeGenOpt::Level OL, bool is64bit);
~SparcTargetMachine() override;
+ const SparcSubtarget *getSubtargetImpl() const { return &Subtarget; }
const SparcSubtarget *getSubtargetImpl(const Function &) const override;
// Pass Pipeline Configuration
OpenPOWER on IntegriCloud