575 changes: 551 additions & 24 deletions llvm/lib/Target/Sparc/LeonPasses.cpp

Large diffs are not rendered by default.

110 changes: 104 additions & 6 deletions llvm/lib/Target/Sparc/LeonPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,57 @@ class LLVM_LIBRARY_VISIBILITY LEONMachineFunctionPass
int getUnusedFPRegister(MachineRegisterInfo &MRI);
};

class LLVM_LIBRARY_VISIBILITY InsertNOPLoad : public LEONMachineFunctionPass {
class LLVM_LIBRARY_VISIBILITY ReplaceSDIV : public LEONMachineFunctionPass {
public:
static char ID;

InsertNOPLoad(TargetMachine &tm);
ReplaceSDIV();
ReplaceSDIV(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";
return "ReplaceSDIV: Erratum Fix LBR25: do not emit SDIV, but emit SDIVCC "
"instead";
}
};

class LLVM_LIBRARY_VISIBILITY FixCALL : public LEONMachineFunctionPass {
public:
static char ID;

FixCALL(TargetMachine &tm);
bool runOnMachineFunction(MachineFunction &MF) override;

const char *getPassName() const override {
return "FixCALL: Erratum Fix LBR26: restrict the size of the immediate "
"operand of the CALL instruction to 20 bits";
}
};

class LLVM_LIBRARY_VISIBILITY IgnoreZeroFlag : public LEONMachineFunctionPass {
public:
static char ID;

IgnoreZeroFlag(TargetMachine &tm);
bool runOnMachineFunction(MachineFunction &MF) override;

const char *getPassName() const override {
return "IgnoreZeroFlag: Erratum Fix LBR28: do not rely on the zero bit "
"flag on a divide overflow for SDIVCC and UDIVCC";
}
};

class LLVM_LIBRARY_VISIBILITY InsertNOPDoublePrecision
: public LEONMachineFunctionPass {
public:
static char ID;

InsertNOPDoublePrecision(TargetMachine &tm);
bool runOnMachineFunction(MachineFunction &MF) override;

const char *getPassName() const override {
return "InsertNOPDoublePrecision: Erratum Fix LBR30: insert a NOP before "
"the double precision floating point instruction";
}
};

Expand Down Expand Up @@ -84,6 +124,20 @@ class LLVM_LIBRARY_VISIBILITY ReplaceFMULS : public LEONMachineFunctionPass {
}
};

class LLVM_LIBRARY_VISIBILITY PreventRoundChange
: public LEONMachineFunctionPass {
public:
static char ID;

PreventRoundChange(TargetMachine &tm);
bool runOnMachineFunction(MachineFunction &MF) override;

const char *getPassName() const override {
return "PreventRoundChange: Erratum Fix LBR33: prevent any rounding mode "
"change request: use only the round-to-nearest rounding mode";
}
};

class LLVM_LIBRARY_VISIBILITY FixAllFDIVSQRT : public LEONMachineFunctionPass {
public:
static char ID;
Expand All @@ -96,6 +150,50 @@ class LLVM_LIBRARY_VISIBILITY FixAllFDIVSQRT : public LEONMachineFunctionPass {
"instructions with NOPs and floating-point store";
}
};
} // namespace llvm

class LLVM_LIBRARY_VISIBILITY InsertNOPLoad : public LEONMachineFunctionPass {
public:
static char ID;

InsertNOPLoad(TargetMachine &tm);
bool runOnMachineFunction(MachineFunction &MF) override;

const char *getPassName() const override {
return "InsertNOPLoad: insert a NOP instruction after "
"every single-cycle load instruction when the next instruction is "
"another load/store instruction";
}
};

class LLVM_LIBRARY_VISIBILITY FlushCacheLineSWAP
: public LEONMachineFunctionPass {
public:
static char ID;

FlushCacheLineSWAP(TargetMachine &tm);
bool runOnMachineFunction(MachineFunction &MF) override;

const char *getPassName() const override {
return "FlushCacheLineSWAP: Erratum Fix LBR36: flush cache line containing "
"the lock before performing any of the atomic instructions SWAP and "
"LDSTUB";
}
};

class LLVM_LIBRARY_VISIBILITY InsertNOPsLoadStore
: public LEONMachineFunctionPass {
public:
static char ID;

InsertNOPsLoadStore(TargetMachine &tm);
bool runOnMachineFunction(MachineFunction &MF) override;

const char *getPassName() const override {
return "InsertNOPsLoadStore: Erratum Fix LBR37: insert NOPs between "
"single-precision loads and the store, so the number of "
"instructions between is 4";
}
};
} // namespace lllvm

#endif // LLVM_LIB_TARGET_SPARC_LEON_PASSES_H
144 changes: 74 additions & 70 deletions llvm/lib/Target/Sparc/Sparc.td
Original file line number Diff line number Diff line change
Expand Up @@ -21,35 +21,34 @@ include "llvm/Target/Target.td"
//

def FeatureV9
: SubtargetFeature<"v9", "IsV9", "true",
"Enable SPARC-V9 instructions">;
: SubtargetFeature<"v9", "IsV9", "true", "Enable SPARC-V9 instructions">;
def FeatureV8Deprecated
: SubtargetFeature<"deprecated-v8", "V8DeprecatedInsts", "true",
"Enable deprecated V8 instructions in V9 mode">;
: SubtargetFeature<"deprecated-v8", "V8DeprecatedInsts", "true",
"Enable deprecated V8 instructions in V9 mode">;
def FeatureVIS
: SubtargetFeature<"vis", "IsVIS", "true",
"Enable UltraSPARC Visual Instruction Set extensions">;
: SubtargetFeature<"vis", "IsVIS", "true",
"Enable UltraSPARC Visual Instruction Set extensions">;
def FeatureVIS2
: SubtargetFeature<"vis2", "IsVIS2", "true",
"Enable Visual Instruction Set extensions II">;
: SubtargetFeature<"vis2", "IsVIS2", "true",
"Enable Visual Instruction Set extensions II">;
def FeatureVIS3
: SubtargetFeature<"vis3", "IsVIS3", "true",
"Enable Visual Instruction Set extensions III">;
: SubtargetFeature<"vis3", "IsVIS3", "true",
"Enable Visual Instruction Set extensions III">;
def FeatureLeon
: SubtargetFeature<"leon", "IsLeon", "true",
"Enable LEON extensions">;
: SubtargetFeature<"leon", "IsLeon", "true", "Enable LEON extensions">;

def FeatureHardQuad
: SubtargetFeature<"hard-quad-float", "HasHardQuad", "true",
"Enable quad-word floating point instructions">;
: SubtargetFeature<"hard-quad-float", "HasHardQuad", "true",
"Enable quad-word floating point instructions">;

def UsePopc : SubtargetFeature<"popc", "UsePopc", "true",
"Use the popc (population count) instruction">;

def FeatureSoftFloat : SubtargetFeature<"soft-float", "UseSoftFloat", "true",
"Use software emulation for floating point">;
def FeatureSoftFloat
: SubtargetFeature<"soft-float", "UseSoftFloat", "true",
"Use software emulation for floating point">;

//==== Features added predmoninantly for LEON subtarget support
//==== Features added predmoninantly for LEON subtarget support
include "LeonFeatures.td"

//===----------------------------------------------------------------------===//
Expand All @@ -63,94 +62,99 @@ include "SparcInstrInfo.td"

def SparcInstrInfo : InstrInfo;

def SparcAsmParser : AsmParser {
bit ShouldEmitMatchRegisterName = 0;
}
def SparcAsmParser : AsmParser { bit ShouldEmitMatchRegisterName = 0; }

//===----------------------------------------------------------------------===//
// SPARC processors supported.
//===----------------------------------------------------------------------===//

class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;

def : Proc<"generic", []>;
def : Proc<"v7", []>;
def : Proc<"v8", []>;
def : Proc<"supersparc", []>;
def : Proc<"sparclite", []>;
def : Proc<"f934", []>;
def : Proc<"hypersparc", []>;
def : Proc<"sparclite86x", []>;
def : Proc<"sparclet", []>;
def : Proc<"tsc701", []>;
def : Proc<"myriad2", []>;
def : Proc<"myriad2.1", []>;
def : Proc<"myriad2.2", []>;
def : Proc<"v9", [FeatureV9]>;
def : Proc<"ultrasparc", [FeatureV9, FeatureV8Deprecated, FeatureVIS]>;
def : Proc<"ultrasparc3", [FeatureV9, FeatureV8Deprecated, FeatureVIS,
FeatureVIS2]>;
def : Proc<"niagara", [FeatureV9, FeatureV8Deprecated, FeatureVIS,
FeatureVIS2]>;
def : Proc<"niagara2", [FeatureV9, FeatureV8Deprecated, UsePopc,
FeatureVIS, FeatureVIS2]>;
def : Proc<"niagara3", [FeatureV9, FeatureV8Deprecated, UsePopc,
FeatureVIS, FeatureVIS2]>;
def : Proc<"niagara4", [FeatureV9, FeatureV8Deprecated, UsePopc,
FeatureVIS, FeatureVIS2, FeatureVIS3]>;
: Processor<Name, NoItineraries, Features>;

def : Proc<"generic", []>;
def : Proc<"v7", []>;
def : Proc<"v8", []>;
def : Proc<"supersparc", []>;
def : Proc<"sparclite", []>;
def : Proc<"f934", []>;
def : Proc<"hypersparc", []>;
def : Proc<"sparclite86x", []>;
def : Proc<"sparclet", []>;
def : Proc<"tsc701", []>;
def : Proc<"myriad2", []>;
def : Proc<"myriad2.1", []>;
def : Proc<"myriad2.2", []>;
def : Proc<"v9", [ FeatureV9 ]>;
def : Proc<"ultrasparc", [ FeatureV9, FeatureV8Deprecated, FeatureVIS ]>;
def : Proc<"ultrasparc3",
[ FeatureV9, FeatureV8Deprecated, FeatureVIS, FeatureVIS2 ]>;
def : Proc<"niagara",
[ FeatureV9, FeatureV8Deprecated, FeatureVIS, FeatureVIS2 ]>;
def : Proc<"niagara2", [
FeatureV9, FeatureV8Deprecated, UsePopc, FeatureVIS, FeatureVIS2
]>;
def : Proc<"niagara3", [
FeatureV9, FeatureV8Deprecated, UsePopc, FeatureVIS, FeatureVIS2
]>;
def : Proc<"niagara4", [
FeatureV9, FeatureV8Deprecated, UsePopc, FeatureVIS, FeatureVIS2, FeatureVIS3
]>;

// LEON 2 FT generic
def : Processor<"leon2", LEON2Itineraries,
[FeatureLeon]>;
def : Processor<"leon2", LEON2Itineraries, [ FeatureLeon ]>;

// LEON 2 FT (AT697E)
// TO DO: Place-holder: Processor specific features will be added *very* soon here.
def : Processor<"at697e", LEON2Itineraries,
[FeatureLeon, InsertNOPLoad]>;
// AT697E: Provides full coverage of AT697E - covers all the erratum fixes for
// LEON2 AT697E
def : Processor<"at697e", LEON2Itineraries, [
FeatureLeon, ReplaceSDIV, FixCALL, IgnoreZeroFlag, InsertNOPDoublePrecision
]>;

// LEON 2 FT (AT697F)
// TO DO: Place-holder: Processor specific features will be added *very* soon here.
// AT697F: Provides full coverage of AT697F - covers all the erratum fixes for
// LEON2 AT697F
def : Processor<"at697f", LEON2Itineraries,
[FeatureLeon, InsertNOPLoad]>;

[ FeatureLeon, InsertNOPDoublePrecision ]>;

// LEON 3 FT generic
def : Processor<"leon3", LEON3Itineraries,
[FeatureLeon, UMACSMACSupport]>;
def : Processor<"leon3", LEON3Itineraries, [ FeatureLeon, UMACSMACSupport ]>;

// 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, InsertNOPLoad, FixFSMULD, ReplaceFMULS, FixAllFDIVSQRT]>;
// - covers all the erratum fixes for LEON3, but does not support the CASA
// instruction.
def : Processor<"ut699", LEON3Itineraries, [
FeatureLeon, FixFSMULD, ReplaceFMULS, PreventRoundChange,
FixAllFDIVSQRT, InsertNOPLoad, FlushCacheLineSWAP, InsertNOPsLoadStore
]>;

// LEON3 FT (GR712RC). Provides features for the GR712RC processor.
// - covers all the erratum fixed for LEON3 and support for the CASA instruction.
// - covers all the erratum fixed for LEON3 and support for the CASA
// instruction.
def : Processor<"gr712rc", LEON3Itineraries,
[FeatureLeon, LeonCASA]>;
[ FeatureLeon, LeonCASA ]>;

// LEON 4 FT generic
def : Processor<"leon4", LEON4Itineraries,
[FeatureLeon, UMACSMACSupport, LeonCASA]>;
[ FeatureLeon, LeonCASA ]>;

// LEON 4 FT (GR740)
// TO DO: Place-holder: Processor specific features will be added *very* soon here.
def : Processor<"gr740", LEON4Itineraries,
[FeatureLeon, UMACSMACSupport, LeonCASA]>;
// GR740: Provides full coverage of GR740 - covers all the erratum fixes for
// LEON3 + support to CASA + LEON 4 instruction timings
def : Processor<"gr740", LEON4Itineraries,
[ FeatureLeon, LeonCASA ]> {}

//===----------------------------------------------------------------------===//
// Declare the target which we are implementing
//===----------------------------------------------------------------------===//

def SparcAsmWriter : AsmWriter {
string AsmWriterClassName = "InstPrinter";
string AsmWriterClassName = "InstPrinter";
int PassSubtarget = 1;
int Variant = 0;
}

def Sparc : Target {
// Pull in Instruction Info:
let InstructionSet = SparcInstrInfo;
let AssemblyParsers = [SparcAsmParser];
let AssemblyWriters = [SparcAsmWriter];
let AssemblyParsers = [ SparcAsmParser ];
let AssemblyWriters = [ SparcAsmWriter ];
}
19 changes: 10 additions & 9 deletions llvm/lib/Target/Sparc/SparcISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;


//===----------------------------------------------------------------------===//
// Calling Convention Implementation
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -1636,9 +1635,7 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
// Atomics are supported on SparcV9. 32-bit atomics are also
// supported by some Leon SparcV8 variants. Otherwise, atomics
// are unsupported.
if (Subtarget->isV9())
setMaxAtomicSizeInBitsSupported(64);
else if (Subtarget->hasLeonCasa())
if (Subtarget->isV9() || Subtarget->hasLeonCasa())
setMaxAtomicSizeInBitsSupported(64);
else
setMaxAtomicSizeInBitsSupported(0);
Expand Down Expand Up @@ -2663,7 +2660,6 @@ static SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG,
uint64_t depth = Op.getConstantOperandVal(0);

return getFRAMEADDR(depth, Op, DAG, Subtarget);

}

static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
Expand Down Expand Up @@ -3094,7 +3090,7 @@ MachineBasicBlock *
SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *BB) const {
switch (MI.getOpcode()) {
default: llvm_unreachable("Unknown SELECT_CC!");
default: llvm_unreachable("Unknown Custom Instruction!");
case SP::SELECT_CC_Int_ICC:
case SP::SELECT_CC_FP_ICC:
case SP::SELECT_CC_DFP_ICC:
Expand All @@ -3111,7 +3107,6 @@ SparcTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
case SP::EH_SJLJ_LONGJMP32rr:
case SP::EH_SJLJ_LONGJMP32ri:
return emitEHSjLjLongJmp(MI, BB);

}
}

Expand Down Expand Up @@ -3382,8 +3377,11 @@ SparcTargetLowering::ConstraintType
SparcTargetLowering::getConstraintType(StringRef Constraint) const {
if (Constraint.size() == 1) {
switch (Constraint[0]) {
default: break;
case 'r': return C_RegisterClass;
default:
break;
case 'f':
case 'r':
return C_RegisterClass;
case 'I': // SIMM13
return C_Other;
}
Expand Down Expand Up @@ -3457,6 +3455,9 @@ SparcTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
MVT VT) const {
if (Constraint.size() == 1) {
switch (Constraint[0]) {
case 'f':
return std::make_pair(0U, &SP::FPRegsRegClass);

case 'r':
if (VT == MVT::v2i32)
return std::make_pair(0U, &SP::IntPairRegClass);
Expand Down
9 changes: 8 additions & 1 deletion llvm/lib/Target/Sparc/SparcSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,17 @@ SparcSubtarget &SparcSubtarget::initializeSubtargetDependencies(StringRef CPU,
// Leon features
HasLeonCasa = false;
HasUmacSmac = false;
InsertNOPLoad = false;
PerformSDIVReplace = false;
FixCallImmediates = false;
IgnoreZeroFlag = false;
InsertNOPDoublePrecision = false;
FixFSMULD = false;
ReplaceFMULS = false;
PreventRoundChange = false;
FixAllFDIVSQRT = false;
InsertNOPLoad = false;
FlushCacheLineSWAP = false;
InsertNOPsLoadStore = false;

// Determine default and user specified characteristics
std::string CPUName = CPU;
Expand Down
20 changes: 18 additions & 2 deletions llvm/lib/Target/Sparc/SparcSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ class SparcSubtarget : public SparcGenSubtargetInfo {
bool FixFSMULD;
bool ReplaceFMULS;
bool FixAllFDIVSQRT;
bool UseSoftFpu;
bool PerformSDIVReplace;
bool FixCallImmediates;
bool IgnoreZeroFlag;
bool InsertNOPDoublePrecision;
bool PreventRoundChange;
bool FlushCacheLineSWAP;
bool InsertNOPsLoadStore;

SparcInstrInfo InstrInfo;
SparcTargetLowering TLInfo;
Expand Down Expand Up @@ -85,12 +93,20 @@ class SparcSubtarget : public SparcGenSubtargetInfo {
bool useSoftFloat() const { return UseSoftFloat; }

// Leon options
bool hasUmacSmac() const { return HasUmacSmac; }
bool useSoftFpu() const { return UseSoftFpu; }
bool hasLeonCasa() const { return HasLeonCasa; }
bool insertNOPLoad() const { return InsertNOPLoad; }
bool hasUmacSmac() const { return HasUmacSmac; }
bool performSDIVReplace() const { return PerformSDIVReplace; }
bool fixCallImmediates() const { return FixCallImmediates; }
bool ignoreZeroFlag() const { return IgnoreZeroFlag; }
bool insertNOPDoublePrecision() const { return InsertNOPDoublePrecision; }
bool fixFSMULD() const { return FixFSMULD; }
bool replaceFMULS() const { return ReplaceFMULS; }
bool preventRoundChange() const { return PreventRoundChange; }
bool fixAllFDIVSQRT() const { return FixAllFDIVSQRT; }
bool flushCacheLineSWAP() const { return FlushCacheLineSWAP; }
bool insertNOPsLoadStore() const { return InsertNOPsLoadStore; }
bool insertNOPLoad() const { return InsertNOPLoad; }

/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
Expand Down
50 changes: 34 additions & 16 deletions llvm/lib/Target/Sparc/SparcTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ SparcTargetMachine::SparcTargetMachine(const Target &T, const Triple &TT,

SparcTargetMachine::~SparcTargetMachine() {}

const SparcSubtarget *
const SparcSubtarget *
SparcTargetMachine::getSubtargetImpl(const Function &F) const {
Attribute CPUAttr = F.getFnAttribute("target-cpu");
Attribute FSAttr = F.getFnAttribute("target-features");
Expand All @@ -95,7 +95,7 @@ SparcTargetMachine::getSubtargetImpl(const Function &F) const {
F.hasFnAttribute("use-soft-float") &&
F.getFnAttribute("use-soft-float").getValueAsString() == "true";

if (softFloat)
if (softFloat)
FS += FS.empty() ? "+soft-float" : ",+soft-float";

auto &I = SubtargetMap[CPU + FS];
Expand All @@ -115,7 +115,7 @@ namespace {
class SparcPassConfig : public TargetPassConfig {
public:
SparcPassConfig(SparcTargetMachine *TM, PassManagerBase &PM)
: TargetPassConfig(TM, PM) {}
: TargetPassConfig(TM, PM) {}

SparcTargetMachine &getSparcTargetMachine() const {
return getTM<SparcTargetMachine>();
Expand All @@ -142,28 +142,46 @@ bool SparcPassConfig::addInstSelector() {
return false;
}

void SparcPassConfig::addPreEmitPass(){
void SparcPassConfig::addPreEmitPass() {
addPass(createSparcDelaySlotFillerPass(getSparcTargetMachine()));

if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad())
{
addPass(new InsertNOPLoad(getSparcTargetMachine()));
if (this->getSparcTargetMachine().getSubtargetImpl()->ignoreZeroFlag()) {
addPass(new IgnoreZeroFlag(getSparcTargetMachine()));
}
if (this->getSparcTargetMachine().getSubtargetImpl()->performSDIVReplace()) {
addPass(new ReplaceSDIV(getSparcTargetMachine()));
}
if (this->getSparcTargetMachine().getSubtargetImpl()->fixFSMULD())
{
if (this->getSparcTargetMachine().getSubtargetImpl()->fixCallImmediates()) {
addPass(new FixCALL(getSparcTargetMachine()));
}
if (this->getSparcTargetMachine().getSubtargetImpl()->fixFSMULD()) {
addPass(new FixFSMULD(getSparcTargetMachine()));
}
if (this->getSparcTargetMachine().getSubtargetImpl()->replaceFMULS())
{
if (this->getSparcTargetMachine().getSubtargetImpl()->replaceFMULS()) {
addPass(new ReplaceFMULS(getSparcTargetMachine()));
}
if (this->getSparcTargetMachine().getSubtargetImpl()->fixAllFDIVSQRT())
{
if (this->getSparcTargetMachine().getSubtargetImpl()->preventRoundChange()) {
addPass(new PreventRoundChange(getSparcTargetMachine()));
}
if (this->getSparcTargetMachine().getSubtargetImpl()->fixAllFDIVSQRT()) {
addPass(new FixAllFDIVSQRT(getSparcTargetMachine()));
}
if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPsLoadStore()) {
addPass(new InsertNOPsLoadStore(getSparcTargetMachine()));
}
if (this->getSparcTargetMachine().getSubtargetImpl()->insertNOPLoad()) {
addPass(new InsertNOPLoad(getSparcTargetMachine()));
}
if (this->getSparcTargetMachine().getSubtargetImpl()->flushCacheLineSWAP()) {
addPass(new FlushCacheLineSWAP(getSparcTargetMachine()));
}
if (this->getSparcTargetMachine()
.getSubtargetImpl()
->insertNOPDoublePrecision()) {
addPass(new InsertNOPDoublePrecision(getSparcTargetMachine()));
}
}

void SparcV8TargetMachine::anchor() { }
void SparcV8TargetMachine::anchor() {}

SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
Expand All @@ -173,7 +191,7 @@ SparcV8TargetMachine::SparcV8TargetMachine(const Target &T, const Triple &TT,
CodeGenOpt::Level OL)
: SparcTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}

void SparcV9TargetMachine::anchor() { }
void SparcV9TargetMachine::anchor() {}

SparcV9TargetMachine::SparcV9TargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
Expand Down
20 changes: 20 additions & 0 deletions llvm/test/CodeGen/SPARC/LeonFixCALLPassUT.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
; RUN: llc %s -O0 -march=sparc -mcpu=at697e -o - | FileCheck %s -check-prefix=FIXCALL
; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -mattr=+fixcall -o - | FileCheck %s -check-prefix=FIXCALL

; RUN: llc %s -O0 -march=sparc -mcpu=at697e -mattr=-fixcall -o - | FileCheck %s -check-prefix=NO_FIXCALL
; RUN: llc %s -O0 -march=sparc -mcpu=leon2 -o - | FileCheck %s -check-prefix=NO_FIXCALL


; FIXCALL-LABEL: immediate_call_test
; FIXCALL: call 763288

; NO_FIXCALL-LABEL: immediate_call_test
; NO_FIXCALL: call 2047583640
define void @immediate_call_test() nounwind {
entry:
call void asm sideeffect "call $0", "i"(i32 2047583640) nounwind
ret void
}



13 changes: 13 additions & 0 deletions llvm/test/CodeGen/SPARC/LeonInsertNOPLoad.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s

; CHECK: ld [%o0+%lo(.LCPI0_0)], %f0
; CHECK-NEXT: nop


define float @X() #0 {
entry:
%f = alloca float, align 4
store float 0x3FF3C08320000000, float* %f, align 4
%0 = load float, float* %f, align 4
ret float %0
}
17 changes: 17 additions & 0 deletions llvm/test/CodeGen/SPARC/LeonInsertNOPsDoublePrecision.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
; RUN: llc %s -O0 -march=sparc -mcpu=at697f -o - | FileCheck %s

; CHECK: ldd
; CHECK: ldd
; CHECK-NEXT: nop

define double @mult() #0 {
entry:
%x = alloca double, align 8
%y = alloca double, align 8
store double 3.141590e+00, double* %x, align 8
store double 1.234560e+00, double* %y, align 8
%0 = load double, double* %x, align 8
%1 = load double, double* %y, align 8
%mul = fmul double %0, %1
ret double %mul
}
65 changes: 65 additions & 0 deletions llvm/test/CodeGen/SPARC/LeonPreventRoundChangePassUT.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -o - | FileCheck %s -check-prefix=NO_ROUND_FUNC
; RUN: llc %s -O0 -march=sparc -mcpu=leon3 -mattr=+prvntroundchange -o - | FileCheck %s -check-prefix=NO_ROUND_FUNC

; RUN: llc %s -O0 -march=sparc -mcpu=ut699 -mattr=-prvntroundchange -o - | FileCheck %s -check-prefix=ROUND_FUNC
; RUN: llc %s -O0 -march=sparc -mcpu=leon3 -o - | FileCheck %s -check-prefix=ROUND_FUNC


; NO_ROUND_FUNC-LABEL: test_round_change
; NO_ROUND_FUNC-NOT: fesetround

; ROUND_FUNC-LABEL: test_round_change
; ROUND_FUNC: fesetround

; ModuleID = '<stdin>'
target datalayout = "E-m:e-p:32:32-i64:64-f128:64-n32-S64"
target triple = "sparc-unknown--eabi"

@.str = private unnamed_addr constant [17 x i8] c"-((-a)*b) != a*b\00", align 1
@.str.1 = private unnamed_addr constant [7 x i8] c"test.c\00", align 1
@__PRETTY_FUNCTION__.mult = private unnamed_addr constant [12 x i8] c"void mult()\00", align 1

; Function Attrs: nounwind
define void @test_round_change() #0 {
entry:
%a = alloca double, align 8
%b = alloca double, align 8
%x = alloca float, align 4
store double 1.100000e+00, double* %a, align 8
store double 1.010000e+01, double* %b, align 8
store float 0x400921FA00000000, float* %x, align 4
%call = call i32 @fesetround(i32 2048) #2
%0 = load double, double* %a, align 8
%sub = fsub double -0.000000e+00, %0
%1 = load double, double* %b, align 8
%mul = fmul double %sub, %1
%sub1 = fsub double -0.000000e+00, %mul
%2 = load double, double* %a, align 8
%3 = load double, double* %b, align 8
%mul2 = fmul double %2, %3
%cmp = fcmp une double %sub1, %mul2
br i1 %cmp, label %cond.true, label %cond.false

cond.true: ; preds = %entry
br label %cond.end

cond.false: ; preds = %entry
call void @__assert_fail(i8* getelementptr inbounds ([17 x i8], [17 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.1, i32 0, i32 0), i32 10, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @__PRETTY_FUNCTION__.mult, i32 0, i32 0)) #3
unreachable
; No predecessors!
br label %cond.end

cond.end: ; preds = %4, %cond.true
ret void
}

; Function Attrs: nounwind
declare i32 @fesetround(i32) #0

; Function Attrs: noreturn nounwind
declare void @__assert_fail(i8*, i8*, i32, i8*) #1

attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { noreturn nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { nounwind }
attributes #3 = { noreturn nounwind }
9 changes: 9 additions & 0 deletions llvm/test/CodeGen/SPARC/LeonReplaceSDIVPassUT.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
; RUN: llc %s -O0 -march=sparc -mcpu=at697e -o - | FileCheck %s

; CHECK: sdivcc %o0, %o1, %o0

define i32 @lbr59(i32 %a, i32 %b)
{
%r = sdiv i32 %a, %b
ret i32 %r
}