summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Sparc
diff options
context:
space:
mode:
authorBrian Gaeke <gaeke@uiuc.edu>2004-02-25 18:44:15 +0000
committerBrian Gaeke <gaeke@uiuc.edu>2004-02-25 18:44:15 +0000
commit94e95d2b3eaaf3404b9306c7f402a26beb18c9c4 (patch)
tree01a3a8922d75ff482e96b9905550c37715f16674 /llvm/lib/Target/Sparc
parent864c9014443c716da8851661d8e26c11b16bcca4 (diff)
downloadbcm5719-llvm-94e95d2b3eaaf3404b9306c7f402a26beb18c9c4.tar.gz
bcm5719-llvm-94e95d2b3eaaf3404b9306c7f402a26beb18c9c4.zip
Great renaming: Sparc --> SparcV9
llvm-svn: 11826
Diffstat (limited to 'llvm/lib/Target/Sparc')
-rw-r--r--llvm/lib/Target/Sparc/.cvsignore1
-rw-r--r--llvm/lib/Target/Sparc/EmitAssembly.cpp800
-rw-r--r--llvm/lib/Target/Sparc/EmitBytecodeToAssembly.cpp119
-rw-r--r--llvm/lib/Target/Sparc/InstrSelection/InstrForest.cpp336
-rw-r--r--llvm/lib/Target/Sparc/InstrSelection/InstrSelection.cpp414
-rw-r--r--llvm/lib/Target/Sparc/InstrSelection/InstrSelectionSupport.cpp269
-rw-r--r--llvm/lib/Target/Sparc/InstrSelection/Makefile14
-rw-r--r--llvm/lib/Target/Sparc/LiveVar/BBLiveVar.cpp232
-rw-r--r--llvm/lib/Target/Sparc/LiveVar/BBLiveVar.h90
-rw-r--r--llvm/lib/Target/Sparc/LiveVar/FunctionLiveVarInfo.cpp322
-rw-r--r--llvm/lib/Target/Sparc/LiveVar/FunctionLiveVarInfo.h111
-rw-r--r--llvm/lib/Target/Sparc/LiveVar/Makefile14
-rw-r--r--llvm/lib/Target/Sparc/LiveVar/ValueSet.cpp31
-rw-r--r--llvm/lib/Target/Sparc/Makefile60
-rw-r--r--llvm/lib/Target/Sparc/MappingInfo.cpp299
-rw-r--r--llvm/lib/Target/Sparc/MappingInfo.h49
-rw-r--r--llvm/lib/Target/Sparc/PeepholeOpts.cpp163
-rw-r--r--llvm/lib/Target/Sparc/PreSelection.cpp243
-rw-r--r--llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp185
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/AllocInfo.h91
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/IGNode.cpp62
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/IGNode.h123
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/InterferenceGraph.cpp252
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/InterferenceGraph.h75
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/LiveRange.h184
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/LiveRangeInfo.cpp415
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/LiveRangeInfo.h128
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/Makefile17
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/PhyRegAlloc.cpp1379
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/PhyRegAlloc.h186
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/RegAllocCommon.h32
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/RegClass.cpp250
-rw-r--r--llvm/lib/Target/Sparc/RegAlloc/RegClass.h147
-rw-r--r--llvm/lib/Target/Sparc/Sparc.burg.in351
-rw-r--r--llvm/lib/Target/Sparc/Sparc.cpp238
-rw-r--r--llvm/lib/Target/Sparc/SparcInstr.def553
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrInfo.cpp799
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrSelection.cpp2898
-rw-r--r--llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h227
-rw-r--r--llvm/lib/Target/Sparc/SparcInternals.h134
-rw-r--r--llvm/lib/Target/Sparc/SparcRegClassInfo.cpp397
-rw-r--r--llvm/lib/Target/Sparc/SparcRegClassInfo.h224
-rw-r--r--llvm/lib/Target/Sparc/SparcRegInfo.cpp978
-rw-r--r--llvm/lib/Target/Sparc/SparcV9.td786
-rw-r--r--llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp823
-rw-r--r--llvm/lib/Target/Sparc/SparcV9CodeEmitter.h88
-rw-r--r--llvm/lib/Target/Sparc/SparcV9FrameInfo.cpp65
-rw-r--r--llvm/lib/Target/Sparc/SparcV9FrameInfo.h174
-rw-r--r--llvm/lib/Target/Sparc/SparcV9InstrInfo.h201
-rw-r--r--llvm/lib/Target/Sparc/SparcV9JITInfo.h48
-rw-r--r--llvm/lib/Target/Sparc/SparcV9RegInfo.h193
-rw-r--r--llvm/lib/Target/Sparc/SparcV9TargetMachine.h52
-rw-r--r--llvm/lib/Target/Sparc/SparcV9_F2.td71
-rw-r--r--llvm/lib/Target/Sparc/SparcV9_F3.td267
-rw-r--r--llvm/lib/Target/Sparc/SparcV9_F4.td141
-rw-r--r--llvm/lib/Target/Sparc/SparcV9_Reg.td41
-rw-r--r--llvm/lib/Target/Sparc/StackSlots.cpp54
-rw-r--r--llvm/lib/Target/Sparc/UltraSparcSchedInfo.cpp773
58 files changed, 0 insertions, 17669 deletions
diff --git a/llvm/lib/Target/Sparc/.cvsignore b/llvm/lib/Target/Sparc/.cvsignore
deleted file mode 100644
index 2a06e93b553..00000000000
--- a/llvm/lib/Target/Sparc/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-*.inc
diff --git a/llvm/lib/Target/Sparc/EmitAssembly.cpp b/llvm/lib/Target/Sparc/EmitAssembly.cpp
deleted file mode 100644
index 40aa81cab00..00000000000
--- a/llvm/lib/Target/Sparc/EmitAssembly.cpp
+++ /dev/null
@@ -1,800 +0,0 @@
-//===-- EmitAssembly.cpp - Emit Sparc Specific .s File ---------------------==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements all of the stuff necessary to output a .s file from
-// LLVM. The code in this file assumes that the specified module has already
-// been compiled into the internal data structures of the Module.
-//
-// This code largely consists of two LLVM Pass's: a FunctionPass and a Pass.
-// The FunctionPass is pipelined together with all of the rest of the code
-// generation stages, and the Pass runs at the end to emit code for global
-// variables and such.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Assembly/Writer.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Support/Mangler.h"
-#include "Support/StringExtras.h"
-#include "Support/Statistic.h"
-#include "SparcInternals.h"
-#include <string>
-using namespace llvm;
-
-namespace {
- Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
-
- //===--------------------------------------------------------------------===//
- // Utility functions
-
- /// getAsCString - Return the specified array as a C compatible string, only
- /// if the predicate isString() is true.
- ///
- std::string getAsCString(const ConstantArray *CVA) {
- assert(CVA->isString() && "Array is not string compatible!");
-
- std::string Result = "\"";
- for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
- unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
-
- if (C == '"') {
- Result += "\\\"";
- } else if (C == '\\') {
- Result += "\\\\";
- } else if (isprint(C)) {
- Result += C;
- } else {
- Result += '\\'; // print all other chars as octal value
- // Convert C to octal representation
- Result += ((C >> 6) & 7) + '0';
- Result += ((C >> 3) & 7) + '0';
- Result += ((C >> 0) & 7) + '0';
- }
- }
- Result += "\"";
-
- return Result;
- }
-
- inline bool ArrayTypeIsString(const ArrayType* arrayType) {
- return (arrayType->getElementType() == Type::UByteTy ||
- arrayType->getElementType() == Type::SByteTy);
- }
-
- inline const std::string
- TypeToDataDirective(const Type* type) {
- switch(type->getPrimitiveID())
- {
- case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
- return ".byte";
- case Type::UShortTyID: case Type::ShortTyID:
- return ".half";
- case Type::UIntTyID: case Type::IntTyID:
- return ".word";
- case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID:
- return ".xword";
- case Type::FloatTyID:
- return ".word";
- case Type::DoubleTyID:
- return ".xword";
- case Type::ArrayTyID:
- if (ArrayTypeIsString((ArrayType*) type))
- return ".ascii";
- else
- return "<InvaliDataTypeForPrinting>";
- default:
- return "<InvaliDataTypeForPrinting>";
- }
- }
-
- /// Get the size of the constant for the given target.
- /// If this is an unsized array, return 0.
- ///
- inline unsigned int
- ConstantToSize(const Constant* CV, const TargetMachine& target) {
- if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV)) {
- const ArrayType *aty = cast<ArrayType>(CVA->getType());
- if (ArrayTypeIsString(aty))
- return 1 + CVA->getNumOperands();
- }
-
- return target.findOptimalStorageSize(CV->getType());
- }
-
- /// Align data larger than one L1 cache line on L1 cache line boundaries.
- /// Align all smaller data on the next higher 2^x boundary (4, 8, ...).
- ///
- inline unsigned int
- SizeToAlignment(unsigned int size, const TargetMachine& target) {
- unsigned short cacheLineSize = target.getCacheInfo().getCacheLineSize(1);
- if (size > (unsigned) cacheLineSize / 2)
- return cacheLineSize;
- else
- for (unsigned sz=1; /*no condition*/; sz *= 2)
- if (sz >= size)
- return sz;
- }
-
- /// Get the size of the type and then use SizeToAlignment.
- ///
- inline unsigned int
- TypeToAlignment(const Type* type, const TargetMachine& target) {
- return SizeToAlignment(target.findOptimalStorageSize(type), target);
- }
-
- /// Get the size of the constant and then use SizeToAlignment.
- /// Handles strings as a special case;
- inline unsigned int
- ConstantToAlignment(const Constant* CV, const TargetMachine& target) {
- if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV))
- if (ArrayTypeIsString(cast<ArrayType>(CVA->getType())))
- return SizeToAlignment(1 + CVA->getNumOperands(), target);
-
- return TypeToAlignment(CV->getType(), target);
- }
-
-} // End anonymous namespace
-
-
-
-//===---------------------------------------------------------------------===//
-// Code abstracted away from the AsmPrinter
-//===---------------------------------------------------------------------===//
-
-namespace {
- class AsmPrinter {
- // Mangle symbol names appropriately
- Mangler *Mang;
-
- public:
- std::ostream &toAsm;
- const TargetMachine &Target;
-
- enum Sections {
- Unknown,
- Text,
- ReadOnlyData,
- InitRWData,
- ZeroInitRWData,
- } CurSection;
-
- AsmPrinter(std::ostream &os, const TargetMachine &T)
- : /* idTable(0), */ toAsm(os), Target(T), CurSection(Unknown) {}
-
- ~AsmPrinter() {
- delete Mang;
- }
-
- // (start|end)(Module|Function) - Callback methods invoked by subclasses
- void startModule(Module &M) {
- Mang = new Mangler(M);
- }
-
- void PrintZeroBytesToPad(int numBytes) {
- //
- // Always use single unsigned bytes for padding. We don't know upon
- // what data size the beginning address is aligned, so using anything
- // other than a byte may cause alignment errors in the assembler.
- //
- while (numBytes--)
- printSingleConstantValue(Constant::getNullValue(Type::UByteTy));
- }
-
- /// Print a single constant value.
- ///
- void printSingleConstantValue(const Constant* CV);
-
- /// Print a constant value or values (it may be an aggregate).
- /// Uses printSingleConstantValue() to print each individual value.
- ///
- void printConstantValueOnly(const Constant* CV, int numPadBytesAfter = 0);
-
- // Print a constant (which may be an aggregate) prefixed by all the
- // appropriate directives. Uses printConstantValueOnly() to print the
- // value or values.
- void printConstant(const Constant* CV, std::string valID = "") {
- if (valID.length() == 0)
- valID = getID(CV);
-
- toAsm << "\t.align\t" << ConstantToAlignment(CV, Target) << "\n";
-
- // Print .size and .type only if it is not a string.
- if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV))
- if (CVA->isString()) {
- // print it as a string and return
- toAsm << valID << ":\n";
- toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
- return;
- }
-
- toAsm << "\t.type" << "\t" << valID << ",#object\n";
-
- unsigned int constSize = ConstantToSize(CV, Target);
- if (constSize)
- toAsm << "\t.size" << "\t" << valID << "," << constSize << "\n";
-
- toAsm << valID << ":\n";
-
- printConstantValueOnly(CV);
- }
-
- // enterSection - Use this method to enter a different section of the output
- // executable. This is used to only output necessary section transitions.
- //
- void enterSection(enum Sections S) {
- if (S == CurSection) return; // Only switch section if necessary
- CurSection = S;
-
- toAsm << "\n\t.section ";
- switch (S)
- {
- default: assert(0 && "Bad section name!");
- case Text: toAsm << "\".text\""; break;
- case ReadOnlyData: toAsm << "\".rodata\",#alloc"; break;
- case InitRWData: toAsm << "\".data\",#alloc,#write"; break;
- case ZeroInitRWData: toAsm << "\".bss\",#alloc,#write"; break;
- }
- toAsm << "\n";
- }
-
- // getID Wrappers - Ensure consistent usage
- // Symbol names in Sparc assembly language have these rules:
- // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }*
- // (b) A name beginning in "." is treated as a local name.
- std::string getID(const Function *F) {
- return Mang->getValueName(F);
- }
- std::string getID(const BasicBlock *BB) {
- return ".L_" + getID(BB->getParent()) + "_" + Mang->getValueName(BB);
- }
- std::string getID(const GlobalVariable *GV) {
- return Mang->getValueName(GV);
- }
- std::string getID(const Constant *CV) {
- return ".C_" + Mang->getValueName(CV);
- }
- std::string getID(const GlobalValue *GV) {
- if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV))
- return getID(V);
- else if (const Function *F = dyn_cast<Function>(GV))
- return getID(F);
- assert(0 && "Unexpected type of GlobalValue!");
- return "";
- }
-
- // Combines expressions
- inline std::string ConstantArithExprToString(const ConstantExpr* CE,
- const TargetMachine &TM,
- const std::string &op) {
- return "(" + valToExprString(CE->getOperand(0), TM) + op
- + valToExprString(CE->getOperand(1), TM) + ")";
- }
-
- /// ConstantExprToString() - Convert a ConstantExpr to an asm expression
- /// and return this as a string.
- ///
- std::string ConstantExprToString(const ConstantExpr* CE,
- const TargetMachine& target);
-
- /// valToExprString - Helper function for ConstantExprToString().
- /// Appends result to argument string S.
- ///
- std::string valToExprString(const Value* V, const TargetMachine& target);
- };
-} // End anonymous namespace
-
-
-/// Print a single constant value.
-///
-void AsmPrinter::printSingleConstantValue(const Constant* CV) {
- assert(CV->getType() != Type::VoidTy &&
- CV->getType() != Type::TypeTy &&
- CV->getType() != Type::LabelTy &&
- "Unexpected type for Constant");
-
- assert((!isa<ConstantArray>(CV) && ! isa<ConstantStruct>(CV))
- && "Aggregate types should be handled outside this function");
-
- toAsm << "\t" << TypeToDataDirective(CV->getType()) << "\t";
-
- if (const ConstantPointerRef* CPR = dyn_cast<ConstantPointerRef>(CV)) {
- // This is a constant address for a global variable or method.
- // Use the name of the variable or method as the address value.
- assert(isa<GlobalValue>(CPR->getValue()) && "Unexpected non-global");
- toAsm << getID(CPR->getValue()) << "\n";
- } else if (isa<ConstantPointerNull>(CV)) {
- // Null pointer value
- toAsm << "0\n";
- } else if (const ConstantExpr* CE = dyn_cast<ConstantExpr>(CV)) {
- // Constant expression built from operators, constants, and symbolic addrs
- toAsm << ConstantExprToString(CE, Target) << "\n";
- } else if (CV->getType()->isPrimitiveType()) {
- // Check primitive types last
- if (CV->getType()->isFloatingPoint()) {
- // FP Constants are printed as integer constants to avoid losing
- // precision...
- double Val = cast<ConstantFP>(CV)->getValue();
- if (CV->getType() == Type::FloatTy) {
- float FVal = (float)Val;
- char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules
- toAsm << *(unsigned int*)ProxyPtr;
- } else if (CV->getType() == Type::DoubleTy) {
- char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules
- toAsm << *(uint64_t*)ProxyPtr;
- } else {
- assert(0 && "Unknown floating point type!");
- }
-
- toAsm << "\t! " << CV->getType()->getDescription()
- << " value: " << Val << "\n";
- } else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
- toAsm << (int)CB->getValue() << "\n";
- } else {
- WriteAsOperand(toAsm, CV, false, false) << "\n";
- }
- } else {
- assert(0 && "Unknown elementary type for constant");
- }
-}
-
-/// Print a constant value or values (it may be an aggregate).
-/// Uses printSingleConstantValue() to print each individual value.
-///
-void AsmPrinter::printConstantValueOnly(const Constant* CV,
- int numPadBytesAfter) {
- if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
- if (CVA->isString()) {
- // print the string alone and return
- toAsm << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n";
- } else {
- // Not a string. Print the values in successive locations
- const std::vector<Use> &constValues = CVA->getValues();
- for (unsigned i=0; i < constValues.size(); i++)
- printConstantValueOnly(cast<Constant>(constValues[i].get()));
- }
- } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
- // Print the fields in successive locations. Pad to align if needed!
- const StructLayout *cvsLayout =
- Target.getTargetData().getStructLayout(CVS->getType());
- const std::vector<Use>& constValues = CVS->getValues();
- unsigned sizeSoFar = 0;
- for (unsigned i=0, N = constValues.size(); i < N; i++) {
- const Constant* field = cast<Constant>(constValues[i].get());
-
- // Check if padding is needed and insert one or more 0s.
- unsigned fieldSize =
- Target.getTargetData().getTypeSize(field->getType());
- int padSize = ((i == N-1? cvsLayout->StructSize
- : cvsLayout->MemberOffsets[i+1])
- - cvsLayout->MemberOffsets[i]) - fieldSize;
- sizeSoFar += (fieldSize + padSize);
-
- // Now print the actual field value
- printConstantValueOnly(field, padSize);
- }
- assert(sizeSoFar == cvsLayout->StructSize &&
- "Layout of constant struct may be incorrect!");
- } else if (isa<ConstantAggregateZero>(CV)) {
- PrintZeroBytesToPad(Target.getTargetData().getTypeSize(CV->getType()));
- } else
- printSingleConstantValue(CV);
-
- if (numPadBytesAfter)
- PrintZeroBytesToPad(numPadBytesAfter);
-}
-
-/// ConstantExprToString() - Convert a ConstantExpr to an asm expression
-/// and return this as a string.
-///
-std::string AsmPrinter::ConstantExprToString(const ConstantExpr* CE,
- const TargetMachine& target) {
- std::string S;
- switch(CE->getOpcode()) {
- case Instruction::GetElementPtr:
- { // generate a symbolic expression for the byte address
- const Value* ptrVal = CE->getOperand(0);
- std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
- const TargetData &TD = target.getTargetData();
- S += "(" + valToExprString(ptrVal, target) + ") + ("
- + utostr(TD.getIndexedOffset(ptrVal->getType(),idxVec)) + ")";
- break;
- }
-
- case Instruction::Cast:
- // Support only non-converting casts for now, i.e., a no-op.
- // This assertion is not a complete check.
- assert(target.getTargetData().getTypeSize(CE->getType()) ==
- target.getTargetData().getTypeSize(CE->getOperand(0)->getType()));
- S += "(" + valToExprString(CE->getOperand(0), target) + ")";
- break;
-
- case Instruction::Add:
- S += ConstantArithExprToString(CE, target, ") + (");
- break;
-
- case Instruction::Sub:
- S += ConstantArithExprToString(CE, target, ") - (");
- break;
-
- case Instruction::Mul:
- S += ConstantArithExprToString(CE, target, ") * (");
- break;
-
- case Instruction::Div:
- S += ConstantArithExprToString(CE, target, ") / (");
- break;
-
- case Instruction::Rem:
- S += ConstantArithExprToString(CE, target, ") % (");
- break;
-
- case Instruction::And:
- // Logical && for booleans; bitwise & otherwise
- S += ConstantArithExprToString(CE, target,
- ((CE->getType() == Type::BoolTy)? ") && (" : ") & ("));
- break;
-
- case Instruction::Or:
- // Logical || for booleans; bitwise | otherwise
- S += ConstantArithExprToString(CE, target,
- ((CE->getType() == Type::BoolTy)? ") || (" : ") | ("));
- break;
-
- case Instruction::Xor:
- // Bitwise ^ for all types
- S += ConstantArithExprToString(CE, target, ") ^ (");
- break;
-
- default:
- assert(0 && "Unsupported operator in ConstantExprToString()");
- break;
- }
-
- return S;
-}
-
-/// valToExprString - Helper function for ConstantExprToString().
-/// Appends result to argument string S.
-///
-std::string AsmPrinter::valToExprString(const Value* V,
- const TargetMachine& target) {
- std::string S;
- bool failed = false;
- if (const Constant* CV = dyn_cast<Constant>(V)) { // symbolic or known
- if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV))
- S += std::string(CB == ConstantBool::True ? "1" : "0");
- else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
- S += itostr(CI->getValue());
- else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
- S += utostr(CI->getValue());
- else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
- S += ftostr(CFP->getValue());
- else if (isa<ConstantPointerNull>(CV))
- S += "0";
- else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(CV))
- S += valToExprString(CPR->getValue(), target);
- else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV))
- S += ConstantExprToString(CE, target);
- else
- failed = true;
- } else if (const GlobalValue* GV = dyn_cast<GlobalValue>(V)) {
- S += getID(GV);
- } else
- failed = true;
-
- if (failed) {
- assert(0 && "Cannot convert value to string");
- S += "<illegal-value>";
- }
- return S;
-}
-
-
-//===----------------------------------------------------------------------===//
-// SparcAsmPrinter Code
-//===----------------------------------------------------------------------===//
-
-namespace {
-
- struct SparcAsmPrinter : public FunctionPass, public AsmPrinter {
- inline SparcAsmPrinter(std::ostream &os, const TargetMachine &t)
- : AsmPrinter(os, t) {}
-
- const Function *currFunction;
-
- const char *getPassName() const {
- return "Output Sparc Assembly for Functions";
- }
-
- virtual bool doInitialization(Module &M) {
- startModule(M);
- return false;
- }
-
- virtual bool runOnFunction(Function &F) {
- currFunction = &F;
- emitFunction(F);
- return false;
- }
-
- virtual bool doFinalization(Module &M) {
- emitGlobals(M);
- return false;
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- }
-
- void emitFunction(const Function &F);
- private :
- void emitBasicBlock(const MachineBasicBlock &MBB);
- void emitMachineInst(const MachineInstr *MI);
-
- unsigned int printOperands(const MachineInstr *MI, unsigned int opNum);
- void printOneOperand(const MachineOperand &Op, MachineOpCode opCode);
-
- bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum);
- bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum);
-
- unsigned getOperandMask(unsigned Opcode) {
- switch (Opcode) {
- case V9::SUBccr:
- case V9::SUBcci: return 1 << 3; // Remove CC argument
- default: return 0; // By default, don't hack operands...
- }
- }
-
- void emitGlobals(const Module &M);
- void printGlobalVariable(const GlobalVariable *GV);
- };
-
-} // End anonymous namespace
-
-inline bool
-SparcAsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI,
- unsigned int opNum) {
- switch (MI->getOpcode()) {
- case V9::JMPLCALLr:
- case V9::JMPLCALLi:
- case V9::JMPLRETr:
- case V9::JMPLRETi:
- return (opNum == 0);
- default:
- return false;
- }
-}
-
-inline bool
-SparcAsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI,
- unsigned int opNum) {
- if (Target.getInstrInfo().isLoad(MI->getOpcode()))
- return (opNum == 0);
- else if (Target.getInstrInfo().isStore(MI->getOpcode()))
- return (opNum == 1);
- else
- return false;
-}
-
-
-#define PrintOp1PlusOp2(mop1, mop2, opCode) \
- printOneOperand(mop1, opCode); \
- toAsm << "+"; \
- printOneOperand(mop2, opCode);
-
-unsigned int
-SparcAsmPrinter::printOperands(const MachineInstr *MI,
- unsigned int opNum)
-{
- const MachineOperand& mop = MI->getOperand(opNum);
-
- if (OpIsBranchTargetLabel(MI, opNum)) {
- PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpcode());
- return 2;
- } else if (OpIsMemoryAddressBase(MI, opNum)) {
- toAsm << "[";
- PrintOp1PlusOp2(mop, MI->getOperand(opNum+1), MI->getOpcode());
- toAsm << "]";
- return 2;
- } else {
- printOneOperand(mop, MI->getOpcode());
- return 1;
- }
-}
-
-void
-SparcAsmPrinter::printOneOperand(const MachineOperand &mop,
- MachineOpCode opCode)
-{
- bool needBitsFlag = true;
-
- if (mop.isHiBits32())
- toAsm << "%lm(";
- else if (mop.isLoBits32())
- toAsm << "%lo(";
- else if (mop.isHiBits64())
- toAsm << "%hh(";
- else if (mop.isLoBits64())
- toAsm << "%hm(";
- else
- needBitsFlag = false;
-
- switch (mop.getType())
- {
- case MachineOperand::MO_VirtualRegister:
- case MachineOperand::MO_CCRegister:
- case MachineOperand::MO_MachineRegister:
- {
- int regNum = (int)mop.getReg();
-
- if (regNum == Target.getRegInfo().getInvalidRegNum()) {
- // better to print code with NULL registers than to die
- toAsm << "<NULL VALUE>";
- } else {
- toAsm << "%" << Target.getRegInfo().getUnifiedRegName(regNum);
- }
- break;
- }
-
- case MachineOperand::MO_ConstantPoolIndex:
- {
- toAsm << ".CPI_" << currFunction->getName()
- << "_" << mop.getConstantPoolIndex();
- break;
- }
-
- case MachineOperand::MO_PCRelativeDisp:
- {
- const Value *Val = mop.getVRegValue();
- assert(Val && "\tNULL Value in SparcAsmPrinter");
-
- if (const BasicBlock *BB = dyn_cast<BasicBlock>(Val))
- toAsm << getID(BB);
- else if (const Function *M = dyn_cast<Function>(Val))
- toAsm << getID(M);
- else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Val))
- toAsm << getID(GV);
- else if (const Constant *CV = dyn_cast<Constant>(Val))
- toAsm << getID(CV);
- else
- assert(0 && "Unrecognized value in SparcAsmPrinter");
- break;
- }
-
- case MachineOperand::MO_SignExtendedImmed:
- toAsm << mop.getImmedValue();
- break;
-
- case MachineOperand::MO_UnextendedImmed:
- toAsm << (uint64_t) mop.getImmedValue();
- break;
-
- default:
- toAsm << mop; // use dump field
- break;
- }
-
- if (needBitsFlag)
- toAsm << ")";
-}
-
-void SparcAsmPrinter::emitMachineInst(const MachineInstr *MI) {
- unsigned Opcode = MI->getOpcode();
-
- if (Target.getInstrInfo().isDummyPhiInstr(Opcode))
- return; // IGNORE PHI NODES
-
- toAsm << "\t" << Target.getInstrInfo().getName(Opcode) << "\t";
-
- unsigned Mask = getOperandMask(Opcode);
-
- bool NeedComma = false;
- unsigned N = 1;
- for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N)
- if (! ((1 << OpNum) & Mask)) { // Ignore this operand?
- if (NeedComma) toAsm << ", "; // Handle comma outputting
- NeedComma = true;
- N = printOperands(MI, OpNum);
- } else
- N = 1;
-
- toAsm << "\n";
- ++EmittedInsts;
-}
-
-void SparcAsmPrinter::emitBasicBlock(const MachineBasicBlock &MBB) {
- // Emit a label for the basic block
- toAsm << getID(MBB.getBasicBlock()) << ":\n";
-
- // Loop over all of the instructions in the basic block...
- for (MachineBasicBlock::const_iterator MII = MBB.begin(), MIE = MBB.end();
- MII != MIE; ++MII)
- emitMachineInst(MII);
- toAsm << "\n"; // Separate BB's with newlines
-}
-
-void SparcAsmPrinter::emitFunction(const Function &F) {
- std::string methName = getID(&F);
- toAsm << "!****** Outputing Function: " << methName << " ******\n";
-
- // Emit constant pool for this function
- const MachineConstantPool *MCP = MachineFunction::get(&F).getConstantPool();
- const std::vector<Constant*> &CP = MCP->getConstants();
-
- enterSection(AsmPrinter::ReadOnlyData);
- for (unsigned i = 0, e = CP.size(); i != e; ++i) {
- std::string cpiName = ".CPI_" + F.getName() + "_" + utostr(i);
- printConstant(CP[i], cpiName);
- }
-
- enterSection(AsmPrinter::Text);
- toAsm << "\t.align\t4\n\t.global\t" << methName << "\n";
- //toAsm << "\t.type\t" << methName << ",#function\n";
- toAsm << "\t.type\t" << methName << ", 2\n";
- toAsm << methName << ":\n";
-
- // Output code for all of the basic blocks in the function...
- MachineFunction &MF = MachineFunction::get(&F);
- for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E;++I)
- emitBasicBlock(*I);
-
- // Output a .size directive so the debugger knows the extents of the function
- toAsm << ".EndOf_" << methName << ":\n\t.size "
- << methName << ", .EndOf_"
- << methName << "-" << methName << "\n";
-
- // Put some spaces between the functions
- toAsm << "\n\n";
-}
-
-void SparcAsmPrinter::printGlobalVariable(const GlobalVariable* GV) {
- if (GV->hasExternalLinkage())
- toAsm << "\t.global\t" << getID(GV) << "\n";
-
- if (GV->hasInitializer() && ! GV->getInitializer()->isNullValue()) {
- printConstant(GV->getInitializer(), getID(GV));
- } else {
- toAsm << "\t.align\t" << TypeToAlignment(GV->getType()->getElementType(),
- Target) << "\n";
- toAsm << "\t.type\t" << getID(GV) << ",#object\n";
- toAsm << "\t.reserve\t" << getID(GV) << ","
- << Target.findOptimalStorageSize(GV->getType()->getElementType())
- << "\n";
- }
-}
-
-void SparcAsmPrinter::emitGlobals(const Module &M) {
- // Output global variables...
- for (Module::const_giterator GI = M.gbegin(), GE = M.gend(); GI != GE; ++GI)
- if (! GI->isExternal()) {
- assert(GI->hasInitializer());
- if (GI->isConstant())
- enterSection(AsmPrinter::ReadOnlyData); // read-only, initialized data
- else if (GI->getInitializer()->isNullValue())
- enterSection(AsmPrinter::ZeroInitRWData); // read-write zero data
- else
- enterSection(AsmPrinter::InitRWData); // read-write non-zero data
-
- printGlobalVariable(GI);
- }
-
- toAsm << "\n";
-}
-
-FunctionPass *llvm::createAsmPrinterPass(std::ostream &Out,
- const TargetMachine &TM) {
- return new SparcAsmPrinter(Out, TM);
-}
diff --git a/llvm/lib/Target/Sparc/EmitBytecodeToAssembly.cpp b/llvm/lib/Target/Sparc/EmitBytecodeToAssembly.cpp
deleted file mode 100644
index 40facf3fd99..00000000000
--- a/llvm/lib/Target/Sparc/EmitBytecodeToAssembly.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-//===-- EmitBytecodeToAssembly.cpp - Emit bytecode to Sparc .s File --------==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the pass that writes LLVM bytecode as data to a sparc
-// assembly file. The bytecode gets assembled into a special bytecode section
-// of the executable for use at runtime later.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcInternals.h"
-#include "llvm/Pass.h"
-#include "llvm/Bytecode/Writer.h"
-#include <iostream>
-
-namespace llvm {
-
-using std::ostream;
-
-namespace {
-
- // sparcasmbuf - stream buf for encoding output bytes as .byte directives for
- // the sparc assembler.
- //
- class sparcasmbuf : public std::streambuf {
- std::ostream &BaseStr;
- public:
- typedef char char_type;
- typedef int int_type;
- typedef std::streampos pos_type;
- typedef std::streamoff off_type;
-
- sparcasmbuf(std::ostream &On) : BaseStr(On) {}
-
- virtual int_type overflow(int_type C) {
- if (C != EOF)
- BaseStr << "\t.byte " << C << "\n"; // Output C;
- return C;
- }
- };
-
-
- // osparcasmstream - Define an ostream implementation that uses a sparcasmbuf
- // as the underlying streambuf to write the data to. This streambuf formats
- // the output as .byte directives for sparc output.
- //
- class osparcasmstream : public std::ostream {
- sparcasmbuf sb;
- public:
- typedef char char_type;
- typedef int int_type;
- typedef std::streampos pos_type;
- typedef std::streamoff off_type;
-
- explicit osparcasmstream(std::ostream &On) : std::ostream(&sb), sb(On) { }
-
- sparcasmbuf *rdbuf() const {
- return const_cast<sparcasmbuf*>(&sb);
- }
- };
-
- static void writePrologue (std::ostream &Out, const std::string &comment,
- const std::string &symName) {
- // Prologue:
- // Output a comment describing the object.
- Out << "!" << comment << "\n";
- // Switch the current section to .rodata in the assembly output:
- Out << "\t.section \".rodata\"\n\t.align 8\n";
- // Output a global symbol naming the object:
- Out << "\t.global " << symName << "\n";
- Out << "\t.type " << symName << ",#object\n";
- Out << symName << ":\n";
- }
-
- static void writeEpilogue (std::ostream &Out, const std::string &symName) {
- // Epilogue:
- // Output a local symbol marking the end of the object:
- Out << ".end_" << symName << ":\n";
- // Output size directive giving the size of the object:
- Out << "\t.size " << symName << ", .end_" << symName << "-" << symName
- << "\n";
- }
-
- // SparcBytecodeWriter - Write bytecode out to a stream that is sparc'ified
- class SparcBytecodeWriter : public Pass {
- std::ostream &Out;
- public:
- SparcBytecodeWriter(std::ostream &out) : Out(out) {}
-
- const char *getPassName() const { return "Emit Bytecode to Sparc Assembly";}
-
- virtual bool run(Module &M) {
- // Write an object containing the bytecode to the SPARC assembly stream
- writePrologue (Out, "LLVM BYTECODE OUTPUT", "LLVMBytecode");
- osparcasmstream OS(Out);
- WriteBytecodeToFile(&M, OS);
- writeEpilogue (Out, "LLVMBytecode");
-
- // Write an object containing its length as an integer to the
- // SPARC assembly stream
- writePrologue (Out, "LLVM BYTECODE LENGTH", "llvm_length");
- Out <<"\t.word\t.end_LLVMBytecode-LLVMBytecode\n";
- writeEpilogue (Out, "llvm_length");
-
- return false;
- }
- };
-} // end anonymous namespace
-
-Pass *createBytecodeAsmPrinterPass(std::ostream &Out) {
- return new SparcBytecodeWriter(Out);
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/InstrSelection/InstrForest.cpp b/llvm/lib/Target/Sparc/InstrSelection/InstrForest.cpp
deleted file mode 100644
index fd5056d22d7..00000000000
--- a/llvm/lib/Target/Sparc/InstrSelection/InstrForest.cpp
+++ /dev/null
@@ -1,336 +0,0 @@
-//===-- InstrForest.cpp - Build instruction forest for inst selection -----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// The key goal is to group instructions into a single
-// tree if one or more of them might be potentially combined into a single
-// complex instruction in the target machine.
-// Since this grouping is completely machine-independent, we do it as
-// aggressive as possible to exploit any possible target instructions.
-// In particular, we group two instructions O and I if:
-// (1) Instruction O computes an operand used by instruction I,
-// and (2) O and I are part of the same basic block,
-// and (3) O has only a single use, viz., I.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Constant.h"
-#include "llvm/Function.h"
-#include "llvm/iTerminators.h"
-#include "llvm/iMemory.h"
-#include "llvm/Type.h"
-#include "llvm/CodeGen/InstrForest.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "Support/STLExtras.h"
-#include "Config/alloca.h"
-
-namespace llvm {
-
-//------------------------------------------------------------------------
-// class InstrTreeNode
-//------------------------------------------------------------------------
-
-void
-InstrTreeNode::dump(int dumpChildren, int indent) const {
- dumpNode(indent);
-
- if (dumpChildren) {
- if (LeftChild)
- LeftChild->dump(dumpChildren, indent+1);
- if (RightChild)
- RightChild->dump(dumpChildren, indent+1);
- }
-}
-
-
-InstructionNode::InstructionNode(Instruction* I)
- : InstrTreeNode(NTInstructionNode, I), codeIsFoldedIntoParent(false)
-{
- opLabel = I->getOpcode();
-
- // Distinguish special cases of some instructions such as Ret and Br
- //
- if (opLabel == Instruction::Ret && cast<ReturnInst>(I)->getReturnValue()) {
- opLabel = RetValueOp; // ret(value) operation
- }
- else if (opLabel ==Instruction::Br && !cast<BranchInst>(I)->isUnconditional())
- {
- opLabel = BrCondOp; // br(cond) operation
- } else if (opLabel >= Instruction::SetEQ && opLabel <= Instruction::SetGT) {
- opLabel = SetCCOp; // common label for all SetCC ops
- } else if (opLabel == Instruction::Alloca && I->getNumOperands() > 0) {
- opLabel = AllocaN; // Alloca(ptr, N) operation
- } else if (opLabel == Instruction::GetElementPtr &&
- cast<GetElementPtrInst>(I)->hasIndices()) {
- opLabel = opLabel + 100; // getElem with index vector
- } else if (opLabel == Instruction::Xor &&
- BinaryOperator::isNot(I)) {
- opLabel = (I->getType() == Type::BoolTy)? NotOp // boolean Not operator
- : BNotOp; // bitwise Not operator
- } else if (opLabel == Instruction::And || opLabel == Instruction::Or ||
- opLabel == Instruction::Xor) {
- // Distinguish bitwise operators from logical operators!
- if (I->getType() != Type::BoolTy)
- opLabel = opLabel + 100; // bitwise operator
- } else if (opLabel == Instruction::Cast) {
- const Type *ITy = I->getType();
- switch(ITy->getPrimitiveID())
- {
- case Type::BoolTyID: opLabel = ToBoolTy; break;
- case Type::UByteTyID: opLabel = ToUByteTy; break;
- case Type::SByteTyID: opLabel = ToSByteTy; break;
- case Type::UShortTyID: opLabel = ToUShortTy; break;
- case Type::ShortTyID: opLabel = ToShortTy; break;
- case Type::UIntTyID: opLabel = ToUIntTy; break;
- case Type::IntTyID: opLabel = ToIntTy; break;
- case Type::ULongTyID: opLabel = ToULongTy; break;
- case Type::LongTyID: opLabel = ToLongTy; break;
- case Type::FloatTyID: opLabel = ToFloatTy; break;
- case Type::DoubleTyID: opLabel = ToDoubleTy; break;
- case Type::ArrayTyID: opLabel = ToArrayTy; break;
- case Type::PointerTyID: opLabel = ToPointerTy; break;
- default:
- // Just use `Cast' opcode otherwise. It's probably ignored.
- break;
- }
- }
-}
-
-
-void
-InstructionNode::dumpNode(int indent) const {
- for (int i=0; i < indent; i++)
- std::cerr << " ";
- std::cerr << getInstruction()->getOpcodeName()
- << " [label " << getOpLabel() << "]" << "\n";
-}
-
-void
-VRegListNode::dumpNode(int indent) const {
- for (int i=0; i < indent; i++)
- std::cerr << " ";
-
- std::cerr << "List" << "\n";
-}
-
-
-void
-VRegNode::dumpNode(int indent) const {
- for (int i=0; i < indent; i++)
- std::cerr << " ";
-
- std::cerr << "VReg " << getValue() << "\t(type "
- << (int) getValue()->getValueType() << ")" << "\n";
-}
-
-void
-ConstantNode::dumpNode(int indent) const {
- for (int i=0; i < indent; i++)
- std::cerr << " ";
-
- std::cerr << "Constant " << getValue() << "\t(type "
- << (int) getValue()->getValueType() << ")" << "\n";
-}
-
-void LabelNode::dumpNode(int indent) const {
- for (int i=0; i < indent; i++)
- std::cerr << " ";
-
- std::cerr << "Label " << getValue() << "\n";
-}
-
-//------------------------------------------------------------------------
-// class InstrForest
-//
-// A forest of instruction trees, usually for a single method.
-//------------------------------------------------------------------------
-
-InstrForest::InstrForest(Function *F) {
- for (Function::iterator BB = F->begin(), FE = F->end(); BB != FE; ++BB) {
- for(BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
- buildTreeForInstruction(I);
- }
-}
-
-InstrForest::~InstrForest() {
- for_each(treeRoots.begin(), treeRoots.end(), deleter<InstructionNode>);
-}
-
-void InstrForest::dump() const {
- for (const_root_iterator I = roots_begin(); I != roots_end(); ++I)
- (*I)->dump(/*dumpChildren*/ 1, /*indent*/ 0);
-}
-
-inline void InstrForest::eraseRoot(InstructionNode* node) {
- for (RootSet::reverse_iterator RI=treeRoots.rbegin(), RE=treeRoots.rend();
- RI != RE; ++RI)
- if (*RI == node)
- treeRoots.erase(RI.base()-1);
-}
-
-inline void InstrForest::noteTreeNodeForInstr(Instruction *instr,
- InstructionNode *treeNode) {
- (*this)[instr] = treeNode;
- treeRoots.push_back(treeNode); // mark node as root of a new tree
-}
-
-
-inline void InstrForest::setLeftChild(InstrTreeNode *parent,
- InstrTreeNode *child) {
- parent->LeftChild = child;
- child->Parent = parent;
- if (InstructionNode* instrNode = dyn_cast<InstructionNode>(child))
- eraseRoot(instrNode); // no longer a tree root
-}
-
-inline void InstrForest::setRightChild(InstrTreeNode *parent,
- InstrTreeNode *child) {
- parent->RightChild = child;
- child->Parent = parent;
- if (InstructionNode* instrNode = dyn_cast<InstructionNode>(child))
- eraseRoot(instrNode); // no longer a tree root
-}
-
-
-InstructionNode* InstrForest::buildTreeForInstruction(Instruction *instr) {
- InstructionNode *treeNode = getTreeNodeForInstr(instr);
- if (treeNode) {
- // treeNode has already been constructed for this instruction
- assert(treeNode->getInstruction() == instr);
- return treeNode;
- }
-
- // Otherwise, create a new tree node for this instruction.
- //
- treeNode = new InstructionNode(instr);
- noteTreeNodeForInstr(instr, treeNode);
-
- if (instr->getOpcode() == Instruction::Call) {
- // Operands of call instruction
- return treeNode;
- }
-
- // If the instruction has more than 2 instruction operands,
- // then we need to create artificial list nodes to hold them.
- // (Note that we only count operands that get tree nodes, and not
- // others such as branch labels for a branch or switch instruction.)
- //
- // To do this efficiently, we'll walk all operands, build treeNodes
- // for all appropriate operands and save them in an array. We then
- // insert children at the end, creating list nodes where needed.
- // As a performance optimization, allocate a child array only
- // if a fixed array is too small.
- //
- int numChildren = 0;
- InstrTreeNode** childArray = new InstrTreeNode*[instr->getNumOperands()];
-
- //
- // Walk the operands of the instruction
- //
- for (Instruction::op_iterator O = instr->op_begin(); O!=instr->op_end(); ++O)
- {
- Value* operand = *O;
-
- // Check if the operand is a data value, not an branch label, type,
- // method or module. If the operand is an address type (i.e., label
- // or method) that is used in an non-branching operation, e.g., `add'.
- // that should be considered a data value.
-
- // Check latter condition here just to simplify the next IF.
- bool includeAddressOperand =
- (isa<BasicBlock>(operand) || isa<Function>(operand))
- && !instr->isTerminator();
-
- if (includeAddressOperand || isa<Instruction>(operand) ||
- isa<Constant>(operand) || isa<Argument>(operand) ||
- isa<GlobalVariable>(operand))
- {
- // This operand is a data value
-
- // An instruction that computes the incoming value is added as a
- // child of the current instruction if:
- // the value has only a single use
- // AND both instructions are in the same basic block.
- // AND the current instruction is not a PHI (because the incoming
- // value is conceptually in a predecessor block,
- // even though it may be in the same static block)
- //
- // (Note that if the value has only a single use (viz., `instr'),
- // the def of the value can be safely moved just before instr
- // and therefore it is safe to combine these two instructions.)
- //
- // In all other cases, the virtual register holding the value
- // is used directly, i.e., made a child of the instruction node.
- //
- InstrTreeNode* opTreeNode;
- if (isa<Instruction>(operand) && operand->hasOneUse() &&
- cast<Instruction>(operand)->getParent() == instr->getParent() &&
- instr->getOpcode() != Instruction::PHI &&
- instr->getOpcode() != Instruction::Call)
- {
- // Recursively create a treeNode for it.
- opTreeNode = buildTreeForInstruction((Instruction*)operand);
- } else if (Constant *CPV = dyn_cast<Constant>(operand)) {
- // Create a leaf node for a constant
- opTreeNode = new ConstantNode(CPV);
- } else {
- // Create a leaf node for the virtual register
- opTreeNode = new VRegNode(operand);
- }
-
- childArray[numChildren++] = opTreeNode;
- }
- }
-
- //--------------------------------------------------------------------
- // Add any selected operands as children in the tree.
- // Certain instructions can have more than 2 in some instances (viz.,
- // a CALL or a memory access -- LOAD, STORE, and GetElemPtr -- to an
- // array or struct). Make the operands of every such instruction into
- // a right-leaning binary tree with the operand nodes at the leaves
- // and VRegList nodes as internal nodes.
- //--------------------------------------------------------------------
-
- InstrTreeNode *parent = treeNode;
-
- if (numChildren > 2) {
- unsigned instrOpcode = treeNode->getInstruction()->getOpcode();
- assert(instrOpcode == Instruction::PHI ||
- instrOpcode == Instruction::Call ||
- instrOpcode == Instruction::Load ||
- instrOpcode == Instruction::Store ||
- instrOpcode == Instruction::GetElementPtr);
- }
-
- // Insert the first child as a direct child
- if (numChildren >= 1)
- setLeftChild(parent, childArray[0]);
-
- int n;
-
- // Create a list node for children 2 .. N-1, if any
- for (n = numChildren-1; n >= 2; n--) {
- // We have more than two children
- InstrTreeNode *listNode = new VRegListNode();
- setRightChild(parent, listNode);
- setLeftChild(listNode, childArray[numChildren - n]);
- parent = listNode;
- }
-
- // Now insert the last remaining child (if any).
- if (numChildren >= 2) {
- assert(n == 1);
- setRightChild(parent, childArray[numChildren - 1]);
- }
-
- delete [] childArray;
- return treeNode;
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/InstrSelection/InstrSelection.cpp b/llvm/lib/Target/Sparc/InstrSelection/InstrSelection.cpp
deleted file mode 100644
index 4ddc4edfbb6..00000000000
--- a/llvm/lib/Target/Sparc/InstrSelection/InstrSelection.cpp
+++ /dev/null
@@ -1,414 +0,0 @@
-//===- InstrSelection.cpp - Machine Independent Inst Selection Driver -----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Machine-independent driver file for instruction selection. This file
-// constructs a forest of BURG instruction trees and then uses the
-// BURG-generated tree grammar (BURM) to find the optimal instruction sequences
-// for a given machine.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/InstrSelection.h"
-#include "llvm/Function.h"
-#include "llvm/IntrinsicLowering.h"
-#include "llvm/iPHINode.h"
-#include "llvm/iOther.h"
-#include "llvm/Pass.h"
-#include "llvm/CodeGen/InstrForest.h"
-#include "llvm/CodeGen/InstrSelectionSupport.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegInfo.h"
-#include "Support/CommandLine.h"
-#include "Support/LeakDetector.h"
-
-namespace llvm {
- std::vector<MachineInstr*>
- FixConstantOperandsForInstr(Instruction *I, MachineInstr *MI,
- TargetMachine &TM);
-}
-
-namespace {
- //===--------------------------------------------------------------------===//
- // SelectDebugLevel - Allow command line control over debugging.
- //
- enum SelectDebugLevel_t {
- Select_NoDebugInfo,
- Select_PrintMachineCode,
- Select_DebugInstTrees,
- Select_DebugBurgTrees,
- };
-
- // Enable Debug Options to be specified on the command line
- cl::opt<SelectDebugLevel_t>
- SelectDebugLevel("dselect", cl::Hidden,
- cl::desc("enable instruction selection debug information"),
- cl::values(
- clEnumValN(Select_NoDebugInfo, "n", "disable debug output"),
- clEnumValN(Select_PrintMachineCode, "y", "print generated machine code"),
- clEnumValN(Select_DebugInstTrees, "i",
- "print debugging info for instruction selection"),
- clEnumValN(Select_DebugBurgTrees, "b", "print burg trees"),
- 0));
-
-
- //===--------------------------------------------------------------------===//
- // InstructionSelection Pass
- //
- // This is the actual pass object that drives the instruction selection
- // process.
- //
- class InstructionSelection : public FunctionPass {
- TargetMachine &Target;
- void InsertCodeForPhis(Function &F);
- void InsertPhiElimInstructions(BasicBlock *BB,
- const std::vector<MachineInstr*>& CpVec);
- void SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt);
- void PostprocessMachineCodeForTree(InstructionNode* instrNode,
- int ruleForNode, short* nts);
- public:
- InstructionSelection(TargetMachine &TM) : Target(TM) {}
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesCFG();
- }
-
- bool runOnFunction(Function &F);
- virtual const char *getPassName() const { return "Instruction Selection"; }
- };
-}
-
-
-TmpInstruction::TmpInstruction(MachineCodeForInstruction& mcfi,
- Value *s1, Value *s2, const std::string &name)
- : Instruction(s1->getType(), Instruction::UserOp1, name)
-{
- mcfi.addTemp(this);
-
- Operands.push_back(Use(s1, this)); // s1 must be non-null
- if (s2)
- Operands.push_back(Use(s2, this));
-
- // TmpInstructions should not be garbage checked.
- LeakDetector::removeGarbageObject(this);
-}
-
-// Constructor that requires the type of the temporary to be specified.
-// Both S1 and S2 may be NULL.(
-TmpInstruction::TmpInstruction(MachineCodeForInstruction& mcfi,
- const Type *Ty, Value *s1, Value* s2,
- const std::string &name)
- : Instruction(Ty, Instruction::UserOp1, name)
-{
- mcfi.addTemp(this);
-
- if (s1)
- Operands.push_back(Use(s1, this));
- if (s2)
- Operands.push_back(Use(s2, this));
-
- // TmpInstructions should not be garbage checked.
- LeakDetector::removeGarbageObject(this);
-}
-
-bool InstructionSelection::runOnFunction(Function &F) {
- // First pass - Walk the function, lowering any calls to intrinsic functions
- // which the instruction selector cannot handle.
- for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
- for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; )
- if (CallInst *CI = dyn_cast<CallInst>(I++))
- if (Function *F = CI->getCalledFunction())
- switch (F->getIntrinsicID()) {
-#undef va_start
-#undef va_copy
-#undef va_end
- case Intrinsic::not_intrinsic:
- case Intrinsic::va_start:
- case Intrinsic::va_copy:
- case Intrinsic::va_end:
- // We directly implement these intrinsics. Note that this knowledge
- // is incestuously entangled with the code in
- // SparcInstrSelection.cpp and must be updated when it is updated.
- // Since ALL of the code in this library is incestuously intertwined
- // with it already and sparc specific, we will live with this.
- break;
- default:
- // All other intrinsic calls we must lower.
- Instruction *Before = CI->getPrev();
- Target.getIntrinsicLowering().LowerIntrinsicCall(CI);
- if (Before) { // Move iterator to instruction after call
- I = Before; ++I;
- } else {
- I = BB->begin();
- }
- }
-
- //
- // Build the instruction trees to be given as inputs to BURG.
- //
- InstrForest instrForest(&F);
-
- if (SelectDebugLevel >= Select_DebugInstTrees) {
- std::cerr << "\n\n*** Input to instruction selection for function "
- << F.getName() << "\n\n" << F
- << "\n\n*** Instruction trees for function "
- << F.getName() << "\n\n";
- instrForest.dump();
- }
-
- //
- // Invoke BURG instruction selection for each tree
- //
- for (InstrForest::const_root_iterator RI = instrForest.roots_begin();
- RI != instrForest.roots_end(); ++RI) {
- InstructionNode* basicNode = *RI;
- assert(basicNode->parent() == NULL && "A `root' node has a parent?");
-
- // Invoke BURM to label each tree node with a state
- burm_label(basicNode);
-
- if (SelectDebugLevel >= Select_DebugBurgTrees) {
- printcover(basicNode, 1, 0);
- std::cerr << "\nCover cost == " << treecost(basicNode, 1, 0) <<"\n\n";
- printMatches(basicNode);
- }
-
- // Then recursively walk the tree to select instructions
- SelectInstructionsForTree(basicNode, /*goalnt*/1);
- }
-
- //
- // Create the MachineBasicBlock records and add all of the MachineInstrs
- // defined in the MachineCodeForInstruction objects to also live in the
- // MachineBasicBlock objects.
- //
- MachineFunction &MF = MachineFunction::get(&F);
- for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) {
- MachineBasicBlock *MCBB = new MachineBasicBlock(BI);
- MF.getBasicBlockList().push_back(MCBB);
-
- for (BasicBlock::iterator II = BI->begin(); II != BI->end(); ++II) {
- MachineCodeForInstruction &mvec = MachineCodeForInstruction::get(II);
- MCBB->insert(MCBB->end(), mvec.begin(), mvec.end());
- }
- }
-
- // Insert phi elimination code
- InsertCodeForPhis(F);
-
- if (SelectDebugLevel >= Select_PrintMachineCode) {
- std::cerr << "\n*** Machine instructions after INSTRUCTION SELECTION\n";
- MachineFunction::get(&F).dump();
- }
-
- return true;
-}
-
-
-//-------------------------------------------------------------------------
-// This method inserts phi elimination code for all BBs in a method
-//-------------------------------------------------------------------------
-
-void
-InstructionSelection::InsertCodeForPhis(Function &F) {
- // for all basic blocks in function
- //
- MachineFunction &MF = MachineFunction::get(&F);
- for (MachineFunction::iterator BB = MF.begin(); BB != MF.end(); ++BB) {
- for (BasicBlock::const_iterator IIt = BB->getBasicBlock()->begin();
- const PHINode *PN = dyn_cast<PHINode>(IIt); ++IIt) {
- // FIXME: This is probably wrong...
- Value *PhiCpRes = new PHINode(PN->getType(), "PhiCp:");
-
- // The leak detector shouldn't track these nodes. They are not garbage,
- // even though their parent field is never filled in.
- //
- LeakDetector::removeGarbageObject(PhiCpRes);
-
- // for each incoming value of the phi, insert phi elimination
- //
- for (unsigned i = 0; i < PN->getNumIncomingValues(); ++i) {
- // insert the copy instruction to the predecessor BB
- std::vector<MachineInstr*> mvec, CpVec;
- Target.getRegInfo().cpValue2Value(PN->getIncomingValue(i), PhiCpRes,
- mvec);
- for (std::vector<MachineInstr*>::iterator MI=mvec.begin();
- MI != mvec.end(); ++MI) {
- std::vector<MachineInstr*> CpVec2 =
- FixConstantOperandsForInstr(const_cast<PHINode*>(PN), *MI, Target);
- CpVec2.push_back(*MI);
- CpVec.insert(CpVec.end(), CpVec2.begin(), CpVec2.end());
- }
-
- InsertPhiElimInstructions(PN->getIncomingBlock(i), CpVec);
- }
-
- std::vector<MachineInstr*> mvec;
- Target.getRegInfo().cpValue2Value(PhiCpRes, const_cast<PHINode*>(PN),
- mvec);
- BB->insert(BB->begin(), mvec.begin(), mvec.end());
- } // for each Phi Instr in BB
- } // for all BBs in function
-}
-
-//-------------------------------------------------------------------------
-// Thid method inserts a copy instruction to a predecessor BB as a result
-// of phi elimination.
-//-------------------------------------------------------------------------
-
-void
-InstructionSelection::InsertPhiElimInstructions(BasicBlock *BB,
- const std::vector<MachineInstr*>& CpVec)
-{
- Instruction *TermInst = (Instruction*)BB->getTerminator();
- MachineCodeForInstruction &MC4Term = MachineCodeForInstruction::get(TermInst);
- MachineInstr *FirstMIOfTerm = MC4Term.front();
- assert (FirstMIOfTerm && "No Machine Instrs for terminator");
-
- MachineFunction &MF = MachineFunction::get(BB->getParent());
-
- // FIXME: if PHI instructions existed in the machine code, this would be
- // unnecessary.
- MachineBasicBlock *MBB = 0;
- for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
- if (I->getBasicBlock() == BB) {
- MBB = I;
- break;
- }
-
- MachineBasicBlock::iterator MCIt = FirstMIOfTerm;
-
- assert(MCIt != MBB->end() && "Start inst of terminator not found");
-
- // insert the copy instructions just before the first machine instruction
- // generated for the terminator
- MBB->insert(MCIt, CpVec.begin(), CpVec.end());
-}
-
-
-//---------------------------------------------------------------------------
-// Function SelectInstructionsForTree
-//
-// Recursively walk the tree to select instructions.
-// Do this top-down so that child instructions can exploit decisions
-// made at the child instructions.
-//
-// E.g., if br(setle(reg,const)) decides the constant is 0 and uses
-// a branch-on-integer-register instruction, then the setle node
-// can use that information to avoid generating the SUBcc instruction.
-//
-// Note that this cannot be done bottom-up because setle must do this
-// only if it is a child of the branch (otherwise, the result of setle
-// may be used by multiple instructions).
-//---------------------------------------------------------------------------
-
-void
-InstructionSelection::SelectInstructionsForTree(InstrTreeNode* treeRoot,
- int goalnt)
-{
- // Get the rule that matches this node.
- //
- int ruleForNode = burm_rule(treeRoot->state, goalnt);
-
- if (ruleForNode == 0) {
- std::cerr << "Could not match instruction tree for instr selection\n";
- abort();
- }
-
- // Get this rule's non-terminals and the corresponding child nodes (if any)
- //
- short *nts = burm_nts[ruleForNode];
-
- // First, select instructions for the current node and rule.
- // (If this is a list node, not an instruction, then skip this step).
- // This function is specific to the target architecture.
- //
- if (treeRoot->opLabel != VRegListOp) {
- std::vector<MachineInstr*> minstrVec;
-
- InstructionNode* instrNode = (InstructionNode*)treeRoot;
- assert(instrNode->getNodeType() == InstrTreeNode::NTInstructionNode);
-
- GetInstructionsByRule(instrNode, ruleForNode, nts, Target, minstrVec);
-
- MachineCodeForInstruction &mvec =
- MachineCodeForInstruction::get(instrNode->getInstruction());
- mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end());
- }
-
- // Then, recursively compile the child nodes, if any.
- //
- if (nts[0]) {
- // i.e., there is at least one kid
- InstrTreeNode* kids[2];
- int currentRule = ruleForNode;
- burm_kids(treeRoot, currentRule, kids);
-
- // First skip over any chain rules so that we don't visit
- // the current node again.
- //
- while (ThisIsAChainRule(currentRule)) {
- currentRule = burm_rule(treeRoot->state, nts[0]);
- nts = burm_nts[currentRule];
- burm_kids(treeRoot, currentRule, kids);
- }
-
- // Now we have the first non-chain rule so we have found
- // the actual child nodes. Recursively compile them.
- //
- for (unsigned i = 0; nts[i]; i++) {
- assert(i < 2);
- InstrTreeNode::InstrTreeNodeType nodeType = kids[i]->getNodeType();
- if (nodeType == InstrTreeNode::NTVRegListNode ||
- nodeType == InstrTreeNode::NTInstructionNode)
- SelectInstructionsForTree(kids[i], nts[i]);
- }
- }
-
- // Finally, do any post-processing on this node after its children
- // have been translated
- //
- if (treeRoot->opLabel != VRegListOp)
- PostprocessMachineCodeForTree((InstructionNode*)treeRoot, ruleForNode, nts);
-}
-
-//---------------------------------------------------------------------------
-// Function PostprocessMachineCodeForTree
-//
-// Apply any final cleanups to machine code for the root of a subtree
-// after selection for all its children has been completed.
-//
-void
-InstructionSelection::PostprocessMachineCodeForTree(InstructionNode* instrNode,
- int ruleForNode,
- short* nts)
-{
- // Fix up any constant operands in the machine instructions to either
- // use an immediate field or to load the constant into a register
- // Walk backwards and use direct indexes to allow insertion before current
- //
- Instruction* vmInstr = instrNode->getInstruction();
- MachineCodeForInstruction &mvec = MachineCodeForInstruction::get(vmInstr);
- for (unsigned i = mvec.size(); i != 0; --i) {
- std::vector<MachineInstr*> loadConstVec =
- FixConstantOperandsForInstr(vmInstr, mvec[i-1], Target);
-
- mvec.insert(mvec.begin()+i-1, loadConstVec.begin(), loadConstVec.end());
- }
-}
-
-
-//===----------------------------------------------------------------------===//
-// createInstructionSelectionPass - Public entrypoint for instruction selection
-// and this file as a whole...
-//
-FunctionPass *llvm::createInstructionSelectionPass(TargetMachine &TM) {
- return new InstructionSelection(TM);
-}
diff --git a/llvm/lib/Target/Sparc/InstrSelection/InstrSelectionSupport.cpp b/llvm/lib/Target/Sparc/InstrSelection/InstrSelectionSupport.cpp
deleted file mode 100644
index a7923862cfa..00000000000
--- a/llvm/lib/Target/Sparc/InstrSelection/InstrSelectionSupport.cpp
+++ /dev/null
@@ -1,269 +0,0 @@
-//===-- InstrSelectionSupport.cpp -----------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Target-independent instruction selection code. See SparcInstrSelection.cpp
-// for usage.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/InstrSelectionSupport.h"
-#include "llvm/CodeGen/InstrSelection.h"
-#include "llvm/CodeGen/MachineInstrAnnot.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/InstrForest.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegInfo.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Constants.h"
-#include "llvm/BasicBlock.h"
-#include "llvm/DerivedTypes.h"
-#include "../SparcInstrSelectionSupport.h"
-
-namespace llvm {
-
-// Generate code to load the constant into a TmpInstruction (virtual reg) and
-// returns the virtual register.
-//
-static TmpInstruction*
-InsertCodeToLoadConstant(Function *F,
- Value* opValue,
- Instruction* vmInstr,
- std::vector<MachineInstr*>& loadConstVec,
- TargetMachine& target)
-{
- // Create a tmp virtual register to hold the constant.
- MachineCodeForInstruction &mcfi = MachineCodeForInstruction::get(vmInstr);
- TmpInstruction* tmpReg = new TmpInstruction(mcfi, opValue);
-
- target.getInstrInfo().CreateCodeToLoadConst(target, F, opValue, tmpReg,
- loadConstVec, mcfi);
-
- // Record the mapping from the tmp VM instruction to machine instruction.
- // Do this for all machine instructions that were not mapped to any
- // other temp values created by
- // tmpReg->addMachineInstruction(loadConstVec.back());
-
- return tmpReg;
-}
-
-
-MachineOperand::MachineOperandType
-ChooseRegOrImmed(int64_t intValue,
- bool isSigned,
- MachineOpCode opCode,
- const TargetMachine& target,
- bool canUseImmed,
- unsigned int& getMachineRegNum,
- int64_t& getImmedValue)
-{
- MachineOperand::MachineOperandType opType=MachineOperand::MO_VirtualRegister;
- getMachineRegNum = 0;
- getImmedValue = 0;
-
- if (canUseImmed &&
- target.getInstrInfo().constantFitsInImmedField(opCode, intValue)) {
- opType = isSigned? MachineOperand::MO_SignExtendedImmed
- : MachineOperand::MO_UnextendedImmed;
- getImmedValue = intValue;
- } else if (intValue == 0 &&
- target.getRegInfo().getZeroRegNum() != (unsigned)-1) {
- opType = MachineOperand::MO_MachineRegister;
- getMachineRegNum = target.getRegInfo().getZeroRegNum();
- }
-
- return opType;
-}
-
-
-MachineOperand::MachineOperandType
-ChooseRegOrImmed(Value* val,
- MachineOpCode opCode,
- const TargetMachine& target,
- bool canUseImmed,
- unsigned int& getMachineRegNum,
- int64_t& getImmedValue)
-{
- getMachineRegNum = 0;
- getImmedValue = 0;
-
- // To use reg or immed, constant needs to be integer, bool, or a NULL pointer
- // TargetInstrInfo::ConvertConstantToIntType() does the right conversions:
- bool isValidConstant;
- uint64_t valueToUse =
- target.getInstrInfo().ConvertConstantToIntType(target, val, val->getType(),
- isValidConstant);
- if (! isValidConstant)
- return MachineOperand::MO_VirtualRegister;
-
- // Now check if the constant value fits in the IMMED field.
- //
- return ChooseRegOrImmed((int64_t) valueToUse, val->getType()->isSigned(),
- opCode, target, canUseImmed,
- getMachineRegNum, getImmedValue);
-}
-
-//---------------------------------------------------------------------------
-// Function: FixConstantOperandsForInstr
-//
-// Purpose:
-// Special handling for constant operands of a machine instruction
-// -- if the constant is 0, use the hardwired 0 register, if any;
-// -- if the constant fits in the IMMEDIATE field, use that field;
-// -- else create instructions to put the constant into a register, either
-// directly or by loading explicitly from the constant pool.
-//
-// In the first 2 cases, the operand of `minstr' is modified in place.
-// Returns a vector of machine instructions generated for operands that
-// fall under case 3; these must be inserted before `minstr'.
-//---------------------------------------------------------------------------
-
-std::vector<MachineInstr*>
-FixConstantOperandsForInstr(Instruction* vmInstr,
- MachineInstr* minstr,
- TargetMachine& target)
-{
- std::vector<MachineInstr*> MVec;
-
- MachineOpCode opCode = minstr->getOpcode();
- const TargetInstrInfo& instrInfo = target.getInstrInfo();
- int resultPos = instrInfo.getResultPos(opCode);
- int immedPos = instrInfo.getImmedConstantPos(opCode);
-
- Function *F = vmInstr->getParent()->getParent();
-
- for (unsigned op=0; op < minstr->getNumOperands(); op++)
- {
- const MachineOperand& mop = minstr->getOperand(op);
-
- // Skip the result position, preallocated machine registers, or operands
- // that cannot be constants (CC regs or PC-relative displacements)
- if (resultPos == (int)op ||
- mop.getType() == MachineOperand::MO_MachineRegister ||
- mop.getType() == MachineOperand::MO_CCRegister ||
- mop.getType() == MachineOperand::MO_PCRelativeDisp)
- continue;
-
- bool constantThatMustBeLoaded = false;
- unsigned int machineRegNum = 0;
- int64_t immedValue = 0;
- Value* opValue = NULL;
- MachineOperand::MachineOperandType opType =
- MachineOperand::MO_VirtualRegister;
-
- // Operand may be a virtual register or a compile-time constant
- if (mop.getType() == MachineOperand::MO_VirtualRegister) {
- assert(mop.getVRegValue() != NULL);
- opValue = mop.getVRegValue();
- if (Constant *opConst = dyn_cast<Constant>(opValue)) {
- opType = ChooseRegOrImmed(opConst, opCode, target,
- (immedPos == (int)op), machineRegNum,
- immedValue);
- if (opType == MachineOperand::MO_VirtualRegister)
- constantThatMustBeLoaded = true;
- }
- } else {
- //
- // If the operand is from the constant pool, don't try to change it.
- //
- if (mop.getType() == MachineOperand::MO_ConstantPoolIndex) {
- continue;
- }
- assert(mop.isImmediate());
- bool isSigned = mop.getType() == MachineOperand::MO_SignExtendedImmed;
-
- // Bit-selection flags indicate an instruction that is extracting
- // bits from its operand so ignore this even if it is a big constant.
- if (mop.isHiBits32() || mop.isLoBits32() ||
- mop.isHiBits64() || mop.isLoBits64())
- continue;
-
- opType = ChooseRegOrImmed(mop.getImmedValue(), isSigned,
- opCode, target, (immedPos == (int)op),
- machineRegNum, immedValue);
-
- if (opType == MachineOperand::MO_SignExtendedImmed ||
- opType == MachineOperand::MO_UnextendedImmed) {
- // The optype is an immediate value
- // This means we need to change the opcode, e.g. ADDr -> ADDi
- unsigned newOpcode = convertOpcodeFromRegToImm(opCode);
- minstr->setOpcode(newOpcode);
- }
-
- if (opType == mop.getType())
- continue; // no change: this is the most common case
-
- if (opType == MachineOperand::MO_VirtualRegister) {
- constantThatMustBeLoaded = true;
- opValue = isSigned
- ? (Value*)ConstantSInt::get(Type::LongTy, immedValue)
- : (Value*)ConstantUInt::get(Type::ULongTy,(uint64_t)immedValue);
- }
- }
-
- if (opType == MachineOperand::MO_MachineRegister)
- minstr->SetMachineOperandReg(op, machineRegNum);
- else if (opType == MachineOperand::MO_SignExtendedImmed ||
- opType == MachineOperand::MO_UnextendedImmed) {
- minstr->SetMachineOperandConst(op, opType, immedValue);
- // The optype is or has become an immediate
- // This means we need to change the opcode, e.g. ADDr -> ADDi
- unsigned newOpcode = convertOpcodeFromRegToImm(opCode);
- minstr->setOpcode(newOpcode);
- } else if (constantThatMustBeLoaded ||
- (opValue && isa<GlobalValue>(opValue)))
- { // opValue is a constant that must be explicitly loaded into a reg
- assert(opValue);
- TmpInstruction* tmpReg = InsertCodeToLoadConstant(F, opValue, vmInstr,
- MVec, target);
- minstr->SetMachineOperandVal(op, MachineOperand::MO_VirtualRegister,
- tmpReg);
- }
- }
-
- // Also, check for implicit operands used by the machine instruction
- // (no need to check those defined since they cannot be constants).
- // These include:
- // -- arguments to a Call
- // -- return value of a Return
- // Any such operand that is a constant value needs to be fixed also.
- // The current instructions with implicit refs (viz., Call and Return)
- // have no immediate fields, so the constant always needs to be loaded
- // into a register.
- //
- bool isCall = instrInfo.isCall(opCode);
- unsigned lastCallArgNum = 0; // unused if not a call
- CallArgsDescriptor* argDesc = NULL; // unused if not a call
- if (isCall)
- argDesc = CallArgsDescriptor::get(minstr);
-
- for (unsigned i=0, N=minstr->getNumImplicitRefs(); i < N; ++i)
- if (isa<Constant>(minstr->getImplicitRef(i)) ||
- isa<GlobalValue>(minstr->getImplicitRef(i)))
- {
- Value* oldVal = minstr->getImplicitRef(i);
- TmpInstruction* tmpReg =
- InsertCodeToLoadConstant(F, oldVal, vmInstr, MVec, target);
- minstr->setImplicitRef(i, tmpReg);
-
- if (isCall) {
- // find and replace the argument in the CallArgsDescriptor
- unsigned i=lastCallArgNum;
- while (argDesc->getArgInfo(i).getArgVal() != oldVal)
- ++i;
- assert(i < argDesc->getNumArgs() &&
- "Constant operands to a call *must* be in the arg list");
- lastCallArgNum = i;
- argDesc->getArgInfo(i).replaceArgVal(tmpReg);
- }
- }
-
- return MVec;
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/InstrSelection/Makefile b/llvm/lib/Target/Sparc/InstrSelection/Makefile
deleted file mode 100644
index ac44f3a7241..00000000000
--- a/llvm/lib/Target/Sparc/InstrSelection/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- Target/Sparc/InstrSelection/Makefile ----------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file was developed by the LLVM research group and is distributed under
-# the University of Illinois Open Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../../..
-DIRS =
-LIBRARYNAME = select
-
-include $(LEVEL)/Makefile.common
diff --git a/llvm/lib/Target/Sparc/LiveVar/BBLiveVar.cpp b/llvm/lib/Target/Sparc/LiveVar/BBLiveVar.cpp
deleted file mode 100644
index 9f9aaf5ddef..00000000000
--- a/llvm/lib/Target/Sparc/LiveVar/BBLiveVar.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-//===-- BBLiveVar.cpp - Live Variable Analysis for a BasicBlock -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is a wrapper class for BasicBlock which is used by live var analysis.
-//
-//===----------------------------------------------------------------------===//
-
-#include "BBLiveVar.h"
-#include "FunctionLiveVarInfo.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/Support/CFG.h"
-#include "Support/SetOperations.h"
-#include "../SparcInternals.h"
-
-namespace llvm {
-
-BBLiveVar::BBLiveVar(const BasicBlock &bb,
- const MachineBasicBlock &mbb,
- unsigned id)
- : BB(bb), MBB(mbb), POID(id) {
- InSetChanged = OutSetChanged = false;
-
- calcDefUseSets();
-}
-
-//-----------------------------------------------------------------------------
-// calculates def and use sets for each BB
-// There are two passes over operands of a machine instruction. This is
-// because, we can have instructions like V = V + 1, since we no longer
-// assume single definition.
-//-----------------------------------------------------------------------------
-
-void BBLiveVar::calcDefUseSets() {
- // iterate over all the machine instructions in BB
- for (MachineBasicBlock::const_reverse_iterator MII = MBB.rbegin(),
- MIE = MBB.rend(); MII != MIE; ++MII) {
- const MachineInstr *MI = &*MII;
-
- if (DEBUG_LV >= LV_DEBUG_Verbose) {
- std::cerr << " *Iterating over machine instr ";
- MI->dump();
- std::cerr << "\n";
- }
-
- // iterate over MI operands to find defs
- for (MachineInstr::const_val_op_iterator OpI = MI->begin(), OpE = MI->end();
- OpI != OpE; ++OpI)
- if (OpI.isDef()) // add to Defs if this operand is a def
- addDef(*OpI);
-
- // do for implicit operands as well
- for (unsigned i = 0; i < MI->getNumImplicitRefs(); ++i)
- if (MI->getImplicitOp(i).isDef())
- addDef(MI->getImplicitRef(i));
-
- // iterate over MI operands to find uses
- for (MachineInstr::const_val_op_iterator OpI = MI->begin(), OpE = MI->end();
- OpI != OpE; ++OpI) {
- const Value *Op = *OpI;
-
- if (isa<BasicBlock>(Op))
- continue; // don't process labels
-
- if (OpI.isUse()) { // add to Uses only if this operand is a use
- //
- // *** WARNING: The following code for handling dummy PHI machine
- // instructions is untested. The previous code was broken and I
- // fixed it, but it turned out to be unused as long as Phi
- // elimination is performed during instruction selection.
- //
- // Put Phi operands in UseSet for the incoming edge, not node.
- // They must not "hide" later defs, and must be handled specially
- // during set propagation over the CFG.
- if (MI->getOpcode() == V9::PHI) { // for a phi node
- const Value *ArgVal = Op;
- const BasicBlock *PredBB = cast<BasicBlock>(*++OpI); // next ptr is BB
-
- PredToEdgeInSetMap[PredBB].insert(ArgVal);
-
- if (DEBUG_LV >= LV_DEBUG_Verbose)
- std::cerr << " - phi operand " << RAV(ArgVal) << " came from BB "
- << RAV(PredBB) << "\n";
- } // if( IsPhi )
- else {
- // It is not a Phi use: add to regular use set and remove later defs.
- addUse(Op);
- }
- } // if a use
- } // for all operands
-
- // do for implicit operands as well
- for (unsigned i = 0; i < MI->getNumImplicitRefs(); ++i) {
- assert(MI->getOpcode() != V9::PHI && "Phi cannot have implicit operands");
- const Value *Op = MI->getImplicitRef(i);
-
- if (Op->getType() == Type::LabelTy) // don't process labels
- continue;
-
- if (MI->getImplicitOp(i).isUse())
- addUse(Op);
- }
- } // for all machine instructions
-}
-
-
-
-//-----------------------------------------------------------------------------
-// To add an operand which is a def
-//-----------------------------------------------------------------------------
-void BBLiveVar::addDef(const Value *Op) {
- DefSet.insert(Op); // operand is a def - so add to def set
- InSet.erase(Op); // this definition kills any later uses
- InSetChanged = true;
-
- if (DEBUG_LV >= LV_DEBUG_Verbose) std::cerr << " +Def: " << RAV(Op) << "\n";
-}
-
-
-//-----------------------------------------------------------------------------
-// To add an operand which is a use
-//-----------------------------------------------------------------------------
-void BBLiveVar::addUse(const Value *Op) {
- InSet.insert(Op); // An operand is a use - so add to use set
- DefSet.erase(Op); // remove if there is a def below this use
- InSetChanged = true;
-
- if (DEBUG_LV >= LV_DEBUG_Verbose) std::cerr << " Use: " << RAV(Op) << "\n";
-}
-
-
-//-----------------------------------------------------------------------------
-// Applies the transfer function to a basic block to produce the InSet using
-// the OutSet.
-//-----------------------------------------------------------------------------
-
-bool BBLiveVar::applyTransferFunc() {
- // IMPORTANT: caller should check whether the OutSet changed
- // (else no point in calling)
-
- ValueSet OutMinusDef = set_difference(OutSet, DefSet);
- InSetChanged = set_union(InSet, OutMinusDef);
-
- OutSetChanged = false; // no change to OutSet since transf func applied
- return InSetChanged;
-}
-
-
-//-----------------------------------------------------------------------------
-// calculates Out set using In sets of the successors
-//-----------------------------------------------------------------------------
-
-bool BBLiveVar::setPropagate(ValueSet *OutSet, const ValueSet *InSet,
- const BasicBlock *PredBB) {
- bool Changed = false;
-
- // merge all members of InSet into OutSet of the predecessor
- for (ValueSet::const_iterator InIt = InSet->begin(), InE = InSet->end();
- InIt != InE; ++InIt)
- if ((OutSet->insert(*InIt)).second)
- Changed = true;
-
- //
- //**** WARNING: The following code for handling dummy PHI machine
- // instructions is untested. See explanation above.
- //
- // then merge all members of the EdgeInSet for the predecessor into the OutSet
- const ValueSet& EdgeInSet = PredToEdgeInSetMap[PredBB];
- for (ValueSet::const_iterator InIt = EdgeInSet.begin(), InE = EdgeInSet.end();
- InIt != InE; ++InIt)
- if ((OutSet->insert(*InIt)).second)
- Changed = true;
- //
- //****
-
- return Changed;
-}
-
-
-//-----------------------------------------------------------------------------
-// propagates in set to OutSets of PREDECESSORs
-//-----------------------------------------------------------------------------
-
-bool BBLiveVar::applyFlowFunc(hash_map<const BasicBlock*,
- BBLiveVar*> &BBLiveVarInfo) {
- // IMPORTANT: caller should check whether inset changed
- // (else no point in calling)
-
- // If this BB changed any OutSets of preds whose POID is lower, than we need
- // another iteration...
- //
- bool needAnotherIt = false;
-
- for (pred_const_iterator PI = pred_begin(&BB), PE = pred_end(&BB);
- PI != PE ; ++PI) {
- BBLiveVar *PredLVBB = BBLiveVarInfo[*PI];
-
- // do set union
- if (setPropagate(&PredLVBB->OutSet, &InSet, *PI)) {
- PredLVBB->OutSetChanged = true;
-
- // if the predec POID is lower than mine
- if (PredLVBB->getPOId() <= POID)
- needAnotherIt = true;
- }
- } // for
-
- return needAnotherIt;
-}
-
-
-
-// ----------------- Methods For Debugging (Printing) -----------------
-
-void BBLiveVar::printAllSets() const {
- std::cerr << " Defs: "; printSet(DefSet); std::cerr << "\n";
- std::cerr << " In: "; printSet(InSet); std::cerr << "\n";
- std::cerr << " Out: "; printSet(OutSet); std::cerr << "\n";
-}
-
-void BBLiveVar::printInOutSets() const {
- std::cerr << " In: "; printSet(InSet); std::cerr << "\n";
- std::cerr << " Out: "; printSet(OutSet); std::cerr << "\n";
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/LiveVar/BBLiveVar.h b/llvm/lib/Target/Sparc/LiveVar/BBLiveVar.h
deleted file mode 100644
index 7e5c72e3e46..00000000000
--- a/llvm/lib/Target/Sparc/LiveVar/BBLiveVar.h
+++ /dev/null
@@ -1,90 +0,0 @@
-//===-- BBLiveVar.h - Live Variable Analysis for a BasicBlock ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is a BasicBlock annotation class that is used by live var analysis to
-// hold data flow information for a basic block.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LIVE_VAR_BB_H
-#define LIVE_VAR_BB_H
-
-#include "llvm/CodeGen/ValueSet.h"
-#include "Support/hash_map"
-
-namespace llvm {
-
-class BasicBlock;
-class Value;
-class MachineBasicBlock;
-
-enum LiveVarDebugLevel_t {
- LV_DEBUG_None,
- LV_DEBUG_Normal,
- LV_DEBUG_Instr,
- LV_DEBUG_Verbose
-};
-
-extern LiveVarDebugLevel_t DEBUG_LV;
-
-class BBLiveVar {
- const BasicBlock &BB; // pointer to BasicBlock
- const MachineBasicBlock &MBB; // Pointer to MachineBasicBlock
- unsigned POID; // Post-Order ID
-
- ValueSet DefSet; // Def set (with no preceding uses) for LV analysis
- ValueSet InSet, OutSet; // In & Out for LV analysis
- bool InSetChanged, OutSetChanged; // set if the InSet/OutSet is modified
-
- // map that contains PredBB -> Phi arguments
- // coming in on that edge. such uses have to be
- // treated differently from ordinary uses.
- hash_map<const BasicBlock *, ValueSet> PredToEdgeInSetMap;
-
- // method to propagate an InSet to OutSet of a predecessor
- bool setPropagate(ValueSet *OutSetOfPred,
- const ValueSet *InSetOfThisBB,
- const BasicBlock *PredBB);
-
- // To add an operand which is a def
- void addDef(const Value *Op);
-
- // To add an operand which is a use
- void addUse(const Value *Op);
-
- void calcDefUseSets(); // calculates the Def & Use sets for this BB
-public:
-
- BBLiveVar(const BasicBlock &BB, const MachineBasicBlock &MBB, unsigned POID);
-
- inline bool isInSetChanged() const { return InSetChanged; }
- inline bool isOutSetChanged() const { return OutSetChanged; }
-
- const MachineBasicBlock &getMachineBasicBlock() const { return MBB; }
-
- inline unsigned getPOId() const { return POID; }
-
- bool applyTransferFunc(); // calcultes the In in terms of Out
-
- // calculates Out set using In sets of the predecessors
- bool applyFlowFunc(hash_map<const BasicBlock*, BBLiveVar*> &BBLiveVarInfo);
-
- inline const ValueSet &getOutSet() const { return OutSet; }
- inline ValueSet &getOutSet() { return OutSet; }
-
- inline const ValueSet &getInSet() const { return InSet; }
- inline ValueSet &getInSet() { return InSet; }
-
- void printAllSets() const; // for printing Def/In/Out sets
- void printInOutSets() const; // for printing In/Out sets
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/LiveVar/FunctionLiveVarInfo.cpp b/llvm/lib/Target/Sparc/LiveVar/FunctionLiveVarInfo.cpp
deleted file mode 100644
index 9d5492371a7..00000000000
--- a/llvm/lib/Target/Sparc/LiveVar/FunctionLiveVarInfo.cpp
+++ /dev/null
@@ -1,322 +0,0 @@
-//===-- FunctionLiveVarInfo.cpp - Live Variable Analysis for a Function ---===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is the interface to function level live variable information that is
-// provided by live variable analysis.
-//
-//===----------------------------------------------------------------------===//
-
-#include "FunctionLiveVarInfo.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Support/CFG.h"
-#include "Support/PostOrderIterator.h"
-#include "Support/SetOperations.h"
-#include "Support/CommandLine.h"
-#include "BBLiveVar.h"
-
-namespace llvm {
-
-static RegisterAnalysis<FunctionLiveVarInfo>
-X("livevar", "Live Variable Analysis");
-
-LiveVarDebugLevel_t DEBUG_LV;
-
-static cl::opt<LiveVarDebugLevel_t, true>
-DEBUG_LV_opt("dlivevar", cl::Hidden, cl::location(DEBUG_LV),
- cl::desc("enable live-variable debugging information"),
- cl::values(
-clEnumValN(LV_DEBUG_None , "n", "disable debug output"),
-clEnumValN(LV_DEBUG_Normal , "y", "enable debug output"),
-clEnumValN(LV_DEBUG_Instr, "i", "print live-var sets before/after "
- "every machine instrn"),
-clEnumValN(LV_DEBUG_Verbose, "v", "print def, use sets for every instrn also"),
- 0));
-
-
-
-//-----------------------------------------------------------------------------
-// Accessor Functions
-//-----------------------------------------------------------------------------
-
-// gets OutSet of a BB
-const ValueSet &FunctionLiveVarInfo::getOutSetOfBB(const BasicBlock *BB) const {
- return BBLiveVarInfo.find(BB)->second->getOutSet();
-}
- ValueSet &FunctionLiveVarInfo::getOutSetOfBB(const BasicBlock *BB) {
- return BBLiveVarInfo[BB]->getOutSet();
-}
-
-// gets InSet of a BB
-const ValueSet &FunctionLiveVarInfo::getInSetOfBB(const BasicBlock *BB) const {
- return BBLiveVarInfo.find(BB)->second->getInSet();
-}
-ValueSet &FunctionLiveVarInfo::getInSetOfBB(const BasicBlock *BB) {
- return BBLiveVarInfo[BB]->getInSet();
-}
-
-
-//-----------------------------------------------------------------------------
-// Performs live var analysis for a function
-//-----------------------------------------------------------------------------
-
-bool FunctionLiveVarInfo::runOnFunction(Function &F) {
- M = &F;
- if (DEBUG_LV) std::cerr << "Analysing live variables ...\n";
-
- // create and initialize all the BBLiveVars of the CFG
- constructBBs(M);
-
- unsigned int iter=0;
- while (doSingleBackwardPass(M, iter++))
- ; // Iterate until we are done.
-
- if (DEBUG_LV) std::cerr << "Live Variable Analysis complete!\n";
- return false;
-}
-
-
-//-----------------------------------------------------------------------------
-// constructs BBLiveVars and init Def and In sets
-//-----------------------------------------------------------------------------
-
-void FunctionLiveVarInfo::constructBBs(const Function *F) {
- unsigned POId = 0; // Reverse Depth-first Order ID
- std::map<const BasicBlock*, unsigned> PONumbering;
-
- for (po_iterator<const Function*> BBI = po_begin(M), BBE = po_end(M);
- BBI != BBE; ++BBI)
- PONumbering[*BBI] = POId++;
-
- MachineFunction &MF = MachineFunction::get(F);
- for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
- const BasicBlock &BB = *I->getBasicBlock(); // get the current BB
- if (DEBUG_LV) std::cerr << " For BB " << RAV(BB) << ":\n";
-
- BBLiveVar *LVBB;
- std::map<const BasicBlock*, unsigned>::iterator POI = PONumbering.find(&BB);
- if (POI != PONumbering.end()) {
- // create a new BBLiveVar
- LVBB = new BBLiveVar(BB, *I, POId);
- } else {
- // The PO iterator does not discover unreachable blocks, but the random
- // iterator later may access these blocks. We must make sure to
- // initialize unreachable blocks as well. However, LV info is not correct
- // for those blocks (they are not analyzed)
- //
- LVBB = new BBLiveVar(BB, *I, ++POId);
- }
- BBLiveVarInfo[&BB] = LVBB;
-
- if (DEBUG_LV)
- LVBB->printAllSets();
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// do one backward pass over the CFG (for iterative analysis)
-//-----------------------------------------------------------------------------
-
-bool FunctionLiveVarInfo::doSingleBackwardPass(const Function *M,
- unsigned iter) {
- if (DEBUG_LV) std::cerr << "\n After Backward Pass " << iter << "...\n";
-
- bool NeedAnotherIteration = false;
- for (po_iterator<const Function*> BBI = po_begin(M), BBE = po_end(M);
- BBI != BBE; ++BBI) {
- BBLiveVar *LVBB = BBLiveVarInfo[*BBI];
- assert(LVBB && "BasicBlock information not set for block!");
-
- if (DEBUG_LV) std::cerr << " For BB " << (*BBI)->getName() << ":\n";
-
- // InSets are initialized to "GenSet". Recompute only if OutSet changed.
- if(LVBB->isOutSetChanged())
- LVBB->applyTransferFunc(); // apply the Tran Func to calc InSet
-
- // OutSets are initialized to EMPTY. Recompute on first iter or if InSet
- // changed.
- if (iter == 0 || LVBB->isInSetChanged()) // to calc Outsets of preds
- NeedAnotherIteration |= LVBB->applyFlowFunc(BBLiveVarInfo);
-
- if (DEBUG_LV) LVBB->printInOutSets();
- }
-
- // true if we need to reiterate over the CFG
- return NeedAnotherIteration;
-}
-
-
-void FunctionLiveVarInfo::releaseMemory() {
- // First remove all BBLiveVars created in constructBBs().
- if (M) {
- for (Function::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
- delete BBLiveVarInfo[I];
- BBLiveVarInfo.clear();
- }
- M = 0;
-
- // Then delete all objects of type ValueSet created in calcLiveVarSetsForBB
- // and entered into MInst2LVSetBI and MInst2LVSetAI (these are caches
- // to return ValueSet's before/after a machine instruction quickly).
- // We do not need to free up ValueSets in MInst2LVSetAI because it holds
- // pointers to the same sets as in MInst2LVSetBI (for all instructions
- // except the last one in a BB) or in BBLiveVar (for the last instruction).
- //
- for (hash_map<const MachineInstr*, ValueSet*>::iterator
- MI = MInst2LVSetBI.begin(),
- ME = MInst2LVSetBI.end(); MI != ME; ++MI)
- delete MI->second; // delete all ValueSets in MInst2LVSetBI
-
- MInst2LVSetBI.clear();
- MInst2LVSetAI.clear();
-}
-
-
-
-
-//-----------------------------------------------------------------------------
-// Following functions will give the LiveVar info for any machine instr in
-// a function. It should be called after a call to analyze().
-//
-// These functions calculate live var info for all the machine instrs in a
-// BB when LVInfo for one inst is requested. Hence, this function is useful
-// when live var info is required for many (or all) instructions in a basic
-// block. Also, the arguments to this function does not require specific
-// iterators.
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// Gives live variable information before a machine instruction
-//-----------------------------------------------------------------------------
-
-const ValueSet &
-FunctionLiveVarInfo::getLiveVarSetBeforeMInst(const MachineInstr *MI,
- const BasicBlock *BB) {
- ValueSet* &LVSet = MInst2LVSetBI[MI]; // ref. to map entry
- if (LVSet == NULL && BB != NULL) { // if not found and BB provided
- calcLiveVarSetsForBB(BB); // calc LVSet for all instrs in BB
- assert(LVSet != NULL);
- }
- return *LVSet;
-}
-
-
-//-----------------------------------------------------------------------------
-// Gives live variable information after a machine instruction
-//-----------------------------------------------------------------------------
-
-const ValueSet &
-FunctionLiveVarInfo::getLiveVarSetAfterMInst(const MachineInstr *MI,
- const BasicBlock *BB) {
-
- ValueSet* &LVSet = MInst2LVSetAI[MI]; // ref. to map entry
- if (LVSet == NULL && BB != NULL) { // if not found and BB provided
- calcLiveVarSetsForBB(BB); // calc LVSet for all instrs in BB
- assert(LVSet != NULL);
- }
- return *LVSet;
-}
-
-// This function applies a machine instr to a live var set (accepts OutSet) and
-// makes necessary changes to it (produces InSet). Note that two for loops are
-// used to first kill all defs and then to add all uses. This is because there
-// can be instructions like Val = Val + 1 since we allow multiple defs to a
-// machine instruction operand.
-//
-static void applyTranferFuncForMInst(ValueSet &LVS, const MachineInstr *MInst) {
- for (MachineInstr::const_val_op_iterator OpI = MInst->begin(),
- OpE = MInst->end(); OpI != OpE; ++OpI) {
- if (OpI.isDef()) // kill if this operand is a def
- LVS.erase(*OpI); // this definition kills any uses
- }
-
- // do for implicit operands as well
- for (unsigned i=0; i < MInst->getNumImplicitRefs(); ++i) {
- if (MInst->getImplicitOp(i).isDef())
- LVS.erase(MInst->getImplicitRef(i));
- }
-
- for (MachineInstr::const_val_op_iterator OpI = MInst->begin(),
- OpE = MInst->end(); OpI != OpE; ++OpI) {
- if (!isa<BasicBlock>(*OpI)) // don't process labels
- // add only if this operand is a use
- if (OpI.isUse())
- LVS.insert(*OpI); // An operand is a use - so add to use set
- }
-
- // do for implicit operands as well
- for (unsigned i = 0, e = MInst->getNumImplicitRefs(); i != e; ++i)
- if (MInst->getImplicitOp(i).isUse())
- LVS.insert(MInst->getImplicitRef(i));
-}
-
-//-----------------------------------------------------------------------------
-// This method calculates the live variable information for all the
-// instructions in a basic block and enter the newly constructed live
-// variable sets into a the caches (MInst2LVSetAI, MInst2LVSetBI)
-//-----------------------------------------------------------------------------
-
-void FunctionLiveVarInfo::calcLiveVarSetsForBB(const BasicBlock *BB) {
- BBLiveVar *BBLV = BBLiveVarInfo[BB];
- assert(BBLV && "BBLiveVar annotation doesn't exist?");
- const MachineBasicBlock &MIVec = BBLV->getMachineBasicBlock();
- const MachineFunction &MF = MachineFunction::get(M);
- const TargetMachine &TM = MF.getTarget();
-
- if (DEBUG_LV >= LV_DEBUG_Instr)
- std::cerr << "\n======For BB " << BB->getName()
- << ": Live var sets for instructions======\n";
-
- ValueSet *SetAI = &getOutSetOfBB(BB); // init SetAI with OutSet
- ValueSet CurSet(*SetAI); // CurSet now contains OutSet
-
- // iterate over all the machine instructions in BB
- for (MachineBasicBlock::const_reverse_iterator MII = MIVec.rbegin(),
- MIE = MIVec.rend(); MII != MIE; ++MII) {
- // MI is cur machine inst
- const MachineInstr *MI = &*MII;
-
- MInst2LVSetAI[MI] = SetAI; // record in After Inst map
-
- applyTranferFuncForMInst(CurSet, MI); // apply the transfer Func
- ValueSet *NewSet = new ValueSet(CurSet); // create a new set with a copy
- // of the set after T/F
- MInst2LVSetBI[MI] = NewSet; // record in Before Inst map
-
- // If the current machine instruction has delay slots, mark values
- // used by this instruction as live before and after each delay slot
- // instruction (After(MI) is the same as Before(MI+1) except for last MI).
- if (unsigned DS = TM.getInstrInfo().getNumDelaySlots(MI->getOpcode())) {
- MachineBasicBlock::const_iterator fwdMII = MII.base(); // ptr to *next* MI
- for (unsigned i = 0; i < DS; ++i, ++fwdMII) {
- assert(fwdMII != MIVec.end() && "Missing instruction in delay slot?");
- const MachineInstr* DelaySlotMI = fwdMII;
- if (! TM.getInstrInfo().isNop(DelaySlotMI->getOpcode())) {
- set_union(*MInst2LVSetBI[DelaySlotMI], *NewSet);
- if (i+1 == DS)
- set_union(*MInst2LVSetAI[DelaySlotMI], *NewSet);
- }
- }
- }
-
- if (DEBUG_LV >= LV_DEBUG_Instr) {
- std::cerr << "\nLive var sets before/after instruction " << *MI;
- std::cerr << " Before: "; printSet(*NewSet); std::cerr << "\n";
- std::cerr << " After : "; printSet(*SetAI); std::cerr << "\n";
- }
-
- // SetAI will be used in the next iteration
- SetAI = NewSet;
- }
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/LiveVar/FunctionLiveVarInfo.h b/llvm/lib/Target/Sparc/LiveVar/FunctionLiveVarInfo.h
deleted file mode 100644
index 23a9d93a6eb..00000000000
--- a/llvm/lib/Target/Sparc/LiveVar/FunctionLiveVarInfo.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//===-- CodeGen/FunctionLiveVarInfo.h - LiveVar Analysis --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is the interface for live variable info of a function that is required
-// by any other part of the compiler
-//
-// After the analysis, getInSetOfBB or getOutSetofBB can be called to get
-// live var info of a BB.
-//
-// The live var set before an instruction can be obtained in 2 ways:
-//
-// 1. Use the method getLiveVarSetAfterInst(Instruction *) to get the LV Info
-// just after an instruction. (also exists getLiveVarSetBeforeInst(..))
-//
-// This function caluclates the LV info for a BB only once and caches that
-// info. If the cache does not contain the LV info of the instruction, it
-// calculates the LV info for the whole BB and caches them.
-//
-// Getting liveVar info this way uses more memory since, LV info should be
-// cached. However, if you need LV info of nearly all the instructions of a
-// BB, this is the best and simplest interfrace.
-//
-// 2. Use the OutSet and applyTranferFuncForInst(const Instruction *const Inst)
-// declared in LiveVarSet and traverse the instructions of a basic block in
-// reverse (using const_reverse_iterator in the BB class).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef FUNCTION_LIVE_VAR_INFO_H
-#define FUNCTION_LIVE_VAR_INFO_H
-
-#include "Support/hash_map"
-#include "llvm/Pass.h"
-#include "llvm/CodeGen/ValueSet.h"
-
-namespace llvm {
-
-class BBLiveVar;
-class MachineInstr;
-
-class FunctionLiveVarInfo : public FunctionPass {
- // Machine Instr to LiveVarSet Map for providing LVset BEFORE each inst
- // These sets are owned by this map and will be freed in releaseMemory().
- hash_map<const MachineInstr *, ValueSet *> MInst2LVSetBI;
-
- // Machine Instr to LiveVarSet Map for providing LVset AFTER each inst.
- // These sets are just pointers to sets in MInst2LVSetBI or BBLiveVar.
- hash_map<const MachineInstr *, ValueSet *> MInst2LVSetAI;
-
- hash_map<const BasicBlock*, BBLiveVar*> BBLiveVarInfo;
-
- // Stored Function that the data is computed with respect to
- const Function *M;
-
- // --------- private methods -----------------------------------------
-
- // constructs BBLiveVars and init Def and In sets
- void constructBBs(const Function *F);
-
- // do one backward pass over the CFG
- bool doSingleBackwardPass(const Function *F, unsigned int iter);
-
- // calculates live var sets for instructions in a BB
- void calcLiveVarSetsForBB(const BasicBlock *BB);
-
-public:
- // --------- Implement the FunctionPass interface ----------------------
-
- // runOnFunction - Perform analysis, update internal data structures.
- virtual bool runOnFunction(Function &F);
-
- // releaseMemory - After LiveVariable analysis has been used, forget!
- virtual void releaseMemory();
-
- // getAnalysisUsage - Provide self!
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- }
-
- // --------- Functions to access analysis results -------------------
-
- // get OutSet of a BB
- const ValueSet &getOutSetOfBB(const BasicBlock *BB) const;
- ValueSet &getOutSetOfBB(const BasicBlock *BB) ;
-
- // get InSet of a BB
- const ValueSet &getInSetOfBB(const BasicBlock *BB) const;
- ValueSet &getInSetOfBB(const BasicBlock *BB) ;
-
- // gets the Live var set BEFORE an instruction.
- // if BB is specified and the live var set has not yet been computed,
- // it will be computed on demand.
- const ValueSet &getLiveVarSetBeforeMInst(const MachineInstr *MI,
- const BasicBlock *BB = 0);
-
- // gets the Live var set AFTER an instruction
- // if BB is specified and the live var set has not yet been computed,
- // it will be computed on demand.
- const ValueSet &getLiveVarSetAfterMInst(const MachineInstr *MI,
- const BasicBlock *BB = 0);
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/LiveVar/Makefile b/llvm/lib/Target/Sparc/LiveVar/Makefile
deleted file mode 100644
index 90a664e56ce..00000000000
--- a/llvm/lib/Target/Sparc/LiveVar/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- lib/Target/Sparc/LiveVar/Makefile -------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file was developed by the LLVM research group and is distributed under
-# the University of Illinois Open Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../../..
-LIBRARYNAME = livevar
-
-include $(LEVEL)/Makefile.common
-
diff --git a/llvm/lib/Target/Sparc/LiveVar/ValueSet.cpp b/llvm/lib/Target/Sparc/LiveVar/ValueSet.cpp
deleted file mode 100644
index fd8289675a2..00000000000
--- a/llvm/lib/Target/Sparc/LiveVar/ValueSet.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-// FIXME: Eliminate this file.
-
-#include "llvm/CodeGen/ValueSet.h"
-#include "llvm/Value.h"
-#include <iostream>
-
-namespace llvm {
-
-std::ostream &operator<<(std::ostream &O, RAV V) { // func to print a Value
- const Value &v = V.V;
- if (v.hasName())
- return O << (void*)&v << "(" << v.getName() << ") ";
- else if (isa<Constant>(v))
- return O << (void*)&v << "(" << v << ") ";
- else
- return O << (void*)&v << " ";
-}
-
-void printSet(const ValueSet &S) {
- for (ValueSet::const_iterator I = S.begin(), E = S.end(); I != E; ++I)
- std::cerr << RAV(*I);
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/Makefile b/llvm/lib/Target/Sparc/Makefile
deleted file mode 100644
index 619c9d02e7c..00000000000
--- a/llvm/lib/Target/Sparc/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
-##===- lib/Target/Sparc/Makefile ---------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file was developed by the LLVM research group and is distributed under
-# the University of Illinois Open Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-LEVEL = ../../..
-LIBRARYNAME = sparc
-DIRS = InstrSelection RegAlloc LiveVar
-
-ExtraSource = Sparc.burm.cpp
-
-include $(LEVEL)/Makefile.common
-
-ifdef ENABLE_OPTIMIZED
- DEBUG_FLAG =
-else
- DEBUG_FLAG = -D_DEBUG
-endif
-
-Sparc.burg.in1 : $(SourceDir)/Sparc.burg.in
- $(CXX) -E -I$(LLVM_SRC_ROOT)/include $(DEBUG_FLAG) -x c++ $< | $(SED) '/^#/d' | $(SED) 's/Ydefine/#define/' > $@
-
-Sparc.burm : Sparc.burg.in1
- $(CXX) -E -I$(LLVM_SRC_ROOT)/include $(DEBUG_FLAG) -x c++ $< | $(SED) '/^#/d' | $(SED) 's/^Xinclude/#include/' | $(SED) 's/^Xdefine/#define/' > $@
-
-Sparc.burm.cpp: Sparc.burm
- @echo "Burging `basename $<`"
- $(RunBurg) $< -o $@
-
-$(BUILD_OBJ_DIR)/Debug/Sparc.burm.lo: Sparc.burm.cpp
- $(CompileG) $< -o $@
-
-$(BUILD_OBJ_DIR)/Release/Sparc.burm.lo: Sparc.burm.cpp
- $(CompileO) $< -o $@
-
-$(BUILD_OBJ_DIR)/Profile/Sparc.burm.lo: Sparc.burm.cpp
- $(CompileP) $< -o $@
-
-$(BUILD_OBJ_DIR)/Depend/Sparc.burm.d: $(BUILD_OBJ_DIR)/Depend/.dir
- touch $@
-
-TARGET_NAME := SparcV9
-
-TABLEGEN_FILES := $(notdir $(wildcard $(SourceDir)/*.td))
-
-# Make sure that tblgen is run, first thing.
-$(SourceDepend): $(TARGET_NAME)CodeEmitter.inc
-
-$(TARGET_NAME)CodeEmitter.cpp:: $(TARGET_NAME)CodeEmitter.inc
-
-$(TARGET_NAME)CodeEmitter.inc:: $(SourceDir)/$(TARGET_NAME).td $(TABLEGEN_FILES) $(TBLGEN)
- @echo "Tblgen'ing `basename $<`"
- $(TBLGEN) -I $(SourceDir) $< -gen-emitter -o $@
-
-clean::
- $(RM) -f $(TARGET_NAME)CodeEmitter.inc Sparc.burg.in1 Sparc.burm Sparc.burm.cpp
-
diff --git a/llvm/lib/Target/Sparc/MappingInfo.cpp b/llvm/lib/Target/Sparc/MappingInfo.cpp
deleted file mode 100644
index 4648c54e48e..00000000000
--- a/llvm/lib/Target/Sparc/MappingInfo.cpp
+++ /dev/null
@@ -1,299 +0,0 @@
-//===- MappingInfo.cpp - create LLVM info and output to .s file ---------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains a FunctionPass called MappingInfoAsmPrinter,
-// which creates two maps: one between LLVM Instructions and MachineInstrs
-// (the "LLVM I TO MI MAP"), and another between MachineBasicBlocks and
-// MachineInstrs (the "BB TO MI MAP").
-//
-// As a side effect, it outputs this information as .byte directives to
-// the assembly file. The output is designed to survive the SPARC assembler,
-// in order that the Reoptimizer may read it in from memory later when the
-// binary is loaded. Therefore, it may contain some hidden SPARC-architecture
-// dependencies. Currently this question is purely theoretical as the
-// Reoptimizer works only on the SPARC.
-//
-// The LLVM I TO MI MAP consists of a set of information for each
-// BasicBlock in a Function, ordered from begin() to end(). The information
-// for a BasicBlock consists of
-// 1) its (0-based) index in the Function,
-// 2) the number of LLVM Instructions it contains, and
-// 3) information for each Instruction, in sequence from the begin()
-// to the end() of the BasicBlock. The information for an Instruction
-// consists of
-// 1) its (0-based) index in the BasicBlock,
-// 2) the number of MachineInstrs that correspond to that Instruction
-// (as reported by MachineCodeForInstruction), and
-// 3) the MachineInstr number calculated by create_MI_to_number_Key,
-// for each of the MachineInstrs that correspond to that Instruction.
-//
-// The BB TO MI MAP consists of a three-element tuple for each
-// MachineBasicBlock in a function, ordered from begin() to end() of
-// its MachineFunction: first, the index of the MachineBasicBlock in the
-// function; second, the number of the MachineBasicBlock in the function
-// as computed by create_BB_to_MInumber_Key; and third, the number of
-// MachineInstrs in the MachineBasicBlock.
-//
-//===--------------------------------------------------------------------===//
-
-#include "MappingInfo.h"
-#include "llvm/Pass.h"
-#include "llvm/Module.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "Support/StringExtras.h"
-
-namespace llvm {
-
-namespace {
- class MappingInfoAsmPrinter : public FunctionPass {
- std::ostream &Out;
- public:
- MappingInfoAsmPrinter(std::ostream &out) : Out(out){}
- const char *getPassName () const { return "Instr. Mapping Info Collector"; }
- bool runOnFunction(Function &FI);
- typedef std::map<const MachineInstr*, unsigned> InstructionKey;
- private:
- MappingInfo *currentOutputMap;
- std::map<Function *, unsigned> Fkey; // Function # for all functions.
- bool doInitialization(Module &M);
- void create_BB_to_MInumber_Key(Function &FI, InstructionKey &key);
- void create_MI_to_number_Key(Function &FI, InstructionKey &key);
- void buildBBMIMap (Function &FI, MappingInfo &Map);
- void buildLMIMap (Function &FI, MappingInfo &Map);
- void writeNumber(unsigned X);
- void selectOutputMap (MappingInfo &m) { currentOutputMap = &m; }
- void outByte (unsigned char b) { currentOutputMap->outByte (b); }
- bool doFinalization (Module &M);
- };
-}
-
-/// getMappingInfoAsmPrinterPass - Static factory method: returns a new
-/// MappingInfoAsmPrinter Pass object, which uses OUT as its output
-/// stream for assembly output.
-///
-Pass *getMappingInfoAsmPrinterPass(std::ostream &out){
- return (new MappingInfoAsmPrinter(out));
-}
-
-/// runOnFunction - Builds up the maps for the given function FI and then
-/// writes them out as assembly code to the current output stream OUT.
-/// This is an entry point to the pass, called by the PassManager.
-///
-bool MappingInfoAsmPrinter::runOnFunction(Function &FI) {
- unsigned num = Fkey[&FI]; // Function number for the current function.
-
- // Create objects to hold the maps.
- MappingInfo LMIMap ("LLVM I TO MI MAP", "LMIMap", num);
- MappingInfo BBMIMap ("BB TO MI MAP", "BBMIMap", num);
-
- // Now, build the maps.
- buildLMIMap (FI, LMIMap);
- buildBBMIMap (FI, BBMIMap);
-
- // Now, write out the maps.
- LMIMap.dumpAssembly (Out);
- BBMIMap.dumpAssembly (Out);
-
- return false;
-}
-
-/// writeNumber - Write out the number X as a sequence of .byte
-/// directives to the current output stream Out. This method performs a
-/// run-length encoding of the unsigned integers X that are output.
-///
-void MappingInfoAsmPrinter::writeNumber(unsigned X) {
- unsigned i=0;
- do {
- unsigned tmp = X & 127;
- X >>= 7;
- if (X) tmp |= 128;
- outByte (tmp);
- ++i;
- } while(X);
-}
-
-/// doInitialization - Assign a number to each Function, as follows:
-/// Functions are numbered starting at 0 at the begin() of each Module.
-/// Functions which are External (and thus have 0 basic blocks) are not
-/// inserted into the maps, and are not assigned a number. The side-effect
-/// of this method is to fill in Fkey to contain the mapping from Functions
-/// to numbers. (This method is called automatically by the PassManager.)
-///
-bool MappingInfoAsmPrinter::doInitialization(Module &M) {
- unsigned i = 0;
- for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) {
- if (FI->isExternal()) continue;
- Fkey[FI] = i;
- ++i;
- }
- return false; // Success.
-}
-
-/// create_BB_to_MInumber_Key -- Assign a number to each MachineBasicBlock
-/// in the given Function, as follows: Numbering starts at zero in each
-/// Function. MachineBasicBlocks are numbered from begin() to end()
-/// in the Function's corresponding MachineFunction. Each successive
-/// MachineBasicBlock increments the numbering by the number of instructions
-/// it contains. The side-effect of this method is to fill in the parameter
-/// KEY with the mapping of MachineBasicBlocks to numbers. KEY
-/// is keyed on MachineInstrs, so each MachineBasicBlock is represented
-/// therein by its first MachineInstr.
-///
-void MappingInfoAsmPrinter::create_BB_to_MInumber_Key(Function &FI,
- InstructionKey &key) {
- unsigned i = 0;
- MachineFunction &MF = MachineFunction::get(&FI);
- for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
- BI != BE; ++BI) {
- MachineBasicBlock &miBB = *BI;
- key[&miBB.front()] = i;
- i = i+(miBB.size());
- }
-}
-
-/// create_MI_to_number_Key - Assign a number to each MachineInstr
-/// in the given Function with respect to its enclosing MachineBasicBlock, as
-/// follows: Numberings start at 0 in each MachineBasicBlock. MachineInstrs
-/// are numbered from begin() to end() in their MachineBasicBlock. Each
-/// MachineInstr is numbered, then the numbering is incremented by 1. The
-/// side-effect of this method is to fill in the parameter KEY
-/// with the mapping from MachineInstrs to numbers.
-///
-void MappingInfoAsmPrinter::create_MI_to_number_Key(Function &FI,
- InstructionKey &key) {
- MachineFunction &MF = MachineFunction::get(&FI);
- for (MachineFunction::iterator BI=MF.begin(), BE=MF.end(); BI != BE; ++BI) {
- MachineBasicBlock &miBB = *BI;
- unsigned j = 0;
- for(MachineBasicBlock::iterator miI = miBB.begin(), miE = miBB.end();
- miI != miE; ++miI, ++j) {
- key[miI] = j;
- }
- }
-}
-
-/// buildBBMIMap - Build the BB TO MI MAP for the function FI,
-/// and save it into the parameter MAP.
-///
-void MappingInfoAsmPrinter::buildBBMIMap(Function &FI, MappingInfo &Map) {
- unsigned bb = 0;
-
- // First build temporary table used to write out the map.
- InstructionKey BBkey;
- create_BB_to_MInumber_Key(FI, BBkey);
-
- selectOutputMap (Map);
- MachineFunction &MF = MachineFunction::get(&FI);
- for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
- BI != BE; ++BI, ++bb) {
- MachineBasicBlock &miBB = *BI;
- writeNumber(bb);
- writeNumber(BBkey[&miBB.front()]);
- writeNumber(miBB.size());
- }
-}
-
-/// buildLMIMap - Build the LLVM I TO MI MAP for the function FI,
-/// and save it into the parameter MAP.
-///
-void MappingInfoAsmPrinter::buildLMIMap(Function &FI, MappingInfo &Map) {
- unsigned bb = 0;
- // First build temporary table used to write out the map.
- InstructionKey MIkey;
- create_MI_to_number_Key(FI, MIkey);
-
- selectOutputMap (Map);
- for (Function::iterator BI = FI.begin(), BE = FI.end();
- BI != BE; ++BI, ++bb) {
- unsigned li = 0;
- writeNumber(bb);
- writeNumber(BI->size());
- for (BasicBlock::iterator II = BI->begin(), IE = BI->end(); II != IE;
- ++II, ++li) {
- MachineCodeForInstruction& miI = MachineCodeForInstruction::get(II);
- writeNumber(li);
- writeNumber(miI.size());
- for (MachineCodeForInstruction::iterator miII = miI.begin(),
- miIE = miI.end(); miII != miIE; ++miII) {
- writeNumber(MIkey[*miII]);
- }
- }
- }
-}
-
-void MappingInfo::byteVector::dumpAssembly (std::ostream &Out) {
- for (iterator i = begin (), e = end (); i != e; ++i)
- Out << ".byte " << (int)*i << "\n";
-}
-
-static void writePrologue (std::ostream &Out, const std::string &comment,
- const std::string &symName) {
- // Prologue:
- // Output a comment describing the object.
- Out << "!" << comment << "\n";
- // Switch the current section to .rodata in the assembly output:
- Out << "\t.section \".rodata\"\n\t.align 8\n";
- // Output a global symbol naming the object:
- Out << "\t.global " << symName << "\n";
- Out << "\t.type " << symName << ",#object\n";
- Out << symName << ":\n";
-}
-
-static void writeEpilogue (std::ostream &Out, const std::string &symName) {
- // Epilogue:
- // Output a local symbol marking the end of the object:
- Out << ".end_" << symName << ":\n";
- // Output size directive giving the size of the object:
- Out << "\t.size " << symName << ", .end_" << symName << "-" << symName
- << "\n";
-}
-
-void MappingInfo::dumpAssembly (std::ostream &Out) {
- const std::string &name (symbolPrefix + utostr (functionNumber));
- writePrologue (Out, comment, name);
- // The LMIMap and BBMIMap are supposed to start with a length word:
- Out << "\t.word .end_" << name << "-" << name << "\n";
- bytes.dumpAssembly (Out);
- writeEpilogue (Out, name);
-}
-
-/// doFinalization - This method writes out two tables, named
-/// FunctionBB and FunctionLI, which map Function numbers (as in
-/// doInitialization) to the BBMIMap and LMIMap tables. (This used to
-/// be the "FunctionInfo" pass.)
-///
-bool MappingInfoAsmPrinter::doFinalization (Module &M) {
- unsigned f;
-
- writePrologue(Out, "FUNCTION TO BB MAP", "FunctionBB");
- f=0;
- for(Module::iterator FI = M.begin (), FE = M.end (); FE != FI; ++FI) {
- if (FI->isExternal ())
- continue;
- Out << "\t.xword BBMIMap" << f << "\n";
- ++f;
- }
- writeEpilogue(Out, "FunctionBB");
-
- writePrologue(Out, "FUNCTION TO LI MAP", "FunctionLI");
- f=0;
- for(Module::iterator FI = M.begin (), FE = M.end (); FE != FI; ++FI) {
- if (FI->isExternal ())
- continue;
- Out << "\t.xword LMIMap" << f << "\n";
- ++f;
- }
- writeEpilogue(Out, "FunctionLI");
-
- return false;
-}
-
-} // End llvm namespace
-
diff --git a/llvm/lib/Target/Sparc/MappingInfo.h b/llvm/lib/Target/Sparc/MappingInfo.h
deleted file mode 100644
index 6af116a6da2..00000000000
--- a/llvm/lib/Target/Sparc/MappingInfo.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===- lib/Target/Sparc/MappingInfo.h ---------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Data structures to support the Reoptimizer's Instruction-to-MachineInstr
-// mapping information gatherer.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MAPPINGINFO_H
-#define MAPPINGINFO_H
-
-#include <iosfwd>
-#include <vector>
-#include <string>
-
-namespace llvm {
-
-class Pass;
-
-Pass *getMappingInfoAsmPrinterPass(std::ostream &out);
-
-class MappingInfo {
- struct byteVector : public std::vector <unsigned char> {
- void dumpAssembly (std::ostream &Out);
- };
- std::string comment;
- std::string symbolPrefix;
- unsigned functionNumber;
- byteVector bytes;
-public:
- void outByte (unsigned char b) { bytes.push_back (b); }
- MappingInfo (std::string Comment, std::string SymbolPrefix,
- unsigned FunctionNumber) : comment(Comment),
- symbolPrefix(SymbolPrefix), functionNumber(FunctionNumber) {}
- void dumpAssembly (std::ostream &Out);
- unsigned char *getBytes (unsigned &length) {
- length = bytes.size(); return &bytes[0];
- }
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/PeepholeOpts.cpp b/llvm/lib/Target/Sparc/PeepholeOpts.cpp
deleted file mode 100644
index dc56100a1eb..00000000000
--- a/llvm/lib/Target/Sparc/PeepholeOpts.cpp
+++ /dev/null
@@ -1,163 +0,0 @@
-//===-- PeepholeOpts.cpp --------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Support for performing several peephole opts in one or a few passes over the
-// machine code of a method.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcInternals.h"
-#include "llvm/BasicBlock.h"
-#include "llvm/Pass.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "Support/STLExtras.h"
-
-namespace llvm {
-
-//************************* Internal Functions *****************************/
-
-static inline void
-DeleteInstruction(MachineBasicBlock& mvec,
- MachineBasicBlock::iterator& BBI,
- const TargetMachine& target) {
- // Check if this instruction is in a delay slot of its predecessor.
- if (BBI != mvec.begin()) {
- const TargetInstrInfo& mii = target.getInstrInfo();
- MachineBasicBlock::iterator predMI = prior(BBI);
- if (unsigned ndelay = mii.getNumDelaySlots(predMI->getOpcode())) {
- // This instruction is in a delay slot of its predecessor, so
- // replace it with a nop. By replacing in place, we save having
- // to update the I-I maps.
- //
- assert(ndelay == 1 && "Not yet handling multiple-delay-slot targets");
- BBI->replace(mii.getNOPOpCode(), 0);
- return;
- }
- }
-
- // The instruction is not in a delay slot, so we can simply erase it.
- mvec.erase(BBI);
- BBI = mvec.end();
-}
-
-//******************* Individual Peephole Optimizations ********************/
-
-//----------------------------------------------------------------------------
-// Function: IsUselessCopy
-// Decide whether a machine instruction is a redundant copy:
-// -- ADD with g0 and result and operand are identical, or
-// -- OR with g0 and result and operand are identical, or
-// -- FMOVS or FMOVD and result and operand are identical.
-// Other cases are possible but very rare that they would be useless copies,
-// so it's not worth analyzing them.
-//----------------------------------------------------------------------------
-
-static bool IsUselessCopy(const TargetMachine &target, const MachineInstr* MI) {
- if (MI->getOpcode() == V9::FMOVS || MI->getOpcode() == V9::FMOVD) {
- return (// both operands are allocated to the same register
- MI->getOperand(0).getReg() == MI->getOperand(1).getReg());
- } else if (MI->getOpcode() == V9::ADDr || MI->getOpcode() == V9::ORr ||
- MI->getOpcode() == V9::ADDi || MI->getOpcode() == V9::ORi) {
- unsigned srcWithDestReg;
-
- for (srcWithDestReg = 0; srcWithDestReg < 2; ++srcWithDestReg)
- if (MI->getOperand(srcWithDestReg).hasAllocatedReg() &&
- MI->getOperand(srcWithDestReg).getReg()
- == MI->getOperand(2).getReg())
- break;
-
- if (srcWithDestReg == 2)
- return false;
- else {
- // else source and dest are allocated to the same register
- unsigned otherOp = 1 - srcWithDestReg;
- return (// either operand otherOp is register %g0
- (MI->getOperand(otherOp).hasAllocatedReg() &&
- MI->getOperand(otherOp).getReg() ==
- target.getRegInfo().getZeroRegNum()) ||
-
- // or operand otherOp == 0
- (MI->getOperand(otherOp).getType()
- == MachineOperand::MO_SignExtendedImmed &&
- MI->getOperand(otherOp).getImmedValue() == 0));
- }
- }
- else
- return false;
-}
-
-inline bool
-RemoveUselessCopies(MachineBasicBlock& mvec,
- MachineBasicBlock::iterator& BBI,
- const TargetMachine& target) {
- if (IsUselessCopy(target, BBI)) {
- DeleteInstruction(mvec, BBI, target);
- return true;
- }
- return false;
-}
-
-
-//************************ Class Implementations **************************/
-
-class PeepholeOpts: public BasicBlockPass {
- const TargetMachine &target;
- bool visit(MachineBasicBlock& mvec,
- MachineBasicBlock::iterator BBI) const;
-public:
- PeepholeOpts(const TargetMachine &TM): target(TM) { }
- bool runOnBasicBlock(BasicBlock &BB); // apply this pass to each BB
- virtual const char *getPassName() const { return "Peephole Optimization"; }
-
- // getAnalysisUsage - this pass preserves the CFG
- void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesCFG();
- }
-};
-
-// Apply a list of peephole optimizations to this machine instruction
-// within its local context. They are allowed to delete MI or any
-// instruction before MI, but not
-//
-bool PeepholeOpts::visit(MachineBasicBlock& mvec,
- MachineBasicBlock::iterator BBI) const {
- // Remove redundant copy instructions
- return RemoveUselessCopies(mvec, BBI, target);
-}
-
-
-bool PeepholeOpts::runOnBasicBlock(BasicBlock &BB) {
- // Get the machine instructions for this BB
- // FIXME: MachineBasicBlock::get() is deprecated, hence inlining the function
- const Function *F = BB.getParent();
- MachineFunction &MF = MachineFunction::get(F);
- MachineBasicBlock *MBB = NULL;
- for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
- if (I->getBasicBlock() == &BB)
- MBB = I;
-
- assert(MBB && "MachineBasicBlock object not found for specified block!");
- MachineBasicBlock &mvec = *MBB;
-
- for (MachineBasicBlock::iterator I = mvec.begin(), E = mvec.end(); I != E; )
- visit(mvec, I++);
-
- return true;
-}
-
-/// createPeepholeOptsPass - Public entry point for peephole optimization
-///
-FunctionPass* createPeepholeOptsPass(const TargetMachine &TM) {
- return new PeepholeOpts(TM);
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/PreSelection.cpp b/llvm/lib/Target/Sparc/PreSelection.cpp
deleted file mode 100644
index 5bb9b2b3619..00000000000
--- a/llvm/lib/Target/Sparc/PreSelection.cpp
+++ /dev/null
@@ -1,243 +0,0 @@
-//===- PreSelection.cpp - Specialize LLVM code for target machine ---------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the PreSelection pass which specializes LLVM code for a
-// target machine, while remaining in legal portable LLVM form and
-// preserving type information and type safety. This is meant to enable
-// dataflow optimizations on target-specific operations such as accesses to
-// constants, globals, and array indexing.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcInternals.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/iMemory.h"
-#include "llvm/iPHINode.h"
-#include "llvm/iOther.h"
-#include "llvm/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/InstVisitor.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Transforms/Scalar.h"
-#include <algorithm>
-
-namespace llvm {
-
-namespace {
-
- //===--------------------------------------------------------------------===//
- // PreSelection Pass - Specialize LLVM code for the current target machine.
- //
- class PreSelection : public FunctionPass, public InstVisitor<PreSelection> {
- const TargetInstrInfo &instrInfo;
-
- public:
- PreSelection(const TargetMachine &T)
- : instrInfo(T.getInstrInfo()) {}
-
- // runOnFunction - apply this pass to each Function
- bool runOnFunction(Function &F) {
- visit(F);
- return true;
- }
-
- // These methods do the actual work of specializing code
- void visitInstruction(Instruction &I); // common work for every instr.
- void visitGetElementPtrInst(GetElementPtrInst &I);
- void visitCallInst(CallInst &I);
- void visitPHINode(PHINode &PN);
-
- // Helper functions for visiting operands of every instruction
- //
- // visitOperands() works on every operand in [firstOp, lastOp-1].
- // If lastOp==0, lastOp defaults to #operands or #incoming Phi values.
- //
- // visitOneOperand() does all the work for one operand.
- //
- void visitOperands(Instruction &I, int firstOp=0);
- void visitOneOperand(Instruction &I, Value* Op, unsigned opNum,
- Instruction& insertBefore);
- };
-
-#if 0
- // Register the pass...
- RegisterPass<PreSelection> X("preselect",
- "Specialize LLVM code for a target machine"
- createPreselectionPass);
-#endif
-
-} // end anonymous namespace
-
-
-//------------------------------------------------------------------------------
-// Helper functions used by methods of class PreSelection
-//------------------------------------------------------------------------------
-
-
-// getGlobalAddr(): Put address of a global into a v. register.
-static GetElementPtrInst* getGlobalAddr(Value* ptr, Instruction& insertBefore) {
- if (isa<ConstantPointerRef>(ptr))
- ptr = cast<ConstantPointerRef>(ptr)->getValue();
-
- return (isa<GlobalVariable>(ptr))
- ? new GetElementPtrInst(ptr,
- std::vector<Value*>(1, ConstantSInt::get(Type::LongTy, 0U)),
- "addrOfGlobal", &insertBefore)
- : NULL;
-}
-
-// Wrapper on Constant::classof to use in find_if
-inline static bool nonConstant(const Use& U) {
- return ! isa<Constant>(U);
-}
-
-static Instruction* DecomposeConstantExpr(ConstantExpr* CE,
- Instruction& insertBefore)
-{
- Value *getArg1, *getArg2;
-
- switch(CE->getOpcode())
- {
- case Instruction::Cast:
- getArg1 = CE->getOperand(0);
- if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg1))
- getArg1 = DecomposeConstantExpr(CEarg, insertBefore);
- return new CastInst(getArg1, CE->getType(), "constantCast",&insertBefore);
-
- case Instruction::GetElementPtr:
- assert(find_if(CE->op_begin()+1, CE->op_end(),nonConstant) == CE->op_end()
- && "All indices in ConstantExpr getelementptr must be constant!");
- getArg1 = CE->getOperand(0);
- if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg1))
- getArg1 = DecomposeConstantExpr(CEarg, insertBefore);
- else if (GetElementPtrInst* gep = getGlobalAddr(getArg1, insertBefore))
- getArg1 = gep;
- return new GetElementPtrInst(getArg1,
- std::vector<Value*>(CE->op_begin()+1, CE->op_end()),
- "constantGEP", &insertBefore);
-
- default: // must be a binary operator
- assert(CE->getOpcode() >= Instruction::BinaryOpsBegin &&
- CE->getOpcode() < Instruction::BinaryOpsEnd &&
- "Unrecognized opcode in ConstantExpr");
- getArg1 = CE->getOperand(0);
- if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg1))
- getArg1 = DecomposeConstantExpr(CEarg, insertBefore);
- getArg2 = CE->getOperand(1);
- if (ConstantExpr* CEarg = dyn_cast<ConstantExpr>(getArg2))
- getArg2 = DecomposeConstantExpr(CEarg, insertBefore);
- return BinaryOperator::create((Instruction::BinaryOps) CE->getOpcode(),
- getArg1, getArg2,
- "constantBinaryOp", &insertBefore);
- }
-}
-
-
-//------------------------------------------------------------------------------
-// Instruction visitor methods to perform instruction-specific operations
-//------------------------------------------------------------------------------
-inline void
-PreSelection::visitOneOperand(Instruction &I, Value* Op, unsigned opNum,
- Instruction& insertBefore)
-{
- assert(&insertBefore != NULL && "Must have instruction to insert before.");
-
- if (GetElementPtrInst* gep = getGlobalAddr(Op, insertBefore)) {
- I.setOperand(opNum, gep); // replace global operand
- return; // nothing more to do for this op.
- }
-
- Constant* CV = dyn_cast<Constant>(Op);
- if (CV == NULL)
- return;
-
- if (ConstantExpr* CE = dyn_cast<ConstantExpr>(CV)) {
- // load-time constant: factor it out so we optimize as best we can
- Instruction* computeConst = DecomposeConstantExpr(CE, insertBefore);
- I.setOperand(opNum, computeConst); // replace expr operand with result
- } else if (instrInfo.ConstantTypeMustBeLoaded(CV)) {
- // load address of constant into a register, then load the constant
- // this is now done during instruction selection
- // the constant will live in the MachineConstantPool later on
- } else if (instrInfo.ConstantMayNotFitInImmedField(CV, &I)) {
- // put the constant into a virtual register using a cast
- CastInst* castI = new CastInst(CV, CV->getType(), "copyConst",
- &insertBefore);
- I.setOperand(opNum, castI); // replace operand with copy in v.reg.
- }
-}
-
-/// visitOperands - transform individual operands of all instructions:
-/// -- Load "large" int constants into a virtual register. What is large
-/// depends on the type of instruction and on the target architecture.
-/// -- For any constants that cannot be put in an immediate field,
-/// load address into virtual register first, and then load the constant.
-///
-/// firstOp and lastOp can be used to skip leading and trailing operands.
-/// If lastOp is 0, it defaults to #operands or #incoming Phi values.
-///
-inline void PreSelection::visitOperands(Instruction &I, int firstOp) {
- // For any instruction other than PHI, copies go just before the instr.
- for (unsigned i = firstOp, e = I.getNumOperands(); i != e; ++i)
- visitOneOperand(I, I.getOperand(i), i, I);
-}
-
-
-void PreSelection::visitPHINode(PHINode &PN) {
- // For a PHI, operand copies must be before the terminator of the
- // appropriate predecessor basic block. Remaining logic is simple
- // so just handle PHIs and other instructions separately.
- //
- for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i)
- visitOneOperand(PN, PN.getIncomingValue(i),
- PN.getOperandNumForIncomingValue(i),
- *PN.getIncomingBlock(i)->getTerminator());
- // do not call visitOperands!
-}
-
-// Common work for *all* instructions. This needs to be called explicitly
-// by other visit<InstructionType> functions.
-inline void PreSelection::visitInstruction(Instruction &I) {
- visitOperands(I); // Perform operand transformations
-}
-
-// GetElementPtr instructions: check if pointer is a global
-void PreSelection::visitGetElementPtrInst(GetElementPtrInst &I) {
- Instruction* curI = &I;
-
- // Decompose multidimensional array references
- if (I.getNumIndices() >= 2) {
- // DecomposeArrayRef() replaces I and deletes it, if successful,
- // so remember predecessor in order to find the replacement instruction.
- // Also remember the basic block in case there is no predecessor.
- Instruction* prevI = I.getPrev();
- BasicBlock* bb = I.getParent();
- if (DecomposeArrayRef(&I))
- // first instr. replacing I
- curI = cast<GetElementPtrInst>(prevI? prevI->getNext() : &bb->front());
- }
-
- // Perform other transformations common to all instructions
- visitInstruction(*curI);
-}
-
-void PreSelection::visitCallInst(CallInst &I) {
- // Tell visitOperands to ignore the function name if this is a direct call.
- visitOperands(I, (/*firstOp=*/ I.getCalledFunction()? 1 : 0));
-}
-
-/// createPreSelectionPass - Public entry point for the PreSelection pass
-///
-FunctionPass* createPreSelectionPass(const TargetMachine &TM) {
- return new PreSelection(TM);
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp b/llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp
deleted file mode 100644
index 77aa098e311..00000000000
--- a/llvm/lib/Target/Sparc/PrologEpilogCodeInserter.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-//===-- PrologEpilogCodeInserter.cpp - Insert Prolog & Epilog code for fn -===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Insert SAVE/RESTORE instructions for the function
-//
-// Insert prolog code at the unique function entry point.
-// Insert epilog code at each function exit point.
-// InsertPrologEpilog invokes these only if the function is not compiled
-// with the leaf function optimization.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcInternals.h"
-#include "SparcRegClassInfo.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/Pass.h"
-#include "llvm/Function.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Intrinsics.h"
-
-namespace llvm {
-
-namespace {
- struct InsertPrologEpilogCode : public MachineFunctionPass {
- const char *getPassName() const { return "Sparc Prolog/Epilog Inserter"; }
-
- bool runOnMachineFunction(MachineFunction &F) {
- if (!F.getInfo()->isCompiledAsLeafMethod()) {
- InsertPrologCode(F);
- InsertEpilogCode(F);
- }
- return false;
- }
-
- void InsertPrologCode(MachineFunction &F);
- void InsertEpilogCode(MachineFunction &F);
- };
-
-} // End anonymous namespace
-
-//------------------------------------------------------------------------
-// Create prolog and epilog code for procedure entry and exit
-//------------------------------------------------------------------------
-
-void InsertPrologEpilogCode::InsertPrologCode(MachineFunction &MF)
-{
- std::vector<MachineInstr*> mvec;
- const TargetMachine &TM = MF.getTarget();
- const TargetFrameInfo& frameInfo = TM.getFrameInfo();
-
- // The second operand is the stack size. If it does not fit in the
- // immediate field, we have to use a free register to hold the size.
- // See the comments below for the choice of this register.
- //
- unsigned staticStackSize = MF.getInfo()->getStaticStackSize();
-
- if (staticStackSize < (unsigned) frameInfo.getMinStackFrameSize())
- staticStackSize = (unsigned) frameInfo.getMinStackFrameSize();
-
- if (unsigned padsz = (staticStackSize %
- (unsigned) frameInfo.getStackFrameSizeAlignment()))
- staticStackSize += frameInfo.getStackFrameSizeAlignment() - padsz;
-
- int32_t C = - (int) staticStackSize;
- int SP = TM.getRegInfo().getStackPointer();
- if (TM.getInstrInfo().constantFitsInImmedField(V9::SAVEi,staticStackSize)) {
- mvec.push_back(BuildMI(V9::SAVEi, 3).addMReg(SP).addSImm(C)
- .addMReg(SP, MachineOperand::Def));
- } else {
- // We have to put the stack size value into a register before SAVE.
- // Use register %g1 since it is volatile across calls. Note that the
- // local (%l) and in (%i) registers cannot be used before the SAVE!
- // Do this by creating a code sequence equivalent to:
- // SETSW -(stackSize), %g1
- int uregNum = TM.getRegInfo().getUnifiedRegNum(
- TM.getRegInfo().getRegClassIDOfType(Type::IntTy),
- SparcIntRegClass::g1);
-
- MachineInstr* M = BuildMI(V9::SETHI, 2).addSImm(C)
- .addMReg(uregNum, MachineOperand::Def);
- M->setOperandHi32(0);
- mvec.push_back(M);
-
- M = BuildMI(V9::ORi, 3).addMReg(uregNum).addSImm(C)
- .addMReg(uregNum, MachineOperand::Def);
- M->setOperandLo32(1);
- mvec.push_back(M);
-
- M = BuildMI(V9::SRAi5, 3).addMReg(uregNum).addZImm(0)
- .addMReg(uregNum, MachineOperand::Def);
- mvec.push_back(M);
-
- // Now generate the SAVE using the value in register %g1
- M = BuildMI(V9::SAVEr,3).addMReg(SP).addMReg(uregNum)
- .addMReg(SP,MachineOperand::Def);
- mvec.push_back(M);
- }
-
- // For varargs function bodies, insert instructions to copy incoming
- // register arguments for the ... list to the stack.
- // The first K=6 arguments are always received via int arg regs
- // (%i0 ... %i5 if K=6) .
- // By copying the varargs arguments to the stack, va_arg() then can
- // simply assume that all vararg arguments are in an array on the stack.
- //
- if (MF.getFunction()->getFunctionType()->isVarArg()) {
- int numFixedArgs = MF.getFunction()->getFunctionType()->getNumParams();
- int numArgRegs = TM.getRegInfo().getNumOfIntArgRegs();
- if (numFixedArgs < numArgRegs) {
- bool ignore;
- int firstArgReg = TM.getRegInfo().getUnifiedRegNum(
- TM.getRegInfo().getRegClassIDOfType(Type::IntTy),
- SparcIntRegClass::i0);
- int fpReg = TM.getFrameInfo().getIncomingArgBaseRegNum();
- int argSize = TM.getFrameInfo().getSizeOfEachArgOnStack();
- int firstArgOffset=TM.getFrameInfo().getFirstIncomingArgOffset(MF,ignore);
- int nextArgOffset = firstArgOffset + numFixedArgs * argSize;
-
- for (int i=numFixedArgs; i < numArgRegs; ++i) {
- mvec.push_back(BuildMI(V9::STXi, 3).addMReg(firstArgReg+i).
- addMReg(fpReg).addSImm(nextArgOffset));
- nextArgOffset += argSize;
- }
- }
- }
-
- MF.front().insert(MF.front().begin(), mvec.begin(), mvec.end());
-}
-
-void InsertPrologEpilogCode::InsertEpilogCode(MachineFunction &MF)
-{
- const TargetMachine &TM = MF.getTarget();
- const TargetInstrInfo &MII = TM.getInstrInfo();
-
- for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
- MachineBasicBlock &MBB = *I;
- const BasicBlock &BB = *I->getBasicBlock();
- const Instruction *TermInst = (Instruction*)BB.getTerminator();
- if (TermInst->getOpcode() == Instruction::Ret)
- {
- int ZR = TM.getRegInfo().getZeroRegNum();
- MachineInstr *Restore =
- BuildMI(V9::RESTOREi, 3).addMReg(ZR).addSImm(0)
- .addMReg(ZR, MachineOperand::Def);
-
- MachineCodeForInstruction &termMvec =
- MachineCodeForInstruction::get(TermInst);
-
- // Remove the NOPs in the delay slots of the return instruction
- unsigned numNOPs = 0;
- while (termMvec.back()->getOpcode() == V9::NOP)
- {
- assert( termMvec.back() == &MBB.back());
- termMvec.pop_back();
- MBB.erase(&MBB.back());
- ++numNOPs;
- }
- assert(termMvec.back() == &MBB.back());
-
- // Check that we found the right number of NOPs and have the right
- // number of instructions to replace them.
- unsigned ndelays = MII.getNumDelaySlots(termMvec.back()->getOpcode());
- assert(numNOPs == ndelays && "Missing NOPs in delay slots?");
- assert(ndelays == 1 && "Cannot use epilog code for delay slots?");
-
- // Append the epilog code to the end of the basic block.
- MBB.push_back(Restore);
- }
- }
-}
-
-FunctionPass *createPrologEpilogInsertionPass() {
- return new InsertPrologEpilogCode();
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/RegAlloc/AllocInfo.h b/llvm/lib/Target/Sparc/RegAlloc/AllocInfo.h
deleted file mode 100644
index b4407523c4c..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/AllocInfo.h
+++ /dev/null
@@ -1,91 +0,0 @@
-//===-- AllocInfo.h - Store info about regalloc decisions -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This header file contains the data structure used to save the state
-// of the global, graph-coloring register allocator.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ALLOCINFO_H
-#define ALLOCINFO_H
-
-#include "llvm/Type.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Constants.h"
-
-namespace llvm {
-
-/// AllocInfo - Structure representing one instruction's operand's-worth of
-/// register allocation state. We create tables made out of these data
-/// structures to generate mapping information for this register allocator.
-///
-struct AllocInfo {
- unsigned Instruction;
- int Operand; // (-1 if Instruction, or 0...n-1 for an operand.)
- enum AllocStateTy { NotAllocated = 0, Allocated, Spilled };
- AllocStateTy AllocState;
- int Placement;
-
- AllocInfo (unsigned Instruction_, unsigned Operand_,
- AllocStateTy AllocState_, int Placement_) :
- Instruction (Instruction_), Operand (Operand_),
- AllocState (AllocState_), Placement (Placement_) { }
-
- /// getConstantType - Return a StructType representing an AllocInfo object.
- ///
- static StructType *getConstantType () {
- std::vector<const Type *> TV;
- TV.push_back (Type::UIntTy);
- TV.push_back (Type::IntTy);
- TV.push_back (Type::UIntTy);
- TV.push_back (Type::IntTy);
- return StructType::get (TV);
- }
-
- /// toConstant - Convert this AllocInfo into an LLVM Constant of type
- /// getConstantType(), and return the Constant.
- ///
- Constant *toConstant () const {
- StructType *ST = getConstantType ();
- std::vector<Constant *> CV;
- CV.push_back (ConstantUInt::get (Type::UIntTy, Instruction));
- CV.push_back (ConstantSInt::get (Type::IntTy, Operand));
- CV.push_back (ConstantUInt::get (Type::UIntTy, AllocState));
- CV.push_back (ConstantSInt::get (Type::IntTy, Placement));
- return ConstantStruct::get (ST, CV);
- }
-
- /// AllocInfos compare equal if the allocation placements are equal
- /// (i.e., they can be equal even if they refer to operands from two
- /// different instructions.)
- ///
- bool operator== (const AllocInfo &X) const {
- return (X.AllocState == AllocState) && (X.Placement == Placement);
- }
- bool operator!= (const AllocInfo &X) const { return !(*this == X); }
-
- /// Returns a human-readable string representation of the AllocState member.
- ///
- const std::string allocStateToString () const {
- static const char *AllocStateNames[] =
- { "NotAllocated", "Allocated", "Spilled" };
- return std::string (AllocStateNames[AllocState]);
- }
-};
-
-static inline std::ostream &operator << (std::ostream &OS, AllocInfo &S) {
- OS << "(Instruction " << S.Instruction << " Operand " << S.Operand
- << " AllocState " << S.allocStateToString () << " Placement "
- << S.Placement << ")";
- return OS;
-}
-
-} // End llvm namespace
-
-#endif // ALLOCINFO_H
diff --git a/llvm/lib/Target/Sparc/RegAlloc/IGNode.cpp b/llvm/lib/Target/Sparc/RegAlloc/IGNode.cpp
deleted file mode 100644
index a76fdeaa037..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/IGNode.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//===-- IGNode.cpp --------------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements an Interference graph node for coloring-based register
-// allocation.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IGNode.h"
-#include <algorithm>
-#include <iostream>
-
-namespace llvm {
-
-//-----------------------------------------------------------------------------
-// Sets this IGNode on stack and reduce the degree of neighbors
-//-----------------------------------------------------------------------------
-
-void IGNode::pushOnStack() {
- OnStack = true;
- int neighs = AdjList.size();
-
- if (neighs < 0) {
- std::cerr << "\nAdj List size = " << neighs;
- assert(0 && "Invalid adj list size");
- }
-
- for (int i=0; i < neighs; i++)
- AdjList[i]->decCurDegree();
-}
-
-//-----------------------------------------------------------------------------
-// Deletes an adjacency node. IGNodes are deleted when coalescing merges
-// two IGNodes together.
-//-----------------------------------------------------------------------------
-
-void IGNode::delAdjIGNode(const IGNode *Node) {
- std::vector<IGNode *>::iterator It=find(AdjList.begin(), AdjList.end(), Node);
- assert(It != AdjList.end() && "The node must be there!");
- AdjList.erase(It);
-}
-
-//-----------------------------------------------------------------------------
-// Get the number of unique neighbors if these two nodes are merged
-//-----------------------------------------------------------------------------
-
-unsigned
-IGNode::getCombinedDegree(const IGNode* otherNode) const {
- std::vector<IGNode*> nbrs(AdjList);
- nbrs.insert(nbrs.end(), otherNode->AdjList.begin(), otherNode->AdjList.end());
- sort(nbrs.begin(), nbrs.end());
- std::vector<IGNode*>::iterator new_end = unique(nbrs.begin(), nbrs.end());
- return new_end - nbrs.begin();
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/RegAlloc/IGNode.h b/llvm/lib/Target/Sparc/RegAlloc/IGNode.h
deleted file mode 100644
index 9fdc7a6ac07..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/IGNode.h
+++ /dev/null
@@ -1,123 +0,0 @@
-//===-- IGNode.h - Represent a node in an interference graph ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file represents a node in an interference graph.
-//
-// For efficiency, the AdjList is updated only once - ie. we can add but not
-// remove nodes from AdjList.
-//
-// The removal of nodes from IG is simulated by decrementing the CurDegree.
-// If this node is put on stack (that is removed from IG), the CurDegree of all
-// the neighbors are decremented and this node is marked OnStack. Hence
-// the effective neighbors in the AdjList are the ones that do not have the
-// OnStack flag set (therefore, they are in the IG).
-//
-// The methods that modify/use the CurDegree must be called only
-// after all modifications to the IG are over (i.e., all neighbors are fixed).
-//
-// The vector representation is the most efficient one for adj list.
-// Though nodes are removed when coalescing is done, we access it in sequence
-// for far many times when coloring (colorNode()).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef IGNODE_H
-#define IGNODE_H
-
-#include "LiveRange.h"
-#include <vector>
-
-namespace llvm {
-
-class RegClass;
-
-//----------------------------------------------------------------------------
-// Class IGNode
-//
-// Represents a node in an interference graph.
-//----------------------------------------------------------------------------
-
-class IGNode {
- const unsigned Index; // index within IGNodeList
- bool OnStack; // this has been pushed on to stack for coloring
- std::vector<IGNode *> AdjList;// adjacency list for this live range
-
- int CurDegree;
- //
- // set by InterferenceGraph::setCurDegreeOfIGNodes() after calculating
- // all adjacency lists.
- // Decremented when a neighbor is pushed on to the stack.
- // After that, never incremented/set again nor used.
-
- LiveRange *const ParentLR;
-public:
-
- IGNode(LiveRange *LR, unsigned index) : Index(index), ParentLR(LR) {
- OnStack = false;
- CurDegree = -1;
- ParentLR->setUserIGNode(this);
- }
-
- inline unsigned int getIndex() const { return Index; }
-
- // adjLists must be updated only once. However, the CurDegree can be changed
- //
- inline void addAdjIGNode(IGNode *AdjNode) { AdjList.push_back(AdjNode); }
-
- inline IGNode *getAdjIGNode(unsigned ind) const
- { assert ( ind < AdjList.size()); return AdjList[ind]; }
-
- // delete a node in AdjList - node must be in the list
- // should not be called often
- //
- void delAdjIGNode(const IGNode *Node);
-
- inline unsigned getNumOfNeighbors() const { return AdjList.size(); }
-
- // Get the number of unique neighbors if these two nodes are merged
- unsigned getCombinedDegree(const IGNode* otherNode) const;
-
- inline bool isOnStack() const { return OnStack; }
-
- // remove form IG and pushes on to stack (reduce the degree of neighbors)
- //
- void pushOnStack();
-
- // CurDegree is the effective number of neighbors when neighbors are
- // pushed on to the stack during the coloring phase. Must be called
- // after all modifications to the IG are over (i.e., all neighbors are
- // fixed).
- //
- inline void setCurDegree() {
- assert(CurDegree == -1);
- CurDegree = AdjList.size();
- }
-
- inline int getCurDegree() const { return CurDegree; }
-
- // called when a neigh is pushed on to stack
- //
- inline void decCurDegree() { assert(CurDegree > 0); --CurDegree; }
-
- // The following methods call the methods in ParentLR
- // They are added to this class for convenience
- // If many of these are called within a single scope,
- // consider calling the methods directly on LR
- inline bool hasColor() const { return ParentLR->hasColor(); }
-
- inline unsigned int getColor() const { return ParentLR->getColor(); }
-
- inline void setColor(unsigned Col) { ParentLR->setColor(Col); }
-
- inline LiveRange *getParentLR() const { return ParentLR; }
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/RegAlloc/InterferenceGraph.cpp b/llvm/lib/Target/Sparc/RegAlloc/InterferenceGraph.cpp
deleted file mode 100644
index 3cef19ea0e0..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/InterferenceGraph.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-//===-- InterferenceGraph.cpp ---------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Interference graph for coloring-based register allocation for LLVM.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IGNode.h"
-#include "InterferenceGraph.h"
-#include "RegAllocCommon.h"
-#include "Support/STLExtras.h"
-#include <algorithm>
-
-namespace llvm {
-
-// for asserting this IG node is infact in the IGNodeList of this class
-inline static void assertIGNode(const InterferenceGraph *IG,
- const IGNode *Node) {
- assert(IG->getIGNodeList()[Node->getIndex()] == Node);
-}
-
-//-----------------------------------------------------------------------------
-// Constructor: Records the RegClass and initalizes IGNodeList.
-// The matrix is NOT yet created by the constructor. Call createGraph()
-// to create it after adding all IGNodes to the IGNodeList.
-//-----------------------------------------------------------------------------
-InterferenceGraph::InterferenceGraph(RegClass *const RC) : RegCl(RC) {
- IG = NULL;
- Size = 0;
- if( DEBUG_RA >= RA_DEBUG_Interference)
- std::cerr << "Interference graph created!\n";
-}
-
-
-//-----------------------------------------------------------------------------
-// destructor. Deletes the bit matrix and all IGNodes
-//-----------------------------------------------------------------------------
-InterferenceGraph:: ~InterferenceGraph() {
- // delete the matrix
- for(unsigned int r=0; r < IGNodeList.size(); ++r)
- delete[] IG[r];
- delete[] IG;
-
- // delete all IGNodes in the IGNodeList
- for_each(IGNodeList.begin(), IGNodeList.end(), deleter<IGNode>);
-}
-
-
-
-//-----------------------------------------------------------------------------
-// Creates (dynamically allocates) the bit matrix necessary to hold the
-// interference graph.
-//-----------------------------------------------------------------------------
-void InterferenceGraph::createGraph()
-{
- Size = IGNodeList.size();
- IG = new char*[Size];
- for( unsigned int r=0; r < Size; ++r)
- IG[r] = new char[Size];
-
- // init IG matrix
- for(unsigned int i=0; i < Size; i++)
- for(unsigned int j=0; j < Size; j++)
- IG[i][j] = 0;
-}
-
-//-----------------------------------------------------------------------------
-// creates a new IGNode for the given live range and add to IG
-//-----------------------------------------------------------------------------
-void InterferenceGraph::addLRToIG(LiveRange *const LR)
-{
- IGNodeList.push_back(new IGNode(LR, IGNodeList.size()));
-}
-
-
-//-----------------------------------------------------------------------------
-// set interference for two live ranges
-// update both the matrix and AdjLists of nodes.
-// If there is already an interference between LR1 and LR2, adj lists
-// are not updated. LR1 and LR2 must be distinct since if not, it suggests
-// that there is some wrong logic in some other method.
-//-----------------------------------------------------------------------------
-void InterferenceGraph::setInterference(const LiveRange *const LR1,
- const LiveRange *const LR2 ) {
- assert(LR1 != LR2);
-
- IGNode *IGNode1 = LR1->getUserIGNode();
- IGNode *IGNode2 = LR2->getUserIGNode();
-
- assertIGNode(this, IGNode1);
- assertIGNode(this, IGNode2);
-
- unsigned row = IGNode1->getIndex();
- unsigned col = IGNode2->getIndex();
-
- char *val;
-
- if( DEBUG_RA >= RA_DEBUG_Interference)
- std::cerr << "setting intf for: [" << row << "][" << col << "]\n";
-
- ( row > col) ? val = &IG[row][col]: val = &IG[col][row];
-
- if( ! (*val) ) { // if this interf is not previously set
- *val = 1; // add edges between nodes
- IGNode1->addAdjIGNode( IGNode2 );
- IGNode2->addAdjIGNode( IGNode1 );
- }
-
-}
-
-
-//----------------------------------------------------------------------------
-// return whether two live ranges interfere
-//----------------------------------------------------------------------------
-unsigned InterferenceGraph::getInterference(const LiveRange *const LR1,
- const LiveRange *const LR2) const {
- assert(LR1 != LR2);
- assertIGNode(this, LR1->getUserIGNode());
- assertIGNode(this, LR2->getUserIGNode());
-
- const unsigned int row = LR1->getUserIGNode()->getIndex();
- const unsigned int col = LR2->getUserIGNode()->getIndex();
-
- char ret;
- if (row > col)
- ret = IG[row][col];
- else
- ret = IG[col][row];
- return ret;
-
-}
-
-
-//----------------------------------------------------------------------------
-// Merge 2 IGNodes. The neighbors of the SrcNode will be added to the DestNode.
-// Then the IGNode2L will be deleted. Necessary for coalescing.
-// IMPORTANT: The live ranges are NOT merged by this method. Use
-// LiveRangeInfo::unionAndUpdateLRs for that purpose.
-//----------------------------------------------------------------------------
-
-void InterferenceGraph::mergeIGNodesOfLRs(const LiveRange *LR1,
- LiveRange *LR2) {
-
- assert( LR1 != LR2); // cannot merge the same live range
-
- IGNode *const DestNode = LR1->getUserIGNode();
- IGNode *SrcNode = LR2->getUserIGNode();
-
- assertIGNode(this, DestNode);
- assertIGNode(this, SrcNode);
-
- if( DEBUG_RA >= RA_DEBUG_Interference) {
- std::cerr << "Merging LRs: \""; printSet(*LR1);
- std::cerr << "\" and \""; printSet(*LR2);
- std::cerr << "\"\n";
- }
-
- unsigned SrcDegree = SrcNode->getNumOfNeighbors();
- const unsigned SrcInd = SrcNode->getIndex();
-
-
- // for all neighs of SrcNode
- for(unsigned i=0; i < SrcDegree; i++) {
- IGNode *NeighNode = SrcNode->getAdjIGNode(i);
-
- LiveRange *const LROfNeigh = NeighNode->getParentLR();
-
- // delete edge between src and neigh - even neigh == dest
- NeighNode->delAdjIGNode(SrcNode);
-
- // set the matrix posn to 0 betn src and neigh - even neigh == dest
- const unsigned NInd = NeighNode->getIndex();
- ( SrcInd > NInd) ? (IG[SrcInd][NInd]=0) : (IG[NInd][SrcInd]=0) ;
-
-
- if( LR1 != LROfNeigh) { // if the neigh != dest
-
- // add edge betwn Dest and Neigh - if there is no current edge
- setInterference(LR1, LROfNeigh );
- }
-
- }
-
- IGNodeList[ SrcInd ] = NULL;
-
- // SrcNode is no longer necessary - LR2 must be deleted by the caller
- delete( SrcNode );
-
-}
-
-
-//----------------------------------------------------------------------------
-// must be called after modifications to the graph are over but before
-// pushing IGNodes on to the stack for coloring.
-//----------------------------------------------------------------------------
-void InterferenceGraph::setCurDegreeOfIGNodes()
-{
- unsigned Size = IGNodeList.size();
-
- for( unsigned i=0; i < Size; i++) {
- IGNode *Node = IGNodeList[i];
- if( Node )
- Node->setCurDegree();
- }
-}
-
-
-
-
-
-//--------------------- debugging (Printing) methods -----------------------
-
-//----------------------------------------------------------------------------
-// Print the IGnodes
-//----------------------------------------------------------------------------
-void InterferenceGraph::printIG() const {
- for(unsigned i=0; i < Size; i++) {
- const IGNode *const Node = IGNodeList[i];
- if(Node) {
- std::cerr << " [" << i << "] ";
-
- for( unsigned int j=0; j < Size; j++)
- if(IG[i][j])
- std::cerr << "(" << i << "," << j << ") ";
- std::cerr << "\n";
- }
- }
-}
-
-//----------------------------------------------------------------------------
-// Print the IGnodes in the IGNode List
-//----------------------------------------------------------------------------
-void InterferenceGraph::printIGNodeList() const {
- for(unsigned i=0; i < IGNodeList.size() ; ++i) {
- const IGNode *const Node = IGNodeList[i];
-
- if (Node) {
- std::cerr << " [" << Node->getIndex() << "] ";
- printSet(*Node->getParentLR());
- //int Deg = Node->getCurDegree();
- std::cerr << "\t <# of Neighs: " << Node->getNumOfNeighbors() << ">\n";
- }
- }
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/RegAlloc/InterferenceGraph.h b/llvm/lib/Target/Sparc/RegAlloc/InterferenceGraph.h
deleted file mode 100644
index 79850c1fcf0..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/InterferenceGraph.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//===-- InterferenceGraph.h - Interference graph for register coloring -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-/* Title: InterferenceGraph.h -*- C++ -*-
- Author: Ruchira Sasanka
- Date: July 20, 01
- Purpose: Interference Graph used for register coloring.
-
- Notes:
- Adj Info is stored in the lower trangular matrix (i.e., row > col )
-
- This class must be used in the following way:
-
- * Construct class
- * call addLRToIG as many times to add ALL LRs to this IG
- * call createGraph to create the actual matrix
- * Then setInterference, getInterference, mergeIGNodesOfLRs can be
- called as desired to modify the graph.
- * Once the modifications to the graph are over, call
- setCurDegreeOfIGNodes() before pushing IGNodes on to stack for coloring.
-*/
-
-#ifndef INTERFERENCEGRAPH_H
-#define INTERFERENCEGRAPH_H
-
-#include <vector>
-
-namespace llvm {
-
-class LiveRange;
-class RegClass;
-class IGNode;
-
-class InterferenceGraph {
- char **IG; // a poiner to the interference graph
- unsigned int Size; // size of a side of the IG
- RegClass *const RegCl; // RegCl contains this IG
- std::vector<IGNode *> IGNodeList; // a list of all IGNodes in a reg class
-
- public:
- // the matrix is not yet created by the constructor. Call createGraph()
- // to create it after adding all IGNodes to the IGNodeList
- InterferenceGraph(RegClass *RC);
- ~InterferenceGraph();
-
- void createGraph();
-
- void addLRToIG(LiveRange *LR);
-
- void setInterference(const LiveRange *LR1,
- const LiveRange *LR2);
-
- unsigned getInterference(const LiveRange *LR1,
- const LiveRange *LR2) const ;
-
- void mergeIGNodesOfLRs(const LiveRange *LR1, LiveRange *LR2);
-
- std::vector<IGNode *> &getIGNodeList() { return IGNodeList; }
- const std::vector<IGNode *> &getIGNodeList() const { return IGNodeList; }
-
- void setCurDegreeOfIGNodes();
-
- void printIG() const;
- void printIGNodeList() const;
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/RegAlloc/LiveRange.h b/llvm/lib/Target/Sparc/RegAlloc/LiveRange.h
deleted file mode 100644
index d6e2cf63072..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/LiveRange.h
+++ /dev/null
@@ -1,184 +0,0 @@
-//===-- LiveRange.h - Store info about a live range -------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Implements a live range using a ValueSet. A LiveRange is a simple set
-// of Values.
-//
-// Since the Value pointed by a use is the same as of its def, it is sufficient
-// to keep only defs in a LiveRange.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LIVERANGE_H
-#define LIVERANGE_H
-
-#include "llvm/Value.h"
-#include "llvm/CodeGen/ValueSet.h"
-
-namespace llvm {
-
-class RegClass;
-class IGNode;
-
-class LiveRange : public ValueSet {
- RegClass *MyRegClass; // register class (e.g., int, FP) for this LR
-
- /// doesSpanAcrossCalls - Does this live range span across calls?
- /// This information is used by graph coloring algo to avoid allocating
- /// volatile colors to live ranges that span across calls (since they have to
- /// be saved/restored)
- ///
- bool doesSpanAcrossCalls;
-
- IGNode *UserIGNode; // IGNode which uses this LR
- int Color; // color assigned to this live range
- bool mustSpill; // whether this LR must be spilt
-
- /// mustSaveAcrossCalls - whether this LR must be saved accross calls
- /// ***TODO REMOVE this
- ///
- bool mustSaveAcrossCalls;
-
- /// SuggestedColor - if this LR has a suggested color, can it be
- /// really alloated? A suggested color cannot be allocated when the
- /// suggested color is volatile and when there are call
- /// interferences.
- ///
- int SuggestedColor; // The suggested color for this LR
-
- /// CanUseSuggestedCol - It is possible that a suggested color for
- /// this live range is not available before graph coloring (e.g., it
- /// can be allocated to another live range which interferes with
- /// this)
- ///
- bool CanUseSuggestedCol;
-
- /// SpilledStackOffsetFromFP - If this LR is spilled, its stack
- /// offset from *FP*. The spilled offsets must always be relative to
- /// the FP.
- ///
- int SpilledStackOffsetFromFP;
-
- /// HasSpillOffset 0 Whether this live range has a spill offset
- ///
- bool HasSpillOffset;
-
- /// The spill cost of this live range. Calculated using loop depth of
- /// each reference to each Value in the live range
- ///
- unsigned SpillCost;
-
-public:
- LiveRange() {
- Color = SuggestedColor = -1; // not yet colored
- mustSpill = mustSaveAcrossCalls = false;
- MyRegClass = 0;
- UserIGNode = 0;
- doesSpanAcrossCalls = false;
- CanUseSuggestedCol = true;
- HasSpillOffset = false;
- SpillCost = 0;
- }
-
- void setRegClass(RegClass *RC) { MyRegClass = RC; }
-
- RegClass *getRegClass() const { assert(MyRegClass); return MyRegClass; }
- unsigned getRegClassID() const;
-
- bool hasColor() const { return Color != -1; }
-
- unsigned getColor() const { assert(Color != -1); return (unsigned)Color; }
-
- void setColor(unsigned Col) { Color = (int)Col; }
-
- inline void setCallInterference() {
- doesSpanAcrossCalls = 1;
- }
- inline void clearCallInterference() {
- doesSpanAcrossCalls = 0;
- }
-
- inline bool isCallInterference() const {
- return doesSpanAcrossCalls == 1;
- }
-
- inline void markForSpill() { mustSpill = true; }
-
- inline bool isMarkedForSpill() const { return mustSpill; }
-
- inline void setSpillOffFromFP(int StackOffset) {
- assert(mustSpill && "This LR is not spilled");
- SpilledStackOffsetFromFP = StackOffset;
- HasSpillOffset = true;
- }
-
- inline void modifySpillOffFromFP(int StackOffset) {
- assert(mustSpill && "This LR is not spilled");
- SpilledStackOffsetFromFP = StackOffset;
- HasSpillOffset = true;
- }
-
- inline bool hasSpillOffset() const {
- return HasSpillOffset;
- }
-
- inline int getSpillOffFromFP() const {
- assert(HasSpillOffset && "This LR is not spilled");
- return SpilledStackOffsetFromFP;
- }
-
- inline void markForSaveAcrossCalls() { mustSaveAcrossCalls = true; }
-
- inline void setUserIGNode(IGNode *IGN) {
- assert(!UserIGNode); UserIGNode = IGN;
- }
-
- // getUserIGNode - NULL if the user is not allocated
- inline IGNode *getUserIGNode() const { return UserIGNode; }
-
- inline const Type *getType() const {
- return (*begin())->getType(); // set's don't have a front
- }
-
- inline void setSuggestedColor(int Col) {
- if (SuggestedColor == -1)
- SuggestedColor = Col;
- }
-
- inline unsigned getSuggestedColor() const {
- assert(SuggestedColor != -1); // only a valid color is obtained
- return (unsigned)SuggestedColor;
- }
-
- inline bool hasSuggestedColor() const {
- return SuggestedColor != -1;
- }
-
- inline bool isSuggestedColorUsable() const {
- assert(hasSuggestedColor() && "No suggested color");
- return CanUseSuggestedCol;
- }
-
- inline void setSuggestedColorUsable(bool val) {
- assert(hasSuggestedColor() && "No suggested color");
- CanUseSuggestedCol = val;
- }
-
- inline void addSpillCost(unsigned cost) {
- SpillCost += cost;
- }
-
- inline unsigned getSpillCost() const {
- return SpillCost;
- }
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/RegAlloc/LiveRangeInfo.cpp b/llvm/lib/Target/Sparc/RegAlloc/LiveRangeInfo.cpp
deleted file mode 100644
index 100f9eb4c62..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/LiveRangeInfo.cpp
+++ /dev/null
@@ -1,415 +0,0 @@
-//===-- LiveRangeInfo.cpp -------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Live range construction for coloring-based register allocation for LLVM.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IGNode.h"
-#include "LiveRangeInfo.h"
-#include "RegAllocCommon.h"
-#include "RegClass.h"
-#include "llvm/Function.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetRegInfo.h"
-#include "Support/SetOperations.h"
-
-namespace llvm {
-
-unsigned LiveRange::getRegClassID() const { return getRegClass()->getID(); }
-
-LiveRangeInfo::LiveRangeInfo(const Function *F, const TargetMachine &tm,
- std::vector<RegClass *> &RCL)
- : Meth(F), TM(tm), RegClassList(RCL), MRI(tm.getRegInfo()) { }
-
-
-LiveRangeInfo::~LiveRangeInfo() {
- for (LiveRangeMapType::iterator MI = LiveRangeMap.begin();
- MI != LiveRangeMap.end(); ++MI) {
-
- if (MI->first && MI->second) {
- LiveRange *LR = MI->second;
-
- // we need to be careful in deleting LiveRanges in LiveRangeMap
- // since two/more Values in the live range map can point to the same
- // live range. We have to make the other entries NULL when we delete
- // a live range.
-
- for (LiveRange::iterator LI = LR->begin(); LI != LR->end(); ++LI)
- LiveRangeMap[*LI] = 0;
-
- delete LR;
- }
- }
-}
-
-
-//---------------------------------------------------------------------------
-// union two live ranges into one. The 2nd LR is deleted. Used for coalescing.
-// Note: the caller must make sure that L1 and L2 are distinct and both
-// LRs don't have suggested colors
-//---------------------------------------------------------------------------
-
-void LiveRangeInfo::unionAndUpdateLRs(LiveRange *L1, LiveRange *L2) {
- assert(L1 != L2 && (!L1->hasSuggestedColor() || !L2->hasSuggestedColor()));
- assert(! (L1->hasColor() && L2->hasColor()) ||
- L1->getColor() == L2->getColor());
-
- set_union(*L1, *L2); // add elements of L2 to L1
-
- for(ValueSet::iterator L2It = L2->begin(); L2It != L2->end(); ++L2It) {
- //assert(( L1->getTypeID() == L2->getTypeID()) && "Merge:Different types");
-
- L1->insert(*L2It); // add the var in L2 to L1
- LiveRangeMap[*L2It] = L1; // now the elements in L2 should map
- //to L1
- }
-
- // set call interference for L1 from L2
- if (L2->isCallInterference())
- L1->setCallInterference();
-
- // add the spill costs
- L1->addSpillCost(L2->getSpillCost());
-
- // If L2 has a color, give L1 that color. Note that L1 may have had the same
- // color or none, but would not have a different color as asserted above.
- if (L2->hasColor())
- L1->setColor(L2->getColor());
-
- // Similarly, if LROfUse(L2) has a suggested color, the new range
- // must have the same color.
- if (L2->hasSuggestedColor())
- L1->setSuggestedColor(L2->getSuggestedColor());
-
- delete L2; // delete L2 as it is no longer needed
-}
-
-
-//---------------------------------------------------------------------------
-// Method for creating a single live range for a definition.
-// The definition must be represented by a virtual register (a Value).
-// Note: this function does *not* check that no live range exists for def.
-//---------------------------------------------------------------------------
-
-LiveRange*
-LiveRangeInfo::createNewLiveRange(const Value* Def, bool isCC /* = false*/)
-{
- LiveRange* DefRange = new LiveRange(); // Create a new live range,
- DefRange->insert(Def); // add Def to it,
- LiveRangeMap[Def] = DefRange; // and update the map.
-
- // set the register class of the new live range
- DefRange->setRegClass(RegClassList[MRI.getRegClassIDOfType(Def->getType(),
- isCC)]);
-
- if (DEBUG_RA >= RA_DEBUG_LiveRanges) {
- std::cerr << " Creating a LR for def ";
- if (isCC) std::cerr << " (CC Register!)";
- std::cerr << " : " << RAV(Def) << "\n";
- }
- return DefRange;
-}
-
-
-LiveRange*
-LiveRangeInfo::createOrAddToLiveRange(const Value* Def, bool isCC /* = false*/)
-{
- LiveRange *DefRange = LiveRangeMap[Def];
-
- // check if the LR is already there (because of multiple defs)
- if (!DefRange) {
- DefRange = createNewLiveRange(Def, isCC);
- } else { // live range already exists
- DefRange->insert(Def); // add the operand to the range
- LiveRangeMap[Def] = DefRange; // make operand point to merged set
- if (DEBUG_RA >= RA_DEBUG_LiveRanges)
- std::cerr << " Added to existing LR for def: " << RAV(Def) << "\n";
- }
- return DefRange;
-}
-
-
-//---------------------------------------------------------------------------
-// Method for constructing all live ranges in a function. It creates live
-// ranges for all values defined in the instruction stream. Also, it
-// creates live ranges for all incoming arguments of the function.
-//---------------------------------------------------------------------------
-void LiveRangeInfo::constructLiveRanges() {
-
- if (DEBUG_RA >= RA_DEBUG_LiveRanges)
- std::cerr << "Constructing Live Ranges ...\n";
-
- // first find the live ranges for all incoming args of the function since
- // those LRs start from the start of the function
- for (Function::const_aiterator AI = Meth->abegin(); AI != Meth->aend(); ++AI)
- createNewLiveRange(AI, /*isCC*/ false);
-
- // Now suggest hardware registers for these function args
- MRI.suggestRegs4MethodArgs(Meth, *this);
-
- // Now create LRs for machine instructions. A new LR will be created
- // only for defs in the machine instr since, we assume that all Values are
- // defined before they are used. However, there can be multiple defs for
- // the same Value in machine instructions.
- //
- // Also, find CALL and RETURN instructions, which need extra work.
- //
- MachineFunction &MF = MachineFunction::get(Meth);
- for (MachineFunction::iterator BBI = MF.begin(); BBI != MF.end(); ++BBI) {
- MachineBasicBlock &MBB = *BBI;
-
- // iterate over all the machine instructions in BB
- for(MachineBasicBlock::iterator MInstIterator = MBB.begin();
- MInstIterator != MBB.end(); ++MInstIterator) {
- MachineInstr *MInst = MInstIterator;
-
- // If the machine instruction is a call/return instruction, add it to
- // CallRetInstrList for processing its args, ret value, and ret addr.
- //
- if(TM.getInstrInfo().isReturn(MInst->getOpcode()) ||
- TM.getInstrInfo().isCall(MInst->getOpcode()))
- CallRetInstrList.push_back(MInst);
-
- // iterate over explicit MI operands and create a new LR
- // for each operand that is defined by the instruction
- for (MachineInstr::val_op_iterator OpI = MInst->begin(),
- OpE = MInst->end(); OpI != OpE; ++OpI)
- if (OpI.isDef()) {
- const Value *Def = *OpI;
- bool isCC = (OpI.getMachineOperand().getType()
- == MachineOperand::MO_CCRegister);
- LiveRange* LR = createOrAddToLiveRange(Def, isCC);
-
- // If the operand has a pre-assigned register,
- // set it directly in the LiveRange
- if (OpI.getMachineOperand().hasAllocatedReg()) {
- unsigned getClassId;
- LR->setColor(MRI.getClassRegNum(OpI.getMachineOperand().getReg(),
- getClassId));
- }
- }
-
- // iterate over implicit MI operands and create a new LR
- // for each operand that is defined by the instruction
- for (unsigned i = 0; i < MInst->getNumImplicitRefs(); ++i)
- if (MInst->getImplicitOp(i).isDef()) {
- const Value *Def = MInst->getImplicitRef(i);
- LiveRange* LR = createOrAddToLiveRange(Def, /*isCC*/ false);
-
- // If the implicit operand has a pre-assigned register,
- // set it directly in the LiveRange
- if (MInst->getImplicitOp(i).hasAllocatedReg()) {
- unsigned getClassId;
- LR->setColor(MRI.getClassRegNum(
- MInst->getImplicitOp(i).getReg(),
- getClassId));
- }
- }
-
- } // for all machine instructions in the BB
- } // for all BBs in function
-
- // Now we have to suggest clors for call and return arg live ranges.
- // Also, if there are implicit defs (e.g., retun value of a call inst)
- // they must be added to the live range list
- //
- suggestRegs4CallRets();
-
- if( DEBUG_RA >= RA_DEBUG_LiveRanges)
- std::cerr << "Initial Live Ranges constructed!\n";
-}
-
-
-//---------------------------------------------------------------------------
-// If some live ranges must be colored with specific hardware registers
-// (e.g., for outgoing call args), suggesting of colors for such live
-// ranges is done using target specific function. Those functions are called
-// from this function. The target specific methods must:
-// 1) suggest colors for call and return args.
-// 2) create new LRs for implicit defs in machine instructions
-//---------------------------------------------------------------------------
-void LiveRangeInfo::suggestRegs4CallRets() {
- std::vector<MachineInstr*>::iterator It = CallRetInstrList.begin();
- for( ; It != CallRetInstrList.end(); ++It) {
- MachineInstr *MInst = *It;
- MachineOpCode OpCode = MInst->getOpcode();
-
- if ((TM.getInstrInfo()).isReturn(OpCode))
- MRI.suggestReg4RetValue(MInst, *this);
- else if ((TM.getInstrInfo()).isCall(OpCode))
- MRI.suggestRegs4CallArgs(MInst, *this);
- else
- assert( 0 && "Non call/ret instr in CallRetInstrList" );
- }
-}
-
-
-//--------------------------------------------------------------------------
-// The following method coalesces live ranges when possible. This method
-// must be called after the interference graph has been constructed.
-
-
-/* Algorithm:
- for each BB in function
- for each machine instruction (inst)
- for each definition (def) in inst
- for each operand (op) of inst that is a use
- if the def and op are of the same register type
- if the def and op do not interfere //i.e., not simultaneously live
- if (degree(LR of def) + degree(LR of op)) <= # avail regs
- if both LRs do not have suggested colors
- merge2IGNodes(def, op) // i.e., merge 2 LRs
-
-*/
-//---------------------------------------------------------------------------
-
-
-// Checks if live range LR interferes with any node assigned or suggested to
-// be assigned the specified color
-//
-inline bool InterferesWithColor(const LiveRange& LR, unsigned color) {
- IGNode* lrNode = LR.getUserIGNode();
- for (unsigned n=0, NN = lrNode->getNumOfNeighbors(); n < NN; n++) {
- LiveRange *neighLR = lrNode->getAdjIGNode(n)->getParentLR();
- if (neighLR->hasColor() && neighLR->getColor() == color)
- return true;
- if (neighLR->hasSuggestedColor() && neighLR->getSuggestedColor() == color)
- return true;
- }
- return false;
-}
-
-// Cannot coalesce if any of the following is true:
-// (1) Both LRs have suggested colors (should be "different suggested colors"?)
-// (2) Both LR1 and LR2 have colors and the colors are different
-// (but if the colors are the same, it is definitely safe to coalesce)
-// (3) LR1 has color and LR2 interferes with any LR that has the same color
-// (4) LR2 has color and LR1 interferes with any LR that has the same color
-//
-inline bool InterfsPreventCoalescing(const LiveRange& LROfDef,
- const LiveRange& LROfUse) {
- // (4) if they have different suggested colors, cannot coalesce
- if (LROfDef.hasSuggestedColor() && LROfUse.hasSuggestedColor())
- return true;
-
- // if neither has a color, nothing more to do.
- if (! LROfDef.hasColor() && ! LROfUse.hasColor())
- return false;
-
- // (2, 3) if L1 has color...
- if (LROfDef.hasColor()) {
- if (LROfUse.hasColor())
- return (LROfUse.getColor() != LROfDef.getColor());
- return InterferesWithColor(LROfUse, LROfDef.getColor());
- }
-
- // (4) else only LROfUse has a color: check if that could interfere
- return InterferesWithColor(LROfDef, LROfUse.getColor());
-}
-
-
-void LiveRangeInfo::coalesceLRs()
-{
- if(DEBUG_RA >= RA_DEBUG_LiveRanges)
- std::cerr << "\nCoalescing LRs ...\n";
-
- MachineFunction &MF = MachineFunction::get(Meth);
- for (MachineFunction::iterator BBI = MF.begin(); BBI != MF.end(); ++BBI) {
- MachineBasicBlock &MBB = *BBI;
-
- // iterate over all the machine instructions in BB
- for(MachineBasicBlock::iterator MII = MBB.begin(); MII != MBB.end(); ++MII){
- const MachineInstr *MI = MII;
-
- if( DEBUG_RA >= RA_DEBUG_LiveRanges) {
- std::cerr << " *Iterating over machine instr ";
- MI->dump();
- std::cerr << "\n";
- }
-
- // iterate over MI operands to find defs
- for(MachineInstr::const_val_op_iterator DefI = MI->begin(),
- DefE = MI->end(); DefI != DefE; ++DefI) {
- if (DefI.isDef()) { // this operand is modified
- LiveRange *LROfDef = getLiveRangeForValue( *DefI );
- RegClass *RCOfDef = LROfDef->getRegClass();
-
- MachineInstr::const_val_op_iterator UseI = MI->begin(),
- UseE = MI->end();
- for( ; UseI != UseE; ++UseI) { // for all uses
- LiveRange *LROfUse = getLiveRangeForValue( *UseI );
- if (!LROfUse) { // if LR of use is not found
- //don't warn about labels
- if (!isa<BasicBlock>(*UseI) && DEBUG_RA >= RA_DEBUG_LiveRanges)
- std::cerr << " !! Warning: No LR for use " << RAV(*UseI)<< "\n";
- continue; // ignore and continue
- }
-
- if (LROfUse == LROfDef) // nothing to merge if they are same
- continue;
-
- if (MRI.getRegTypeForLR(LROfDef) ==
- MRI.getRegTypeForLR(LROfUse)) {
- // If the two RegTypes are the same
- if (!RCOfDef->getInterference(LROfDef, LROfUse) ) {
-
- unsigned CombinedDegree =
- LROfDef->getUserIGNode()->getNumOfNeighbors() +
- LROfUse->getUserIGNode()->getNumOfNeighbors();
-
- if (CombinedDegree > RCOfDef->getNumOfAvailRegs()) {
- // get more precise estimate of combined degree
- CombinedDegree = LROfDef->getUserIGNode()->
- getCombinedDegree(LROfUse->getUserIGNode());
- }
-
- if (CombinedDegree <= RCOfDef->getNumOfAvailRegs()) {
- // if both LRs do not have different pre-assigned colors
- // and both LRs do not have suggested colors
- if (! InterfsPreventCoalescing(*LROfDef, *LROfUse)) {
- RCOfDef->mergeIGNodesOfLRs(LROfDef, LROfUse);
- unionAndUpdateLRs(LROfDef, LROfUse);
- }
-
- } // if combined degree is less than # of regs
- } // if def and use do not interfere
- }// if reg classes are the same
- } // for all uses
- } // if def
- } // for all defs
- } // for all machine instructions
- } // for all BBs
-
- if (DEBUG_RA >= RA_DEBUG_LiveRanges)
- std::cerr << "\nCoalescing Done!\n";
-}
-
-/*--------------------------- Debug code for printing ---------------*/
-
-
-void LiveRangeInfo::printLiveRanges() {
- LiveRangeMapType::iterator HMI = LiveRangeMap.begin(); // hash map iterator
- std::cerr << "\nPrinting Live Ranges from Hash Map:\n";
- for( ; HMI != LiveRangeMap.end(); ++HMI) {
- if (HMI->first && HMI->second) {
- std::cerr << " Value* " << RAV(HMI->first) << "\t: ";
- if (IGNode* igNode = HMI->second->getUserIGNode())
- std::cerr << "LR# " << igNode->getIndex();
- else
- std::cerr << "LR# " << "<no-IGNode>";
- std::cerr << "\t:Values = "; printSet(*HMI->second); std::cerr << "\n";
- }
- }
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/RegAlloc/LiveRangeInfo.h b/llvm/lib/Target/Sparc/RegAlloc/LiveRangeInfo.h
deleted file mode 100644
index a8d0e7152f1..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/LiveRangeInfo.h
+++ /dev/null
@@ -1,128 +0,0 @@
-//===-- LiveRangeInfo.h - Track all LiveRanges for a Function ----*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the class LiveRangeInfo which constructs and keeps
-// the LiveRangeMap which contains all the live ranges used in a method.
-//
-// Assumptions:
-//
-// All variables (llvm Values) are defined before they are used. However, a
-// constant may not be defined in the machine instruction stream if it can be
-// used as an immediate value within a machine instruction. However, register
-// allocation does not have to worry about immediate constants since they
-// do not require registers.
-//
-// Since an llvm Value has a list of uses associated, it is sufficient to
-// record only the defs in a Live Range.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LIVERANGEINFO_H
-#define LIVERANGEINFO_H
-
-#include "llvm/CodeGen/ValueSet.h"
-#include "Support/hash_map"
-
-namespace llvm {
-
-class LiveRange;
-class MachineInstr;
-class RegClass;
-class TargetRegInfo;
-class TargetMachine;
-class Value;
-class Function;
-class Instruction;
-
-typedef hash_map<const Value*, LiveRange*> LiveRangeMapType;
-
-//----------------------------------------------------------------------------
-// Class LiveRangeInfo
-//
-// Constructs and keeps the LiveRangeMap which contains all the live
-// ranges used in a method. Also contain methods to coalesce live ranges.
-//----------------------------------------------------------------------------
-
-class LiveRangeInfo {
- const Function *const Meth; // Func for which live range info is held
- LiveRangeMapType LiveRangeMap; // A map from Value * to LiveRange * to
- // record all live ranges in a method
- // created by constructLiveRanges
-
- const TargetMachine& TM; // target machine description
-
- std::vector<RegClass *> & RegClassList;// vector containing register classess
-
- const TargetRegInfo& MRI; // machine reg info
-
- std::vector<MachineInstr*> CallRetInstrList; // a list of all call/ret instrs
-
-
- //------------ Private methods (see LiveRangeInfo.cpp for description)-------
-
- LiveRange* createNewLiveRange (const Value* Def,
- bool isCC = false);
-
- LiveRange* createOrAddToLiveRange (const Value* Def,
- bool isCC = false);
-
- void unionAndUpdateLRs (LiveRange *L1,
- LiveRange *L2);
-
- void addInterference (const Instruction *Inst,
- const ValueSet *LVSet);
-
- void suggestRegs4CallRets ();
-
- const Function *getMethod () const { return Meth; }
-
-public:
-
- LiveRangeInfo(const Function *F,
- const TargetMachine& tm,
- std::vector<RegClass *> & RCList);
-
-
- /// Destructor to destroy all LiveRanges in the LiveRange Map
- ///
- ~LiveRangeInfo();
-
- // Main entry point for live range construction
- //
- void constructLiveRanges();
-
- /// return the common live range map for this method
- ///
- inline const LiveRangeMapType *getLiveRangeMap() const
- { return &LiveRangeMap; }
-
- /// Method used to get the live range containing a Value.
- /// This may return NULL if no live range exists for a Value (eg, some consts)
- ///
- inline LiveRange *getLiveRangeForValue(const Value *Val) {
- return LiveRangeMap[Val];
- }
- inline const LiveRange *getLiveRangeForValue(const Value *Val) const {
- LiveRangeMapType::const_iterator I = LiveRangeMap.find(Val);
- return I->second;
- }
-
- /// Method for coalescing live ranges. Called only after interference info
- /// is calculated.
- ///
- void coalesceLRs();
-
- /// debugging method to print the live ranges
- ///
- void printLiveRanges();
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/RegAlloc/Makefile b/llvm/lib/Target/Sparc/RegAlloc/Makefile
deleted file mode 100644
index 374c70f08a0..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-##===- lib/CodeGen/RegAlloc/Makefile -----------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file was developed by the LLVM research group and is distributed under
-# the University of Illinois Open Source License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-LEVEL = ../../../..
-
-DIRS =
-
-LIBRARYNAME = regalloc
-
-BUILD_ARCHIVE = 1
-
-include $(LEVEL)/Makefile.common
diff --git a/llvm/lib/Target/Sparc/RegAlloc/PhyRegAlloc.cpp b/llvm/lib/Target/Sparc/RegAlloc/PhyRegAlloc.cpp
deleted file mode 100644
index 7b224119cef..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/PhyRegAlloc.cpp
+++ /dev/null
@@ -1,1379 +0,0 @@
-//===-- PhyRegAlloc.cpp ---------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Traditional graph-coloring global register allocator currently used
-// by the SPARC back-end.
-//
-// NOTE: This register allocator has some special support
-// for the Reoptimizer, such as not saving some registers on calls to
-// the first-level instrumentation function.
-//
-// NOTE 2: This register allocator can save its state in a global
-// variable in the module it's working on. This feature is not
-// thread-safe; if you have doubts, leave it turned off.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AllocInfo.h"
-#include "IGNode.h"
-#include "PhyRegAlloc.h"
-#include "RegAllocCommon.h"
-#include "RegClass.h"
-#include "../LiveVar/FunctionLiveVarInfo.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/iOther.h"
-#include "llvm/Module.h"
-#include "llvm/Type.h"
-#include "llvm/Analysis/LoopInfo.h"
-#include "llvm/CodeGen/InstrSelection.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineInstrAnnot.h"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/Support/InstIterator.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "Support/CommandLine.h"
-#include "Support/SetOperations.h"
-#include "Support/STLExtras.h"
-#include <cmath>
-
-namespace llvm {
-
-RegAllocDebugLevel_t DEBUG_RA;
-
-/// The reoptimizer wants to be able to grovel through the register
-/// allocator's state after it has done its job. This is a hack.
-///
-PhyRegAlloc::SavedStateMapTy ExportedFnAllocState;
-const bool SaveStateToModule = true;
-
-static cl::opt<RegAllocDebugLevel_t, true>
-DRA_opt("dregalloc", cl::Hidden, cl::location(DEBUG_RA),
- cl::desc("enable register allocation debugging information"),
- cl::values(
- clEnumValN(RA_DEBUG_None , "n", "disable debug output"),
- clEnumValN(RA_DEBUG_Results, "y", "debug output for allocation results"),
- clEnumValN(RA_DEBUG_Coloring, "c", "debug output for graph coloring step"),
- clEnumValN(RA_DEBUG_Interference,"ig","debug output for interference graphs"),
- clEnumValN(RA_DEBUG_LiveRanges , "lr","debug output for live ranges"),
- clEnumValN(RA_DEBUG_Verbose, "v", "extra debug output"),
- 0));
-
-static cl::opt<bool>
-SaveRegAllocState("save-ra-state", cl::Hidden,
- cl::desc("write reg. allocator state into module"));
-
-FunctionPass *getRegisterAllocator(TargetMachine &T) {
- return new PhyRegAlloc (T);
-}
-
-void PhyRegAlloc::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<LoopInfo> ();
- AU.addRequired<FunctionLiveVarInfo> ();
-}
-
-
-/// Initialize interference graphs (one in each reg class) and IGNodeLists
-/// (one in each IG). The actual nodes will be pushed later.
-///
-void PhyRegAlloc::createIGNodeListsAndIGs() {
- if (DEBUG_RA >= RA_DEBUG_LiveRanges) std::cerr << "Creating LR lists ...\n";
-
- LiveRangeMapType::const_iterator HMI = LRI->getLiveRangeMap()->begin();
- LiveRangeMapType::const_iterator HMIEnd = LRI->getLiveRangeMap()->end();
-
- for (; HMI != HMIEnd ; ++HMI ) {
- if (HMI->first) {
- LiveRange *L = HMI->second; // get the LiveRange
- if (!L) {
- if (DEBUG_RA)
- std::cerr << "\n**** ?!?WARNING: NULL LIVE RANGE FOUND FOR: "
- << RAV(HMI->first) << "****\n";
- continue;
- }
-
- // if the Value * is not null, and LR is not yet written to the IGNodeList
- if (!(L->getUserIGNode()) ) {
- RegClass *const RC = // RegClass of first value in the LR
- RegClassList[ L->getRegClassID() ];
- RC->addLRToIG(L); // add this LR to an IG
- }
- }
- }
-
- // init RegClassList
- for ( unsigned rc=0; rc < NumOfRegClasses ; rc++)
- RegClassList[rc]->createInterferenceGraph();
-
- if (DEBUG_RA >= RA_DEBUG_LiveRanges) std::cerr << "LRLists Created!\n";
-}
-
-
-/// Add all interferences for a given instruction. Interference occurs only
-/// if the LR of Def (Inst or Arg) is of the same reg class as that of live
-/// var. The live var passed to this function is the LVset AFTER the
-/// instruction.
-///
-void PhyRegAlloc::addInterference(const Value *Def, const ValueSet *LVSet,
- bool isCallInst) {
- ValueSet::const_iterator LIt = LVSet->begin();
-
- // get the live range of instruction
- const LiveRange *const LROfDef = LRI->getLiveRangeForValue( Def );
-
- IGNode *const IGNodeOfDef = LROfDef->getUserIGNode();
- assert( IGNodeOfDef );
-
- RegClass *const RCOfDef = LROfDef->getRegClass();
-
- // for each live var in live variable set
- for ( ; LIt != LVSet->end(); ++LIt) {
-
- if (DEBUG_RA >= RA_DEBUG_Verbose)
- std::cerr << "< Def=" << RAV(Def) << ", Lvar=" << RAV(*LIt) << "> ";
-
- // get the live range corresponding to live var
- LiveRange *LROfVar = LRI->getLiveRangeForValue(*LIt);
-
- // LROfVar can be null if it is a const since a const
- // doesn't have a dominating def - see Assumptions above
- if (LROfVar)
- if (LROfDef != LROfVar) // do not set interf for same LR
- if (RCOfDef == LROfVar->getRegClass()) // 2 reg classes are the same
- RCOfDef->setInterference( LROfDef, LROfVar);
- }
-}
-
-
-/// For a call instruction, this method sets the CallInterference flag in
-/// the LR of each variable live in the Live Variable Set live after the
-/// call instruction (except the return value of the call instruction - since
-/// the return value does not interfere with that call itself).
-///
-void PhyRegAlloc::setCallInterferences(const MachineInstr *MInst,
- const ValueSet *LVSetAft) {
- if (DEBUG_RA >= RA_DEBUG_Interference)
- std::cerr << "\n For call inst: " << *MInst;
-
- // for each live var in live variable set after machine inst
- for (ValueSet::const_iterator LIt = LVSetAft->begin(), LEnd = LVSetAft->end();
- LIt != LEnd; ++LIt) {
-
- // get the live range corresponding to live var
- LiveRange *const LR = LRI->getLiveRangeForValue(*LIt );
-
- // LR can be null if it is a const since a const
- // doesn't have a dominating def - see Assumptions above
- if (LR ) {
- if (DEBUG_RA >= RA_DEBUG_Interference) {
- std::cerr << "\n\tLR after Call: ";
- printSet(*LR);
- }
- LR->setCallInterference();
- if (DEBUG_RA >= RA_DEBUG_Interference) {
- std::cerr << "\n ++After adding call interference for LR: " ;
- printSet(*LR);
- }
- }
-
- }
-
- // Now find the LR of the return value of the call
- // We do this because, we look at the LV set *after* the instruction
- // to determine, which LRs must be saved across calls. The return value
- // of the call is live in this set - but it does not interfere with call
- // (i.e., we can allocate a volatile register to the return value)
- CallArgsDescriptor* argDesc = CallArgsDescriptor::get(MInst);
-
- if (const Value *RetVal = argDesc->getReturnValue()) {
- LiveRange *RetValLR = LRI->getLiveRangeForValue( RetVal );
- assert( RetValLR && "No LR for RetValue of call");
- RetValLR->clearCallInterference();
- }
-
- // If the CALL is an indirect call, find the LR of the function pointer.
- // That has a call interference because it conflicts with outgoing args.
- if (const Value *AddrVal = argDesc->getIndirectFuncPtr()) {
- LiveRange *AddrValLR = LRI->getLiveRangeForValue( AddrVal );
- assert( AddrValLR && "No LR for indirect addr val of call");
- AddrValLR->setCallInterference();
- }
-}
-
-
-/// Create interferences in the IG of each RegClass, and calculate the spill
-/// cost of each Live Range (it is done in this method to save another pass
-/// over the code).
-///
-void PhyRegAlloc::buildInterferenceGraphs() {
- if (DEBUG_RA >= RA_DEBUG_Interference)
- std::cerr << "Creating interference graphs ...\n";
-
- unsigned BBLoopDepthCost;
- for (MachineFunction::iterator BBI = MF->begin(), BBE = MF->end();
- BBI != BBE; ++BBI) {
- const MachineBasicBlock &MBB = *BBI;
- const BasicBlock *BB = MBB.getBasicBlock();
-
- // find the 10^(loop_depth) of this BB
- BBLoopDepthCost = (unsigned)pow(10.0, LoopDepthCalc->getLoopDepth(BB));
-
- // get the iterator for machine instructions
- MachineBasicBlock::const_iterator MII = MBB.begin();
-
- // iterate over all the machine instructions in BB
- for ( ; MII != MBB.end(); ++MII) {
- const MachineInstr *MInst = MII;
-
- // get the LV set after the instruction
- const ValueSet &LVSetAI = LVI->getLiveVarSetAfterMInst(MInst, BB);
- bool isCallInst = TM.getInstrInfo().isCall(MInst->getOpcode());
-
- if (isCallInst) {
- // set the isCallInterference flag of each live range which extends
- // across this call instruction. This information is used by graph
- // coloring algorithm to avoid allocating volatile colors to live ranges
- // that span across calls (since they have to be saved/restored)
- setCallInterferences(MInst, &LVSetAI);
- }
-
- // iterate over all MI operands to find defs
- for (MachineInstr::const_val_op_iterator OpI = MInst->begin(),
- OpE = MInst->end(); OpI != OpE; ++OpI) {
- if (OpI.isDef()) // create a new LR since def
- addInterference(*OpI, &LVSetAI, isCallInst);
-
- // Calculate the spill cost of each live range
- LiveRange *LR = LRI->getLiveRangeForValue(*OpI);
- if (LR) LR->addSpillCost(BBLoopDepthCost);
- }
-
- // Mark all operands of pseudo-instructions as interfering with one
- // another. This must be done because pseudo-instructions may be
- // expanded to multiple instructions by the assembler, so all the
- // operands must get distinct registers.
- if (TM.getInstrInfo().isPseudoInstr(MInst->getOpcode()))
- addInterf4PseudoInstr(MInst);
-
- // Also add interference for any implicit definitions in a machine
- // instr (currently, only calls have this).
- unsigned NumOfImpRefs = MInst->getNumImplicitRefs();
- for (unsigned z=0; z < NumOfImpRefs; z++)
- if (MInst->getImplicitOp(z).isDef())
- addInterference( MInst->getImplicitRef(z), &LVSetAI, isCallInst );
-
- } // for all machine instructions in BB
- } // for all BBs in function
-
- // add interferences for function arguments. Since there are no explicit
- // defs in the function for args, we have to add them manually
- addInterferencesForArgs();
-
- if (DEBUG_RA >= RA_DEBUG_Interference)
- std::cerr << "Interference graphs calculated!\n";
-}
-
-
-/// Mark all operands of the given MachineInstr as interfering with one
-/// another.
-///
-void PhyRegAlloc::addInterf4PseudoInstr(const MachineInstr *MInst) {
- bool setInterf = false;
-
- // iterate over MI operands to find defs
- for (MachineInstr::const_val_op_iterator It1 = MInst->begin(),
- ItE = MInst->end(); It1 != ItE; ++It1) {
- const LiveRange *LROfOp1 = LRI->getLiveRangeForValue(*It1);
- assert((LROfOp1 || It1.isDef()) && "No LR for Def in PSEUDO insruction");
-
- MachineInstr::const_val_op_iterator It2 = It1;
- for (++It2; It2 != ItE; ++It2) {
- const LiveRange *LROfOp2 = LRI->getLiveRangeForValue(*It2);
-
- if (LROfOp2) {
- RegClass *RCOfOp1 = LROfOp1->getRegClass();
- RegClass *RCOfOp2 = LROfOp2->getRegClass();
-
- if (RCOfOp1 == RCOfOp2 ){
- RCOfOp1->setInterference( LROfOp1, LROfOp2 );
- setInterf = true;
- }
- } // if Op2 has a LR
- } // for all other defs in machine instr
- } // for all operands in an instruction
-
- if (!setInterf && MInst->getNumOperands() > 2) {
- std::cerr << "\nInterf not set for any operand in pseudo instr:\n";
- std::cerr << *MInst;
- assert(0 && "Interf not set for pseudo instr with > 2 operands" );
- }
-}
-
-
-/// Add interferences for incoming arguments to a function.
-///
-void PhyRegAlloc::addInterferencesForArgs() {
- // get the InSet of root BB
- const ValueSet &InSet = LVI->getInSetOfBB(&Fn->front());
-
- for (Function::const_aiterator AI = Fn->abegin(); AI != Fn->aend(); ++AI) {
- // add interferences between args and LVars at start
- addInterference(AI, &InSet, false);
-
- if (DEBUG_RA >= RA_DEBUG_Interference)
- std::cerr << " - %% adding interference for argument " << RAV(AI) << "\n";
- }
-}
-
-
-/// The following are utility functions used solely by updateMachineCode and
-/// the functions that it calls. They should probably be folded back into
-/// updateMachineCode at some point.
-///
-
-// used by: updateMachineCode (1 time), PrependInstructions (1 time)
-inline void InsertBefore(MachineInstr* newMI, MachineBasicBlock& MBB,
- MachineBasicBlock::iterator& MII) {
- MII = MBB.insert(MII, newMI);
- ++MII;
-}
-
-// used by: AppendInstructions (1 time)
-inline void InsertAfter(MachineInstr* newMI, MachineBasicBlock& MBB,
- MachineBasicBlock::iterator& MII) {
- ++MII; // insert before the next instruction
- MII = MBB.insert(MII, newMI);
-}
-
-// used by: updateMachineCode (2 times)
-inline void PrependInstructions(std::vector<MachineInstr *> &IBef,
- MachineBasicBlock& MBB,
- MachineBasicBlock::iterator& MII,
- const std::string& msg) {
- if (!IBef.empty()) {
- MachineInstr* OrigMI = MII;
- std::vector<MachineInstr *>::iterator AdIt;
- for (AdIt = IBef.begin(); AdIt != IBef.end() ; ++AdIt) {
- if (DEBUG_RA) {
- if (OrigMI) std::cerr << "For MInst:\n " << *OrigMI;
- std::cerr << msg << "PREPENDed instr:\n " << **AdIt << "\n";
- }
- InsertBefore(*AdIt, MBB, MII);
- }
- }
-}
-
-// used by: updateMachineCode (1 time)
-inline void AppendInstructions(std::vector<MachineInstr *> &IAft,
- MachineBasicBlock& MBB,
- MachineBasicBlock::iterator& MII,
- const std::string& msg) {
- if (!IAft.empty()) {
- MachineInstr* OrigMI = MII;
- std::vector<MachineInstr *>::iterator AdIt;
- for ( AdIt = IAft.begin(); AdIt != IAft.end() ; ++AdIt ) {
- if (DEBUG_RA) {
- if (OrigMI) std::cerr << "For MInst:\n " << *OrigMI;
- std::cerr << msg << "APPENDed instr:\n " << **AdIt << "\n";
- }
- InsertAfter(*AdIt, MBB, MII);
- }
- }
-}
-
-/// Set the registers for operands in the given MachineInstr, if a register was
-/// successfully allocated. Return true if any of its operands has been marked
-/// for spill.
-///
-bool PhyRegAlloc::markAllocatedRegs(MachineInstr* MInst)
-{
- bool instrNeedsSpills = false;
-
- // First, set the registers for operands in the machine instruction
- // if a register was successfully allocated. Do this first because we
- // will need to know which registers are already used by this instr'n.
- for (unsigned OpNum=0; OpNum < MInst->getNumOperands(); ++OpNum) {
- MachineOperand& Op = MInst->getOperand(OpNum);
- if (Op.getType() == MachineOperand::MO_VirtualRegister ||
- Op.getType() == MachineOperand::MO_CCRegister) {
- const Value *const Val = Op.getVRegValue();
- if (const LiveRange* LR = LRI->getLiveRangeForValue(Val)) {
- // Remember if any operand needs spilling
- instrNeedsSpills |= LR->isMarkedForSpill();
-
- // An operand may have a color whether or not it needs spilling
- if (LR->hasColor())
- MInst->SetRegForOperand(OpNum,
- MRI.getUnifiedRegNum(LR->getRegClassID(),
- LR->getColor()));
- }
- }
- } // for each operand
-
- return instrNeedsSpills;
-}
-
-/// Mark allocated registers (using markAllocatedRegs()) on the instruction
-/// that MII points to. Then, if it's a call instruction, insert caller-saving
-/// code before and after it. Finally, insert spill code before and after it,
-/// using insertCode4SpilledLR().
-///
-void PhyRegAlloc::updateInstruction(MachineBasicBlock::iterator& MII,
- MachineBasicBlock &MBB) {
- MachineInstr* MInst = MII;
- unsigned Opcode = MInst->getOpcode();
-
- // Reset tmp stack positions so they can be reused for each machine instr.
- MF->getInfo()->popAllTempValues();
-
- // Mark the operands for which regs have been allocated.
- bool instrNeedsSpills = markAllocatedRegs(MII);
-
-#ifndef NDEBUG
- // Mark that the operands have been updated. Later,
- // setRelRegsUsedByThisInst() is called to find registers used by each
- // MachineInst, and it should not be used for an instruction until
- // this is done. This flag just serves as a sanity check.
- OperandsColoredMap[MInst] = true;
-#endif
-
- // Now insert caller-saving code before/after the call.
- // Do this before inserting spill code since some registers must be
- // used by save/restore and spill code should not use those registers.
- if (TM.getInstrInfo().isCall(Opcode)) {
- AddedInstrns &AI = AddedInstrMap[MInst];
- insertCallerSavingCode(AI.InstrnsBefore, AI.InstrnsAfter, MInst,
- MBB.getBasicBlock());
- }
-
- // Now insert spill code for remaining operands not allocated to
- // registers. This must be done even for call return instructions
- // since those are not handled by the special code above.
- if (instrNeedsSpills)
- for (unsigned OpNum=0; OpNum < MInst->getNumOperands(); ++OpNum) {
- MachineOperand& Op = MInst->getOperand(OpNum);
- if (Op.getType() == MachineOperand::MO_VirtualRegister ||
- Op.getType() == MachineOperand::MO_CCRegister) {
- const Value* Val = Op.getVRegValue();
- if (const LiveRange *LR = LRI->getLiveRangeForValue(Val))
- if (LR->isMarkedForSpill())
- insertCode4SpilledLR(LR, MII, MBB, OpNum);
- }
- } // for each operand
-}
-
-/// Iterate over all the MachineBasicBlocks in the current function and set
-/// the allocated registers for each instruction (using updateInstruction()),
-/// after register allocation is complete. Then move code out of delay slots.
-///
-void PhyRegAlloc::updateMachineCode()
-{
- // Insert any instructions needed at method entry
- MachineBasicBlock::iterator MII = MF->front().begin();
- PrependInstructions(AddedInstrAtEntry.InstrnsBefore, MF->front(), MII,
- "At function entry: \n");
- assert(AddedInstrAtEntry.InstrnsAfter.empty() &&
- "InstrsAfter should be unnecessary since we are just inserting at "
- "the function entry point here.");
-
- for (MachineFunction::iterator BBI = MF->begin(), BBE = MF->end();
- BBI != BBE; ++BBI) {
- MachineBasicBlock &MBB = *BBI;
-
- // Iterate over all machine instructions in BB and mark operands with
- // their assigned registers or insert spill code, as appropriate.
- // Also, fix operands of call/return instructions.
- for (MachineBasicBlock::iterator MII = MBB.begin(); MII != MBB.end(); ++MII)
- if (! TM.getInstrInfo().isDummyPhiInstr(MII->getOpcode()))
- updateInstruction(MII, MBB);
-
- // Now, move code out of delay slots of branches and returns if needed.
- // (Also, move "after" code from calls to the last delay slot instruction.)
- // Moving code out of delay slots is needed in 2 situations:
- // (1) If this is a branch and it needs instructions inserted after it,
- // move any existing instructions out of the delay slot so that the
- // instructions can go into the delay slot. This only supports the
- // case that #instrsAfter <= #delay slots.
- //
- // (2) If any instruction in the delay slot needs
- // instructions inserted, move it out of the delay slot and before the
- // branch because putting code before or after it would be VERY BAD!
- //
- // If the annul bit of the branch is set, neither of these is legal!
- // If so, we need to handle spill differently but annulling is not yet used.
- for (MachineBasicBlock::iterator MII = MBB.begin(); MII != MBB.end(); ++MII)
- if (unsigned delaySlots =
- TM.getInstrInfo().getNumDelaySlots(MII->getOpcode())) {
- MachineBasicBlock::iterator DelaySlotMI = next(MII);
- assert(DelaySlotMI != MBB.end() && "no instruction for delay slot");
-
- // Check the 2 conditions above:
- // (1) Does a branch need instructions added after it?
- // (2) O/w does delay slot instr. need instrns before or after?
- bool isBranch = (TM.getInstrInfo().isBranch(MII->getOpcode()) ||
- TM.getInstrInfo().isReturn(MII->getOpcode()));
- bool cond1 = (isBranch &&
- AddedInstrMap.count(MII) &&
- AddedInstrMap[MII].InstrnsAfter.size() > 0);
- bool cond2 = (AddedInstrMap.count(DelaySlotMI) &&
- (AddedInstrMap[DelaySlotMI].InstrnsBefore.size() > 0 ||
- AddedInstrMap[DelaySlotMI].InstrnsAfter.size() > 0));
-
- if (cond1 || cond2) {
- assert(delaySlots==1 &&
- "InsertBefore does not yet handle >1 delay slots!");
-
- if (DEBUG_RA) {
- std::cerr << "\nRegAlloc: Moved instr. with added code: "
- << *DelaySlotMI
- << " out of delay slots of instr: " << *MII;
- }
-
- // move instruction before branch
- MBB.insert(MII, MBB.remove(DelaySlotMI));
-
- // On cond1 we are done (we already moved the
- // instruction out of the delay slot). On cond2 we need
- // to insert a nop in place of the moved instruction
- if (cond2) {
- MBB.insert(MII, BuildMI(TM.getInstrInfo().getNOPOpCode(),1));
- }
- }
- else {
- // For non-branch instr with delay slots (probably a call), move
- // InstrAfter to the instr. in the last delay slot.
- MachineBasicBlock::iterator tmp = next(MII, delaySlots);
- move2DelayedInstr(MII, tmp);
- }
- }
-
- // Finally iterate over all instructions in BB and insert before/after
- for (MachineBasicBlock::iterator MII=MBB.begin(); MII != MBB.end(); ++MII) {
- MachineInstr *MInst = MII;
-
- // do not process Phis
- if (TM.getInstrInfo().isDummyPhiInstr(MInst->getOpcode()))
- continue;
-
- // if there are any added instructions...
- if (AddedInstrMap.count(MInst)) {
- AddedInstrns &CallAI = AddedInstrMap[MInst];
-
-#ifndef NDEBUG
- bool isBranch = (TM.getInstrInfo().isBranch(MInst->getOpcode()) ||
- TM.getInstrInfo().isReturn(MInst->getOpcode()));
- assert((!isBranch ||
- AddedInstrMap[MInst].InstrnsAfter.size() <=
- TM.getInstrInfo().getNumDelaySlots(MInst->getOpcode())) &&
- "Cannot put more than #delaySlots instrns after "
- "branch or return! Need to handle temps differently.");
-#endif
-
-#ifndef NDEBUG
- // Temporary sanity checking code to detect whether the same machine
- // instruction is ever inserted twice before/after a call.
- // I suspect this is happening but am not sure. --Vikram, 7/1/03.
- std::set<const MachineInstr*> instrsSeen;
- for (int i = 0, N = CallAI.InstrnsBefore.size(); i < N; ++i) {
- assert(instrsSeen.count(CallAI.InstrnsBefore[i]) == 0 &&
- "Duplicate machine instruction in InstrnsBefore!");
- instrsSeen.insert(CallAI.InstrnsBefore[i]);
- }
- for (int i = 0, N = CallAI.InstrnsAfter.size(); i < N; ++i) {
- assert(instrsSeen.count(CallAI.InstrnsAfter[i]) == 0 &&
- "Duplicate machine instruction in InstrnsBefore/After!");
- instrsSeen.insert(CallAI.InstrnsAfter[i]);
- }
-#endif
-
- // Now add the instructions before/after this MI.
- // We do this here to ensure that spill for an instruction is inserted
- // as close as possible to an instruction (see above insertCode4Spill)
- if (! CallAI.InstrnsBefore.empty())
- PrependInstructions(CallAI.InstrnsBefore, MBB, MII,"");
-
- if (! CallAI.InstrnsAfter.empty())
- AppendInstructions(CallAI.InstrnsAfter, MBB, MII,"");
-
- } // if there are any added instructions
- } // for each machine instruction
- }
-}
-
-
-/// Insert spill code for AN operand whose LR was spilled. May be called
-/// repeatedly for a single MachineInstr if it has many spilled operands. On
-/// each call, it finds a register which is not live at that instruction and
-/// also which is not used by other spilled operands of the same
-/// instruction. Then it uses this register temporarily to accommodate the
-/// spilled value.
-///
-void PhyRegAlloc::insertCode4SpilledLR(const LiveRange *LR,
- MachineBasicBlock::iterator& MII,
- MachineBasicBlock &MBB,
- const unsigned OpNum) {
- MachineInstr *MInst = MII;
- const BasicBlock *BB = MBB.getBasicBlock();
-
- assert((! TM.getInstrInfo().isCall(MInst->getOpcode()) || OpNum == 0) &&
- "Outgoing arg of a call must be handled elsewhere (func arg ok)");
- assert(! TM.getInstrInfo().isReturn(MInst->getOpcode()) &&
- "Return value of a ret must be handled elsewhere");
-
- MachineOperand& Op = MInst->getOperand(OpNum);
- bool isDef = Op.isDef();
- bool isUse = Op.isUse();
- unsigned RegType = MRI.getRegTypeForLR(LR);
- int SpillOff = LR->getSpillOffFromFP();
- RegClass *RC = LR->getRegClass();
-
- // Get the live-variable set to find registers free before this instr.
- const ValueSet &LVSetBef = LVI->getLiveVarSetBeforeMInst(MInst, BB);
-
-#ifndef NDEBUG
- // If this instr. is in the delay slot of a branch or return, we need to
- // include all live variables before that branch or return -- we don't want to
- // trample those! Verify that the set is included in the LV set before MInst.
- if (MII != MBB.begin()) {
- MachineBasicBlock::iterator PredMI = prior(MII);
- if (unsigned DS = TM.getInstrInfo().getNumDelaySlots(PredMI->getOpcode()))
- assert(set_difference(LVI->getLiveVarSetBeforeMInst(PredMI), LVSetBef)
- .empty() && "Live-var set before branch should be included in "
- "live-var set of each delay slot instruction!");
- }
-#endif
-
- MF->getInfo()->pushTempValue(MRI.getSpilledRegSize(RegType));
-
- std::vector<MachineInstr*> MIBef, MIAft;
- std::vector<MachineInstr*> AdIMid;
-
- // Choose a register to hold the spilled value, if one was not preallocated.
- // This may insert code before and after MInst to free up the value. If so,
- // this code should be first/last in the spill sequence before/after MInst.
- int TmpRegU=(LR->hasColor()
- ? MRI.getUnifiedRegNum(LR->getRegClassID(),LR->getColor())
- : getUsableUniRegAtMI(RegType, &LVSetBef, MInst, MIBef,MIAft));
-
- // Set the operand first so that it this register does not get used
- // as a scratch register for later calls to getUsableUniRegAtMI below
- MInst->SetRegForOperand(OpNum, TmpRegU);
-
- // get the added instructions for this instruction
- AddedInstrns &AI = AddedInstrMap[MInst];
-
- // We may need a scratch register to copy the spilled value to/from memory.
- // This may itself have to insert code to free up a scratch register.
- // Any such code should go before (after) the spill code for a load (store).
- // The scratch reg is not marked as used because it is only used
- // for the copy and not used across MInst.
- int scratchRegType = -1;
- int scratchReg = -1;
- if (MRI.regTypeNeedsScratchReg(RegType, scratchRegType)) {
- scratchReg = getUsableUniRegAtMI(scratchRegType, &LVSetBef,
- MInst, MIBef, MIAft);
- assert(scratchReg != MRI.getInvalidRegNum());
- }
-
- if (isUse) {
- // for a USE, we have to load the value of LR from stack to a TmpReg
- // and use the TmpReg as one operand of instruction
-
- // actual loading instruction(s)
- MRI.cpMem2RegMI(AdIMid, MRI.getFramePointer(), SpillOff, TmpRegU,
- RegType, scratchReg);
-
- // the actual load should be after the instructions to free up TmpRegU
- MIBef.insert(MIBef.end(), AdIMid.begin(), AdIMid.end());
- AdIMid.clear();
- }
-
- if (isDef) { // if this is a Def
- // for a DEF, we have to store the value produced by this instruction
- // on the stack position allocated for this LR
-
- // actual storing instruction(s)
- MRI.cpReg2MemMI(AdIMid, TmpRegU, MRI.getFramePointer(), SpillOff,
- RegType, scratchReg);
-
- MIAft.insert(MIAft.begin(), AdIMid.begin(), AdIMid.end());
- } // if !DEF
-
- // Finally, insert the entire spill code sequences before/after MInst
- AI.InstrnsBefore.insert(AI.InstrnsBefore.end(), MIBef.begin(), MIBef.end());
- AI.InstrnsAfter.insert(AI.InstrnsAfter.begin(), MIAft.begin(), MIAft.end());
-
- if (DEBUG_RA) {
- std::cerr << "\nFor Inst:\n " << *MInst;
- std::cerr << "SPILLED LR# " << LR->getUserIGNode()->getIndex();
- std::cerr << "; added Instructions:";
- for_each(MIBef.begin(), MIBef.end(), std::mem_fun(&MachineInstr::dump));
- for_each(MIAft.begin(), MIAft.end(), std::mem_fun(&MachineInstr::dump));
- }
-}
-
-
-/// Insert caller saving/restoring instructions before/after a call machine
-/// instruction (before or after any other instructions that were inserted for
-/// the call).
-///
-void
-PhyRegAlloc::insertCallerSavingCode(std::vector<MachineInstr*> &instrnsBefore,
- std::vector<MachineInstr*> &instrnsAfter,
- MachineInstr *CallMI,
- const BasicBlock *BB) {
- assert(TM.getInstrInfo().isCall(CallMI->getOpcode()));
-
- // hash set to record which registers were saved/restored
- hash_set<unsigned> PushedRegSet;
-
- CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI);
-
- // if the call is to a instrumentation function, do not insert save and
- // restore instructions the instrumentation function takes care of save
- // restore for volatile regs.
- //
- // FIXME: this should be made general, not specific to the reoptimizer!
- const Function *Callee = argDesc->getCallInst()->getCalledFunction();
- bool isLLVMFirstTrigger = Callee && Callee->getName() == "llvm_first_trigger";
-
- // Now check if the call has a return value (using argDesc) and if so,
- // find the LR of the TmpInstruction representing the return value register.
- // (using the last or second-last *implicit operand* of the call MI).
- // Insert it to to the PushedRegSet since we must not save that register
- // and restore it after the call.
- // We do this because, we look at the LV set *after* the instruction
- // to determine, which LRs must be saved across calls. The return value
- // of the call is live in this set - but we must not save/restore it.
- if (const Value *origRetVal = argDesc->getReturnValue()) {
- unsigned retValRefNum = (CallMI->getNumImplicitRefs() -
- (argDesc->getIndirectFuncPtr()? 1 : 2));
- const TmpInstruction* tmpRetVal =
- cast<TmpInstruction>(CallMI->getImplicitRef(retValRefNum));
- assert(tmpRetVal->getOperand(0) == origRetVal &&
- tmpRetVal->getType() == origRetVal->getType() &&
- "Wrong implicit ref?");
- LiveRange *RetValLR = LRI->getLiveRangeForValue(tmpRetVal);
- assert(RetValLR && "No LR for RetValue of call");
-
- if (! RetValLR->isMarkedForSpill())
- PushedRegSet.insert(MRI.getUnifiedRegNum(RetValLR->getRegClassID(),
- RetValLR->getColor()));
- }
-
- const ValueSet &LVSetAft = LVI->getLiveVarSetAfterMInst(CallMI, BB);
- ValueSet::const_iterator LIt = LVSetAft.begin();
-
- // for each live var in live variable set after machine inst
- for( ; LIt != LVSetAft.end(); ++LIt) {
- // get the live range corresponding to live var
- LiveRange *const LR = LRI->getLiveRangeForValue(*LIt);
-
- // LR can be null if it is a const since a const
- // doesn't have a dominating def - see Assumptions above
- if (LR) {
- if (! LR->isMarkedForSpill()) {
- assert(LR->hasColor() && "LR is neither spilled nor colored?");
- unsigned RCID = LR->getRegClassID();
- unsigned Color = LR->getColor();
-
- if (MRI.isRegVolatile(RCID, Color) ) {
- // if this is a call to the first-level reoptimizer
- // instrumentation entry point, and the register is not
- // modified by call, don't save and restore it.
- if (isLLVMFirstTrigger && !MRI.modifiedByCall(RCID, Color))
- continue;
-
- // if the value is in both LV sets (i.e., live before and after
- // the call machine instruction)
- unsigned Reg = MRI.getUnifiedRegNum(RCID, Color);
-
- // if we haven't already pushed this register...
- if( PushedRegSet.find(Reg) == PushedRegSet.end() ) {
- unsigned RegType = MRI.getRegTypeForLR(LR);
-
- // Now get two instructions - to push on stack and pop from stack
- // and add them to InstrnsBefore and InstrnsAfter of the
- // call instruction
- int StackOff =
- MF->getInfo()->pushTempValue(MRI.getSpilledRegSize(RegType));
-
- //---- Insert code for pushing the reg on stack ----------
-
- std::vector<MachineInstr*> AdIBef, AdIAft;
-
- // We may need a scratch register to copy the saved value
- // to/from memory. This may itself have to insert code to
- // free up a scratch register. Any such code should go before
- // the save code. The scratch register, if any, is by default
- // temporary and not "used" by the instruction unless the
- // copy code itself decides to keep the value in the scratch reg.
- int scratchRegType = -1;
- int scratchReg = -1;
- if (MRI.regTypeNeedsScratchReg(RegType, scratchRegType))
- { // Find a register not live in the LVSet before CallMI
- const ValueSet &LVSetBef =
- LVI->getLiveVarSetBeforeMInst(CallMI, BB);
- scratchReg = getUsableUniRegAtMI(scratchRegType, &LVSetBef,
- CallMI, AdIBef, AdIAft);
- assert(scratchReg != MRI.getInvalidRegNum());
- }
-
- if (AdIBef.size() > 0)
- instrnsBefore.insert(instrnsBefore.end(),
- AdIBef.begin(), AdIBef.end());
-
- MRI.cpReg2MemMI(instrnsBefore, Reg, MRI.getFramePointer(),
- StackOff, RegType, scratchReg);
-
- if (AdIAft.size() > 0)
- instrnsBefore.insert(instrnsBefore.end(),
- AdIAft.begin(), AdIAft.end());
-
- //---- Insert code for popping the reg from the stack ----------
- AdIBef.clear();
- AdIAft.clear();
-
- // We may need a scratch register to copy the saved value
- // from memory. This may itself have to insert code to
- // free up a scratch register. Any such code should go
- // after the save code. As above, scratch is not marked "used".
- scratchRegType = -1;
- scratchReg = -1;
- if (MRI.regTypeNeedsScratchReg(RegType, scratchRegType))
- { // Find a register not live in the LVSet after CallMI
- scratchReg = getUsableUniRegAtMI(scratchRegType, &LVSetAft,
- CallMI, AdIBef, AdIAft);
- assert(scratchReg != MRI.getInvalidRegNum());
- }
-
- if (AdIBef.size() > 0)
- instrnsAfter.insert(instrnsAfter.end(),
- AdIBef.begin(), AdIBef.end());
-
- MRI.cpMem2RegMI(instrnsAfter, MRI.getFramePointer(), StackOff,
- Reg, RegType, scratchReg);
-
- if (AdIAft.size() > 0)
- instrnsAfter.insert(instrnsAfter.end(),
- AdIAft.begin(), AdIAft.end());
-
- PushedRegSet.insert(Reg);
-
- if(DEBUG_RA) {
- std::cerr << "\nFor call inst:" << *CallMI;
- std::cerr << " -inserted caller saving instrs: Before:\n\t ";
- for_each(instrnsBefore.begin(), instrnsBefore.end(),
- std::mem_fun(&MachineInstr::dump));
- std::cerr << " -and After:\n\t ";
- for_each(instrnsAfter.begin(), instrnsAfter.end(),
- std::mem_fun(&MachineInstr::dump));
- }
- } // if not already pushed
- } // if LR has a volatile color
- } // if LR has color
- } // if there is a LR for Var
- } // for each value in the LV set after instruction
-}
-
-
-/// Returns the unified register number of a temporary register to be used
-/// BEFORE MInst. If no register is available, it will pick one and modify
-/// MIBef and MIAft to contain instructions used to free up this returned
-/// register.
-///
-int PhyRegAlloc::getUsableUniRegAtMI(const int RegType,
- const ValueSet *LVSetBef,
- MachineInstr *MInst,
- std::vector<MachineInstr*>& MIBef,
- std::vector<MachineInstr*>& MIAft) {
- RegClass* RC = getRegClassByID(MRI.getRegClassIDOfRegType(RegType));
-
- int RegU = getUnusedUniRegAtMI(RC, RegType, MInst, LVSetBef);
-
- if (RegU == -1) {
- // we couldn't find an unused register. Generate code to free up a reg by
- // saving it on stack and restoring after the instruction
-
- int TmpOff = MF->getInfo()->pushTempValue(MRI.getSpilledRegSize(RegType));
-
- RegU = getUniRegNotUsedByThisInst(RC, RegType, MInst);
-
- // Check if we need a scratch register to copy this register to memory.
- int scratchRegType = -1;
- if (MRI.regTypeNeedsScratchReg(RegType, scratchRegType)) {
- int scratchReg = getUsableUniRegAtMI(scratchRegType, LVSetBef,
- MInst, MIBef, MIAft);
- assert(scratchReg != MRI.getInvalidRegNum());
-
- // We may as well hold the value in the scratch register instead
- // of copying it to memory and back. But we have to mark the
- // register as used by this instruction, so it does not get used
- // as a scratch reg. by another operand or anyone else.
- ScratchRegsUsed.insert(std::make_pair(MInst, scratchReg));
- MRI.cpReg2RegMI(MIBef, RegU, scratchReg, RegType);
- MRI.cpReg2RegMI(MIAft, scratchReg, RegU, RegType);
- } else { // the register can be copied directly to/from memory so do it.
- MRI.cpReg2MemMI(MIBef, RegU, MRI.getFramePointer(), TmpOff, RegType);
- MRI.cpMem2RegMI(MIAft, MRI.getFramePointer(), TmpOff, RegU, RegType);
- }
- }
-
- return RegU;
-}
-
-
-/// Returns the register-class register number of a new unused register that
-/// can be used to accommodate a temporary value. May be called repeatedly
-/// for a single MachineInstr. On each call, it finds a register which is not
-/// live at that instruction and which is not used by any spilled operands of
-/// that instruction.
-///
-int PhyRegAlloc::getUnusedUniRegAtMI(RegClass *RC, const int RegType,
- const MachineInstr *MInst,
- const ValueSet* LVSetBef) {
- RC->clearColorsUsed(); // Reset array
-
- if (LVSetBef == NULL) {
- LVSetBef = &LVI->getLiveVarSetBeforeMInst(MInst);
- assert(LVSetBef != NULL && "Unable to get live-var set before MInst?");
- }
-
- ValueSet::const_iterator LIt = LVSetBef->begin();
-
- // for each live var in live variable set after machine inst
- for ( ; LIt != LVSetBef->end(); ++LIt) {
- // Get the live range corresponding to live var, and its RegClass
- LiveRange *const LRofLV = LRI->getLiveRangeForValue(*LIt );
-
- // LR can be null if it is a const since a const
- // doesn't have a dominating def - see Assumptions above
- if (LRofLV && LRofLV->getRegClass() == RC && LRofLV->hasColor())
- RC->markColorsUsed(LRofLV->getColor(),
- MRI.getRegTypeForLR(LRofLV), RegType);
- }
-
- // It is possible that one operand of this MInst was already spilled
- // and it received some register temporarily. If that's the case,
- // it is recorded in machine operand. We must skip such registers.
- setRelRegsUsedByThisInst(RC, RegType, MInst);
-
- int unusedReg = RC->getUnusedColor(RegType); // find first unused color
- if (unusedReg >= 0)
- return MRI.getUnifiedRegNum(RC->getID(), unusedReg);
-
- return -1;
-}
-
-
-/// Return the unified register number of a register in class RC which is not
-/// used by any operands of MInst.
-///
-int PhyRegAlloc::getUniRegNotUsedByThisInst(RegClass *RC,
- const int RegType,
- const MachineInstr *MInst) {
- RC->clearColorsUsed();
-
- setRelRegsUsedByThisInst(RC, RegType, MInst);
-
- // find the first unused color
- int unusedReg = RC->getUnusedColor(RegType);
- assert(unusedReg >= 0 &&
- "FATAL: No free register could be found in reg class!!");
-
- return MRI.getUnifiedRegNum(RC->getID(), unusedReg);
-}
-
-
-/// Modify the IsColorUsedArr of register class RC, by setting the bits
-/// corresponding to register RegNo. This is a helper method of
-/// setRelRegsUsedByThisInst().
-///
-static void markRegisterUsed(int RegNo, RegClass *RC, int RegType,
- const TargetRegInfo &TRI) {
- unsigned classId = 0;
- int classRegNum = TRI.getClassRegNum(RegNo, classId);
- if (RC->getID() == classId)
- RC->markColorsUsed(classRegNum, RegType, RegType);
-}
-
-void PhyRegAlloc::setRelRegsUsedByThisInst(RegClass *RC, int RegType,
- const MachineInstr *MI) {
- assert(OperandsColoredMap[MI] == true &&
- "Illegal to call setRelRegsUsedByThisInst() until colored operands "
- "are marked for an instruction.");
-
- // Add the registers already marked as used by the instruction. Both
- // explicit and implicit operands are set.
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i)
- if (MI->getOperand(i).hasAllocatedReg())
- markRegisterUsed(MI->getOperand(i).getReg(), RC, RegType,MRI);
-
- for (unsigned i = 0, e = MI->getNumImplicitRefs(); i != e; ++i)
- if (MI->getImplicitOp(i).hasAllocatedReg())
- markRegisterUsed(MI->getImplicitOp(i).getReg(), RC, RegType,MRI);
-
- // Add all of the scratch registers that are used to save values across the
- // instruction (e.g., for saving state register values).
- std::pair<ScratchRegsUsedTy::iterator, ScratchRegsUsedTy::iterator>
- IR = ScratchRegsUsed.equal_range(MI);
- for (ScratchRegsUsedTy::iterator I = IR.first; I != IR.second; ++I)
- markRegisterUsed(I->second, RC, RegType, MRI);
-
- // If there are implicit references, mark their allocated regs as well
- for (unsigned z=0; z < MI->getNumImplicitRefs(); z++)
- if (const LiveRange*
- LRofImpRef = LRI->getLiveRangeForValue(MI->getImplicitRef(z)))
- if (LRofImpRef->hasColor())
- // this implicit reference is in a LR that received a color
- RC->markColorsUsed(LRofImpRef->getColor(),
- MRI.getRegTypeForLR(LRofImpRef), RegType);
-}
-
-
-/// If there are delay slots for an instruction, the instructions added after
-/// it must really go after the delayed instruction(s). So, we Move the
-/// InstrAfter of that instruction to the corresponding delayed instruction
-/// using the following method.
-///
-void PhyRegAlloc::move2DelayedInstr(const MachineInstr *OrigMI,
- const MachineInstr *DelayedMI)
-{
- // "added after" instructions of the original instr
- std::vector<MachineInstr *> &OrigAft = AddedInstrMap[OrigMI].InstrnsAfter;
-
- if (DEBUG_RA && OrigAft.size() > 0) {
- std::cerr << "\nRegAlloc: Moved InstrnsAfter for: " << *OrigMI;
- std::cerr << " to last delay slot instrn: " << *DelayedMI;
- }
-
- // "added after" instructions of the delayed instr
- std::vector<MachineInstr *> &DelayedAft=AddedInstrMap[DelayedMI].InstrnsAfter;
-
- // go thru all the "added after instructions" of the original instruction
- // and append them to the "added after instructions" of the delayed
- // instructions
- DelayedAft.insert(DelayedAft.end(), OrigAft.begin(), OrigAft.end());
-
- // empty the "added after instructions" of the original instruction
- OrigAft.clear();
-}
-
-
-void PhyRegAlloc::colorIncomingArgs()
-{
- MRI.colorMethodArgs(Fn, *LRI, AddedInstrAtEntry.InstrnsBefore,
- AddedInstrAtEntry.InstrnsAfter);
-}
-
-
-/// Determine whether the suggested color of each live range is really usable,
-/// and then call its setSuggestedColorUsable() method to record the answer. A
-/// suggested color is NOT usable when the suggested color is volatile AND
-/// when there are call interferences.
-///
-void PhyRegAlloc::markUnusableSugColors()
-{
- LiveRangeMapType::const_iterator HMI = (LRI->getLiveRangeMap())->begin();
- LiveRangeMapType::const_iterator HMIEnd = (LRI->getLiveRangeMap())->end();
-
- for (; HMI != HMIEnd ; ++HMI ) {
- if (HMI->first) {
- LiveRange *L = HMI->second; // get the LiveRange
- if (L && L->hasSuggestedColor ())
- L->setSuggestedColorUsable
- (!(MRI.isRegVolatile (L->getRegClassID (), L->getSuggestedColor ())
- && L->isCallInterference ()));
- }
- } // for all LR's in hash map
-}
-
-
-/// For each live range that is spilled, allocates a new spill position on the
-/// stack, and set the stack offsets of the live range that will be spilled to
-/// that position. This must be called just after coloring the LRs.
-///
-void PhyRegAlloc::allocateStackSpace4SpilledLRs() {
- if (DEBUG_RA) std::cerr << "\nSetting LR stack offsets for spills...\n";
-
- LiveRangeMapType::const_iterator HMI = LRI->getLiveRangeMap()->begin();
- LiveRangeMapType::const_iterator HMIEnd = LRI->getLiveRangeMap()->end();
-
- for ( ; HMI != HMIEnd ; ++HMI) {
- if (HMI->first && HMI->second) {
- LiveRange *L = HMI->second; // get the LiveRange
- if (L->isMarkedForSpill()) { // NOTE: allocating size of long Type **
- int stackOffset = MF->getInfo()->allocateSpilledValue(Type::LongTy);
- L->setSpillOffFromFP(stackOffset);
- if (DEBUG_RA)
- std::cerr << " LR# " << L->getUserIGNode()->getIndex()
- << ": stack-offset = " << stackOffset << "\n";
- }
- }
- } // for all LR's in hash map
-}
-
-
-void PhyRegAlloc::saveStateForValue (std::vector<AllocInfo> &state,
- const Value *V, unsigned Insn, int Opnd) {
- LiveRangeMapType::const_iterator HMI = LRI->getLiveRangeMap ()->find (V);
- LiveRangeMapType::const_iterator HMIEnd = LRI->getLiveRangeMap ()->end ();
- AllocInfo::AllocStateTy AllocState = AllocInfo::NotAllocated;
- int Placement = -1;
- if ((HMI != HMIEnd) && HMI->second) {
- LiveRange *L = HMI->second;
- assert ((L->hasColor () || L->isMarkedForSpill ())
- && "Live range exists but not colored or spilled");
- if (L->hasColor ()) {
- AllocState = AllocInfo::Allocated;
- Placement = MRI.getUnifiedRegNum (L->getRegClassID (),
- L->getColor ());
- } else if (L->isMarkedForSpill ()) {
- AllocState = AllocInfo::Spilled;
- assert (L->hasSpillOffset ()
- && "Live range marked for spill but has no spill offset");
- Placement = L->getSpillOffFromFP ();
- }
- }
- state.push_back (AllocInfo (Insn, Opnd, AllocState, Placement));
-}
-
-
-/// Save the global register allocation decisions made by the register
-/// allocator so that they can be accessed later (sort of like "poor man's
-/// debug info").
-///
-void PhyRegAlloc::saveState () {
- std::vector<AllocInfo> &state = FnAllocState[Fn];
- unsigned Insn = 0;
- for (const_inst_iterator II=inst_begin (Fn), IE=inst_end (Fn); II!=IE; ++II){
- saveStateForValue (state, (*II), Insn, -1);
- for (unsigned i = 0; i < (*II)->getNumOperands (); ++i) {
- const Value *V = (*II)->getOperand (i);
- // Don't worry about it unless it's something whose reg. we'll need.
- if (!isa<Argument> (V) && !isa<Instruction> (V))
- continue;
- saveStateForValue (state, V, Insn, i);
- }
- ++Insn;
- }
-}
-
-
-/// Check the saved state filled in by saveState(), and abort if it looks
-/// wrong. Only used when debugging. FIXME: Currently it just prints out
-/// the state, which isn't quite as useful.
-///
-void PhyRegAlloc::verifySavedState () {
- std::vector<AllocInfo> &state = FnAllocState[Fn];
- unsigned Insn = 0;
- for (const_inst_iterator II=inst_begin (Fn), IE=inst_end (Fn); II!=IE; ++II) {
- const Instruction *I = *II;
- MachineCodeForInstruction &Instrs = MachineCodeForInstruction::get (I);
- std::cerr << "Instruction:\n" << " " << *I << "\n"
- << "MachineCodeForInstruction:\n";
- for (unsigned i = 0, n = Instrs.size (); i != n; ++i)
- std::cerr << " " << *Instrs[i] << "\n";
- std::cerr << "FnAllocState:\n";
- for (unsigned i = 0; i < state.size (); ++i) {
- AllocInfo &S = state[i];
- if (Insn == S.Instruction)
- std::cerr << " " << S << "\n";
- }
- std::cerr << "----------\n";
- ++Insn;
- }
-}
-
-
-/// Finish the job of saveState(), by collapsing FnAllocState into an LLVM
-/// Constant and stuffing it inside the Module. (NOTE: Soon, there will be
-/// other, better ways of storing the saved state; this one is cumbersome and
-/// does not work well with the JIT.)
-///
-bool PhyRegAlloc::doFinalization (Module &M) {
- if (!SaveRegAllocState)
- return false; // Nothing to do here, unless we're saving state.
-
- // If saving state into the module, just copy new elements to the
- // correct global.
- if (!SaveStateToModule) {
- ExportedFnAllocState = FnAllocState;
- // FIXME: should ONLY copy new elements in FnAllocState
- return false;
- }
-
- // Convert FnAllocState to a single Constant array and add it
- // to the Module.
- ArrayType *AT = ArrayType::get (AllocInfo::getConstantType (), 0);
- std::vector<const Type *> TV;
- TV.push_back (Type::UIntTy);
- TV.push_back (AT);
- PointerType *PT = PointerType::get (StructType::get (TV));
-
- std::vector<Constant *> allstate;
- for (Module::iterator I = M.begin (), E = M.end (); I != E; ++I) {
- Function *F = I;
- if (F->isExternal ()) continue;
- if (FnAllocState.find (F) == FnAllocState.end ()) {
- allstate.push_back (ConstantPointerNull::get (PT));
- } else {
- std::vector<AllocInfo> &state = FnAllocState[F];
-
- // Convert state into an LLVM ConstantArray, and put it in a
- // ConstantStruct (named S) along with its size.
- std::vector<Constant *> stateConstants;
- for (unsigned i = 0, s = state.size (); i != s; ++i)
- stateConstants.push_back (state[i].toConstant ());
- unsigned Size = stateConstants.size ();
- ArrayType *AT = ArrayType::get (AllocInfo::getConstantType (), Size);
- std::vector<const Type *> TV;
- TV.push_back (Type::UIntTy);
- TV.push_back (AT);
- StructType *ST = StructType::get (TV);
- std::vector<Constant *> CV;
- CV.push_back (ConstantUInt::get (Type::UIntTy, Size));
- CV.push_back (ConstantArray::get (AT, stateConstants));
- Constant *S = ConstantStruct::get (ST, CV);
-
- GlobalVariable *GV =
- new GlobalVariable (ST, true,
- GlobalValue::InternalLinkage, S,
- F->getName () + ".regAllocState", &M);
-
- // Have: { uint, [Size x { uint, int, uint, int }] } *
- // Cast it to: { uint, [0 x { uint, int, uint, int }] } *
- Constant *CE = ConstantExpr::getCast (ConstantPointerRef::get (GV), PT);
- allstate.push_back (CE);
- }
- }
-
- unsigned Size = allstate.size ();
- // Final structure type is:
- // { uint, [Size x { uint, [0 x { uint, int, uint, int }] } *] }
- std::vector<const Type *> TV2;
- TV2.push_back (Type::UIntTy);
- ArrayType *AT2 = ArrayType::get (PT, Size);
- TV2.push_back (AT2);
- StructType *ST2 = StructType::get (TV2);
- std::vector<Constant *> CV2;
- CV2.push_back (ConstantUInt::get (Type::UIntTy, Size));
- CV2.push_back (ConstantArray::get (AT2, allstate));
- new GlobalVariable (ST2, true, GlobalValue::ExternalLinkage,
- ConstantStruct::get (ST2, CV2), "_llvm_regAllocState",
- &M);
- return false; // No error.
-}
-
-
-/// Allocate registers for the machine code previously generated for F using
-/// the graph-coloring algorithm.
-///
-bool PhyRegAlloc::runOnFunction (Function &F) {
- if (DEBUG_RA)
- std::cerr << "\n********* Function "<< F.getName () << " ***********\n";
-
- Fn = &F;
- MF = &MachineFunction::get (Fn);
- LVI = &getAnalysis<FunctionLiveVarInfo> ();
- LRI = new LiveRangeInfo (Fn, TM, RegClassList);
- LoopDepthCalc = &getAnalysis<LoopInfo> ();
-
- // Create each RegClass for the target machine and add it to the
- // RegClassList. This must be done before calling constructLiveRanges().
- for (unsigned rc = 0; rc != NumOfRegClasses; ++rc)
- RegClassList.push_back (new RegClass (Fn, &TM.getRegInfo (),
- MRI.getMachineRegClass (rc)));
-
- LRI->constructLiveRanges(); // create LR info
- if (DEBUG_RA >= RA_DEBUG_LiveRanges)
- LRI->printLiveRanges();
-
- createIGNodeListsAndIGs(); // create IGNode list and IGs
-
- buildInterferenceGraphs(); // build IGs in all reg classes
-
- if (DEBUG_RA >= RA_DEBUG_LiveRanges) {
- // print all LRs in all reg classes
- for ( unsigned rc=0; rc < NumOfRegClasses ; rc++)
- RegClassList[rc]->printIGNodeList();
-
- // print IGs in all register classes
- for ( unsigned rc=0; rc < NumOfRegClasses ; rc++)
- RegClassList[rc]->printIG();
- }
-
- LRI->coalesceLRs(); // coalesce all live ranges
-
- if (DEBUG_RA >= RA_DEBUG_LiveRanges) {
- // print all LRs in all reg classes
- for (unsigned rc=0; rc < NumOfRegClasses; rc++)
- RegClassList[rc]->printIGNodeList();
-
- // print IGs in all register classes
- for (unsigned rc=0; rc < NumOfRegClasses; rc++)
- RegClassList[rc]->printIG();
- }
-
- // mark un-usable suggested color before graph coloring algorithm.
- // When this is done, the graph coloring algo will not reserve
- // suggested color unnecessarily - they can be used by another LR
- markUnusableSugColors();
-
- // color all register classes using the graph coloring algo
- for (unsigned rc=0; rc < NumOfRegClasses ; rc++)
- RegClassList[rc]->colorAllRegs();
-
- // After graph coloring, if some LRs did not receive a color (i.e, spilled)
- // a position for such spilled LRs
- allocateStackSpace4SpilledLRs();
-
- // Reset the temp. area on the stack before use by the first instruction.
- // This will also happen after updating each instruction.
- MF->getInfo()->popAllTempValues();
-
- // color incoming args - if the correct color was not received
- // insert code to copy to the correct register
- colorIncomingArgs();
-
- // Save register allocation state for this function in a Constant.
- if (SaveRegAllocState)
- saveState();
- if (DEBUG_RA) { // Check our work.
- verifySavedState ();
- }
-
- // Now update the machine code with register names and add any additional
- // code inserted by the register allocator to the instruction stream.
- updateMachineCode();
-
- if (DEBUG_RA) {
- std::cerr << "\n**** Machine Code After Register Allocation:\n\n";
- MF->dump();
- }
-
- // Tear down temporary data structures
- for (unsigned rc = 0; rc < NumOfRegClasses; ++rc)
- delete RegClassList[rc];
- RegClassList.clear ();
- AddedInstrMap.clear ();
- OperandsColoredMap.clear ();
- ScratchRegsUsed.clear ();
- AddedInstrAtEntry.clear ();
- delete LRI;
-
- if (DEBUG_RA) std::cerr << "\nRegister allocation complete!\n";
- return false; // Function was not modified
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/RegAlloc/PhyRegAlloc.h b/llvm/lib/Target/Sparc/RegAlloc/PhyRegAlloc.h
deleted file mode 100644
index 4ec083c8ea3..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/PhyRegAlloc.h
+++ /dev/null
@@ -1,186 +0,0 @@
-//===-- PhyRegAlloc.h - Graph Coloring Register Allocator -------*- c++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is the main entry point for register allocation.
-//
-// Notes:
-// * RegisterClasses: Each RegClass accepts a
-// TargetRegClass which contains machine specific info about that register
-// class. The code in the RegClass is machine independent and they use
-// access functions in the TargetRegClass object passed into it to get
-// machine specific info.
-//
-// * Machine dependent work: All parts of the register coloring algorithm
-// except coloring of an individual node are machine independent.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef PHYREGALLOC_H
-#define PHYREGALLOC_H
-
-#include "LiveRangeInfo.h"
-#include "llvm/Pass.h"
-#include "llvm/CodeGen/MachineBasicBlock.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegInfo.h"
-#include <map>
-
-namespace llvm {
-
-class MachineFunction;
-class FunctionLiveVarInfo;
-class MachineInstr;
-class LoopInfo;
-class RegClass;
-class Constant;
-
-//----------------------------------------------------------------------------
-// Class AddedInstrns:
-// When register allocator inserts new instructions in to the existing
-// instruction stream, it does NOT directly modify the instruction stream.
-// Rather, it creates an object of AddedInstrns and stick it in the
-// AddedInstrMap for an existing instruction. This class contains two vectors
-// to store such instructions added before and after an existing instruction.
-//----------------------------------------------------------------------------
-
-struct AddedInstrns {
- std::vector<MachineInstr*> InstrnsBefore;//Insts added BEFORE an existing inst
- std::vector<MachineInstr*> InstrnsAfter; //Insts added AFTER an existing inst
- inline void clear () { InstrnsBefore.clear (); InstrnsAfter.clear (); }
-};
-
-//----------------------------------------------------------------------------
-// class PhyRegAlloc:
-// Main class the register allocator. Call runOnFunction() to allocate
-// registers for a Function.
-//----------------------------------------------------------------------------
-
-class PhyRegAlloc : public FunctionPass {
- std::vector<RegClass *> RegClassList; // vector of register classes
- const TargetMachine &TM; // target machine
- const Function *Fn; // name of the function we work on
- MachineFunction *MF; // descriptor for method's native code
- FunctionLiveVarInfo *LVI; // LV information for this method
- // (already computed for BBs)
- LiveRangeInfo *LRI; // LR info (will be computed)
- const TargetRegInfo &MRI; // Machine Register information
- const unsigned NumOfRegClasses; // recorded here for efficiency
-
- // Map to indicate whether operands of each MachineInstr have been
- // updated according to their assigned colors. This is only used in
- // assertion checking (debug builds).
- std::map<const MachineInstr *, bool> OperandsColoredMap;
-
- // AddedInstrMap - Used to store instrns added in this phase
- std::map<const MachineInstr *, AddedInstrns> AddedInstrMap;
-
- // ScratchRegsUsed - Contains scratch register uses for a particular MI.
- typedef std::multimap<const MachineInstr*, int> ScratchRegsUsedTy;
- ScratchRegsUsedTy ScratchRegsUsed;
-
- AddedInstrns AddedInstrAtEntry; // to store instrns added at entry
- const LoopInfo *LoopDepthCalc; // to calculate loop depths
-
- PhyRegAlloc(const PhyRegAlloc&); // DO NOT IMPLEMENT
- void operator=(const PhyRegAlloc&); // DO NOT IMPLEMENT
-public:
- typedef std::map<const Function *, std::vector<AllocInfo> > SavedStateMapTy;
-
- inline PhyRegAlloc (const TargetMachine &TM_) :
- TM (TM_), MRI (TM.getRegInfo ()),
- NumOfRegClasses (MRI.getNumOfRegClasses ()) { }
- virtual ~PhyRegAlloc() { }
-
- /// runOnFunction - Main method called for allocating registers.
- ///
- virtual bool runOnFunction (Function &F);
-
- virtual bool doFinalization (Module &M);
-
- virtual void getAnalysisUsage (AnalysisUsage &AU) const;
-
- const char *getPassName () const {
- return "Traditional graph-coloring reg. allocator";
- }
-
- inline const RegClass* getRegClassByID(unsigned id) const {
- return RegClassList[id];
- }
- inline RegClass *getRegClassByID(unsigned id) { return RegClassList[id]; }
-
-private:
- SavedStateMapTy FnAllocState;
-
- void addInterference(const Value *Def, const ValueSet *LVSet,
- bool isCallInst);
- bool markAllocatedRegs(MachineInstr* MInst);
-
- void addInterferencesForArgs();
- void createIGNodeListsAndIGs();
- void buildInterferenceGraphs();
-
- void saveStateForValue (std::vector<AllocInfo> &state,
- const Value *V, unsigned Insn, int Opnd);
- void saveState();
- void verifySavedState();
-
- void setCallInterferences(const MachineInstr *MI,
- const ValueSet *LVSetAft);
-
- void move2DelayedInstr(const MachineInstr *OrigMI,
- const MachineInstr *DelayedMI);
-
- void markUnusableSugColors();
- void allocateStackSpace4SpilledLRs();
-
- void insertCode4SpilledLR(const LiveRange *LR,
- MachineBasicBlock::iterator& MII,
- MachineBasicBlock &MBB, unsigned OpNum);
-
- /// Method for inserting caller saving code. The caller must save all the
- /// volatile registers live across a call.
- ///
- void insertCallerSavingCode(std::vector<MachineInstr*>& instrnsBefore,
- std::vector<MachineInstr*>& instrnsAfter,
- MachineInstr *CallMI,
- const BasicBlock *BB);
-
- void colorIncomingArgs();
- void colorCallRetArgs();
- void updateMachineCode();
- void updateInstruction(MachineBasicBlock::iterator& MII,
- MachineBasicBlock &MBB);
-
- int getUsableUniRegAtMI(int RegType, const ValueSet *LVSetBef,
- MachineInstr *MI,
- std::vector<MachineInstr*>& MIBef,
- std::vector<MachineInstr*>& MIAft);
-
- /// Callback method used to find unused registers.
- /// LVSetBef is the live variable set to search for an unused register.
- /// If it is not specified, the LV set before the current MI is used.
- /// This is sufficient as long as no new copy instructions are generated
- /// to copy the free register to memory.
- ///
- int getUnusedUniRegAtMI(RegClass *RC, int RegType,
- const MachineInstr *MI,
- const ValueSet *LVSetBef = 0);
-
- void setRelRegsUsedByThisInst(RegClass *RC, int RegType,
- const MachineInstr *MI);
-
- int getUniRegNotUsedByThisInst(RegClass *RC, int RegType,
- const MachineInstr *MI);
-
- void addInterf4PseudoInstr(const MachineInstr *MI);
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/RegAlloc/RegAllocCommon.h b/llvm/lib/Target/Sparc/RegAlloc/RegAllocCommon.h
deleted file mode 100644
index 7dd86b205af..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/RegAllocCommon.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//===-- RegAllocCommon.h --------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Shared declarations for register allocation.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef REGALLOCCOMMON_H
-#define REGALLOCCOMMON_H
-
-namespace llvm {
-
-enum RegAllocDebugLevel_t {
- RA_DEBUG_None = 0,
- RA_DEBUG_Results = 1,
- RA_DEBUG_Coloring = 2,
- RA_DEBUG_Interference = 3,
- RA_DEBUG_LiveRanges = 4,
- RA_DEBUG_Verbose = 5
-};
-
-extern RegAllocDebugLevel_t DEBUG_RA;
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/RegAlloc/RegClass.cpp b/llvm/lib/Target/Sparc/RegAlloc/RegClass.cpp
deleted file mode 100644
index 9af87ba0e86..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/RegClass.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-//===-- RegClass.cpp -----------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// class RegClass for coloring-based register allocation for LLVM.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IGNode.h"
-#include "RegAllocCommon.h"
-#include "RegClass.h"
-#include "llvm/Target/TargetRegInfo.h"
-
-namespace llvm {
-
-//----------------------------------------------------------------------------
-// This constructor inits IG. The actual matrix is created by a call to
-// createInterferenceGraph() above.
-//----------------------------------------------------------------------------
-RegClass::RegClass(const Function *M,
- const TargetRegInfo *_MRI_,
- const TargetRegClassInfo *_MRC_)
- : Meth(M), MRI(_MRI_), MRC(_MRC_),
- RegClassID( _MRC_->getRegClassID() ),
- IG(this), IGNodeStack() {
- if (DEBUG_RA >= RA_DEBUG_Interference)
- std::cerr << "Created Reg Class: " << RegClassID << "\n";
-
- IsColorUsedArr.resize(MRC->getNumOfAllRegs());
-}
-
-
-
-//----------------------------------------------------------------------------
-// Main entry point for coloring a register class.
-//----------------------------------------------------------------------------
-void RegClass::colorAllRegs()
-{
- if (DEBUG_RA >= RA_DEBUG_Coloring)
- std::cerr << "Coloring IG of reg class " << RegClassID << " ...\n";
- // pre-color IGNodes
- pushAllIGNodes(); // push all IG Nodes
-
- unsigned int StackSize = IGNodeStack.size();
- IGNode *CurIGNode;
- // for all LRs on stack
- for (unsigned int IGN=0; IGN < StackSize; IGN++) {
- CurIGNode = IGNodeStack.top(); // pop the IGNode on top of stack
- IGNodeStack.pop();
- colorIGNode (CurIGNode); // color it
- }
-}
-
-
-
-//----------------------------------------------------------------------------
-// The method for pushing all IGNodes on to the stack.
-//----------------------------------------------------------------------------
-void RegClass::pushAllIGNodes()
-{
- bool NeedMoreSpills;
-
-
- IG.setCurDegreeOfIGNodes(); // calculate degree of IGNodes
-
- // push non-constrained IGNodes
- bool PushedAll = pushUnconstrainedIGNodes();
-
- if (DEBUG_RA >= RA_DEBUG_Coloring) {
- std::cerr << " Puhsed all-unconstrained IGNodes. ";
- if( PushedAll ) std::cerr << " No constrained nodes left.";
- std::cerr << "\n";
- }
-
- if (PushedAll) // if NO constrained nodes left
- return;
-
-
- // now, we have constrained nodes. So, push one of them (the one with min
- // spill cost) and try to push the others as unConstrained nodes.
- // Repeat this.
-
- do {
- //get node with min spill cost
- IGNode *IGNodeSpill = getIGNodeWithMinSpillCost();
- // push that node on to stack
- IGNodeStack.push(IGNodeSpill);
- // set its OnStack flag and decrement degree of neighs
- IGNodeSpill->pushOnStack();
- // now push NON-constrained ones, if any
- NeedMoreSpills = !pushUnconstrainedIGNodes();
- if (DEBUG_RA >= RA_DEBUG_Coloring)
- std::cerr << "\nConstrained IG Node found !@!" << IGNodeSpill->getIndex();
- } while(NeedMoreSpills); // repeat until we have pushed all
-
-}
-
-
-
-
-//--------------------------------------------------------------------------
-// This method goes thru all IG nodes in the IGNodeList of an IG of a
-// register class and push any unconstrained IG node left (that is not
-// already pushed)
-//--------------------------------------------------------------------------
-
-bool RegClass::pushUnconstrainedIGNodes()
-{
- // # of LRs for this reg class
- unsigned int IGNodeListSize = IG.getIGNodeList().size();
- bool pushedall = true;
-
- // a pass over IGNodeList
- for (unsigned i =0; i < IGNodeListSize; i++) {
-
- // get IGNode i from IGNodeList
- IGNode *IGNode = IG.getIGNodeList()[i];
-
- if (!IGNode ) // can be null due to merging
- continue;
-
- // if already pushed on stack, continue. This can happen since this
- // method can be called repeatedly until all constrained nodes are
- // pushed
- if (IGNode->isOnStack() )
- continue;
- // if the degree of IGNode is lower
- if ((unsigned) IGNode->getCurDegree() < MRC->getNumOfAvailRegs()) {
- IGNodeStack.push( IGNode ); // push IGNode on to the stack
- IGNode->pushOnStack(); // set OnStack and dec deg of neighs
-
- if (DEBUG_RA >= RA_DEBUG_Coloring) {
- std::cerr << " pushed un-constrained IGNode " << IGNode->getIndex()
- << " on to stack\n";
- }
- }
- else pushedall = false; // we didn't push all live ranges
-
- } // for
-
- // returns true if we pushed all live ranges - else false
- return pushedall;
-}
-
-
-
-//----------------------------------------------------------------------------
-// Get the IGNode with the minimum spill cost
-//----------------------------------------------------------------------------
-IGNode * RegClass::getIGNodeWithMinSpillCost() {
- unsigned int IGNodeListSize = IG.getIGNodeList().size();
- double MinSpillCost = 0;
- IGNode *MinCostIGNode = NULL;
- bool isFirstNode = true;
-
- // pass over IGNodeList to find the IGNode with minimum spill cost
- // among all IGNodes that are not yet pushed on to the stack
- for (unsigned int i =0; i < IGNodeListSize; i++) {
- IGNode *IGNode = IG.getIGNodeList()[i];
-
- if (!IGNode) // can be null due to merging
- continue;
-
- if (!IGNode->isOnStack()) {
- double SpillCost = (double) IGNode->getParentLR()->getSpillCost() /
- (double) (IGNode->getCurDegree() + 1);
-
- if (isFirstNode) { // for the first IG node
- MinSpillCost = SpillCost;
- MinCostIGNode = IGNode;
- isFirstNode = false;
- } else if (MinSpillCost > SpillCost) {
- MinSpillCost = SpillCost;
- MinCostIGNode = IGNode;
- }
- }
- }
-
- assert (MinCostIGNode && "No IGNode to spill");
- return MinCostIGNode;
-}
-
-
-//----------------------------------------------------------------------------
-// Color the IGNode using the machine specific code.
-//----------------------------------------------------------------------------
-void RegClass::colorIGNode(IGNode *const Node) {
- if (! Node->hasColor()) { // not colored as an arg etc.
-
- // init all elements of to IsColorUsedAr false;
- clearColorsUsed();
-
- // initialize all colors used by neighbors of this node to true
- LiveRange *LR = Node->getParentLR();
- unsigned NumNeighbors = Node->getNumOfNeighbors();
- for (unsigned n=0; n < NumNeighbors; n++) {
- IGNode *NeighIGNode = Node->getAdjIGNode(n);
- LiveRange *NeighLR = NeighIGNode->getParentLR();
-
- // Don't use a color if it is in use by the neighbor,
- // or is suggested for use by the neighbor,
- // markColorsUsed() should be given the color and the reg type for
- // LR, not for NeighLR, because it should mark registers used based on
- // the type we are looking for, not on the regType for the neighbour.
- if (NeighLR->hasColor())
- this->markColorsUsed(NeighLR->getColor(),
- MRI->getRegTypeForLR(NeighLR),
- MRI->getRegTypeForLR(LR)); // use LR, not NeighLR
- else if (NeighLR->hasSuggestedColor() &&
- NeighLR->isSuggestedColorUsable())
- this->markColorsUsed(NeighLR->getSuggestedColor(),
- MRI->getRegTypeForLR(NeighLR),
- MRI->getRegTypeForLR(LR)); // use LR, not NeighLR
- }
-
- // call the target specific code for coloring
- //
- MRC->colorIGNode(Node, IsColorUsedArr);
- } else {
- if (DEBUG_RA >= RA_DEBUG_Coloring) {
- std::cerr << " Node " << Node->getIndex();
- std::cerr << " already colored with color " << Node->getColor() << "\n";
- }
- }
-
-
- if (!Node->hasColor() ) {
- if (DEBUG_RA >= RA_DEBUG_Coloring) {
- std::cerr << " Node " << Node->getIndex();
- std::cerr << " - could not find a color (needs spilling)\n";
- }
- }
-}
-
-void RegClass::printIGNodeList() const {
- std::cerr << "IG Nodes for Register Class " << RegClassID << ":" << "\n";
- IG.printIGNodeList();
-}
-
-void RegClass::printIG() {
- std::cerr << "IG for Register Class " << RegClassID << ":" << "\n";
- IG.printIG();
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/RegAlloc/RegClass.h b/llvm/lib/Target/Sparc/RegAlloc/RegClass.h
deleted file mode 100644
index 0071f7c2129..00000000000
--- a/llvm/lib/Target/Sparc/RegAlloc/RegClass.h
+++ /dev/null
@@ -1,147 +0,0 @@
-//===-- RegClass.h - Machine Independent register coloring ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-/* Title: RegClass.h -*- C++ -*-
- Author: Ruchira Sasanka
- Date: Aug 20, 01
- Purpose: Contains machine independent methods for register coloring.
-
-*/
-
-#ifndef REGCLASS_H
-#define REGCLASS_H
-
-#include "llvm/Target/TargetRegInfo.h"
-#include "InterferenceGraph.h"
-#include <stack>
-
-namespace llvm {
-
-class TargetRegClassInfo;
-
-
-//-----------------------------------------------------------------------------
-// Class RegClass
-//
-// Implements a machine independent register class.
-//
-// This is the class that contains all data structures and common algos
-// for coloring a particular register class (e.g., int class, fp class).
-// This class is hardware independent. This class accepts a hardware
-// dependent description of machine registers (TargetRegInfo class) to
-// get hardware specific info and to color an individual IG node.
-//
-// This class contains the InterferenceGraph (IG).
-// Also it contains an IGNode stack that can be used for coloring.
-// The class provides some easy access methods to the IG methods, since these
-// methods are called thru a register class.
-//
-//-----------------------------------------------------------------------------
-class RegClass {
- const Function *const Meth; // Function we are working on
- const TargetRegInfo *MRI; // Machine register information
- const TargetRegClassInfo *const MRC; // Machine reg. class for this RegClass
- const unsigned RegClassID; // my int ID
-
- InterferenceGraph IG; // Interference graph - constructed by
- // buildInterferenceGraph
- std::stack<IGNode *> IGNodeStack; // the stack used for coloring
-
- // IsColorUsedArr - An array used for coloring each node. This array must be
- // of size MRC->getNumOfAllRegs(). Allocated once in the constructor for
- // efficiency.
- //
- std::vector<bool> IsColorUsedArr;
-
-
-
- //--------------------------- private methods ------------------------------
-
- void pushAllIGNodes();
-
- bool pushUnconstrainedIGNodes();
-
- IGNode * getIGNodeWithMinSpillCost();
-
- void colorIGNode(IGNode *const Node);
-
- // This directly marks the colors used by a particular register number
- // within the register class. External users should use the public
- // versions of this function below.
- inline void markColorUsed(unsigned classRegNum) {
- assert(classRegNum < IsColorUsedArr.size() && "Invalid register used?");
- IsColorUsedArr[classRegNum] = true;
- }
-
- inline bool isColorUsed(unsigned regNum) const {
- assert(regNum < IsColorUsedArr.size() && "Invalid register used?");
- return IsColorUsedArr[regNum];
- }
-
- public:
-
- RegClass(const Function *M,
- const TargetRegInfo *_MRI_,
- const TargetRegClassInfo *_MRC_);
-
- inline void createInterferenceGraph() { IG.createGraph(); }
-
- inline InterferenceGraph &getIG() { return IG; }
-
- inline const unsigned getID() const { return RegClassID; }
-
- inline const TargetRegClassInfo* getTargetRegClass() const { return MRC; }
-
- // main method called for coloring regs
- //
- void colorAllRegs();
-
- inline unsigned getNumOfAvailRegs() const
- { return MRC->getNumOfAvailRegs(); }
-
-
- // --- following methods are provided to access the IG contained within this
- // ---- RegClass easilly.
-
- inline void addLRToIG(LiveRange *const LR)
- { IG.addLRToIG(LR); }
-
- inline void setInterference(const LiveRange *const LR1,
- const LiveRange *const LR2)
- { IG.setInterference(LR1, LR2); }
-
- inline unsigned getInterference(const LiveRange *const LR1,
- const LiveRange *const LR2) const
- { return IG.getInterference(LR1, LR2); }
-
- inline void mergeIGNodesOfLRs(const LiveRange *const LR1,
- LiveRange *const LR2)
- { IG.mergeIGNodesOfLRs(LR1, LR2); }
-
-
- inline void clearColorsUsed() {
- IsColorUsedArr.clear();
- IsColorUsedArr.resize(MRC->getNumOfAllRegs());
- }
- inline void markColorsUsed(unsigned ClassRegNum,
- int UserRegType,
- int RegTypeWanted) {
- MRC->markColorsUsed(ClassRegNum, UserRegType, RegTypeWanted,IsColorUsedArr);
- }
- inline int getUnusedColor(int machineRegType) const {
- return MRC->findUnusedColor(machineRegType, IsColorUsedArr);
- }
-
- void printIGNodeList() const;
- void printIG();
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/Sparc.burg.in b/llvm/lib/Target/Sparc/Sparc.burg.in
deleted file mode 100644
index 38dc2439ce8..00000000000
--- a/llvm/lib/Target/Sparc/Sparc.burg.in
+++ /dev/null
@@ -1,351 +0,0 @@
-%{ // -*- C++ -*-
-/* ===----------------------------------------------------------------------===
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===*/
-
-Xinclude <cstdio>
-Xinclude <llvm/CodeGen/InstrForest.h>
-
-typedef llvm::InstrTreeNode* NODEPTR_TYPE;
-Xdefine OP_LABEL(p) ((p)->opLabel)
-Xdefine LEFT_CHILD(p) ((p)->LeftChild)
-Xdefine RIGHT_CHILD(p) ((p)->RightChild)
-Xdefine STATE_LABEL(p) ((p)->state)
-Xdefine PANIC printf
-
-// Get definitions for various instruction values that we will need...
-#define HANDLE_TERM_INST(N, OPC, CLASS) Ydefine OPC##OPCODE N
-#define HANDLE_UNARY_INST(N, OPC, CLASS) Ydefine OPC##OPCODE N
-#define HANDLE_BINARY_INST(N, OPC, CLASS) Ydefine OPC##OPCODE N
-#define HANDLE_MEMORY_INST(N, OPC, CLASS) Ydefine OPC##OPCODE N
-#define HANDLE_OTHER_INST(N, OPC, CLASS) Ydefine OPC##OPCODE N
-
-#include "llvm/Instruction.def"
-
-%}
-
-%start stmt
-
-%term Ret=RetOPCODE /* return void from a function */
-%term RetValue=101 /* return a value from a function */
-%term BrUncond=BrOPCODE
-%term BrCond=102
-%term Switch=SwitchOPCODE
- /* 4 is unused */
-%term Add=AddOPCODE
-%term Sub=SubOPCODE
-%term Mul=MulOPCODE
-%term Div=DivOPCODE
-%term Rem=RemOPCODE
-%term And=AndOPCODE
-%term Or=OrOPCODE
-%term Xor=XorOPCODE
- /* Use the next 4 to distinguish bitwise operators from
- * logical operators. This is no longer used for Sparc,
- * but may be useful for other target machines.
- * The last one is the bitwise Not(val) == XOR val, 11..1.
- * Note that it is also a binary operator, not unary.
- */
-%term BAnd=111
-%term BOr=112
-%term BXor=113
-%term BNot=213
- /* The next one is the boolean Not(val) == bool XOR val, true
- * Note that it is also a binary operator, not unary.
- */
-%term Not=313
-
-%term SetCC=114 /* use this to match all SetCC instructions */
- /* %term SetEQ=13 */
- /* %term SetNE=14 */
- /* %term SetLE=15 */
- /* %term SetGE=16 */
- /* %term SetLT=17 */
- /* %term SetGT=18 */
-%term Malloc=MallocOPCODE
-%term Free=FreeOPCODE
-%term Alloca=AllocaOPCODE
-%term AllocaN=122 /* alloca with arg N */
-%term Load=LoadOPCODE
-%term Store=StoreOPCODE
-%term GetElemPtr=GetElementPtrOPCODE
-%term GetElemPtrIdx=125 /* getElemPtr with index vector */
-
-%term Phi=PHIOPCODE
-
-%term Cast=CastOPCODE /* cast that will be ignored. others are made explicit */
-%term ToBoolTy=127
-%term ToUByteTy=128
-%term ToSByteTy=129
-%term ToUShortTy=130
-%term ToShortTy=131
-%term ToUIntTy=132
-%term ToIntTy=133
-%term ToULongTy=134
-%term ToLongTy=135
-%term ToFloatTy=136
-%term ToDoubleTy=137
-%term ToArrayTy=138
-%term ToPointerTy=139
-
-%term Call=CallOPCODE
-%term Shl=ShlOPCODE
-%term Shr=ShrOPCODE
-%term VANext=VANextOPCODE
-%term VAArg=VAArgOPCODE
- /* 33...46 are unused */
- /*
- * The foll. values should match the constants in InstrForest.h
- */
-%term VRegList=97
-%term VReg=98
-%term Constant=99
-%term Label=100
- /* 50+i is a variant of i, as defined above */
-
-
-%%
-/*-----------------------------------------------------------------------*
- * The productions of the grammar.
- * Note that all chain rules are numbered 101 and above.
- * Also, a special case of production X is numbered 100+X, 200+X, etc.
- * The cost of a 1-cycle operation is represented as 10, to allow
- * finer comparisons of costs (effectively, fractions of 1/10).
- *-----------------------------------------------------------------------*/
-
- /*
- * The top-level statements
- */
-stmt: Ret = 1 (30);
-stmt: RetValue(reg) = 2 (30);
-stmt: Store(reg,reg) = 3 (10);
-stmt: Store(reg,ptrreg) = 4 (10);
-stmt: BrUncond = 5 (20);
-stmt: BrCond(setCC) = 6 (20); /* branch on cond. code */
-stmt: BrCond(setCCconst) = 206 (10); /* may save one instruction */
-stmt: BrCond(reg) = 8 (20); /* may avoid an extra instr */
-stmt: BrCond(Constant) = 208 (20); /* may avoid an extra instr */
-stmt: Switch(reg) = 9 (30); /* cost = load + branch */
-
-stmt: reg = 111 (0);
-
- /*
- * List node used for nodes with more than 2 children
- */
-reg: VRegList(reg,reg) = 10 (0);
-
- /*
- * Special case non-terminals to help combine unary instructions.
- * Eg1: zdouble <- todouble(xfloat) * todouble(yfloat)
- * Eg2: c <- a AND (NOT b).
- * Note that the costs are counted for the special non-terminals here,
- * and should not be counted again for the reg productions later.
- */
-not: Not(reg,reg) = 21 (10);
-tobool: ToBoolTy(reg) = 22 (10);
-not: Not(tobool, reg) = 322 (10); // fold cast-to-bool into not
-toubyte: ToUByteTy(reg) = 23 (10);
-tosbyte: ToSByteTy(reg) = 24 (10);
-toushort: ToUShortTy(reg) = 25 (10);
-toshort: ToShortTy(reg) = 26 (10);
-touint: ToUIntTy(reg) = 27 (10);
-toint: ToIntTy(reg) = 28 (10);
-toulong: ToULongTy(reg) = 29 (10);
-tolong: ToLongTy(reg) = 30 (10);
-tofloat: ToFloatTy(reg) = 31 (10);
-todouble: ToDoubleTy(reg) = 32 (10);
-todoubleConst: ToDoubleTy(Constant) = 232 (10);
-
- /*
- * All the ways to produce a boolean value (Not and ToBoolTy are above):
- * -- boolean operators: Not, And, Or, ..., ToBoolTy, SetCC
- * -- an existing boolean register not in the same tree
- * -- a boolean constant
- *
- * For And, Or, Xor, we add special cases for when:
- * (a) one operand is a constant.
- * (b) one operand is a NOT, to use the ANDN, ORN, and XORN instrns.
- * We do not need the cases when both operands are constant
- * because constant folding should take care of that beforehand.
- */
-reg: And(reg,reg) = 38 (10);
-reg: And(reg,not) = 138 (0); /* cost is counted for not */
-reg: And(reg,Constant) = 238 (10);
-reg: Or (reg,reg) = 39 (10);
-reg: Or (reg,not) = 139 (0); /* cost is counted for not */
-reg: Or (reg,Constant) = 239 (10);
-reg: Xor(reg,reg) = 40 (10);
-reg: Xor(reg,not) = 140 (0); /* cost is counted for not */
-reg: Xor(reg,Constant) = 240 (10);
-
- /* Special case non-terms for BrCond(setCC) and BrCond(setCCconst) */
-setCCconst: SetCC(reg,Constant) = 41 (5);
-setCC: SetCC(reg,reg) = 42 (10);
-
-reg: not = 221 (0);
-reg: tobool = 222 (0);
-reg: setCCconst = 241 (0);
-reg: setCC = 242 (0);
-
- /*
- * Special case non-terminals for the unary cast operators.
- * Some of these can be folded into other operations (e.g., todouble).
- * The rest are just for uniformity.
- */
-reg: toubyte = 123 (0);
-reg: tosbyte = 124 (0);
-reg: toushort = 125 (0);
-reg: toshort = 126 (0);
-reg: touint = 127 (0);
-reg: toint = 128 (0);
-reg: toulong = 129 (0);
-reg: tolong = 130 (0);
-reg: tofloat = 131 (0);
-reg: todouble = 132 (0);
-reg: todoubleConst = 133 (0);
-
-reg: ToArrayTy(reg) = 19 (10);
-reg: ToPointerTy(reg) = 20 (10);
-
- /*
- * The binary arithmetic operators.
- */
-reg: Add(reg,reg) = 33 (10);
-reg: Sub(reg,reg) = 34 (10);
-reg: Mul(reg,reg) = 35 (30);
-reg: Mul(todouble,todouble) = 135 (20); /* avoids 1-2 type converts */
-reg: Div(reg,reg) = 36 (60);
-reg: Rem(reg,reg) = 37 (60);
-
- /*
- * The binary bitwise logical operators.
- */
-reg: BAnd(reg,reg) = 338 (10);
-reg: BAnd(reg,bnot) = 438 ( 0); /* cost is counted for not */
-reg: BOr( reg,reg) = 339 (10);
-reg: BOr( reg,bnot) = 439 ( 0); /* cost is counted for not */
-reg: BXor(reg,reg) = 340 (10);
-reg: BXor(reg,bnot) = 440 ( 0); /* cost is counted for not */
-
-reg: bnot = 321 ( 0);
-bnot: BNot(reg,reg) = 421 (10);
-
- /*
- * Special cases for the binary operators with one constant argument.
- * Not and BNot are effectively just one argument, so not needed here.
- */
-reg: Add(reg,Constant) = 233 (10);
-reg: Sub(reg,Constant) = 234 (10);
-reg: Mul(reg,Constant) = 235 (30);
-reg: Mul(todouble,todoubleConst) = 335 (20); /* avoids 1-2 type converts */
-reg: Div(reg,Constant) = 236 (60);
-reg: Rem(reg,Constant) = 237 (60);
-
-reg: BAnd(reg,Constant) = 538 (0);
-reg: BOr( reg,Constant) = 539 (0);
-reg: BXor(reg,Constant) = 540 (0);
-
- /*
- * Memory access instructions
- */
-reg: Load(reg) = 51 (30);
-reg: Load(ptrreg) = 52 (20); /* 1 counted for ptrreg */
-reg: ptrreg = 155 (0);
-ptrreg: GetElemPtr(reg) = 55 (10);
-ptrreg: GetElemPtrIdx(reg,reg) = 56 (10);
-reg: Alloca = 57 (10);
-reg: AllocaN(reg) = 58 (10);
-
- /*
- * Other operators producing register values
- */
-reg: Call = 61 (20); /* just ignore the operands! */
-reg: Shl(reg,reg) = 62 (20); /* 1 for issue restrictions */
-reg: Shr(reg,reg) = 63 (20); /* 1 for issue restrictions */
-reg: Phi(reg,reg) = 64 (0);
-reg: VANext(reg) = 65 (40); /* incr stack slot pointer */
-reg: VAArg(reg) = 66 (40); /* get a vararg */
-
- /*
- * Finally, leaf nodes of expression trees.
- */
-reg: VReg = 71 (0);
-reg: Constant = 72 (3); /* prefer direct use */
-
-
-
-%%
-/*-----------------------------------------------------------------------*
- * The rest of this file provides code to print the cover produced
- * by BURG and information about computed tree cost and matches.
- * This code was taken from sample.gr provided with BURG.
- *-----------------------------------------------------------------------*/
-
-void printcover(NODEPTR_TYPE p, int goalnt, int indent) {
- int eruleno = burm_rule(STATE_LABEL(p), goalnt);
- short *nts = burm_nts[eruleno];
- NODEPTR_TYPE kids[10];
- int i;
-
- if (eruleno == 0) {
- printf("no cover\n");
- return;
- }
- for (i = 0; i < indent; i++)
- printf(".");
- printf("%s\n", burm_string[eruleno]);
- burm_kids(p, eruleno, kids);
- for (i = 0; nts[i]; i++)
- printcover(kids[i], nts[i], indent+1);
-}
-
-void printtree(NODEPTR_TYPE p) {
- int op = burm_op_label(p);
-
- printf("%s", burm_opname[op]);
- switch (burm_arity[op]) {
- case 0:
- break;
- case 1:
- printf("(");
- printtree(burm_child(p, 0));
- printf(")");
- break;
- case 2:
- printf("(");
- printtree(burm_child(p, 0));
- printf(", ");
- printtree(burm_child(p, 1));
- printf(")");
- break;
- }
-}
-
-int treecost(NODEPTR_TYPE p, int goalnt, int costindex) {
- int eruleno = burm_rule(STATE_LABEL(p), goalnt);
- int cost = burm_cost[eruleno][costindex], i;
- short *nts = burm_nts[eruleno];
- NODEPTR_TYPE kids[10];
-
- burm_kids(p, eruleno, kids);
- for (i = 0; nts[i]; i++)
- cost += treecost(kids[i], nts[i], costindex);
- return cost;
-}
-
-void printMatches(NODEPTR_TYPE p) {
- int nt;
- int eruleno;
-
- printf("Node 0x%lx= ", (unsigned long)p);
- printtree(p);
- printf(" matched rules:\n");
- for (nt = 1; burm_ntname[nt] != (char*)NULL; nt++)
- if ((eruleno = burm_rule(STATE_LABEL(p), nt)) != 0)
- printf("\t%s\n", burm_string[eruleno]);
-}
diff --git a/llvm/lib/Target/Sparc/Sparc.cpp b/llvm/lib/Target/Sparc/Sparc.cpp
deleted file mode 100644
index 2b4c3cb1801..00000000000
--- a/llvm/lib/Target/Sparc/Sparc.cpp
+++ /dev/null
@@ -1,238 +0,0 @@
-//===-- Sparc.cpp - General implementation file for the Sparc Target ------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Primary interface to machine description for the UltraSPARC. Primarily just
-// initializes machine-dependent parameters in class TargetMachine, and creates
-// machine-dependent subclasses for classes such as TargetInstrInfo.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Function.h"
-#include "llvm/IntrinsicLowering.h"
-#include "llvm/PassManager.h"
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/CodeGen/InstrSelection.h"
-#include "llvm/CodeGen/InstrScheduling.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/Target/TargetMachineImpls.h"
-#include "llvm/Transforms/Scalar.h"
-#include "MappingInfo.h"
-#include "SparcInternals.h"
-#include "SparcTargetMachine.h"
-#include "Support/CommandLine.h"
-
-using namespace llvm;
-
-static const unsigned ImplicitRegUseList[] = { 0 }; /* not used yet */
-// Build the MachineInstruction Description Array...
-const TargetInstrDescriptor llvm::SparcMachineInstrDesc[] = {
-#define I(ENUM, OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
- NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS) \
- { OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
- NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS, 0, \
- ImplicitRegUseList, ImplicitRegUseList },
-#include "SparcInstr.def"
-};
-
-//---------------------------------------------------------------------------
-// Command line options to control choice of code generation passes.
-//---------------------------------------------------------------------------
-
-namespace {
- cl::opt<bool> DisableSched("disable-sched",
- cl::desc("Disable local scheduling pass"));
-
- cl::opt<bool> DisablePeephole("disable-peephole",
- cl::desc("Disable peephole optimization pass"));
-
- cl::opt<bool> EmitMappingInfo("enable-maps",
- cl::desc("Emit LLVM-to-MachineCode mapping info to assembly"));
-
- cl::opt<bool> DisableStrip("disable-strip",
- cl::desc("Do not strip the LLVM bytecode in executable"));
-}
-
-//===---------------------------------------------------------------------===//
-// Code generation/destruction passes
-//===---------------------------------------------------------------------===//
-
-namespace {
- class ConstructMachineFunction : public FunctionPass {
- TargetMachine &Target;
- public:
- ConstructMachineFunction(TargetMachine &T) : Target(T) {}
-
- const char *getPassName() const {
- return "ConstructMachineFunction";
- }
-
- bool runOnFunction(Function &F) {
- MachineFunction::construct(&F, Target).getInfo()->CalculateArgSize();
- return false;
- }
- };
-
- struct DestroyMachineFunction : public FunctionPass {
- const char *getPassName() const { return "FreeMachineFunction"; }
-
- static void freeMachineCode(Instruction &I) {
- MachineCodeForInstruction::destroy(&I);
- }
-
- bool runOnFunction(Function &F) {
- for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
- for (BasicBlock::iterator I = FI->begin(), E = FI->end(); I != E; ++I)
- MachineCodeForInstruction::get(I).dropAllReferences();
-
- for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
- for_each(FI->begin(), FI->end(), freeMachineCode);
-
- MachineFunction::destruct(&F);
- return false;
- }
- };
-
- FunctionPass *createMachineCodeConstructionPass(TargetMachine &Target) {
- return new ConstructMachineFunction(Target);
- }
-}
-
-FunctionPass *llvm::createSparcMachineCodeDestructionPass() {
- return new DestroyMachineFunction();
-}
-
-
-SparcTargetMachine::SparcTargetMachine(IntrinsicLowering *il)
- : TargetMachine("UltraSparc-Native", il, false),
- schedInfo(*this),
- regInfo(*this),
- frameInfo(*this),
- cacheInfo(*this),
- jitInfo(*this) {
-}
-
-/// addPassesToEmitAssembly - This method controls the entire code generation
-/// process for the ultra sparc.
-///
-bool
-SparcTargetMachine::addPassesToEmitAssembly(PassManager &PM, std::ostream &Out)
-{
- // The following 3 passes used to be inserted specially by llc.
- // Replace malloc and free instructions with library calls.
- PM.add(createLowerAllocationsPass());
-
- // Strip all of the symbols from the bytecode so that it will be smaller...
- if (!DisableStrip)
- PM.add(createSymbolStrippingPass());
-
- // FIXME: implement the switch instruction in the instruction selector.
- PM.add(createLowerSwitchPass());
-
- // FIXME: implement the invoke/unwind instructions!
- PM.add(createLowerInvokePass());
-
- // decompose multi-dimensional array references into single-dim refs
- PM.add(createDecomposeMultiDimRefsPass());
-
- // Construct and initialize the MachineFunction object for this fn.
- PM.add(createMachineCodeConstructionPass(*this));
-
- //Insert empty stackslots in the stack frame of each function
- //so %fp+offset-8 and %fp+offset-16 are empty slots now!
- PM.add(createStackSlotsPass(*this));
-
- // Specialize LLVM code for this target machine and then
- // run basic dataflow optimizations on LLVM code.
- PM.add(createPreSelectionPass(*this));
- PM.add(createReassociatePass());
- PM.add(createLICMPass());
- PM.add(createGCSEPass());
-
- PM.add(createInstructionSelectionPass(*this));
-
- if (!DisableSched)
- PM.add(createInstructionSchedulingWithSSAPass(*this));
-
- PM.add(getRegisterAllocator(*this));
- PM.add(createPrologEpilogInsertionPass());
-
- if (!DisablePeephole)
- PM.add(createPeepholeOptsPass(*this));
-
- if (EmitMappingInfo)
- PM.add(getMappingInfoAsmPrinterPass(Out));
-
- // Output assembly language to the .s file. Assembly emission is split into
- // two parts: Function output and Global value output. This is because
- // function output is pipelined with all of the rest of code generation stuff,
- // allowing machine code representations for functions to be free'd after the
- // function has been emitted.
- PM.add(createAsmPrinterPass(Out, *this));
- PM.add(createSparcMachineCodeDestructionPass()); // Free mem no longer needed
-
- // Emit bytecode to the assembly file into its special section next
- if (EmitMappingInfo)
- PM.add(createBytecodeAsmPrinterPass(Out));
-
- return false;
-}
-
-/// addPassesToJITCompile - This method controls the JIT method of code
-/// generation for the UltraSparc.
-///
-void SparcJITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
- const TargetData &TD = TM.getTargetData();
-
- PM.add(new TargetData("lli", TD.isLittleEndian(), TD.getPointerSize(),
- TD.getPointerAlignment(), TD.getDoubleAlignment()));
-
- // Replace malloc and free instructions with library calls.
- // Do this after tracing until lli implements these lib calls.
- // For now, it will emulate malloc and free internally.
- PM.add(createLowerAllocationsPass());
-
- // FIXME: implement the switch instruction in the instruction selector.
- PM.add(createLowerSwitchPass());
-
- // FIXME: implement the invoke/unwind instructions!
- PM.add(createLowerInvokePass());
-
- // decompose multi-dimensional array references into single-dim refs
- PM.add(createDecomposeMultiDimRefsPass());
-
- // Construct and initialize the MachineFunction object for this fn.
- PM.add(createMachineCodeConstructionPass(TM));
-
- // Specialize LLVM code for this target machine and then
- // run basic dataflow optimizations on LLVM code.
- PM.add(createPreSelectionPass(TM));
- PM.add(createReassociatePass());
- // FIXME: these passes crash the FunctionPassManager when being added...
- //PM.add(createLICMPass());
- //PM.add(createGCSEPass());
-
- PM.add(createInstructionSelectionPass(TM));
-
- PM.add(getRegisterAllocator(TM));
- PM.add(createPrologEpilogInsertionPass());
-
- if (!DisablePeephole)
- PM.add(createPeepholeOptsPass(TM));
-}
-
-/// allocateSparcTargetMachine - Allocate and return a subclass of TargetMachine
-/// that implements the Sparc backend. (the llvm/CodeGen/Sparc.h interface)
-///
-TargetMachine *llvm::allocateSparcTargetMachine(const Module &M,
- IntrinsicLowering *IL) {
- return new SparcTargetMachine(IL);
-}
diff --git a/llvm/lib/Target/Sparc/SparcInstr.def b/llvm/lib/Target/Sparc/SparcInstr.def
deleted file mode 100644
index 8c7c7c749e9..00000000000
--- a/llvm/lib/Target/Sparc/SparcInstr.def
+++ /dev/null
@@ -1,553 +0,0 @@
-//===-- SparcInstr.def - Sparc Instruction Information -----------*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file describes all of the instructions that the sparc backend uses. It
-// relys on an external 'I' macro being defined that takes the arguments
-// specified below, and is used to make all of the information relevant to an
-// instruction be in one place.
-//
-//===----------------------------------------------------------------------===//
-
-// NOTE: No include guards desired
-
-#ifndef I
-#errror "Must define I macro before including SparcInstr.def!"
-#endif
-
-// Constants for defining the maximum constant size field.
-// One #define per bit size
-//
-#define B5 ((1 << 5) - 1)
-#define B6 ((1 << 6) - 1)
-#define B12 ((1 << 12) - 1)
-#define B15 ((1 << 15) - 1)
-#define B18 ((1 << 18) - 1)
-#define B21 ((1 << 21) - 1)
-#define B22 ((1 << 22) - 1)
-#define B29 ((1 << 29) - 1)
-
-// Arguments passed into the I macro
-// enum name,
-// opCodeString,
-// numOperands,
-// resultPosition (0-based; -1 if no result),
-// maxImmedConst,
-// immedIsSignExtended,
-// numDelaySlots (in cycles)
-// latency (in cycles)
-// instr sched class (defined above)
-// instr class flags (defined in TargetInstrInfo.h)
-
-
-
-I(NOP, "nop", 0, -1, 0, false, 0, 1, SPARC_NONE, M_NOP_FLAG)
-
-// Synthetic SPARC assembly opcodes for setting a register to a constant.
-// Max immediate constant should be ignored for both these instructions.
-// Use a latency > 1 since this may generate as many as 3 instructions.
-I(SETSW, "setsw", 2, 1, 0, true , 0, 2, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG | M_PSEUDO_FLAG )
-I(SETUW, "setuw", 2, 1, 0, false, 0, 2, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG | M_ARITH_FLAG | M_PSEUDO_FLAG )
-I(SETX, "setx", 3, 2, 0, true, 0, 2, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG | M_ARITH_FLAG | M_PSEUDO_FLAG )
-
-// Set high-order bits of register and clear low-order bits
-I(SETHI, "sethi", 2, 1, B22, false, 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG | M_ARITH_FLAG)
-
-// Add or add with carry.
-I(ADDr , "add", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(ADDi , "add", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(ADDccr, "addcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-I(ADDcci, "addcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-I(ADDCr , "addc", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(ADDCi , "addc", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(ADDCccr, "addccc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-I(ADDCcci, "addccc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-
-// Subtract or subtract with carry.
-I(SUBr , "sub", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(SUBi , "sub", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(SUBccr , "subcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-I(SUBcci , "subcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-I(SUBCr , "subc", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(SUBCi , "subc", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(SUBCccr, "subccc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-I(SUBCcci, "subccc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-
-// Integer multiply, signed divide, unsigned divide.
-// Note that the deprecated 32-bit multiply and multiply-step are not used.
-I(MULXr , "mulx", 3, 2, B12, true , 0, 3, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(MULXi , "mulx", 3, 2, B12, true , 0, 3, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(SDIVXr, "sdivx", 3, 2, B12, true , 0, 6, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(SDIVXi, "sdivx", 3, 2, B12, true , 0, 6, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(UDIVXr, "udivx", 3, 2, B12, true , 0, 6, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-I(UDIVXi, "udivx", 3, 2, B12, true , 0, 6, SPARC_IEUN, M_INT_FLAG | M_ARITH_FLAG)
-
- // Floating point add, subtract, compare.
- // Note that destination of FCMP* instructions is operand 0, not operand 2.
-I(FADDS, "fadds", 3, 2, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FADDD, "faddd", 3, 2, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FADDQ, "faddq", 3, 2, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FSUBS, "fsubs", 3, 2, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FSUBD, "fsubd", 3, 2, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FSUBQ, "fsubq", 3, 2, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FCMPS, "fcmps", 3, 0, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-I(FCMPD, "fcmpd", 3, 0, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-I(FCMPQ, "fcmpq", 3, 0, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG | M_CC_FLAG )
-// NOTE: FCMPE{S,D,Q}: FP Compare With Exception are currently unused!
-
-// Floating point multiply or divide.
-I(FMULS , "fmuls", 3, 2, 0, false, 0, 3, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FMULD , "fmuld", 3, 2, 0, false, 0, 3, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FMULQ , "fmulq", 3, 2, 0, false, 0, 0, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FSMULD, "fsmuld", 3, 2, 0, false, 0, 3, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FDMULQ, "fdmulq", 3, 2, 0, false, 0, 0, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FDIVS , "fdivs", 3, 2, 0, false, 0, 12, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FDIVD , "fdivd", 3, 2, 0, false, 0, 22, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FDIVQ , "fdivq", 3, 2, 0, false, 0, 0, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FSQRTS, "fsqrts", 3, 2, 0, false, 0, 12, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FSQRTD, "fsqrtd", 3, 2, 0, false, 0, 22, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FSQRTQ, "fsqrtq", 3, 2, 0, false, 0, 0, SPARC_FPM, M_FLOAT_FLAG | M_ARITH_FLAG)
-
-// Logical operations
-I(ANDr , "and", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ANDi , "and", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ANDccr , "andcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ANDcci , "andcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ANDNr , "andn", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ANDNi , "andn", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ANDNccr, "andncc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ANDNcci, "andncc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-
-I(ORr , "or", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ORi , "or", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ORccr , "orcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ORcci , "orcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ORNr , "orn", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ORNi , "orn", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ORNccr, "orncc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-I(ORNcci, "orncc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-
-I(XORr , "xor", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(XORi , "xor", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(XORccr , "xorcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-I(XORcci , "xorcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-I(XNORr , "xnor", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(XNORi , "xnor", 3, 2, B12, true , 0, 1, SPARC_IEUN, M_INT_FLAG | M_LOGICAL_FLAG)
-I(XNORccr, "xnorcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-I(XNORcci, "xnorcc", 4, 2, B12, true , 0, 1, SPARC_IEU1, M_INT_FLAG | M_LOGICAL_FLAG)
-
-// Shift operations
-I(SLLr5 , "sll", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG)
-I(SLLi5 , "sll", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG)
-I(SRLr5 , "srl", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG)
-I(SRLi5 , "srl", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG)
-I(SRAr5 , "sra", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG)
-I(SRAi5 , "sra", 3, 2, B5, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG)
-I(SLLXr6, "sllx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG)
-I(SLLXi6, "sllx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG)
-I(SRLXr6, "srlx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG)
-I(SRLXi6, "srlx", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_LOGICAL_FLAG)
-I(SRAXr6, "srax", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG)
-I(SRAXi6, "srax", 3, 2, B6, true , 0, 1, SPARC_IEU0, M_INT_FLAG | M_ARITH_FLAG)
-
-// Floating point move, negate, and abs instructions
-I(FMOVS, "fmovs", 2, 1, 0, false, 0, 1, SPARC_FPA, M_FLOAT_FLAG)
-I(FMOVD, "fmovd", 2, 1, 0, false, 0, 1, SPARC_FPA, M_FLOAT_FLAG)
-//I(FMOVQ, "fmovq", 2, 1, 0, false, 0, ?, SPARC_FPA, M_FLOAT_FLAG)
-I(FNEGS, "fnegs", 2, 1, 0, false, 0, 1, SPARC_FPA, M_FLOAT_FLAG)
-I(FNEGD, "fnegd", 2, 1, 0, false, 0, 1, SPARC_FPA, M_FLOAT_FLAG)
-//I(FNEGQ, "fnegq", 2, 1, 0, false, 0, ?, SPARC_FPA, M_FLOAT_FLAG)
-I(FABSS, "fabss", 2, 1, 0, false, 0, 1, SPARC_FPA, M_FLOAT_FLAG)
-I(FABSD, "fabsd", 2, 1, 0, false, 0, 1, SPARC_FPA, M_FLOAT_FLAG)
-//I(FABSQ, "fabsq", 2, 1, 0, false, 0, ?, SPARC_FPA, M_FLOAT_FLAG)
-
-// Convert from floating point to floating point formats
-I(FSTOD, "fstod", 2, 1, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FSTOQ, "fstoq", 2, 1, 0, false, 0, 0, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FDTOS, "fdtos", 2, 1, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FDTOQ, "fdtoq", 2, 1, 0, false, 0, 0, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FQTOS, "fqtos", 2, 1, 0, false, 0, 0, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-I(FQTOD, "fqtod", 2, 1, 0, false, 0, 0, SPARC_FPA, M_FLOAT_FLAG | M_ARITH_FLAG)
-
-// Convert from floating point to integer formats.
-// Note that this accesses both integer and floating point registers.
-I(FSTOX, "fstox", 2, 1, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-I(FDTOX, "fdtox", 2, 1, 0, false, 0, 0, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-I(FQTOX, "fqtox", 2, 1, 0, false, 0, 2, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-I(FSTOI, "fstoi", 2, 1, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-I(FDTOI, "fdtoi", 2, 1, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-I(FQTOI, "fqtoi", 2, 1, 0, false, 0, 0, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-
-// Convert from integer to floating point formats
-// Note that this accesses both integer and floating point registers.
-I(FXTOS, "fxtos", 2, 1, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-I(FXTOD, "fxtod", 2, 1, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-I(FXTOQ, "fxtoq", 2, 1, 0, false, 0, 0, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-I(FITOS, "fitos", 2, 1, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-I(FITOD, "fitod", 2, 1, 0, false, 0, 3, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-I(FITOQ, "fitoq", 2, 1, 0, false, 0, 0, SPARC_FPA, M_FLOAT_FLAG | M_INT_FLAG | M_ARITH_FLAG)
-
-// Branch on integer comparison with zero.
-// Latency excludes the delay slot since it can be issued in same cycle.
-I(BRZ , "brz", 2, -1, B15, true , 1, 1, SPARC_CTI, M_INT_FLAG | M_BRANCH_FLAG)
-I(BRLEZ, "brlez", 2, -1, B15, true , 1, 1, SPARC_CTI, M_INT_FLAG | M_BRANCH_FLAG)
-I(BRLZ , "brlz", 2, -1, B15, true , 1, 1, SPARC_CTI, M_INT_FLAG | M_BRANCH_FLAG)
-I(BRNZ , "brnz", 2, -1, B15, true , 1, 1, SPARC_CTI, M_INT_FLAG | M_BRANCH_FLAG)
-I(BRGZ , "brgz", 2, -1, B15, true , 1, 1, SPARC_CTI, M_INT_FLAG | M_BRANCH_FLAG)
-I(BRGEZ, "brgez", 2, -1, B15, true , 1, 1, SPARC_CTI, M_INT_FLAG | M_BRANCH_FLAG)
-
-// Branch on integer condition code.
-// The first argument specifies the ICC register: %icc or %xcc
-// Latency includes the delay slot.
-I(BA , "ba", 1, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BN , "bn", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BNE , "bne", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BE , "be", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BG , "bg", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BLE , "ble", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BGE , "bge", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BL , "bl", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BGU , "bgu", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BLEU, "bleu", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BCC , "bcc", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BCS , "bcs", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BPOS, "bpos", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BNEG, "bneg", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BVC , "bvc", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(BVS , "bvs", 2, -1, B21, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-
-// Branch on floating point condition code.
-// The first argument is the FCCn register (0 <= n <= 3).
-// Latency includes the delay slot.
-I(FBA , "fba", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBN , "fbn", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBU , "fbu", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBG , "fbg", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBUG , "fbug", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBL , "fbl", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBUL , "fbul", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBLG , "fblg", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBNE , "fbne", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBE , "fbe", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBUE , "fbue", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBGE , "fbge", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBUGE, "fbuge", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBLE , "fble", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBULE, "fbule", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-I(FBO , "fbo", 2, -1, B18, true , 1, 2, SPARC_CTI, M_CC_FLAG | M_BRANCH_FLAG)
-
-// Conditional move on integer comparison with zero.
-I(MOVRZr , "movrz", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRZi , "movrz", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRLEZr, "movrlez", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRLEZi, "movrlez", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRLZr , "movrlz", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRLZi , "movrlz", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRNZr , "movrnz", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRNZi , "movrnz", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRGZr , "movrgz", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRGZi , "movrgz", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRGEZr, "movrgez", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-I(MOVRGEZi, "movrgez", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_INT_FLAG)
-
-// Conditional move on integer condition code.
-// The first argument specifies the ICC register: %icc or %xcc
-I(MOVAr , "mova", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVAi , "mova", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVNr , "movn", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVNi , "movn", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVNEr , "movne", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVNEi , "movne", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVEr , "move", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVEi , "move", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVGr , "movg", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVGi , "movg", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVLEr , "movle", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVLEi , "movle", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVGEr , "movge", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVGEi , "movge", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVLr , "movl", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVLi , "movl", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVGUr , "movgu", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVGUi , "movgu", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVLEUr, "movleu", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVLEUi, "movleu", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVCCr , "movcc", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVCCi , "movcc", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVCSr , "movcs", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVCSi , "movcs", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVPOSr, "movpos", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVPOSi, "movpos", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVNEGr, "movneg", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVNEGi, "movneg", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVVCr , "movvc", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVVCi , "movvc", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVVSr , "movvs", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVVSi , "movvs", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-
-// Conditional move (of integer register) on floating point condition code.
-// The first argument is the FCCn register (0 <= n <= 3).
-// Note that the enum name above is not the same as the assembly mnemonic
-// because some of the assembly mnemonics are the same as the move on
-// integer CC (e.g., MOVG), and we cannot have the same enum entry twice.
-I(MOVFAr , "mova", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFAi , "mova", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFNr , "movn", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFNi , "movn", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFUr , "movu", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFUi , "movu", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFGr , "movg", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFGi , "movg", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFUGr , "movug", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFUGi , "movug", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFLr , "movl", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFLi , "movl", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFULr , "movul", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFULi , "movul", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFLGr , "movlg", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFLGi , "movlg", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFNEr , "movne", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFNEi , "movne", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFEr , "move", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFEi , "move", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFUEr , "movue", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFUEi , "movue", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFGEr , "movge", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFGEi , "movge", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFUGEr, "movuge", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFUGEi, "movuge", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFLEr , "movle", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFLEi , "movle", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFULEr, "movule", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFULEi, "movule", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFOr , "movo", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-I(MOVFOi , "movo", 3, 2, B12, true , 0, 2, SPARC_SINGLE, M_CC_FLAG | M_INT_FLAG)
-
-// Conditional move of floating point register on each of the above:
-// i. on integer comparison with zero.
-// ii. on integer condition code
-// iii. on floating point condition code
-// Note that the same set is repeated for S,D,Q register classes.
-I(FMOVRSZ ,"fmovrsz", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRSLEZ,"fmovrslez",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRSLZ ,"fmovrslz", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRSNZ ,"fmovrsnz", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRSGZ ,"fmovrsgz", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRSGEZ,"fmovrsgez",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-
-I(FMOVSA , "fmovsa", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSN , "fmovsn", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSNE , "fmovsne", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSE , "fmovse", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSG , "fmovsg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSLE , "fmovsle", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSGE , "fmovsge", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSL , "fmovsl", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSGU , "fmovsgu", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSLEU, "fmovsleu", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSCC , "fmovscc", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSCS , "fmovscs", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSPOS, "fmovspos", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSNEG, "fmovsneg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSVC , "fmovsvc", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSVS , "fmovsvs", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-
-I(FMOVSFA , "fmovsa", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFN , "fmovsn", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFU , "fmovsu", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFG , "fmovsg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFUG , "fmovsug", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFL , "fmovsl", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFUL , "fmovsul", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFLG , "fmovslg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFNE , "fmovsne", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFE , "fmovse", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFUE , "fmovsue", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFGE , "fmovsge", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFUGE, "fmovsuge",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFLE , "fmovsle", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFULE, "fmovslue",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVSFO , "fmovso", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-
-I(FMOVRDZ , "fmovrdz", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRDLEZ, "fmovrdlez",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRDLZ , "fmovrdlz",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRDNZ , "fmovrdnz",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRDGZ , "fmovrdgz",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRDGEZ, "fmovrdgez",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-
-I(FMOVDA , "fmovda", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDN , "fmovdn", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDNE , "fmovdne", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDE , "fmovde", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDG , "fmovdg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDLE , "fmovdle", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDGE , "fmovdge", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDL , "fmovdl", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDGU , "fmovdgu", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDLEU, "fmovdleu", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDCC , "fmovdcc", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDCS , "fmovdcs", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDPOS, "fmovdpos", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDNEG, "fmovdneg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDVC , "fmovdvc", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDVS , "fmovdvs", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-
-I(FMOVDFA , "fmovda", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFN , "fmovdn", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFU , "fmovdu", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFG , "fmovdg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFUG , "fmovdug", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFL , "fmovdl", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFUL , "fmovdul", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFLG , "fmovdlg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFNE , "fmovdne", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFE , "fmovde", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFUE , "fmovdue", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFGE , "fmovdge", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFUGE, "fmovduge",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFLE , "fmovdle", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFULE, "fmovdule",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVDFO , "fmovdo", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-
-I(FMOVRQZ , "fmovrqz", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRQLEZ, "fmovrqlez",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRQLZ , "fmovrqlz",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRQNZ , "fmovrqnz",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRQGZ , "fmovrqgz",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-I(FMOVRQGEZ, "fmovrqgez",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CONDL_FLAG | M_FLOAT_FLAG | M_INT_FLAG)
-
-I(FMOVQA , "fmovqa", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQN , "fmovqn", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQNE , "fmovqne", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQE , "fmovqe", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQG , "fmovqg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQLE , "fmovqle", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQGE , "fmovqge", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQL , "fmovql", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQGU , "fmovqgu", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQLEU, "fmovqleu", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQCC , "fmovqcc", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQCS , "fmovqcs", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQPOS, "fmovqpos", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQNEG, "fmovqneg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQVC , "fmovqvc", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQVS , "fmovqvs", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-
-I(FMOVQFA , "fmovqa", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFN , "fmovqn", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFU , "fmovqu", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFG , "fmovqg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFUG , "fmovqug", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFL , "fmovql", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFUL , "fmovqul", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFLG , "fmovqlg", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFNE , "fmovqne", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFE , "fmovqe", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFUE , "fmovque", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFGE , "fmovqge", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFUGE, "fmovquge",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFLE , "fmovqle", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFULE, "fmovqule",3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-I(FMOVQFO , "fmovqo", 3, 2, 0, false, 0, 2, SPARC_SINGLE, M_CC_FLAG | M_FLOAT_FLAG)
-
-// Load integer instructions
-// Latency includes 1 cycle for address generation (Sparc IIi),
-// plus 3 cycles assumed for average miss penalty (bias towards L1 hits).
-// Signed loads of less than 64 bits need an extra cycle for sign-extension.
-//
-// Not reflected here: After a 3-cycle loads, all subsequent consecutive
-// loads also require 3 cycles to avoid contention for the load return
-// stage. Latency returns to 2 cycles after the first cycle with no load.
-I(LDSBr, "ldsb", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDSBi, "ldsb", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDSHr, "ldsh", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDSHi, "ldsh", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDSWr, "ldsw", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDSWi, "ldsw", 3, 2, B12, true , 0, 6, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDUBr, "ldub", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDUBi, "ldub", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDUHr, "lduh", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDUHi, "lduh", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDUWr, "lduw", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDUWi, "lduw", 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDXr , "ldx" , 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-I(LDXi , "ldx" , 3, 2, B12, true , 0, 5, SPARC_LD, M_INT_FLAG | M_LOAD_FLAG)
-
-// Load floating-point instructions
-// Latency includes 1 cycle for address generation (Sparc IIi)
-I(LDFr , "ld", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG)
-I(LDFi , "ld", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG)
-I(LDDFr, "ldd", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG)
-I(LDDFi, "ldd", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG)
-I(LDQFr, "ldq", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG)
-I(LDQFi, "ldq", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG)
-I(LDFSRr, "ld", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG)
-I(LDFSRi, "ld", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG)
-I(LDXFSRr, "ldx", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG)
-I(LDXFSRi, "ldx", 3, 2, B12, true , 0, 5, SPARC_LD, M_FLOAT_FLAG | M_LOAD_FLAG)
-
-// Store integer instructions.
-// Requires 1 cycle for address generation (Sparc IIi).
-// Default latency is 0 because value is not explicitly used.
-I(STBr, "stb", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG)
-I(STBi, "stb", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG)
-I(STHr, "sth", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG)
-I(STHi, "sth", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG)
-I(STWr, "stw", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG)
-I(STWi, "stw", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG)
-I(STXr, "stx", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG)
-I(STXi, "stx", 3, -1, B12, true , 0, 0, SPARC_ST, M_INT_FLAG | M_STORE_FLAG)
-
-// Store floating-point instructions (Sparc IIi)
-I(STFr, "st", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG)
-I(STFi, "st", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG)
-I(STDFr, "std", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG)
-I(STDFi, "std", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG)
-I(STFSRr, "st", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG)
-I(STFSRi, "st", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG)
-I(STXFSRr, "stx", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG)
-I(STXFSRi, "stx", 3, -1, B12, true , 0, 0, SPARC_ST, M_FLOAT_FLAG | M_STORE_FLAG)
-
-// Call, Return and "Jump and link". Operand (2) for JMPL is marked as
-// a "result" because JMPL stores the return address for the call in it.
-// Latency includes the delay slot.
-I(CALL, "call", 1, -1, B29, true , 1, 2, SPARC_CTI, M_CALL_FLAG)
-I(JMPLCALLr, "jmpl", 3, 2, B12, true , 1, 2, SPARC_CTI, M_CALL_FLAG)
-I(JMPLCALLi, "jmpl", 3, 2, B12, true , 1, 2, SPARC_CTI, M_CALL_FLAG)
-I(JMPLRETr, "jmpl", 3, 2, B12, true , 1, 2, SPARC_CTI, M_RET_FLAG)
-I(JMPLRETi, "jmpl", 3, 2, B12, true , 1, 2, SPARC_CTI, M_RET_FLAG)
-I(RETURNr, "return", 2, -1, 0, false, 1, 2, SPARC_CTI, M_RET_FLAG)
-I(RETURNi, "return", 2, -1, 0, false, 1, 2, SPARC_CTI, M_RET_FLAG)
-
-// SAVE and restore instructions
-I(SAVEr, "save", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG)
-I(SAVEi, "save", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG)
-I(RESTOREr, "restore", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG)
-I(RESTOREi, "restore", 3, 2, B12, true , 0, 1, SPARC_SINGLE, M_INT_FLAG | M_ARITH_FLAG)
-
-// Read and Write CCR register from/to an int reg
-I(RDCCR, "rd", 2, 1, 0, false, 0, 1, SPARC_SINGLE, M_INT_FLAG | M_CC_FLAG)
-I(WRCCRr, "wr", 3, 2, 0, false, 0, 1, SPARC_SINGLE, M_INT_FLAG | M_CC_FLAG)
-I(WRCCRi, "wr", 3, 2, 0, false, 0, 1, SPARC_SINGLE, M_INT_FLAG | M_CC_FLAG)
-
-// Synthetic phi operation for near-SSA form of machine code
-// Number of operands is variable, indicated by -1. Result is the first op.
-I(PHI, "<phi>", -1, 0, 0, false, 0, 0, SPARC_INV, M_DUMMY_PHI_FLAG)
-
-
-#undef B5
-#undef B6
-#undef B12
-#undef B15
-#undef B18
-#undef B21
-#undef B22
-#undef B29
-
-#undef I
diff --git a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp b/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
deleted file mode 100644
index af458ea0399..00000000000
--- a/llvm/lib/Target/Sparc/SparcInstrInfo.cpp
+++ /dev/null
@@ -1,799 +0,0 @@
-//===-- SparcInstrInfo.cpp ------------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Function.h"
-#include "llvm/iTerminators.h"
-#include "llvm/CodeGen/InstrSelection.h"
-#include "llvm/CodeGen/InstrSelectionSupport.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "SparcInternals.h"
-#include "SparcInstrSelectionSupport.h"
-#include "SparcInstrInfo.h"
-
-namespace llvm {
-
-static const uint32_t MAXLO = (1 << 10) - 1; // set bits set by %lo(*)
-static const uint32_t MAXSIMM = (1 << 12) - 1; // set bits in simm13 field of OR
-
-//---------------------------------------------------------------------------
-// Function ConvertConstantToIntType
-//
-// Function to get the value of an integral constant in the form
-// that must be put into the machine register. The specified constant is
-// interpreted as (i.e., converted if necessary to) the specified destination
-// type. The result is always returned as an uint64_t, since the representation
-// of int64_t and uint64_t are identical. The argument can be any known const.
-//
-// isValidConstant is set to true if a valid constant was found.
-//---------------------------------------------------------------------------
-
-uint64_t
-SparcInstrInfo::ConvertConstantToIntType(const TargetMachine &target,
- const Value *V,
- const Type *destType,
- bool &isValidConstant) const
-{
- isValidConstant = false;
- uint64_t C = 0;
-
- if (! destType->isIntegral() && ! isa<PointerType>(destType))
- return C;
-
- if (! isa<Constant>(V))
- return C;
-
- // ConstantPointerRef: no conversions needed: get value and return it
- if (const ConstantPointerRef* CPR = dyn_cast<ConstantPointerRef>(V)) {
- // A ConstantPointerRef is just a reference to GlobalValue.
- isValidConstant = true; // may be overwritten by recursive call
- return (CPR->isNullValue()? 0
- : ConvertConstantToIntType(target, CPR->getValue(), destType,
- isValidConstant));
- }
-
- // ConstantBool: no conversions needed: get value and return it
- if (const ConstantBool *CB = dyn_cast<ConstantBool>(V)) {
- isValidConstant = true;
- return (uint64_t) CB->getValue();
- }
-
- // For other types of constants, some conversion may be needed.
- // First, extract the constant operand according to its own type
- if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
- switch(CE->getOpcode()) {
- case Instruction::Cast: // recursively get the value as cast
- C = ConvertConstantToIntType(target, CE->getOperand(0), CE->getType(),
- isValidConstant);
- break;
- default: // not simplifying other ConstantExprs
- break;
- }
- else if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
- isValidConstant = true;
- C = CI->getRawValue();
- }
- else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
- isValidConstant = true;
- double fC = CFP->getValue();
- C = (destType->isSigned()? (uint64_t) (int64_t) fC
- : (uint64_t) fC);
- }
-
- // Now if a valid value was found, convert it to destType.
- if (isValidConstant) {
- unsigned opSize = target.getTargetData().getTypeSize(V->getType());
- unsigned destSize = target.getTargetData().getTypeSize(destType);
- uint64_t maskHi = (destSize < 8)? (1U << 8*destSize) - 1 : ~0;
- assert(opSize <= 8 && destSize <= 8 && ">8-byte int type unexpected");
-
- if (destType->isSigned()) {
- if (opSize > destSize) // operand is larger than dest:
- C = C & maskHi; // mask high bits
-
- if (opSize > destSize ||
- (opSize == destSize && ! V->getType()->isSigned()))
- if (C & (1U << (8*destSize - 1)))
- C = C | ~maskHi; // sign-extend from destSize to 64 bits
- }
- else {
- if (opSize > destSize || (V->getType()->isSigned() && destSize < 8)) {
- // operand is larger than dest,
- // OR both are equal but smaller than the full register size
- // AND operand is signed, so it may have extra sign bits:
- // mask high bits
- C = C & maskHi;
- }
- }
- }
-
- return C;
-}
-
-
-//----------------------------------------------------------------------------
-// Function: CreateSETUWConst
-//
-// Set a 32-bit unsigned constant in the register `dest', using
-// SETHI, OR in the worst case. This function correctly emulates
-// the SETUW pseudo-op for SPARC v9 (if argument isSigned == false).
-//
-// The isSigned=true case is used to implement SETSW without duplicating code.
-//
-// Optimize some common cases:
-// (1) Small value that fits in simm13 field of OR: don't need SETHI.
-// (2) isSigned = true and C is a small negative signed value, i.e.,
-// high bits are 1, and the remaining bits fit in simm13(OR).
-//----------------------------------------------------------------------------
-
-static inline void
-CreateSETUWConst(const TargetMachine& target, uint32_t C,
- Instruction* dest, std::vector<MachineInstr*>& mvec,
- bool isSigned = false)
-{
- MachineInstr *miSETHI = NULL, *miOR = NULL;
-
- // In order to get efficient code, we should not generate the SETHI if
- // all high bits are 1 (i.e., this is a small signed value that fits in
- // the simm13 field of OR). So we check for and handle that case specially.
- // NOTE: The value C = 0x80000000 is bad: sC < 0 *and* -sC < 0.
- // In fact, sC == -sC, so we have to check for this explicitly.
- int32_t sC = (int32_t) C;
- bool smallNegValue =isSigned && sC < 0 && sC != -sC && -sC < (int32_t)MAXSIMM;
-
- // Set the high 22 bits in dest if non-zero and simm13 field of OR not enough
- if (!smallNegValue && (C & ~MAXLO) && C > MAXSIMM) {
- miSETHI = BuildMI(V9::SETHI, 2).addZImm(C).addRegDef(dest);
- miSETHI->setOperandHi32(0);
- mvec.push_back(miSETHI);
- }
-
- // Set the low 10 or 12 bits in dest. This is necessary if no SETHI
- // was generated, or if the low 10 bits are non-zero.
- if (miSETHI==NULL || C & MAXLO) {
- if (miSETHI) {
- // unsigned value with high-order bits set using SETHI
- miOR = BuildMI(V9::ORi,3).addReg(dest).addZImm(C).addRegDef(dest);
- miOR->setOperandLo32(1);
- } else {
- // unsigned or small signed value that fits in simm13 field of OR
- assert(smallNegValue || (C & ~MAXSIMM) == 0);
- miOR = BuildMI(V9::ORi, 3).addMReg(target.getRegInfo()
- .getZeroRegNum())
- .addSImm(sC).addRegDef(dest);
- }
- mvec.push_back(miOR);
- }
-
- assert((miSETHI || miOR) && "Oops, no code was generated!");
-}
-
-
-//----------------------------------------------------------------------------
-// Function: CreateSETSWConst
-//
-// Set a 32-bit signed constant in the register `dest', with sign-extension
-// to 64 bits. This uses SETHI, OR, SRA in the worst case.
-// This function correctly emulates the SETSW pseudo-op for SPARC v9.
-//
-// Optimize the same cases as SETUWConst, plus:
-// (1) SRA is not needed for positive or small negative values.
-//----------------------------------------------------------------------------
-
-static inline void
-CreateSETSWConst(const TargetMachine& target, int32_t C,
- Instruction* dest, std::vector<MachineInstr*>& mvec)
-{
- // Set the low 32 bits of dest
- CreateSETUWConst(target, (uint32_t) C, dest, mvec, /*isSigned*/true);
-
- // Sign-extend to the high 32 bits if needed.
- // NOTE: The value C = 0x80000000 is bad: -C == C and so -C is < MAXSIMM
- if (C < 0 && (C == -C || -C > (int32_t) MAXSIMM))
- mvec.push_back(BuildMI(V9::SRAi5,3).addReg(dest).addZImm(0).addRegDef(dest));
-}
-
-
-//----------------------------------------------------------------------------
-// Function: CreateSETXConst
-//
-// Set a 64-bit signed or unsigned constant in the register `dest'.
-// Use SETUWConst for each 32 bit word, plus a left-shift-by-32 in between.
-// This function correctly emulates the SETX pseudo-op for SPARC v9.
-//
-// Optimize the same cases as SETUWConst for each 32 bit word.
-//----------------------------------------------------------------------------
-
-static inline void
-CreateSETXConst(const TargetMachine& target, uint64_t C,
- Instruction* tmpReg, Instruction* dest,
- std::vector<MachineInstr*>& mvec)
-{
- assert(C > (unsigned int) ~0 && "Use SETUW/SETSW for 32-bit values!");
-
- MachineInstr* MI;
-
- // Code to set the upper 32 bits of the value in register `tmpReg'
- CreateSETUWConst(target, (C >> 32), tmpReg, mvec);
-
- // Shift tmpReg left by 32 bits
- mvec.push_back(BuildMI(V9::SLLXi6, 3).addReg(tmpReg).addZImm(32)
- .addRegDef(tmpReg));
-
- // Code to set the low 32 bits of the value in register `dest'
- CreateSETUWConst(target, C, dest, mvec);
-
- // dest = OR(tmpReg, dest)
- mvec.push_back(BuildMI(V9::ORr,3).addReg(dest).addReg(tmpReg).addRegDef(dest));
-}
-
-
-//----------------------------------------------------------------------------
-// Function: CreateSETUWLabel
-//
-// Set a 32-bit constant (given by a symbolic label) in the register `dest'.
-//----------------------------------------------------------------------------
-
-static inline void
-CreateSETUWLabel(const TargetMachine& target, Value* val,
- Instruction* dest, std::vector<MachineInstr*>& mvec)
-{
- MachineInstr* MI;
-
- // Set the high 22 bits in dest
- MI = BuildMI(V9::SETHI, 2).addReg(val).addRegDef(dest);
- MI->setOperandHi32(0);
- mvec.push_back(MI);
-
- // Set the low 10 bits in dest
- MI = BuildMI(V9::ORr, 3).addReg(dest).addReg(val).addRegDef(dest);
- MI->setOperandLo32(1);
- mvec.push_back(MI);
-}
-
-
-//----------------------------------------------------------------------------
-// Function: CreateSETXLabel
-//
-// Set a 64-bit constant (given by a symbolic label) in the register `dest'.
-//----------------------------------------------------------------------------
-
-static inline void
-CreateSETXLabel(const TargetMachine& target,
- Value* val, Instruction* tmpReg, Instruction* dest,
- std::vector<MachineInstr*>& mvec)
-{
- assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
- "I only know about constant values and global addresses");
-
- MachineInstr* MI;
-
- MI = BuildMI(V9::SETHI, 2).addPCDisp(val).addRegDef(tmpReg);
- MI->setOperandHi64(0);
- mvec.push_back(MI);
-
- MI = BuildMI(V9::ORi, 3).addReg(tmpReg).addPCDisp(val).addRegDef(tmpReg);
- MI->setOperandLo64(1);
- mvec.push_back(MI);
-
- mvec.push_back(BuildMI(V9::SLLXi6, 3).addReg(tmpReg).addZImm(32)
- .addRegDef(tmpReg));
- MI = BuildMI(V9::SETHI, 2).addPCDisp(val).addRegDef(dest);
- MI->setOperandHi32(0);
- mvec.push_back(MI);
-
- MI = BuildMI(V9::ORr, 3).addReg(dest).addReg(tmpReg).addRegDef(dest);
- mvec.push_back(MI);
-
- MI = BuildMI(V9::ORi, 3).addReg(dest).addPCDisp(val).addRegDef(dest);
- MI->setOperandLo32(1);
- mvec.push_back(MI);
-}
-
-
-//----------------------------------------------------------------------------
-// Function: CreateUIntSetInstruction
-//
-// Create code to Set an unsigned constant in the register `dest'.
-// Uses CreateSETUWConst, CreateSETSWConst or CreateSETXConst as needed.
-// CreateSETSWConst is an optimization for the case that the unsigned value
-// has all ones in the 33 high bits (so that sign-extension sets them all).
-//----------------------------------------------------------------------------
-
-static inline void
-CreateUIntSetInstruction(const TargetMachine& target,
- uint64_t C, Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi)
-{
- static const uint64_t lo32 = (uint32_t) ~0;
- if (C <= lo32) // High 32 bits are 0. Set low 32 bits.
- CreateSETUWConst(target, (uint32_t) C, dest, mvec);
- else if ((C & ~lo32) == ~lo32 && (C & (1U << 31))) {
- // All high 33 (not 32) bits are 1s: sign-extension will take care
- // of high 32 bits, so use the sequence for signed int
- CreateSETSWConst(target, (int32_t) C, dest, mvec);
- } else if (C > lo32) {
- // C does not fit in 32 bits
- TmpInstruction* tmpReg = new TmpInstruction(mcfi, Type::IntTy);
- CreateSETXConst(target, C, tmpReg, dest, mvec);
- }
-}
-
-
-//----------------------------------------------------------------------------
-// Function: CreateIntSetInstruction
-//
-// Create code to Set a signed constant in the register `dest'.
-// Really the same as CreateUIntSetInstruction.
-//----------------------------------------------------------------------------
-
-static inline void
-CreateIntSetInstruction(const TargetMachine& target,
- int64_t C, Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi)
-{
- CreateUIntSetInstruction(target, (uint64_t) C, dest, mvec, mcfi);
-}
-
-
-//---------------------------------------------------------------------------
-// Create a table of LLVM opcode -> max. immediate constant likely to
-// be usable for that operation.
-//---------------------------------------------------------------------------
-
-// Entry == 0 ==> no immediate constant field exists at all.
-// Entry > 0 ==> abs(immediate constant) <= Entry
-//
-std::vector<int> MaxConstantsTable(Instruction::OtherOpsEnd);
-
-static int
-MaxConstantForInstr(unsigned llvmOpCode)
-{
- int modelOpCode = -1;
-
- if (llvmOpCode >= Instruction::BinaryOpsBegin &&
- llvmOpCode < Instruction::BinaryOpsEnd)
- modelOpCode = V9::ADDi;
- else
- switch(llvmOpCode) {
- case Instruction::Ret: modelOpCode = V9::JMPLCALLi; break;
-
- case Instruction::Malloc:
- case Instruction::Alloca:
- case Instruction::GetElementPtr:
- case Instruction::PHI:
- case Instruction::Cast:
- case Instruction::Call: modelOpCode = V9::ADDi; break;
-
- case Instruction::Shl:
- case Instruction::Shr: modelOpCode = V9::SLLXi6; break;
-
- default: break;
- };
-
- return (modelOpCode < 0)? 0: SparcMachineInstrDesc[modelOpCode].maxImmedConst;
-}
-
-static void
-InitializeMaxConstantsTable()
-{
- unsigned op;
- assert(MaxConstantsTable.size() == Instruction::OtherOpsEnd &&
- "assignments below will be illegal!");
- for (op = Instruction::TermOpsBegin; op < Instruction::TermOpsEnd; ++op)
- MaxConstantsTable[op] = MaxConstantForInstr(op);
- for (op = Instruction::BinaryOpsBegin; op < Instruction::BinaryOpsEnd; ++op)
- MaxConstantsTable[op] = MaxConstantForInstr(op);
- for (op = Instruction::MemoryOpsBegin; op < Instruction::MemoryOpsEnd; ++op)
- MaxConstantsTable[op] = MaxConstantForInstr(op);
- for (op = Instruction::OtherOpsBegin; op < Instruction::OtherOpsEnd; ++op)
- MaxConstantsTable[op] = MaxConstantForInstr(op);
-}
-
-
-//---------------------------------------------------------------------------
-// class SparcInstrInfo
-//
-// Purpose:
-// Information about individual instructions.
-// Most information is stored in the SparcMachineInstrDesc array above.
-// Other information is computed on demand, and most such functions
-// default to member functions in base class TargetInstrInfo.
-//---------------------------------------------------------------------------
-
-/*ctor*/
-SparcInstrInfo::SparcInstrInfo()
- : TargetInstrInfo(SparcMachineInstrDesc,
- /*descSize = */ V9::NUM_TOTAL_OPCODES,
- /*numRealOpCodes = */ V9::NUM_REAL_OPCODES)
-{
- InitializeMaxConstantsTable();
-}
-
-bool
-SparcInstrInfo::ConstantMayNotFitInImmedField(const Constant* CV,
- const Instruction* I) const
-{
- if (I->getOpcode() >= MaxConstantsTable.size()) // user-defined op (or bug!)
- return true;
-
- if (isa<ConstantPointerNull>(CV)) // can always use %g0
- return false;
-
- if (isa<SwitchInst>(I)) // Switch instructions will be lowered!
- return false;
-
- if (const ConstantInt* CI = dyn_cast<ConstantInt>(CV))
- return labs((int64_t)CI->getRawValue()) > MaxConstantsTable[I->getOpcode()];
-
- if (isa<ConstantBool>(CV))
- return 1 > MaxConstantsTable[I->getOpcode()];
-
- return true;
-}
-
-//
-// Create an instruction sequence to put the constant `val' into
-// the virtual register `dest'. `val' may be a Constant or a
-// GlobalValue, viz., the constant address of a global variable or function.
-// The generated instructions are returned in `mvec'.
-// Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineFunction.
-//
-void
-SparcInstrInfo::CreateCodeToLoadConst(const TargetMachine& target,
- Function* F,
- Value* val,
- Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const
-{
- assert(isa<Constant>(val) || isa<GlobalValue>(val) &&
- "I only know about constant values and global addresses");
-
- // Use a "set" instruction for known constants or symbolic constants (labels)
- // that can go in an integer reg.
- // We have to use a "load" instruction for all other constants,
- // in particular, floating point constants.
- //
- const Type* valType = val->getType();
-
- // A ConstantPointerRef is just a reference to GlobalValue.
- while (isa<ConstantPointerRef>(val))
- val = cast<ConstantPointerRef>(val)->getValue();
-
- if (isa<GlobalValue>(val)) {
- TmpInstruction* tmpReg =
- new TmpInstruction(mcfi, PointerType::get(val->getType()), val);
- CreateSETXLabel(target, val, tmpReg, dest, mvec);
- return;
- }
-
- bool isValid;
- uint64_t C = ConvertConstantToIntType(target, val, dest->getType(), isValid);
- if (isValid) {
- if (dest->getType()->isSigned())
- CreateUIntSetInstruction(target, C, dest, mvec, mcfi);
- else
- CreateIntSetInstruction(target, (int64_t) C, dest, mvec, mcfi);
-
- } else {
- // Make an instruction sequence to load the constant, viz:
- // SETX <addr-of-constant>, tmpReg, addrReg
- // LOAD /*addr*/ addrReg, /*offset*/ 0, dest
-
- // First, create a tmp register to be used by the SETX sequence.
- TmpInstruction* tmpReg =
- new TmpInstruction(mcfi, PointerType::get(val->getType()));
-
- // Create another TmpInstruction for the address register
- TmpInstruction* addrReg =
- new TmpInstruction(mcfi, PointerType::get(val->getType()));
-
- // Get the constant pool index for this constant
- MachineConstantPool *CP = MachineFunction::get(F).getConstantPool();
- Constant *C = cast<Constant>(val);
- unsigned CPI = CP->getConstantPoolIndex(C);
-
- // Put the address of the constant into a register
- MachineInstr* MI;
-
- MI = BuildMI(V9::SETHI, 2).addConstantPoolIndex(CPI).addRegDef(tmpReg);
- MI->setOperandHi64(0);
- mvec.push_back(MI);
-
- MI = BuildMI(V9::ORi, 3).addReg(tmpReg).addConstantPoolIndex(CPI)
- .addRegDef(tmpReg);
- MI->setOperandLo64(1);
- mvec.push_back(MI);
-
- mvec.push_back(BuildMI(V9::SLLXi6, 3).addReg(tmpReg).addZImm(32)
- .addRegDef(tmpReg));
- MI = BuildMI(V9::SETHI, 2).addConstantPoolIndex(CPI).addRegDef(addrReg);
- MI->setOperandHi32(0);
- mvec.push_back(MI);
-
- MI = BuildMI(V9::ORr, 3).addReg(addrReg).addReg(tmpReg).addRegDef(addrReg);
- mvec.push_back(MI);
-
- MI = BuildMI(V9::ORi, 3).addReg(addrReg).addConstantPoolIndex(CPI)
- .addRegDef(addrReg);
- MI->setOperandLo32(1);
- mvec.push_back(MI);
-
- // Now load the constant from out ConstantPool label
- unsigned Opcode = ChooseLoadInstruction(val->getType());
- Opcode = convertOpcodeFromRegToImm(Opcode);
- mvec.push_back(BuildMI(Opcode, 3)
- .addReg(addrReg).addSImm((int64_t)0).addRegDef(dest));
- }
-}
-
-
-// Create an instruction sequence to copy an integer register `val'
-// to a floating point register `dest' by copying to memory and back.
-// val must be an integral type. dest must be a Float or Double.
-// The generated instructions are returned in `mvec'.
-// Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineFunction.
-//
-void
-SparcInstrInfo::CreateCodeToCopyIntToFloat(const TargetMachine& target,
- Function* F,
- Value* val,
- Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const
-{
- assert((val->getType()->isIntegral() || isa<PointerType>(val->getType()))
- && "Source type must be integral (integer or bool) or pointer");
- assert(dest->getType()->isFloatingPoint()
- && "Dest type must be float/double");
-
- // Get a stack slot to use for the copy
- int offset = MachineFunction::get(F).getInfo()->allocateLocalVar(val);
-
- // Get the size of the source value being copied.
- size_t srcSize = target.getTargetData().getTypeSize(val->getType());
-
- // Store instruction stores `val' to [%fp+offset].
- // The store and load opCodes are based on the size of the source value.
- // If the value is smaller than 32 bits, we must sign- or zero-extend it
- // to 32 bits since the load-float will load 32 bits.
- // Note that the store instruction is the same for signed and unsigned ints.
- const Type* storeType = (srcSize <= 4)? Type::IntTy : Type::LongTy;
- Value* storeVal = val;
- if (srcSize < target.getTargetData().getTypeSize(Type::FloatTy)) {
- // sign- or zero-extend respectively
- storeVal = new TmpInstruction(mcfi, storeType, val);
- if (val->getType()->isSigned())
- CreateSignExtensionInstructions(target, F, val, storeVal, 8*srcSize,
- mvec, mcfi);
- else
- CreateZeroExtensionInstructions(target, F, val, storeVal, 8*srcSize,
- mvec, mcfi);
- }
-
- unsigned FPReg = target.getRegInfo().getFramePointer();
- unsigned StoreOpcode = ChooseStoreInstruction(storeType);
- StoreOpcode = convertOpcodeFromRegToImm(StoreOpcode);
- mvec.push_back(BuildMI(StoreOpcode, 3)
- .addReg(storeVal).addMReg(FPReg).addSImm(offset));
-
- // Load instruction loads [%fp+offset] to `dest'.
- // The type of the load opCode is the floating point type that matches the
- // stored type in size:
- // On SparcV9: float for int or smaller, double for long.
- //
- const Type* loadType = (srcSize <= 4)? Type::FloatTy : Type::DoubleTy;
- unsigned LoadOpcode = ChooseLoadInstruction(loadType);
- LoadOpcode = convertOpcodeFromRegToImm(LoadOpcode);
- mvec.push_back(BuildMI(LoadOpcode, 3)
- .addMReg(FPReg).addSImm(offset).addRegDef(dest));
-}
-
-// Similarly, create an instruction sequence to copy an FP register
-// `val' to an integer register `dest' by copying to memory and back.
-// The generated instructions are returned in `mvec'.
-// Any temp. virtual registers (TmpInstruction) created are recorded in mcfi.
-// Temporary stack space required is allocated via MachineFunction.
-//
-void
-SparcInstrInfo::CreateCodeToCopyFloatToInt(const TargetMachine& target,
- Function* F,
- Value* val,
- Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const
-{
- const Type* opTy = val->getType();
- const Type* destTy = dest->getType();
-
- assert(opTy->isFloatingPoint() && "Source type must be float/double");
- assert((destTy->isIntegral() || isa<PointerType>(destTy))
- && "Dest type must be integer, bool or pointer");
-
- // FIXME: For now, we allocate permanent space because the stack frame
- // manager does not allow locals to be allocated (e.g., for alloca) after
- // a temp is allocated!
- //
- int offset = MachineFunction::get(F).getInfo()->allocateLocalVar(val);
-
- unsigned FPReg = target.getRegInfo().getFramePointer();
-
- // Store instruction stores `val' to [%fp+offset].
- // The store opCode is based only the source value being copied.
- //
- unsigned StoreOpcode = ChooseStoreInstruction(opTy);
- StoreOpcode = convertOpcodeFromRegToImm(StoreOpcode);
- mvec.push_back(BuildMI(StoreOpcode, 3)
- .addReg(val).addMReg(FPReg).addSImm(offset));
-
- // Load instruction loads [%fp+offset] to `dest'.
- // The type of the load opCode is the integer type that matches the
- // source type in size:
- // On SparcV9: int for float, long for double.
- // Note that we *must* use signed loads even for unsigned dest types, to
- // ensure correct sign-extension for UByte, UShort or UInt:
- //
- const Type* loadTy = (opTy == Type::FloatTy)? Type::IntTy : Type::LongTy;
- unsigned LoadOpcode = ChooseLoadInstruction(loadTy);
- LoadOpcode = convertOpcodeFromRegToImm(LoadOpcode);
- mvec.push_back(BuildMI(LoadOpcode, 3).addMReg(FPReg)
- .addSImm(offset).addRegDef(dest));
-}
-
-
-// Create instruction(s) to copy src to dest, for arbitrary types
-// The generated instructions are returned in `mvec'.
-// Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineFunction.
-//
-void
-SparcInstrInfo::CreateCopyInstructionsByType(const TargetMachine& target,
- Function *F,
- Value* src,
- Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const
-{
- bool loadConstantToReg = false;
-
- const Type* resultType = dest->getType();
-
- MachineOpCode opCode = ChooseAddInstructionByType(resultType);
- if (opCode == V9::INVALID_OPCODE) {
- assert(0 && "Unsupported result type in CreateCopyInstructionsByType()");
- return;
- }
-
- // if `src' is a constant that doesn't fit in the immed field or if it is
- // a global variable (i.e., a constant address), generate a load
- // instruction instead of an add
- //
- if (isa<Constant>(src)) {
- unsigned int machineRegNum;
- int64_t immedValue;
- MachineOperand::MachineOperandType opType =
- ChooseRegOrImmed(src, opCode, target, /*canUseImmed*/ true,
- machineRegNum, immedValue);
-
- if (opType == MachineOperand::MO_VirtualRegister)
- loadConstantToReg = true;
- }
- else if (isa<GlobalValue>(src))
- loadConstantToReg = true;
-
- if (loadConstantToReg) {
- // `src' is constant and cannot fit in immed field for the ADD
- // Insert instructions to "load" the constant into a register
- target.getInstrInfo().CreateCodeToLoadConst(target, F, src, dest,
- mvec, mcfi);
- } else {
- // Create a reg-to-reg copy instruction for the given type:
- // -- For FP values, create a FMOVS or FMOVD instruction
- // -- For non-FP values, create an add-with-0 instruction (opCode as above)
- // Make `src' the second operand, in case it is a small constant!
- //
- MachineInstr* MI;
- if (resultType->isFloatingPoint())
- MI = (BuildMI(resultType == Type::FloatTy? V9::FMOVS : V9::FMOVD, 2)
- .addReg(src).addRegDef(dest));
- else {
- const Type* Ty =isa<PointerType>(resultType)? Type::ULongTy :resultType;
- MI = (BuildMI(opCode, 3)
- .addSImm((int64_t) 0).addReg(src).addRegDef(dest));
- }
- mvec.push_back(MI);
- }
-}
-
-
-// Helper function for sign-extension and zero-extension.
-// For SPARC v9, we sign-extend the given operand using SLL; SRA/SRL.
-inline void
-CreateBitExtensionInstructions(bool signExtend,
- const TargetMachine& target,
- Function* F,
- Value* srcVal,
- Value* destVal,
- unsigned int numLowBits,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi)
-{
- MachineInstr* M;
-
- assert(numLowBits <= 32 && "Otherwise, nothing should be done here!");
-
- if (numLowBits < 32) {
- // SLL is needed since operand size is < 32 bits.
- TmpInstruction *tmpI = new TmpInstruction(mcfi, destVal->getType(),
- srcVal, destVal, "make32");
- mvec.push_back(BuildMI(V9::SLLXi6, 3).addReg(srcVal)
- .addZImm(32-numLowBits).addRegDef(tmpI));
- srcVal = tmpI;
- }
-
- mvec.push_back(BuildMI(signExtend? V9::SRAi5 : V9::SRLi5, 3)
- .addReg(srcVal).addZImm(32-numLowBits).addRegDef(destVal));
-}
-
-
-// Create instruction sequence to produce a sign-extended register value
-// from an arbitrary-sized integer value (sized in bits, not bytes).
-// The generated instructions are returned in `mvec'.
-// Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineFunction.
-//
-void
-SparcInstrInfo::CreateSignExtensionInstructions(
- const TargetMachine& target,
- Function* F,
- Value* srcVal,
- Value* destVal,
- unsigned int numLowBits,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const
-{
- CreateBitExtensionInstructions(/*signExtend*/ true, target, F, srcVal,
- destVal, numLowBits, mvec, mcfi);
-}
-
-
-// Create instruction sequence to produce a zero-extended register value
-// from an arbitrary-sized integer value (sized in bits, not bytes).
-// For SPARC v9, we sign-extend the given operand using SLL; SRL.
-// The generated instructions are returned in `mvec'.
-// Any temp. registers (TmpInstruction) created are recorded in mcfi.
-// Any stack space required is allocated via MachineFunction.
-//
-void
-SparcInstrInfo::CreateZeroExtensionInstructions(
- const TargetMachine& target,
- Function* F,
- Value* srcVal,
- Value* destVal,
- unsigned int numLowBits,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const
-{
- CreateBitExtensionInstructions(/*signExtend*/ false, target, F, srcVal,
- destVal, numLowBits, mvec, mcfi);
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/SparcInstrSelection.cpp b/llvm/lib/Target/Sparc/SparcInstrSelection.cpp
deleted file mode 100644
index 57f1251af73..00000000000
--- a/llvm/lib/Target/Sparc/SparcInstrSelection.cpp
+++ /dev/null
@@ -1,2898 +0,0 @@
-//===-- SparcInstrSelection.cpp -------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// BURS instruction selection for SPARC V9 architecture.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Instructions.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/Module.h"
-#include "llvm/CodeGen/InstrForest.h"
-#include "llvm/CodeGen/InstrSelection.h"
-#include "llvm/CodeGen/InstrSelectionSupport.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineInstrAnnot.h"
-#include "SparcInstrSelectionSupport.h"
-#include "SparcInternals.h"
-#include "SparcRegClassInfo.h"
-#include "SparcRegInfo.h"
-#include "Support/MathExtras.h"
-#include <algorithm>
-#include <cmath>
-
-namespace llvm {
-
-static inline void Add3OperandInstr(unsigned Opcode, InstructionNode* Node,
- std::vector<MachineInstr*>& mvec) {
- mvec.push_back(BuildMI(Opcode, 3).addReg(Node->leftChild()->getValue())
- .addReg(Node->rightChild()->getValue())
- .addRegDef(Node->getValue()));
-}
-
-
-//---------------------------------------------------------------------------
-// Function: FoldGetElemChain
-//
-// Purpose:
-// Fold a chain of GetElementPtr instructions containing only
-// constant offsets into an equivalent (Pointer, IndexVector) pair.
-// Returns the pointer Value, and stores the resulting IndexVector
-// in argument chainIdxVec. This is a helper function for
-// FoldConstantIndices that does the actual folding.
-//---------------------------------------------------------------------------
-
-
-// Check for a constant 0.
-static inline bool
-IsZero(Value* idx)
-{
- return (idx == ConstantSInt::getNullValue(idx->getType()));
-}
-
-static Value*
-FoldGetElemChain(InstrTreeNode* ptrNode, std::vector<Value*>& chainIdxVec,
- bool lastInstHasLeadingNonZero)
-{
- InstructionNode* gepNode = dyn_cast<InstructionNode>(ptrNode);
- GetElementPtrInst* gepInst =
- dyn_cast_or_null<GetElementPtrInst>(gepNode ? gepNode->getInstruction() :0);
-
- // ptr value is not computed in this tree or ptr value does not come from GEP
- // instruction
- if (gepInst == NULL)
- return NULL;
-
- // Return NULL if we don't fold any instructions in.
- Value* ptrVal = NULL;
-
- // Now chase the chain of getElementInstr instructions, if any.
- // Check for any non-constant indices and stop there.
- // Also, stop if the first index of child is a non-zero array index
- // and the last index of the current node is a non-array index:
- // in that case, a non-array declared type is being accessed as an array
- // which is not type-safe, but could be legal.
- //
- InstructionNode* ptrChild = gepNode;
- while (ptrChild && (ptrChild->getOpLabel() == Instruction::GetElementPtr ||
- ptrChild->getOpLabel() == GetElemPtrIdx))
- {
- // Child is a GetElemPtr instruction
- gepInst = cast<GetElementPtrInst>(ptrChild->getValue());
- User::op_iterator OI, firstIdx = gepInst->idx_begin();
- User::op_iterator lastIdx = gepInst->idx_end();
- bool allConstantOffsets = true;
-
- // The first index of every GEP must be an array index.
- assert((*firstIdx)->getType() == Type::LongTy &&
- "INTERNAL ERROR: Structure index for a pointer type!");
-
- // If the last instruction had a leading non-zero index, check if the
- // current one references a sequential (i.e., indexable) type.
- // If not, the code is not type-safe and we would create an illegal GEP
- // by folding them, so don't fold any more instructions.
- //
- if (lastInstHasLeadingNonZero)
- if (! isa<SequentialType>(gepInst->getType()->getElementType()))
- break; // cannot fold in any preceding getElementPtr instrs.
-
- // Check that all offsets are constant for this instruction
- for (OI = firstIdx; allConstantOffsets && OI != lastIdx; ++OI)
- allConstantOffsets = isa<ConstantInt>(*OI);
-
- if (allConstantOffsets) {
- // Get pointer value out of ptrChild.
- ptrVal = gepInst->getPointerOperand();
-
- // Insert its index vector at the start, skipping any leading [0]
- // Remember the old size to check if anything was inserted.
- unsigned oldSize = chainIdxVec.size();
- int firstIsZero = IsZero(*firstIdx);
- chainIdxVec.insert(chainIdxVec.begin(), firstIdx + firstIsZero, lastIdx);
-
- // Remember if it has leading zero index: it will be discarded later.
- if (oldSize < chainIdxVec.size())
- lastInstHasLeadingNonZero = !firstIsZero;
-
- // Mark the folded node so no code is generated for it.
- ((InstructionNode*) ptrChild)->markFoldedIntoParent();
-
- // Get the previous GEP instruction and continue trying to fold
- ptrChild = dyn_cast<InstructionNode>(ptrChild->leftChild());
- } else // cannot fold this getElementPtr instr. or any preceding ones
- break;
- }
-
- // If the first getElementPtr instruction had a leading [0], add it back.
- // Note that this instruction is the *last* one that was successfully
- // folded *and* contributed any indices, in the loop above.
- //
- if (ptrVal && ! lastInstHasLeadingNonZero)
- chainIdxVec.insert(chainIdxVec.begin(), ConstantSInt::get(Type::LongTy,0));
-
- return ptrVal;
-}
-
-
-//---------------------------------------------------------------------------
-// Function: GetGEPInstArgs
-//
-// Purpose:
-// Helper function for GetMemInstArgs that handles the final getElementPtr
-// instruction used by (or same as) the memory operation.
-// Extracts the indices of the current instruction and tries to fold in
-// preceding ones if all indices of the current one are constant.
-//---------------------------------------------------------------------------
-
-static Value *
-GetGEPInstArgs(InstructionNode* gepNode,
- std::vector<Value*>& idxVec,
- bool& allConstantIndices)
-{
- allConstantIndices = true;
- GetElementPtrInst* gepI = cast<GetElementPtrInst>(gepNode->getInstruction());
-
- // Default pointer is the one from the current instruction.
- Value* ptrVal = gepI->getPointerOperand();
- InstrTreeNode* ptrChild = gepNode->leftChild();
-
- // Extract the index vector of the GEP instruction.
- // If all indices are constant and first index is zero, try to fold
- // in preceding GEPs with all constant indices.
- for (User::op_iterator OI=gepI->idx_begin(), OE=gepI->idx_end();
- allConstantIndices && OI != OE; ++OI)
- if (! isa<Constant>(*OI))
- allConstantIndices = false; // note: this also terminates loop!
-
- // If we have only constant indices, fold chains of constant indices
- // in this and any preceding GetElemPtr instructions.
- bool foldedGEPs = false;
- bool leadingNonZeroIdx = gepI && ! IsZero(*gepI->idx_begin());
- if (allConstantIndices)
- if (Value* newPtr = FoldGetElemChain(ptrChild, idxVec, leadingNonZeroIdx)) {
- ptrVal = newPtr;
- foldedGEPs = true;
- }
-
- // Append the index vector of the current instruction.
- // Skip the leading [0] index if preceding GEPs were folded into this.
- idxVec.insert(idxVec.end(),
- gepI->idx_begin() + (foldedGEPs && !leadingNonZeroIdx),
- gepI->idx_end());
-
- return ptrVal;
-}
-
-//---------------------------------------------------------------------------
-// Function: GetMemInstArgs
-//
-// Purpose:
-// Get the pointer value and the index vector for a memory operation
-// (GetElementPtr, Load, or Store). If all indices of the given memory
-// operation are constant, fold in constant indices in a chain of
-// preceding GetElementPtr instructions (if any), and return the
-// pointer value of the first instruction in the chain.
-// All folded instructions are marked so no code is generated for them.
-//
-// Return values:
-// Returns the pointer Value to use.
-// Returns the resulting IndexVector in idxVec.
-// Returns true/false in allConstantIndices if all indices are/aren't const.
-//---------------------------------------------------------------------------
-
-static Value*
-GetMemInstArgs(InstructionNode* memInstrNode,
- std::vector<Value*>& idxVec,
- bool& allConstantIndices)
-{
- allConstantIndices = false;
- Instruction* memInst = memInstrNode->getInstruction();
- assert(idxVec.size() == 0 && "Need empty vector to return indices");
-
- // If there is a GetElemPtr instruction to fold in to this instr,
- // it must be in the left child for Load and GetElemPtr, and in the
- // right child for Store instructions.
- InstrTreeNode* ptrChild = (memInst->getOpcode() == Instruction::Store
- ? memInstrNode->rightChild()
- : memInstrNode->leftChild());
-
- // Default pointer is the one from the current instruction.
- Value* ptrVal = ptrChild->getValue();
-
- // Find the "last" GetElemPtr instruction: this one or the immediate child.
- // There will be none if this is a load or a store from a scalar pointer.
- InstructionNode* gepNode = NULL;
- if (isa<GetElementPtrInst>(memInst))
- gepNode = memInstrNode;
- else if (isa<InstructionNode>(ptrChild) && isa<GetElementPtrInst>(ptrVal)) {
- // Child of load/store is a GEP and memInst is its only use.
- // Use its indices and mark it as folded.
- gepNode = cast<InstructionNode>(ptrChild);
- gepNode->markFoldedIntoParent();
- }
-
- // If there are no indices, return the current pointer.
- // Else extract the pointer from the GEP and fold the indices.
- return gepNode ? GetGEPInstArgs(gepNode, idxVec, allConstantIndices)
- : ptrVal;
-}
-
-
-//************************ Internal Functions ******************************/
-
-
-static inline MachineOpCode
-ChooseBprInstruction(const InstructionNode* instrNode)
-{
- MachineOpCode opCode;
-
- Instruction* setCCInstr =
- ((InstructionNode*) instrNode->leftChild())->getInstruction();
-
- switch(setCCInstr->getOpcode())
- {
- case Instruction::SetEQ: opCode = V9::BRZ; break;
- case Instruction::SetNE: opCode = V9::BRNZ; break;
- case Instruction::SetLE: opCode = V9::BRLEZ; break;
- case Instruction::SetGE: opCode = V9::BRGEZ; break;
- case Instruction::SetLT: opCode = V9::BRLZ; break;
- case Instruction::SetGT: opCode = V9::BRGZ; break;
- default:
- assert(0 && "Unrecognized VM instruction!");
- opCode = V9::INVALID_OPCODE;
- break;
- }
-
- return opCode;
-}
-
-
-static inline MachineOpCode
-ChooseBpccInstruction(const InstructionNode* instrNode,
- const BinaryOperator* setCCInstr)
-{
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- bool isSigned = setCCInstr->getOperand(0)->getType()->isSigned();
-
- if (isSigned) {
- switch(setCCInstr->getOpcode())
- {
- case Instruction::SetEQ: opCode = V9::BE; break;
- case Instruction::SetNE: opCode = V9::BNE; break;
- case Instruction::SetLE: opCode = V9::BLE; break;
- case Instruction::SetGE: opCode = V9::BGE; break;
- case Instruction::SetLT: opCode = V9::BL; break;
- case Instruction::SetGT: opCode = V9::BG; break;
- default:
- assert(0 && "Unrecognized VM instruction!");
- break;
- }
- } else {
- switch(setCCInstr->getOpcode())
- {
- case Instruction::SetEQ: opCode = V9::BE; break;
- case Instruction::SetNE: opCode = V9::BNE; break;
- case Instruction::SetLE: opCode = V9::BLEU; break;
- case Instruction::SetGE: opCode = V9::BCC; break;
- case Instruction::SetLT: opCode = V9::BCS; break;
- case Instruction::SetGT: opCode = V9::BGU; break;
- default:
- assert(0 && "Unrecognized VM instruction!");
- break;
- }
- }
-
- return opCode;
-}
-
-static inline MachineOpCode
-ChooseBFpccInstruction(const InstructionNode* instrNode,
- const BinaryOperator* setCCInstr)
-{
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- switch(setCCInstr->getOpcode())
- {
- case Instruction::SetEQ: opCode = V9::FBE; break;
- case Instruction::SetNE: opCode = V9::FBNE; break;
- case Instruction::SetLE: opCode = V9::FBLE; break;
- case Instruction::SetGE: opCode = V9::FBGE; break;
- case Instruction::SetLT: opCode = V9::FBL; break;
- case Instruction::SetGT: opCode = V9::FBG; break;
- default:
- assert(0 && "Unrecognized VM instruction!");
- break;
- }
-
- return opCode;
-}
-
-
-// Create a unique TmpInstruction for a boolean value,
-// representing the CC register used by a branch on that value.
-// For now, hack this using a little static cache of TmpInstructions.
-// Eventually the entire BURG instruction selection should be put
-// into a separate class that can hold such information.
-// The static cache is not too bad because the memory for these
-// TmpInstructions will be freed along with the rest of the Function anyway.
-//
-static TmpInstruction*
-GetTmpForCC(Value* boolVal, const Function *F, const Type* ccType,
- MachineCodeForInstruction& mcfi)
-{
- typedef hash_map<const Value*, TmpInstruction*> BoolTmpCache;
- static BoolTmpCache boolToTmpCache; // Map boolVal -> TmpInstruction*
- static const Function *lastFunction = 0;// Use to flush cache between funcs
-
- assert(boolVal->getType() == Type::BoolTy && "Weird but ok! Delete assert");
-
- if (lastFunction != F) {
- lastFunction = F;
- boolToTmpCache.clear();
- }
-
- // Look for tmpI and create a new one otherwise. The new value is
- // directly written to map using the ref returned by operator[].
- TmpInstruction*& tmpI = boolToTmpCache[boolVal];
- if (tmpI == NULL)
- tmpI = new TmpInstruction(mcfi, ccType, boolVal);
-
- return tmpI;
-}
-
-
-static inline MachineOpCode
-ChooseBccInstruction(const InstructionNode* instrNode,
- const Type*& setCCType)
-{
- InstructionNode* setCCNode = (InstructionNode*) instrNode->leftChild();
- assert(setCCNode->getOpLabel() == SetCCOp);
- BinaryOperator* setCCInstr =cast<BinaryOperator>(setCCNode->getInstruction());
- setCCType = setCCInstr->getOperand(0)->getType();
-
- if (setCCType->isFloatingPoint())
- return ChooseBFpccInstruction(instrNode, setCCInstr);
- else
- return ChooseBpccInstruction(instrNode, setCCInstr);
-}
-
-
-// WARNING: since this function has only one caller, it always returns
-// the opcode that expects an immediate and a register. If this function
-// is ever used in cases where an opcode that takes two registers is required,
-// then modify this function and use convertOpcodeFromRegToImm() where required.
-//
-// It will be necessary to expand convertOpcodeFromRegToImm() to handle the
-// new cases of opcodes.
-static inline MachineOpCode
-ChooseMovFpcciInstruction(const InstructionNode* instrNode)
-{
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- switch(instrNode->getInstruction()->getOpcode())
- {
- case Instruction::SetEQ: opCode = V9::MOVFEi; break;
- case Instruction::SetNE: opCode = V9::MOVFNEi; break;
- case Instruction::SetLE: opCode = V9::MOVFLEi; break;
- case Instruction::SetGE: opCode = V9::MOVFGEi; break;
- case Instruction::SetLT: opCode = V9::MOVFLi; break;
- case Instruction::SetGT: opCode = V9::MOVFGi; break;
- default:
- assert(0 && "Unrecognized VM instruction!");
- break;
- }
-
- return opCode;
-}
-
-
-// ChooseMovpcciForSetCC -- Choose a conditional-move instruction
-// based on the type of SetCC operation.
-//
-// WARNING: since this function has only one caller, it always returns
-// the opcode that expects an immediate and a register. If this function
-// is ever used in cases where an opcode that takes two registers is required,
-// then modify this function and use convertOpcodeFromRegToImm() where required.
-//
-// It will be necessary to expand convertOpcodeFromRegToImm() to handle the
-// new cases of opcodes.
-//
-static MachineOpCode
-ChooseMovpcciForSetCC(const InstructionNode* instrNode)
-{
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- const Type* opType = instrNode->leftChild()->getValue()->getType();
- assert(opType->isIntegral() || isa<PointerType>(opType));
- bool noSign = opType->isUnsigned() || isa<PointerType>(opType);
-
- switch(instrNode->getInstruction()->getOpcode())
- {
- case Instruction::SetEQ: opCode = V9::MOVEi; break;
- case Instruction::SetLE: opCode = noSign? V9::MOVLEUi : V9::MOVLEi; break;
- case Instruction::SetGE: opCode = noSign? V9::MOVCCi : V9::MOVGEi; break;
- case Instruction::SetLT: opCode = noSign? V9::MOVCSi : V9::MOVLi; break;
- case Instruction::SetGT: opCode = noSign? V9::MOVGUi : V9::MOVGi; break;
- case Instruction::SetNE: opCode = V9::MOVNEi; break;
- default: assert(0 && "Unrecognized LLVM instr!"); break;
- }
-
- return opCode;
-}
-
-
-// ChooseMovpregiForSetCC -- Choose a conditional-move-on-register-value
-// instruction based on the type of SetCC operation. These instructions
-// compare a register with 0 and perform the move is the comparison is true.
-//
-// WARNING: like the previous function, this function it always returns
-// the opcode that expects an immediate and a register. See above.
-//
-static MachineOpCode
-ChooseMovpregiForSetCC(const InstructionNode* instrNode)
-{
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- switch(instrNode->getInstruction()->getOpcode())
- {
- case Instruction::SetEQ: opCode = V9::MOVRZi; break;
- case Instruction::SetLE: opCode = V9::MOVRLEZi; break;
- case Instruction::SetGE: opCode = V9::MOVRGEZi; break;
- case Instruction::SetLT: opCode = V9::MOVRLZi; break;
- case Instruction::SetGT: opCode = V9::MOVRGZi; break;
- case Instruction::SetNE: opCode = V9::MOVRNZi; break;
- default: assert(0 && "Unrecognized VM instr!"); break;
- }
-
- return opCode;
-}
-
-
-static inline MachineOpCode
-ChooseConvertToFloatInstr(const TargetMachine& target,
- OpLabel vopCode, const Type* opType)
-{
- assert((vopCode == ToFloatTy || vopCode == ToDoubleTy) &&
- "Unrecognized convert-to-float opcode!");
- assert((opType->isIntegral() || opType->isFloatingPoint() ||
- isa<PointerType>(opType))
- && "Trying to convert a non-scalar type to FLOAT/DOUBLE?");
-
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- unsigned opSize = target.getTargetData().getTypeSize(opType);
-
- if (opType == Type::FloatTy)
- opCode = (vopCode == ToFloatTy? V9::NOP : V9::FSTOD);
- else if (opType == Type::DoubleTy)
- opCode = (vopCode == ToFloatTy? V9::FDTOS : V9::NOP);
- else if (opSize <= 4)
- opCode = (vopCode == ToFloatTy? V9::FITOS : V9::FITOD);
- else {
- assert(opSize == 8 && "Unrecognized type size > 4 and < 8!");
- opCode = (vopCode == ToFloatTy? V9::FXTOS : V9::FXTOD);
- }
-
- return opCode;
-}
-
-static inline MachineOpCode
-ChooseConvertFPToIntInstr(const TargetMachine& target,
- const Type* destType, const Type* opType)
-{
- assert((opType == Type::FloatTy || opType == Type::DoubleTy)
- && "This function should only be called for FLOAT or DOUBLE");
- assert((destType->isIntegral() || isa<PointerType>(destType))
- && "Trying to convert FLOAT/DOUBLE to a non-scalar type?");
-
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- unsigned destSize = target.getTargetData().getTypeSize(destType);
-
- if (destType == Type::UIntTy)
- assert(destType != Type::UIntTy && "Expand FP-to-uint beforehand.");
- else if (destSize <= 4)
- opCode = (opType == Type::FloatTy)? V9::FSTOI : V9::FDTOI;
- else {
- assert(destSize == 8 && "Unrecognized type size > 4 and < 8!");
- opCode = (opType == Type::FloatTy)? V9::FSTOX : V9::FDTOX;
- }
-
- return opCode;
-}
-
-static MachineInstr*
-CreateConvertFPToIntInstr(const TargetMachine& target,
- Value* srcVal,
- Value* destVal,
- const Type* destType)
-{
- MachineOpCode opCode = ChooseConvertFPToIntInstr(target, destType,
- srcVal->getType());
- assert(opCode != V9::INVALID_OPCODE && "Expected to need conversion!");
- return BuildMI(opCode, 2).addReg(srcVal).addRegDef(destVal);
-}
-
-// CreateCodeToConvertFloatToInt: Convert FP value to signed or unsigned integer
-// The FP value must be converted to the dest type in an FP register,
-// and the result is then copied from FP to int register via memory.
-// SPARC does not have a float-to-uint conversion, only a float-to-int (fdtoi).
-// Since fdtoi converts to signed integers, any FP value V between MAXINT+1
-// and MAXUNSIGNED (i.e., 2^31 <= V <= 2^32-1) would be converted incorrectly.
-// Therefore, for converting an FP value to uint32_t, we first need to convert
-// to uint64_t and then to uint32_t.
-//
-static void
-CreateCodeToConvertFloatToInt(const TargetMachine& target,
- Value* opVal,
- Instruction* destI,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi)
-{
- Function* F = destI->getParent()->getParent();
-
- // Create a temporary to represent the FP register into which the
- // int value will placed after conversion. The type of this temporary
- // depends on the type of FP register to use: single-prec for a 32-bit
- // int or smaller; double-prec for a 64-bit int.
- //
- size_t destSize = target.getTargetData().getTypeSize(destI->getType());
-
- const Type* castDestType = destI->getType(); // type for the cast instr result
- const Type* castDestRegType; // type for cast instruction result reg
- TmpInstruction* destForCast; // dest for cast instruction
- Instruction* fpToIntCopyDest = destI; // dest for fp-reg-to-int-reg copy instr
-
- // For converting an FP value to uint32_t, we first need to convert to
- // uint64_t and then to uint32_t, as explained above.
- if (destI->getType() == Type::UIntTy) {
- castDestType = Type::ULongTy; // use this instead of type of destI
- castDestRegType = Type::DoubleTy; // uint64_t needs 64-bit FP register.
- destForCast = new TmpInstruction(mcfi, castDestRegType, opVal);
- fpToIntCopyDest = new TmpInstruction(mcfi, castDestType, destForCast);
- }
- else {
- castDestRegType = (destSize > 4)? Type::DoubleTy : Type::FloatTy;
- destForCast = new TmpInstruction(mcfi, castDestRegType, opVal);
- }
-
- // Create the fp-to-int conversion instruction (src and dest regs are FP regs)
- mvec.push_back(CreateConvertFPToIntInstr(target, opVal, destForCast,
- castDestType));
-
- // Create the fpreg-to-intreg copy code
- target.getInstrInfo().CreateCodeToCopyFloatToInt(target, F, destForCast,
- fpToIntCopyDest, mvec, mcfi);
-
- // Create the uint64_t to uint32_t conversion, if needed
- if (destI->getType() == Type::UIntTy)
- target.getInstrInfo().
- CreateZeroExtensionInstructions(target, F, fpToIntCopyDest, destI,
- /*numLowBits*/ 32, mvec, mcfi);
-}
-
-
-static inline MachineOpCode
-ChooseAddInstruction(const InstructionNode* instrNode)
-{
- return ChooseAddInstructionByType(instrNode->getInstruction()->getType());
-}
-
-
-static inline MachineInstr*
-CreateMovFloatInstruction(const InstructionNode* instrNode,
- const Type* resultType)
-{
- return BuildMI((resultType == Type::FloatTy) ? V9::FMOVS : V9::FMOVD, 2)
- .addReg(instrNode->leftChild()->getValue())
- .addRegDef(instrNode->getValue());
-}
-
-static inline MachineInstr*
-CreateAddConstInstruction(const InstructionNode* instrNode)
-{
- MachineInstr* minstr = NULL;
-
- Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
- assert(isa<Constant>(constOp));
-
- // Cases worth optimizing are:
- // (1) Add with 0 for float or double: use an FMOV of appropriate type,
- // instead of an FADD (1 vs 3 cycles). There is no integer MOV.
- //
- if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
- double dval = FPC->getValue();
- if (dval == 0.0)
- minstr = CreateMovFloatInstruction(instrNode,
- instrNode->getInstruction()->getType());
- }
-
- return minstr;
-}
-
-
-static inline MachineOpCode
-ChooseSubInstructionByType(const Type* resultType)
-{
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- if (resultType->isInteger() || isa<PointerType>(resultType)) {
- opCode = V9::SUBr;
- } else {
- switch(resultType->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = V9::FSUBS; break;
- case Type::DoubleTyID: opCode = V9::FSUBD; break;
- default: assert(0 && "Invalid type for SUB instruction"); break;
- }
- }
-
- return opCode;
-}
-
-
-static inline MachineInstr*
-CreateSubConstInstruction(const InstructionNode* instrNode)
-{
- MachineInstr* minstr = NULL;
-
- Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
- assert(isa<Constant>(constOp));
-
- // Cases worth optimizing are:
- // (1) Sub with 0 for float or double: use an FMOV of appropriate type,
- // instead of an FSUB (1 vs 3 cycles). There is no integer MOV.
- //
- if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
- double dval = FPC->getValue();
- if (dval == 0.0)
- minstr = CreateMovFloatInstruction(instrNode,
- instrNode->getInstruction()->getType());
- }
-
- return minstr;
-}
-
-
-static inline MachineOpCode
-ChooseFcmpInstruction(const InstructionNode* instrNode)
-{
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- Value* operand = ((InstrTreeNode*) instrNode->leftChild())->getValue();
- switch(operand->getType()->getPrimitiveID()) {
- case Type::FloatTyID: opCode = V9::FCMPS; break;
- case Type::DoubleTyID: opCode = V9::FCMPD; break;
- default: assert(0 && "Invalid type for FCMP instruction"); break;
- }
-
- return opCode;
-}
-
-
-// Assumes that leftArg and rightArg are both cast instructions.
-//
-static inline bool
-BothFloatToDouble(const InstructionNode* instrNode)
-{
- InstrTreeNode* leftArg = instrNode->leftChild();
- InstrTreeNode* rightArg = instrNode->rightChild();
- InstrTreeNode* leftArgArg = leftArg->leftChild();
- InstrTreeNode* rightArgArg = rightArg->leftChild();
- assert(leftArg->getValue()->getType() == rightArg->getValue()->getType());
-
- // Check if both arguments are floats cast to double
- return (leftArg->getValue()->getType() == Type::DoubleTy &&
- leftArgArg->getValue()->getType() == Type::FloatTy &&
- rightArgArg->getValue()->getType() == Type::FloatTy);
-}
-
-
-static inline MachineOpCode
-ChooseMulInstructionByType(const Type* resultType)
-{
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- if (resultType->isInteger())
- opCode = V9::MULXr;
- else
- switch(resultType->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = V9::FMULS; break;
- case Type::DoubleTyID: opCode = V9::FMULD; break;
- default: assert(0 && "Invalid type for MUL instruction"); break;
- }
-
- return opCode;
-}
-
-
-
-static inline MachineInstr*
-CreateIntNegInstruction(const TargetMachine& target,
- Value* vreg)
-{
- return BuildMI(V9::SUBr, 3).addMReg(target.getRegInfo().getZeroRegNum())
- .addReg(vreg).addRegDef(vreg);
-}
-
-
-// Create instruction sequence for any shift operation.
-// SLL or SLLX on an operand smaller than the integer reg. size (64bits)
-// requires a second instruction for explicit sign-extension.
-// Note that we only have to worry about a sign-bit appearing in the
-// most significant bit of the operand after shifting (e.g., bit 32 of
-// Int or bit 16 of Short), so we do not have to worry about results
-// that are as large as a normal integer register.
-//
-static inline void
-CreateShiftInstructions(const TargetMachine& target,
- Function* F,
- MachineOpCode shiftOpCode,
- Value* argVal1,
- Value* optArgVal2, /* Use optArgVal2 if not NULL */
- unsigned optShiftNum, /* else use optShiftNum */
- Instruction* destVal,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi)
-{
- assert((optArgVal2 != NULL || optShiftNum <= 64) &&
- "Large shift sizes unexpected, but can be handled below: "
- "You need to check whether or not it fits in immed field below");
-
- // If this is a logical left shift of a type smaller than the standard
- // integer reg. size, we have to extend the sign-bit into upper bits
- // of dest, so we need to put the result of the SLL into a temporary.
- //
- Value* shiftDest = destVal;
- unsigned opSize = target.getTargetData().getTypeSize(argVal1->getType());
-
- if ((shiftOpCode == V9::SLLr5 || shiftOpCode == V9::SLLXr6) && opSize < 8) {
- // put SLL result into a temporary
- shiftDest = new TmpInstruction(mcfi, argVal1, optArgVal2, "sllTmp");
- }
-
- MachineInstr* M = (optArgVal2 != NULL)
- ? BuildMI(shiftOpCode, 3).addReg(argVal1).addReg(optArgVal2)
- .addReg(shiftDest, MachineOperand::Def)
- : BuildMI(shiftOpCode, 3).addReg(argVal1).addZImm(optShiftNum)
- .addReg(shiftDest, MachineOperand::Def);
- mvec.push_back(M);
-
- if (shiftDest != destVal) {
- // extend the sign-bit of the result into all upper bits of dest
- assert(8*opSize <= 32 && "Unexpected type size > 4 and < IntRegSize?");
- target.getInstrInfo().
- CreateSignExtensionInstructions(target, F, shiftDest, destVal,
- 8*opSize, mvec, mcfi);
- }
-}
-
-
-// Does not create any instructions if we cannot exploit constant to
-// create a cheaper instruction.
-// This returns the approximate cost of the instructions generated,
-// which is used to pick the cheapest when both operands are constant.
-static unsigned
-CreateMulConstInstruction(const TargetMachine &target, Function* F,
- Value* lval, Value* rval, Instruction* destVal,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi)
-{
- /* Use max. multiply cost, viz., cost of MULX */
- unsigned cost = target.getInstrInfo().minLatency(V9::MULXr);
- unsigned firstNewInstr = mvec.size();
-
- Value* constOp = rval;
- if (! isa<Constant>(constOp))
- return cost;
-
- // Cases worth optimizing are:
- // (1) Multiply by 0 or 1 for any type: replace with copy (ADD or FMOV)
- // (2) Multiply by 2^x for integer types: replace with Shift
- //
- const Type* resultType = destVal->getType();
-
- if (resultType->isInteger() || isa<PointerType>(resultType)) {
- bool isValidConst;
- int64_t C = (int64_t) target.getInstrInfo().ConvertConstantToIntType(target,
- constOp, constOp->getType(), isValidConst);
- if (isValidConst) {
- unsigned pow;
- bool needNeg = false;
- if (C < 0) {
- needNeg = true;
- C = -C;
- }
-
- if (C == 0 || C == 1) {
- cost = target.getInstrInfo().minLatency(V9::ADDr);
- unsigned Zero = target.getRegInfo().getZeroRegNum();
- MachineInstr* M;
- if (C == 0)
- M =BuildMI(V9::ADDr,3).addMReg(Zero).addMReg(Zero).addRegDef(destVal);
- else
- M = BuildMI(V9::ADDr,3).addReg(lval).addMReg(Zero).addRegDef(destVal);
- mvec.push_back(M);
- } else if (isPowerOf2(C, pow)) {
- unsigned opSize = target.getTargetData().getTypeSize(resultType);
- MachineOpCode opCode = (opSize <= 32)? V9::SLLr5 : V9::SLLXr6;
- CreateShiftInstructions(target, F, opCode, lval, NULL, pow,
- destVal, mvec, mcfi);
- }
-
- if (mvec.size() > 0 && needNeg) {
- // insert <reg = SUB 0, reg> after the instr to flip the sign
- MachineInstr* M = CreateIntNegInstruction(target, destVal);
- mvec.push_back(M);
- }
- }
- } else {
- if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
- double dval = FPC->getValue();
- if (fabs(dval) == 1) {
- MachineOpCode opCode = (dval < 0)
- ? (resultType == Type::FloatTy? V9::FNEGS : V9::FNEGD)
- : (resultType == Type::FloatTy? V9::FMOVS : V9::FMOVD);
- mvec.push_back(BuildMI(opCode,2).addReg(lval).addRegDef(destVal));
- }
- }
- }
-
- if (firstNewInstr < mvec.size()) {
- cost = 0;
- for (unsigned i=firstNewInstr; i < mvec.size(); ++i)
- cost += target.getInstrInfo().minLatency(mvec[i]->getOpcode());
- }
-
- return cost;
-}
-
-
-// Does not create any instructions if we cannot exploit constant to
-// create a cheaper instruction.
-//
-static inline void
-CreateCheapestMulConstInstruction(const TargetMachine &target,
- Function* F,
- Value* lval, Value* rval,
- Instruction* destVal,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi)
-{
- Value* constOp;
- if (isa<Constant>(lval) && isa<Constant>(rval)) {
- // both operands are constant: evaluate and "set" in dest
- Constant* P = ConstantExpr::get(Instruction::Mul,
- cast<Constant>(lval),
- cast<Constant>(rval));
- target.getInstrInfo().CreateCodeToLoadConst(target,F,P,destVal,mvec,mcfi);
- }
- else if (isa<Constant>(rval)) // rval is constant, but not lval
- CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi);
- else if (isa<Constant>(lval)) // lval is constant, but not rval
- CreateMulConstInstruction(target, F, lval, rval, destVal, mvec, mcfi);
-
- // else neither is constant
- return;
-}
-
-// Return NULL if we cannot exploit constant to create a cheaper instruction
-static inline void
-CreateMulInstruction(const TargetMachine &target, Function* F,
- Value* lval, Value* rval, Instruction* destVal,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi,
- MachineOpCode forceMulOp = INVALID_MACHINE_OPCODE)
-{
- unsigned L = mvec.size();
- CreateCheapestMulConstInstruction(target,F, lval, rval, destVal, mvec, mcfi);
- if (mvec.size() == L) {
- // no instructions were added so create MUL reg, reg, reg.
- // Use FSMULD if both operands are actually floats cast to doubles.
- // Otherwise, use the default opcode for the appropriate type.
- MachineOpCode mulOp = ((forceMulOp != INVALID_MACHINE_OPCODE)
- ? forceMulOp
- : ChooseMulInstructionByType(destVal->getType()));
- mvec.push_back(BuildMI(mulOp, 3).addReg(lval).addReg(rval)
- .addRegDef(destVal));
- }
-}
-
-
-// Generate a divide instruction for Div or Rem.
-// For Rem, this assumes that the operand type will be signed if the result
-// type is signed. This is correct because they must have the same sign.
-//
-static inline MachineOpCode
-ChooseDivInstruction(TargetMachine &target,
- const InstructionNode* instrNode)
-{
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- const Type* resultType = instrNode->getInstruction()->getType();
-
- if (resultType->isInteger())
- opCode = resultType->isSigned()? V9::SDIVXr : V9::UDIVXr;
- else
- switch(resultType->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = V9::FDIVS; break;
- case Type::DoubleTyID: opCode = V9::FDIVD; break;
- default: assert(0 && "Invalid type for DIV instruction"); break;
- }
-
- return opCode;
-}
-
-
-// Return if we cannot exploit constant to create a cheaper instruction
-static void
-CreateDivConstInstruction(TargetMachine &target,
- const InstructionNode* instrNode,
- std::vector<MachineInstr*>& mvec)
-{
- Value* LHS = instrNode->leftChild()->getValue();
- Value* constOp = ((InstrTreeNode*) instrNode->rightChild())->getValue();
- if (!isa<Constant>(constOp))
- return;
-
- Instruction* destVal = instrNode->getInstruction();
- unsigned ZeroReg = target.getRegInfo().getZeroRegNum();
-
- // Cases worth optimizing are:
- // (1) Divide by 1 for any type: replace with copy (ADD or FMOV)
- // (2) Divide by 2^x for integer types: replace with SR[L or A]{X}
- //
- const Type* resultType = instrNode->getInstruction()->getType();
-
- if (resultType->isInteger()) {
- unsigned pow;
- bool isValidConst;
- int64_t C = (int64_t) target.getInstrInfo().ConvertConstantToIntType(target,
- constOp, constOp->getType(), isValidConst);
- if (isValidConst) {
- bool needNeg = false;
- if (C < 0) {
- needNeg = true;
- C = -C;
- }
-
- if (C == 1) {
- mvec.push_back(BuildMI(V9::ADDr, 3).addReg(LHS).addMReg(ZeroReg)
- .addRegDef(destVal));
- } else if (isPowerOf2(C, pow)) {
- unsigned opCode;
- Value* shiftOperand;
- unsigned opSize = target.getTargetData().getTypeSize(resultType);
-
- if (resultType->isSigned()) {
- // For N / 2^k, if the operand N is negative,
- // we need to add (2^k - 1) before right-shifting by k, i.e.,
- //
- // (N / 2^k) = N >> k, if N >= 0;
- // (N + 2^k - 1) >> k, if N < 0
- //
- // If N is <= 32 bits, use:
- // sra N, 31, t1 // t1 = ~0, if N < 0, 0 else
- // srl t1, 32-k, t2 // t2 = 2^k - 1, if N < 0, 0 else
- // add t2, N, t3 // t3 = N + 2^k -1, if N < 0, N else
- // sra t3, k, result // result = N / 2^k
- //
- // If N is 64 bits, use:
- // srax N, k-1, t1 // t1 = sign bit in high k positions
- // srlx t1, 64-k, t2 // t2 = 2^k - 1, if N < 0, 0 else
- // add t2, N, t3 // t3 = N + 2^k -1, if N < 0, N else
- // sra t3, k, result // result = N / 2^k
- //
- TmpInstruction *sraTmp, *srlTmp, *addTmp;
- MachineCodeForInstruction& mcfi
- = MachineCodeForInstruction::get(destVal);
- sraTmp = new TmpInstruction(mcfi, resultType, LHS, 0, "getSign");
- srlTmp = new TmpInstruction(mcfi, resultType, LHS, 0, "getPlus2km1");
- addTmp = new TmpInstruction(mcfi, resultType, LHS, srlTmp,"incIfNeg");
-
- // Create the SRA or SRAX instruction to get the sign bit
- mvec.push_back(BuildMI((opSize > 4)? V9::SRAXi6 : V9::SRAi5, 3)
- .addReg(LHS)
- .addSImm((resultType==Type::LongTy)? pow-1 : 31)
- .addRegDef(sraTmp));
-
- // Create the SRL or SRLX instruction to get the sign bit
- mvec.push_back(BuildMI((opSize > 4)? V9::SRLXi6 : V9::SRLi5, 3)
- .addReg(sraTmp)
- .addSImm((resultType==Type::LongTy)? 64-pow : 32-pow)
- .addRegDef(srlTmp));
-
- // Create the ADD instruction to add 2^pow-1 for negative values
- mvec.push_back(BuildMI(V9::ADDr, 3).addReg(LHS).addReg(srlTmp)
- .addRegDef(addTmp));
-
- // Get the shift operand and "right-shift" opcode to do the divide
- shiftOperand = addTmp;
- opCode = (opSize > 4)? V9::SRAXi6 : V9::SRAi5;
- } else {
- // Get the shift operand and "right-shift" opcode to do the divide
- shiftOperand = LHS;
- opCode = (opSize > 4)? V9::SRLXi6 : V9::SRLi5;
- }
-
- // Now do the actual shift!
- mvec.push_back(BuildMI(opCode, 3).addReg(shiftOperand).addZImm(pow)
- .addRegDef(destVal));
- }
-
- if (needNeg && (C == 1 || isPowerOf2(C, pow))) {
- // insert <reg = SUB 0, reg> after the instr to flip the sign
- mvec.push_back(CreateIntNegInstruction(target, destVal));
- }
- }
- } else {
- if (ConstantFP *FPC = dyn_cast<ConstantFP>(constOp)) {
- double dval = FPC->getValue();
- if (fabs(dval) == 1) {
- unsigned opCode =
- (dval < 0) ? (resultType == Type::FloatTy? V9::FNEGS : V9::FNEGD)
- : (resultType == Type::FloatTy? V9::FMOVS : V9::FMOVD);
-
- mvec.push_back(BuildMI(opCode, 2).addReg(LHS).addRegDef(destVal));
- }
- }
- }
-}
-
-
-static void
-CreateCodeForVariableSizeAlloca(const TargetMachine& target,
- Instruction* result,
- unsigned tsize,
- Value* numElementsVal,
- std::vector<MachineInstr*>& getMvec)
-{
- Value* totalSizeVal;
- MachineInstr* M;
- MachineCodeForInstruction& mcfi = MachineCodeForInstruction::get(result);
- Function *F = result->getParent()->getParent();
-
- // Enforce the alignment constraints on the stack pointer at
- // compile time if the total size is a known constant.
- if (isa<Constant>(numElementsVal)) {
- bool isValid;
- int64_t numElem = (int64_t) target.getInstrInfo().
- ConvertConstantToIntType(target, numElementsVal,
- numElementsVal->getType(), isValid);
- assert(isValid && "Unexpectedly large array dimension in alloca!");
- int64_t total = numElem * tsize;
- if (int extra= total % target.getFrameInfo().getStackFrameSizeAlignment())
- total += target.getFrameInfo().getStackFrameSizeAlignment() - extra;
- totalSizeVal = ConstantSInt::get(Type::IntTy, total);
- } else {
- // The size is not a constant. Generate code to compute it and
- // code to pad the size for stack alignment.
- // Create a Value to hold the (constant) element size
- Value* tsizeVal = ConstantSInt::get(Type::IntTy, tsize);
-
- // Create temporary values to hold the result of MUL, SLL, SRL
- // To pad `size' to next smallest multiple of 16:
- // size = (size + 15) & (-16 = 0xfffffffffffffff0)
- //
- TmpInstruction* tmpProd = new TmpInstruction(mcfi,numElementsVal, tsizeVal);
- TmpInstruction* tmpAdd15= new TmpInstruction(mcfi,numElementsVal, tmpProd);
- TmpInstruction* tmpAndf0= new TmpInstruction(mcfi,numElementsVal, tmpAdd15);
-
- // Instruction 1: mul numElements, typeSize -> tmpProd
- // This will optimize the MUL as far as possible.
- CreateMulInstruction(target, F, numElementsVal, tsizeVal, tmpProd, getMvec,
- mcfi, INVALID_MACHINE_OPCODE);
-
- // Instruction 2: andn tmpProd, 0x0f -> tmpAndn
- getMvec.push_back(BuildMI(V9::ADDi, 3).addReg(tmpProd).addSImm(15)
- .addReg(tmpAdd15, MachineOperand::Def));
-
- // Instruction 3: add tmpAndn, 0x10 -> tmpAdd16
- getMvec.push_back(BuildMI(V9::ANDi, 3).addReg(tmpAdd15).addSImm(-16)
- .addReg(tmpAndf0, MachineOperand::Def));
-
- totalSizeVal = tmpAndf0;
- }
-
- // Get the constant offset from SP for dynamically allocated storage
- // and create a temporary Value to hold it.
- MachineFunction& mcInfo = MachineFunction::get(F);
- bool growUp;
- ConstantSInt* dynamicAreaOffset =
- ConstantSInt::get(Type::IntTy,
- target.getFrameInfo().getDynamicAreaOffset(mcInfo,growUp));
- assert(! growUp && "Has SPARC v9 stack frame convention changed?");
-
- unsigned SPReg = target.getRegInfo().getStackPointer();
-
- // Instruction 2: sub %sp, totalSizeVal -> %sp
- getMvec.push_back(BuildMI(V9::SUBr, 3).addMReg(SPReg).addReg(totalSizeVal)
- .addMReg(SPReg,MachineOperand::Def));
-
- // Instruction 3: add %sp, frameSizeBelowDynamicArea -> result
- getMvec.push_back(BuildMI(V9::ADDr,3).addMReg(SPReg).addReg(dynamicAreaOffset)
- .addRegDef(result));
-}
-
-
-static void
-CreateCodeForFixedSizeAlloca(const TargetMachine& target,
- Instruction* result,
- unsigned tsize,
- unsigned numElements,
- std::vector<MachineInstr*>& getMvec)
-{
- assert(tsize > 0 && "Illegal (zero) type size for alloca");
- assert(result && result->getParent() &&
- "Result value is not part of a function?");
- Function *F = result->getParent()->getParent();
- MachineFunction &mcInfo = MachineFunction::get(F);
-
- // Put the variable in the dynamically sized area of the frame if either:
- // (a) The offset is too large to use as an immediate in load/stores
- // (check LDX because all load/stores have the same-size immed. field).
- // (b) The object is "large", so it could cause many other locals,
- // spills, and temporaries to have large offsets.
- // NOTE: We use LARGE = 8 * argSlotSize = 64 bytes.
- // You've gotta love having only 13 bits for constant offset values :-|.
- //
- unsigned paddedSize;
- int offsetFromFP = mcInfo.getInfo()->computeOffsetforLocalVar(result,
- paddedSize,
- tsize * numElements);
-
- if (((int)paddedSize) > 8 * target.getFrameInfo().getSizeOfEachArgOnStack() ||
- ! target.getInstrInfo().constantFitsInImmedField(V9::LDXi,offsetFromFP)) {
- CreateCodeForVariableSizeAlloca(target, result, tsize,
- ConstantSInt::get(Type::IntTy,numElements),
- getMvec);
- return;
- }
-
- // else offset fits in immediate field so go ahead and allocate it.
- offsetFromFP = mcInfo.getInfo()->allocateLocalVar(result, tsize *numElements);
-
- // Create a temporary Value to hold the constant offset.
- // This is needed because it may not fit in the immediate field.
- ConstantSInt* offsetVal = ConstantSInt::get(Type::IntTy, offsetFromFP);
-
- // Instruction 1: add %fp, offsetFromFP -> result
- unsigned FPReg = target.getRegInfo().getFramePointer();
- getMvec.push_back(BuildMI(V9::ADDr, 3).addMReg(FPReg).addReg(offsetVal)
- .addRegDef(result));
-}
-
-
-//------------------------------------------------------------------------
-// Function SetOperandsForMemInstr
-//
-// Choose addressing mode for the given load or store instruction.
-// Use [reg+reg] if it is an indexed reference, and the index offset is
-// not a constant or if it cannot fit in the offset field.
-// Use [reg+offset] in all other cases.
-//
-// This assumes that all array refs are "lowered" to one of these forms:
-// %x = load (subarray*) ptr, constant ; single constant offset
-// %x = load (subarray*) ptr, offsetVal ; single non-constant offset
-// Generally, this should happen via strength reduction + LICM.
-// Also, strength reduction should take care of using the same register for
-// the loop index variable and an array index, when that is profitable.
-//------------------------------------------------------------------------
-
-static void
-SetOperandsForMemInstr(unsigned Opcode,
- std::vector<MachineInstr*>& mvec,
- InstructionNode* vmInstrNode,
- const TargetMachine& target)
-{
- Instruction* memInst = vmInstrNode->getInstruction();
- // Index vector, ptr value, and flag if all indices are const.
- std::vector<Value*> idxVec;
- bool allConstantIndices;
- Value* ptrVal = GetMemInstArgs(vmInstrNode, idxVec, allConstantIndices);
-
- // Now create the appropriate operands for the machine instruction.
- // First, initialize so we default to storing the offset in a register.
- int64_t smallConstOffset = 0;
- Value* valueForRegOffset = NULL;
- MachineOperand::MachineOperandType offsetOpType =
- MachineOperand::MO_VirtualRegister;
-
- // Check if there is an index vector and if so, compute the
- // right offset for structures and for arrays
- //
- if (!idxVec.empty()) {
- const PointerType* ptrType = cast<PointerType>(ptrVal->getType());
-
- // If all indices are constant, compute the combined offset directly.
- if (allConstantIndices) {
- // Compute the offset value using the index vector. Create a
- // virtual reg. for it since it may not fit in the immed field.
- uint64_t offset = target.getTargetData().getIndexedOffset(ptrType,idxVec);
- valueForRegOffset = ConstantSInt::get(Type::LongTy, offset);
- } else {
- // There is at least one non-constant offset. Therefore, this must
- // be an array ref, and must have been lowered to a single non-zero
- // offset. (An extra leading zero offset, if any, can be ignored.)
- // Generate code sequence to compute address from index.
- //
- bool firstIdxIsZero = IsZero(idxVec[0]);
- assert(idxVec.size() == 1U + firstIdxIsZero
- && "Array refs must be lowered before Instruction Selection");
-
- Value* idxVal = idxVec[firstIdxIsZero];
-
- std::vector<MachineInstr*> mulVec;
- Instruction* addr =
- new TmpInstruction(MachineCodeForInstruction::get(memInst),
- Type::ULongTy, memInst);
-
- // Get the array type indexed by idxVal, and compute its element size.
- // The call to getTypeSize() will fail if size is not constant.
- const Type* vecType = (firstIdxIsZero
- ? GetElementPtrInst::getIndexedType(ptrType,
- std::vector<Value*>(1U, idxVec[0]),
- /*AllowCompositeLeaf*/ true)
- : ptrType);
- const Type* eltType = cast<SequentialType>(vecType)->getElementType();
- ConstantUInt* eltSizeVal = ConstantUInt::get(Type::ULongTy,
- target.getTargetData().getTypeSize(eltType));
-
- // CreateMulInstruction() folds constants intelligently enough.
- CreateMulInstruction(target, memInst->getParent()->getParent(),
- idxVal, /* lval, not likely to be const*/
- eltSizeVal, /* rval, likely to be constant */
- addr, /* result */
- mulVec, MachineCodeForInstruction::get(memInst),
- INVALID_MACHINE_OPCODE);
-
- assert(mulVec.size() > 0 && "No multiply code created?");
- mvec.insert(mvec.end(), mulVec.begin(), mulVec.end());
-
- valueForRegOffset = addr;
- }
- } else {
- offsetOpType = MachineOperand::MO_SignExtendedImmed;
- smallConstOffset = 0;
- }
-
- // For STORE:
- // Operand 0 is value, operand 1 is ptr, operand 2 is offset
- // For LOAD or GET_ELEMENT_PTR,
- // Operand 0 is ptr, operand 1 is offset, operand 2 is result.
- //
- unsigned offsetOpNum, ptrOpNum;
- MachineInstr *MI;
- if (memInst->getOpcode() == Instruction::Store) {
- if (offsetOpType == MachineOperand::MO_VirtualRegister) {
- MI = BuildMI(Opcode, 3).addReg(vmInstrNode->leftChild()->getValue())
- .addReg(ptrVal).addReg(valueForRegOffset);
- } else {
- Opcode = convertOpcodeFromRegToImm(Opcode);
- MI = BuildMI(Opcode, 3).addReg(vmInstrNode->leftChild()->getValue())
- .addReg(ptrVal).addSImm(smallConstOffset);
- }
- } else {
- if (offsetOpType == MachineOperand::MO_VirtualRegister) {
- MI = BuildMI(Opcode, 3).addReg(ptrVal).addReg(valueForRegOffset)
- .addRegDef(memInst);
- } else {
- Opcode = convertOpcodeFromRegToImm(Opcode);
- MI = BuildMI(Opcode, 3).addReg(ptrVal).addSImm(smallConstOffset)
- .addRegDef(memInst);
- }
- }
- mvec.push_back(MI);
-}
-
-
-//
-// Substitute operand `operandNum' of the instruction in node `treeNode'
-// in place of the use(s) of that instruction in node `parent'.
-// Check both explicit and implicit operands!
-// Also make sure to skip over a parent who:
-// (1) is a list node in the Burg tree, or
-// (2) itself had its results forwarded to its parent
-//
-static void
-ForwardOperand(InstructionNode* treeNode,
- InstrTreeNode* parent,
- int operandNum)
-{
- assert(treeNode && parent && "Invalid invocation of ForwardOperand");
-
- Instruction* unusedOp = treeNode->getInstruction();
- Value* fwdOp = unusedOp->getOperand(operandNum);
-
- // The parent itself may be a list node, so find the real parent instruction
- while (parent->getNodeType() != InstrTreeNode::NTInstructionNode)
- {
- parent = parent->parent();
- assert(parent && "ERROR: Non-instruction node has no parent in tree.");
- }
- InstructionNode* parentInstrNode = (InstructionNode*) parent;
-
- Instruction* userInstr = parentInstrNode->getInstruction();
- MachineCodeForInstruction &mvec = MachineCodeForInstruction::get(userInstr);
-
- // The parent's mvec would be empty if it was itself forwarded.
- // Recursively call ForwardOperand in that case...
- //
- if (mvec.size() == 0) {
- assert(parent->parent() != NULL &&
- "Parent could not have been forwarded, yet has no instructions?");
- ForwardOperand(treeNode, parent->parent(), operandNum);
- } else {
- for (unsigned i=0, N=mvec.size(); i < N; i++) {
- MachineInstr* minstr = mvec[i];
- for (unsigned i=0, numOps=minstr->getNumOperands(); i < numOps; ++i) {
- const MachineOperand& mop = minstr->getOperand(i);
- if (mop.getType() == MachineOperand::MO_VirtualRegister &&
- mop.getVRegValue() == unusedOp)
- {
- minstr->SetMachineOperandVal(i, MachineOperand::MO_VirtualRegister,
- fwdOp);
- }
- }
-
- for (unsigned i=0,numOps=minstr->getNumImplicitRefs(); i<numOps; ++i)
- if (minstr->getImplicitRef(i) == unusedOp)
- minstr->setImplicitRef(i, fwdOp);
- }
- }
-}
-
-
-inline bool
-AllUsesAreBranches(const Instruction* setccI)
-{
- for (Value::use_const_iterator UI=setccI->use_begin(), UE=setccI->use_end();
- UI != UE; ++UI)
- if (! isa<TmpInstruction>(*UI) // ignore tmp instructions here
- && cast<Instruction>(*UI)->getOpcode() != Instruction::Br)
- return false;
- return true;
-}
-
-// Generate code for any intrinsic that needs a special code sequence
-// instead of a regular call. If not that kind of intrinsic, do nothing.
-// Returns true if code was generated, otherwise false.
-//
-static bool CodeGenIntrinsic(Intrinsic::ID iid, CallInst &callInstr,
- TargetMachine &target,
- std::vector<MachineInstr*>& mvec) {
- switch (iid) {
- default:
- assert(0 && "Unknown intrinsic function call should have been lowered!");
- case Intrinsic::va_start: {
- // Get the address of the first incoming vararg argument on the stack
- bool ignore;
- Function* func = cast<Function>(callInstr.getParent()->getParent());
- int numFixedArgs = func->getFunctionType()->getNumParams();
- int fpReg = target.getFrameInfo().getIncomingArgBaseRegNum();
- int argSize = target.getFrameInfo().getSizeOfEachArgOnStack();
- int firstVarArgOff = numFixedArgs * argSize + target.getFrameInfo().
- getFirstIncomingArgOffset(MachineFunction::get(func), ignore);
- mvec.push_back(BuildMI(V9::ADDi, 3).addMReg(fpReg).addSImm(firstVarArgOff).
- addRegDef(&callInstr));
- return true;
- }
-
- case Intrinsic::va_end:
- return true; // no-op on Sparc
-
- case Intrinsic::va_copy:
- // Simple copy of current va_list (arg1) to new va_list (result)
- mvec.push_back(BuildMI(V9::ORr, 3).
- addMReg(target.getRegInfo().getZeroRegNum()).
- addReg(callInstr.getOperand(1)).
- addRegDef(&callInstr));
- return true;
- }
-}
-
-//******************* Externally Visible Functions *************************/
-
-//------------------------------------------------------------------------
-// External Function: ThisIsAChainRule
-//
-// Purpose:
-// Check if a given BURG rule is a chain rule.
-//------------------------------------------------------------------------
-
-extern bool
-ThisIsAChainRule(int eruleno)
-{
- switch(eruleno)
- {
- case 111: // stmt: reg
- case 123:
- case 124:
- case 125:
- case 126:
- case 127:
- case 128:
- case 129:
- case 130:
- case 131:
- case 132:
- case 133:
- case 155:
- case 221:
- case 222:
- case 241:
- case 242:
- case 243:
- case 244:
- case 245:
- case 321:
- return true; break;
-
- default:
- return false; break;
- }
-}
-
-
-//------------------------------------------------------------------------
-// External Function: GetInstructionsByRule
-//
-// Purpose:
-// Choose machine instructions for the SPARC according to the
-// patterns chosen by the BURG-generated parser.
-//------------------------------------------------------------------------
-
-void
-GetInstructionsByRule(InstructionNode* subtreeRoot,
- int ruleForNode,
- short* nts,
- TargetMachine &target,
- std::vector<MachineInstr*>& mvec)
-{
- bool checkCast = false; // initialize here to use fall-through
- bool maskUnsignedResult = false;
- int nextRule;
- int forwardOperandNum = -1;
- unsigned allocaSize = 0;
- MachineInstr* M, *M2;
- unsigned L;
- bool foldCase = false;
-
- mvec.clear();
-
- // If the code for this instruction was folded into the parent (user),
- // then do nothing!
- if (subtreeRoot->isFoldedIntoParent())
- return;
-
- //
- // Let's check for chain rules outside the switch so that we don't have
- // to duplicate the list of chain rule production numbers here again
- //
- if (ThisIsAChainRule(ruleForNode)) {
- // Chain rules have a single nonterminal on the RHS.
- // Get the rule that matches the RHS non-terminal and use that instead.
- //
- assert(nts[0] && ! nts[1]
- && "A chain rule should have only one RHS non-terminal!");
- nextRule = burm_rule(subtreeRoot->state, nts[0]);
- nts = burm_nts[nextRule];
- GetInstructionsByRule(subtreeRoot, nextRule, nts, target, mvec);
- } else {
- switch(ruleForNode) {
- case 1: // stmt: Ret
- case 2: // stmt: RetValue(reg)
- { // NOTE: Prepass of register allocation is responsible
- // for moving return value to appropriate register.
- // Copy the return value to the required return register.
- // Mark the return Value as an implicit ref of the RET instr..
- // Mark the return-address register as a hidden virtual reg.
- // Finally put a NOP in the delay slot.
- ReturnInst *returnInstr=cast<ReturnInst>(subtreeRoot->getInstruction());
- Value* retVal = returnInstr->getReturnValue();
- MachineCodeForInstruction& mcfi =
- MachineCodeForInstruction::get(returnInstr);
-
- // Create a hidden virtual reg to represent the return address register
- // used by the machine instruction but not represented in LLVM.
- //
- Instruction* returnAddrTmp = new TmpInstruction(mcfi, returnInstr);
-
- MachineInstr* retMI =
- BuildMI(V9::JMPLRETi, 3).addReg(returnAddrTmp).addSImm(8)
- .addMReg(target.getRegInfo().getZeroRegNum(), MachineOperand::Def);
-
- // If there is a value to return, we need to:
- // (a) Sign-extend the value if it is smaller than 8 bytes (reg size)
- // (b) Insert a copy to copy the return value to the appropriate reg.
- // -- For FP values, create a FMOVS or FMOVD instruction
- // -- For non-FP values, create an add-with-0 instruction
- //
- if (retVal != NULL) {
- const SparcRegInfo& regInfo =
- (SparcRegInfo&) target.getRegInfo();
- const Type* retType = retVal->getType();
- unsigned regClassID = regInfo.getRegClassIDOfType(retType);
- unsigned retRegNum = (retType->isFloatingPoint()
- ? (unsigned) SparcFloatRegClass::f0
- : (unsigned) SparcIntRegClass::i0);
- retRegNum = regInfo.getUnifiedRegNum(regClassID, retRegNum);
-
- // () Insert sign-extension instructions for small signed values.
- //
- Value* retValToUse = retVal;
- if (retType->isIntegral() && retType->isSigned()) {
- unsigned retSize = target.getTargetData().getTypeSize(retType);
- if (retSize <= 4) {
- // create a temporary virtual reg. to hold the sign-extension
- retValToUse = new TmpInstruction(mcfi, retVal);
-
- // sign-extend retVal and put the result in the temporary reg.
- target.getInstrInfo().CreateSignExtensionInstructions
- (target, returnInstr->getParent()->getParent(),
- retVal, retValToUse, 8*retSize, mvec, mcfi);
- }
- }
-
- // (b) Now, insert a copy to to the appropriate register:
- // -- For FP values, create a FMOVS or FMOVD instruction
- // -- For non-FP values, create an add-with-0 instruction
- //
- // First, create a virtual register to represent the register and
- // mark this vreg as being an implicit operand of the ret MI.
- TmpInstruction* retVReg =
- new TmpInstruction(mcfi, retValToUse, NULL, "argReg");
-
- retMI->addImplicitRef(retVReg);
-
- if (retType->isFloatingPoint())
- M = (BuildMI(retType==Type::FloatTy? V9::FMOVS : V9::FMOVD, 2)
- .addReg(retValToUse).addReg(retVReg, MachineOperand::Def));
- else
- M = (BuildMI(ChooseAddInstructionByType(retType), 3)
- .addReg(retValToUse).addSImm((int64_t) 0)
- .addReg(retVReg, MachineOperand::Def));
-
- // Mark the operand with the register it should be assigned
- M->SetRegForOperand(M->getNumOperands()-1, retRegNum);
- retMI->SetRegForImplicitRef(retMI->getNumImplicitRefs()-1, retRegNum);
-
- mvec.push_back(M);
- }
-
- // Now insert the RET instruction and a NOP for the delay slot
- mvec.push_back(retMI);
- mvec.push_back(BuildMI(V9::NOP, 0));
-
- break;
- }
-
- case 3: // stmt: Store(reg,reg)
- case 4: // stmt: Store(reg,ptrreg)
- SetOperandsForMemInstr(ChooseStoreInstruction(
- subtreeRoot->leftChild()->getValue()->getType()),
- mvec, subtreeRoot, target);
- break;
-
- case 5: // stmt: BrUncond
- {
- BranchInst *BI = cast<BranchInst>(subtreeRoot->getInstruction());
- mvec.push_back(BuildMI(V9::BA, 1).addPCDisp(BI->getSuccessor(0)));
-
- // delay slot
- mvec.push_back(BuildMI(V9::NOP, 0));
- break;
- }
-
- case 206: // stmt: BrCond(setCCconst)
- { // setCCconst => boolean was computed with `%b = setCC type reg1 const'
- // If the constant is ZERO, we can use the branch-on-integer-register
- // instructions and avoid the SUBcc instruction entirely.
- // Otherwise this is just the same as case 5, so just fall through.
- //
- InstrTreeNode* constNode = subtreeRoot->leftChild()->rightChild();
- assert(constNode &&
- constNode->getNodeType() ==InstrTreeNode::NTConstNode);
- Constant *constVal = cast<Constant>(constNode->getValue());
- bool isValidConst;
-
- if ((constVal->getType()->isInteger()
- || isa<PointerType>(constVal->getType()))
- && target.getInstrInfo().ConvertConstantToIntType(target,
- constVal, constVal->getType(), isValidConst) == 0
- && isValidConst)
- {
- // That constant is a zero after all...
- // Use the left child of setCC as the first argument!
- // Mark the setCC node so that no code is generated for it.
- InstructionNode* setCCNode = (InstructionNode*)
- subtreeRoot->leftChild();
- assert(setCCNode->getOpLabel() == SetCCOp);
- setCCNode->markFoldedIntoParent();
-
- BranchInst* brInst=cast<BranchInst>(subtreeRoot->getInstruction());
-
- M = BuildMI(ChooseBprInstruction(subtreeRoot), 2)
- .addReg(setCCNode->leftChild()->getValue())
- .addPCDisp(brInst->getSuccessor(0));
- mvec.push_back(M);
-
- // delay slot
- mvec.push_back(BuildMI(V9::NOP, 0));
-
- // false branch
- mvec.push_back(BuildMI(V9::BA, 1)
- .addPCDisp(brInst->getSuccessor(1)));
-
- // delay slot
- mvec.push_back(BuildMI(V9::NOP, 0));
- break;
- }
- // ELSE FALL THROUGH
- }
-
- case 6: // stmt: BrCond(setCC)
- { // bool => boolean was computed with SetCC.
- // The branch to use depends on whether it is FP, signed, or unsigned.
- // If it is an integer CC, we also need to find the unique
- // TmpInstruction representing that CC.
- //
- BranchInst* brInst = cast<BranchInst>(subtreeRoot->getInstruction());
- const Type* setCCType;
- unsigned Opcode = ChooseBccInstruction(subtreeRoot, setCCType);
- Value* ccValue = GetTmpForCC(subtreeRoot->leftChild()->getValue(),
- brInst->getParent()->getParent(),
- setCCType,
- MachineCodeForInstruction::get(brInst));
- M = BuildMI(Opcode, 2).addCCReg(ccValue)
- .addPCDisp(brInst->getSuccessor(0));
- mvec.push_back(M);
-
- // delay slot
- mvec.push_back(BuildMI(V9::NOP, 0));
-
- // false branch
- mvec.push_back(BuildMI(V9::BA, 1).addPCDisp(brInst->getSuccessor(1)));
-
- // delay slot
- mvec.push_back(BuildMI(V9::NOP, 0));
- break;
- }
-
- case 208: // stmt: BrCond(boolconst)
- {
- // boolconst => boolean is a constant; use BA to first or second label
- Constant* constVal =
- cast<Constant>(subtreeRoot->leftChild()->getValue());
- unsigned dest = cast<ConstantBool>(constVal)->getValue()? 0 : 1;
-
- M = BuildMI(V9::BA, 1).addPCDisp(
- cast<BranchInst>(subtreeRoot->getInstruction())->getSuccessor(dest));
- mvec.push_back(M);
-
- // delay slot
- mvec.push_back(BuildMI(V9::NOP, 0));
- break;
- }
-
- case 8: // stmt: BrCond(boolreg)
- { // boolreg => boolean is recorded in an integer register.
- // Use branch-on-integer-register instruction.
- //
- BranchInst *BI = cast<BranchInst>(subtreeRoot->getInstruction());
- M = BuildMI(V9::BRNZ, 2).addReg(subtreeRoot->leftChild()->getValue())
- .addPCDisp(BI->getSuccessor(0));
- mvec.push_back(M);
-
- // delay slot
- mvec.push_back(BuildMI(V9::NOP, 0));
-
- // false branch
- mvec.push_back(BuildMI(V9::BA, 1).addPCDisp(BI->getSuccessor(1)));
-
- // delay slot
- mvec.push_back(BuildMI(V9::NOP, 0));
- break;
- }
-
- case 9: // stmt: Switch(reg)
- assert(0 && "*** SWITCH instruction is not implemented yet.");
- break;
-
- case 10: // reg: VRegList(reg, reg)
- assert(0 && "VRegList should never be the topmost non-chain rule");
- break;
-
- case 21: // bool: Not(bool,reg): Compute with a conditional-move-on-reg
- { // First find the unary operand. It may be left or right, usually right.
- Instruction* notI = subtreeRoot->getInstruction();
- Value* notArg = BinaryOperator::getNotArgument(
- cast<BinaryOperator>(subtreeRoot->getInstruction()));
- unsigned ZeroReg = target.getRegInfo().getZeroRegNum();
-
- // Unconditionally set register to 0
- mvec.push_back(BuildMI(V9::SETHI, 2).addZImm(0).addRegDef(notI));
-
- // Now conditionally move 1 into the register.
- // Mark the register as a use (as well as a def) because the old
- // value will be retained if the condition is false.
- mvec.push_back(BuildMI(V9::MOVRZi, 3).addReg(notArg).addZImm(1)
- .addReg(notI, MachineOperand::UseAndDef));
-
- break;
- }
-
- case 421: // reg: BNot(reg,reg): Compute as reg = reg XOR-NOT 0
- { // First find the unary operand. It may be left or right, usually right.
- Value* notArg = BinaryOperator::getNotArgument(
- cast<BinaryOperator>(subtreeRoot->getInstruction()));
- unsigned ZeroReg = target.getRegInfo().getZeroRegNum();
- mvec.push_back(BuildMI(V9::XNORr, 3).addReg(notArg).addMReg(ZeroReg)
- .addRegDef(subtreeRoot->getValue()));
- break;
- }
-
- case 322: // reg: Not(tobool, reg):
- // Fold CAST-TO-BOOL with NOT by inverting the sense of cast-to-bool
- foldCase = true;
- // Just fall through!
-
- case 22: // reg: ToBoolTy(reg):
- {
- Instruction* castI = subtreeRoot->getInstruction();
- Value* opVal = subtreeRoot->leftChild()->getValue();
- assert(opVal->getType()->isIntegral() ||
- isa<PointerType>(opVal->getType()));
-
- // Unconditionally set register to 0
- mvec.push_back(BuildMI(V9::SETHI, 2).addZImm(0).addRegDef(castI));
-
- // Now conditionally move 1 into the register.
- // Mark the register as a use (as well as a def) because the old
- // value will be retained if the condition is false.
- MachineOpCode opCode = foldCase? V9::MOVRZi : V9::MOVRNZi;
- mvec.push_back(BuildMI(opCode, 3).addReg(opVal).addZImm(1)
- .addReg(castI, MachineOperand::UseAndDef));
-
- break;
- }
-
- case 23: // reg: ToUByteTy(reg)
- case 24: // reg: ToSByteTy(reg)
- case 25: // reg: ToUShortTy(reg)
- case 26: // reg: ToShortTy(reg)
- case 27: // reg: ToUIntTy(reg)
- case 28: // reg: ToIntTy(reg)
- case 29: // reg: ToULongTy(reg)
- case 30: // reg: ToLongTy(reg)
- {
- //======================================================================
- // Rules for integer conversions:
- //
- //--------
- // From ISO 1998 C++ Standard, Sec. 4.7:
- //
- // 2. If the destination type is unsigned, the resulting value is
- // the least unsigned integer congruent to the source integer
- // (modulo 2n where n is the number of bits used to represent the
- // unsigned type). [Note: In a two s complement representation,
- // this conversion is conceptual and there is no change in the
- // bit pattern (if there is no truncation). ]
- //
- // 3. If the destination type is signed, the value is unchanged if
- // it can be represented in the destination type (and bitfield width);
- // otherwise, the value is implementation-defined.
- //--------
- //
- // Since we assume 2s complement representations, this implies:
- //
- // -- If operand is smaller than destination, zero-extend or sign-extend
- // according to the signedness of the *operand*: source decides:
- // (1) If operand is signed, sign-extend it.
- // If dest is unsigned, zero-ext the result!
- // (2) If operand is unsigned, our current invariant is that
- // it's high bits are correct, so zero-extension is not needed.
- //
- // -- If operand is same size as or larger than destination,
- // zero-extend or sign-extend according to the signedness of
- // the *destination*: destination decides:
- // (1) If destination is signed, sign-extend (truncating if needed)
- // This choice is implementation defined. We sign-extend the
- // operand, which matches both Sun's cc and gcc3.2.
- // (2) If destination is unsigned, zero-extend (truncating if needed)
- //======================================================================
-
- Instruction* destI = subtreeRoot->getInstruction();
- Function* currentFunc = destI->getParent()->getParent();
- MachineCodeForInstruction& mcfi=MachineCodeForInstruction::get(destI);
-
- Value* opVal = subtreeRoot->leftChild()->getValue();
- const Type* opType = opVal->getType();
- const Type* destType = destI->getType();
- unsigned opSize = target.getTargetData().getTypeSize(opType);
- unsigned destSize = target.getTargetData().getTypeSize(destType);
-
- bool isIntegral = opType->isIntegral() || isa<PointerType>(opType);
-
- if (opType == Type::BoolTy ||
- opType == destType ||
- isIntegral && opSize == destSize && opSize == 8) {
- // nothing to do in all these cases
- forwardOperandNum = 0; // forward first operand to user
-
- } else if (opType->isFloatingPoint()) {
-
- CreateCodeToConvertFloatToInt(target, opVal, destI, mvec, mcfi);
- if (destI->getType()->isUnsigned() && destI->getType() !=Type::UIntTy)
- maskUnsignedResult = true; // not handled by fp->int code
-
- } else if (isIntegral) {
-
- bool opSigned = opType->isSigned();
- bool destSigned = destType->isSigned();
- unsigned extSourceInBits = 8 * std::min<unsigned>(opSize, destSize);
-
- assert(! (opSize == destSize && opSigned == destSigned) &&
- "How can different int types have same size and signedness?");
-
- bool signExtend = (opSize < destSize && opSigned ||
- opSize >= destSize && destSigned);
-
- bool signAndZeroExtend = (opSize < destSize && destSize < 8u &&
- opSigned && !destSigned);
- assert(!signAndZeroExtend || signExtend);
-
- bool zeroExtendOnly = opSize >= destSize && !destSigned;
- assert(!zeroExtendOnly || !signExtend);
-
- if (signExtend) {
- Value* signExtDest = (signAndZeroExtend
- ? new TmpInstruction(mcfi, destType, opVal)
- : destI);
-
- target.getInstrInfo().CreateSignExtensionInstructions
- (target, currentFunc,opVal,signExtDest,extSourceInBits,mvec,mcfi);
-
- if (signAndZeroExtend)
- target.getInstrInfo().CreateZeroExtensionInstructions
- (target, currentFunc, signExtDest, destI, 8*destSize, mvec, mcfi);
- }
- else if (zeroExtendOnly) {
- target.getInstrInfo().CreateZeroExtensionInstructions
- (target, currentFunc, opVal, destI, extSourceInBits, mvec, mcfi);
- }
- else
- forwardOperandNum = 0; // forward first operand to user
-
- } else
- assert(0 && "Unrecognized operand type for convert-to-integer");
-
- break;
- }
-
- case 31: // reg: ToFloatTy(reg):
- case 32: // reg: ToDoubleTy(reg):
- case 232: // reg: ToDoubleTy(Constant):
-
- // If this instruction has a parent (a user) in the tree
- // and the user is translated as an FsMULd instruction,
- // then the cast is unnecessary. So check that first.
- // In the future, we'll want to do the same for the FdMULq instruction,
- // so do the check here instead of only for ToFloatTy(reg).
- //
- if (subtreeRoot->parent() != NULL) {
- const MachineCodeForInstruction& mcfi =
- MachineCodeForInstruction::get(
- cast<InstructionNode>(subtreeRoot->parent())->getInstruction());
- if (mcfi.size() == 0 || mcfi.front()->getOpcode() == V9::FSMULD)
- forwardOperandNum = 0; // forward first operand to user
- }
-
- if (forwardOperandNum != 0) { // we do need the cast
- Value* leftVal = subtreeRoot->leftChild()->getValue();
- const Type* opType = leftVal->getType();
- MachineOpCode opCode=ChooseConvertToFloatInstr(target,
- subtreeRoot->getOpLabel(), opType);
- if (opCode == V9::NOP) { // no conversion needed
- forwardOperandNum = 0; // forward first operand to user
- } else {
- // If the source operand is a non-FP type it must be
- // first copied from int to float register via memory!
- Instruction *dest = subtreeRoot->getInstruction();
- Value* srcForCast;
- int n = 0;
- if (! opType->isFloatingPoint()) {
- // Create a temporary to represent the FP register
- // into which the integer will be copied via memory.
- // The type of this temporary will determine the FP
- // register used: single-prec for a 32-bit int or smaller,
- // double-prec for a 64-bit int.
- //
- uint64_t srcSize =
- target.getTargetData().getTypeSize(leftVal->getType());
- Type* tmpTypeToUse =
- (srcSize <= 4)? Type::FloatTy : Type::DoubleTy;
- MachineCodeForInstruction &destMCFI =
- MachineCodeForInstruction::get(dest);
- srcForCast = new TmpInstruction(destMCFI, tmpTypeToUse, dest);
-
- target.getInstrInfo().CreateCodeToCopyIntToFloat(target,
- dest->getParent()->getParent(),
- leftVal, cast<Instruction>(srcForCast),
- mvec, destMCFI);
- } else
- srcForCast = leftVal;
-
- M = BuildMI(opCode, 2).addReg(srcForCast).addRegDef(dest);
- mvec.push_back(M);
- }
- }
- break;
-
- case 19: // reg: ToArrayTy(reg):
- case 20: // reg: ToPointerTy(reg):
- forwardOperandNum = 0; // forward first operand to user
- break;
-
- case 233: // reg: Add(reg, Constant)
- maskUnsignedResult = true;
- M = CreateAddConstInstruction(subtreeRoot);
- if (M != NULL) {
- mvec.push_back(M);
- break;
- }
- // ELSE FALL THROUGH
-
- case 33: // reg: Add(reg, reg)
- maskUnsignedResult = true;
- Add3OperandInstr(ChooseAddInstruction(subtreeRoot), subtreeRoot, mvec);
- break;
-
- case 234: // reg: Sub(reg, Constant)
- maskUnsignedResult = true;
- M = CreateSubConstInstruction(subtreeRoot);
- if (M != NULL) {
- mvec.push_back(M);
- break;
- }
- // ELSE FALL THROUGH
-
- case 34: // reg: Sub(reg, reg)
- maskUnsignedResult = true;
- Add3OperandInstr(ChooseSubInstructionByType(
- subtreeRoot->getInstruction()->getType()),
- subtreeRoot, mvec);
- break;
-
- case 135: // reg: Mul(todouble, todouble)
- checkCast = true;
- // FALL THROUGH
-
- case 35: // reg: Mul(reg, reg)
- {
- maskUnsignedResult = true;
- MachineOpCode forceOp = ((checkCast && BothFloatToDouble(subtreeRoot))
- ? (MachineOpCode)V9::FSMULD
- : INVALID_MACHINE_OPCODE);
- Instruction* mulInstr = subtreeRoot->getInstruction();
- CreateMulInstruction(target, mulInstr->getParent()->getParent(),
- subtreeRoot->leftChild()->getValue(),
- subtreeRoot->rightChild()->getValue(),
- mulInstr, mvec,
- MachineCodeForInstruction::get(mulInstr),forceOp);
- break;
- }
- case 335: // reg: Mul(todouble, todoubleConst)
- checkCast = true;
- // FALL THROUGH
-
- case 235: // reg: Mul(reg, Constant)
- {
- maskUnsignedResult = true;
- MachineOpCode forceOp = ((checkCast && BothFloatToDouble(subtreeRoot))
- ? (MachineOpCode)V9::FSMULD
- : INVALID_MACHINE_OPCODE);
- Instruction* mulInstr = subtreeRoot->getInstruction();
- CreateMulInstruction(target, mulInstr->getParent()->getParent(),
- subtreeRoot->leftChild()->getValue(),
- subtreeRoot->rightChild()->getValue(),
- mulInstr, mvec,
- MachineCodeForInstruction::get(mulInstr),
- forceOp);
- break;
- }
- case 236: // reg: Div(reg, Constant)
- maskUnsignedResult = true;
- L = mvec.size();
- CreateDivConstInstruction(target, subtreeRoot, mvec);
- if (mvec.size() > L)
- break;
- // ELSE FALL THROUGH
-
- case 36: // reg: Div(reg, reg)
- {
- maskUnsignedResult = true;
-
- // If either operand of divide is smaller than 64 bits, we have
- // to make sure the unused top bits are correct because they affect
- // the result. These bits are already correct for unsigned values.
- // They may be incorrect for signed values, so sign extend to fill in.
- Instruction* divI = subtreeRoot->getInstruction();
- Value* divOp1 = subtreeRoot->leftChild()->getValue();
- Value* divOp2 = subtreeRoot->rightChild()->getValue();
- Value* divOp1ToUse = divOp1;
- Value* divOp2ToUse = divOp2;
- if (divI->getType()->isSigned()) {
- unsigned opSize=target.getTargetData().getTypeSize(divI->getType());
- if (opSize < 8) {
- MachineCodeForInstruction& mcfi=MachineCodeForInstruction::get(divI);
- divOp1ToUse = new TmpInstruction(mcfi, divOp1);
- divOp2ToUse = new TmpInstruction(mcfi, divOp2);
- target.getInstrInfo().
- CreateSignExtensionInstructions(target,
- divI->getParent()->getParent(),
- divOp1, divOp1ToUse,
- 8*opSize, mvec, mcfi);
- target.getInstrInfo().
- CreateSignExtensionInstructions(target,
- divI->getParent()->getParent(),
- divOp2, divOp2ToUse,
- 8*opSize, mvec, mcfi);
- }
- }
-
- mvec.push_back(BuildMI(ChooseDivInstruction(target, subtreeRoot), 3)
- .addReg(divOp1ToUse)
- .addReg(divOp2ToUse)
- .addRegDef(divI));
-
- break;
- }
-
- case 37: // reg: Rem(reg, reg)
- case 237: // reg: Rem(reg, Constant)
- {
- maskUnsignedResult = true;
-
- Instruction* remI = subtreeRoot->getInstruction();
- Value* divOp1 = subtreeRoot->leftChild()->getValue();
- Value* divOp2 = subtreeRoot->rightChild()->getValue();
-
- MachineCodeForInstruction& mcfi = MachineCodeForInstruction::get(remI);
-
- // If second operand of divide is smaller than 64 bits, we have
- // to make sure the unused top bits are correct because they affect
- // the result. These bits are already correct for unsigned values.
- // They may be incorrect for signed values, so sign extend to fill in.
- //
- Value* divOpToUse = divOp2;
- if (divOp2->getType()->isSigned()) {
- unsigned opSize=target.getTargetData().getTypeSize(divOp2->getType());
- if (opSize < 8) {
- divOpToUse = new TmpInstruction(mcfi, divOp2);
- target.getInstrInfo().
- CreateSignExtensionInstructions(target,
- remI->getParent()->getParent(),
- divOp2, divOpToUse,
- 8*opSize, mvec, mcfi);
- }
- }
-
- // Now compute: result = rem V1, V2 as:
- // result = V1 - (V1 / signExtend(V2)) * signExtend(V2)
- //
- TmpInstruction* quot = new TmpInstruction(mcfi, divOp1, divOpToUse);
- TmpInstruction* prod = new TmpInstruction(mcfi, quot, divOpToUse);
-
- mvec.push_back(BuildMI(ChooseDivInstruction(target, subtreeRoot), 3)
- .addReg(divOp1).addReg(divOpToUse).addRegDef(quot));
-
- mvec.push_back(BuildMI(ChooseMulInstructionByType(remI->getType()), 3)
- .addReg(quot).addReg(divOpToUse).addRegDef(prod));
-
- mvec.push_back(BuildMI(ChooseSubInstructionByType(remI->getType()), 3)
- .addReg(divOp1).addReg(prod).addRegDef(remI));
-
- break;
- }
-
- case 38: // bool: And(bool, bool)
- case 138: // bool: And(bool, not)
- case 238: // bool: And(bool, boolconst)
- case 338: // reg : BAnd(reg, reg)
- case 538: // reg : BAnd(reg, Constant)
- Add3OperandInstr(V9::ANDr, subtreeRoot, mvec);
- break;
-
- case 438: // bool: BAnd(bool, bnot)
- { // Use the argument of NOT as the second argument!
- // Mark the NOT node so that no code is generated for it.
- // If the type is boolean, set 1 or 0 in the result register.
- InstructionNode* notNode = (InstructionNode*) subtreeRoot->rightChild();
- Value* notArg = BinaryOperator::getNotArgument(
- cast<BinaryOperator>(notNode->getInstruction()));
- notNode->markFoldedIntoParent();
- Value *lhs = subtreeRoot->leftChild()->getValue();
- Value *dest = subtreeRoot->getValue();
- mvec.push_back(BuildMI(V9::ANDNr, 3).addReg(lhs).addReg(notArg)
- .addReg(dest, MachineOperand::Def));
-
- if (notArg->getType() == Type::BoolTy) {
- // set 1 in result register if result of above is non-zero
- mvec.push_back(BuildMI(V9::MOVRNZi, 3).addReg(dest).addZImm(1)
- .addReg(dest, MachineOperand::UseAndDef));
- }
-
- break;
- }
-
- case 39: // bool: Or(bool, bool)
- case 139: // bool: Or(bool, not)
- case 239: // bool: Or(bool, boolconst)
- case 339: // reg : BOr(reg, reg)
- case 539: // reg : BOr(reg, Constant)
- Add3OperandInstr(V9::ORr, subtreeRoot, mvec);
- break;
-
- case 439: // bool: BOr(bool, bnot)
- { // Use the argument of NOT as the second argument!
- // Mark the NOT node so that no code is generated for it.
- // If the type is boolean, set 1 or 0 in the result register.
- InstructionNode* notNode = (InstructionNode*) subtreeRoot->rightChild();
- Value* notArg = BinaryOperator::getNotArgument(
- cast<BinaryOperator>(notNode->getInstruction()));
- notNode->markFoldedIntoParent();
- Value *lhs = subtreeRoot->leftChild()->getValue();
- Value *dest = subtreeRoot->getValue();
-
- mvec.push_back(BuildMI(V9::ORNr, 3).addReg(lhs).addReg(notArg)
- .addReg(dest, MachineOperand::Def));
-
- if (notArg->getType() == Type::BoolTy) {
- // set 1 in result register if result of above is non-zero
- mvec.push_back(BuildMI(V9::MOVRNZi, 3).addReg(dest).addZImm(1)
- .addReg(dest, MachineOperand::UseAndDef));
- }
-
- break;
- }
-
- case 40: // bool: Xor(bool, bool)
- case 140: // bool: Xor(bool, not)
- case 240: // bool: Xor(bool, boolconst)
- case 340: // reg : BXor(reg, reg)
- case 540: // reg : BXor(reg, Constant)
- Add3OperandInstr(V9::XORr, subtreeRoot, mvec);
- break;
-
- case 440: // bool: BXor(bool, bnot)
- { // Use the argument of NOT as the second argument!
- // Mark the NOT node so that no code is generated for it.
- // If the type is boolean, set 1 or 0 in the result register.
- InstructionNode* notNode = (InstructionNode*) subtreeRoot->rightChild();
- Value* notArg = BinaryOperator::getNotArgument(
- cast<BinaryOperator>(notNode->getInstruction()));
- notNode->markFoldedIntoParent();
- Value *lhs = subtreeRoot->leftChild()->getValue();
- Value *dest = subtreeRoot->getValue();
- mvec.push_back(BuildMI(V9::XNORr, 3).addReg(lhs).addReg(notArg)
- .addReg(dest, MachineOperand::Def));
-
- if (notArg->getType() == Type::BoolTy) {
- // set 1 in result register if result of above is non-zero
- mvec.push_back(BuildMI(V9::MOVRNZi, 3).addReg(dest).addZImm(1)
- .addReg(dest, MachineOperand::UseAndDef));
- }
- break;
- }
-
- case 41: // setCCconst: SetCC(reg, Constant)
- { // Comparison is with a constant:
- //
- // If the bool result must be computed into a register (see below),
- // and the constant is int ZERO, we can use the MOVR[op] instructions
- // and avoid the SUBcc instruction entirely.
- // Otherwise this is just the same as case 42, so just fall through.
- //
- // The result of the SetCC must be computed and stored in a register if
- // it is used outside the current basic block (so it must be computed
- // as a boolreg) or it is used by anything other than a branch.
- // We will use a conditional move to do this.
- //
- Instruction* setCCInstr = subtreeRoot->getInstruction();
- bool computeBoolVal = (subtreeRoot->parent() == NULL ||
- ! AllUsesAreBranches(setCCInstr));
-
- if (computeBoolVal) {
- InstrTreeNode* constNode = subtreeRoot->rightChild();
- assert(constNode &&
- constNode->getNodeType() ==InstrTreeNode::NTConstNode);
- Constant *constVal = cast<Constant>(constNode->getValue());
- bool isValidConst;
-
- if ((constVal->getType()->isInteger()
- || isa<PointerType>(constVal->getType()))
- && target.getInstrInfo().ConvertConstantToIntType(target,
- constVal, constVal->getType(), isValidConst) == 0
- && isValidConst)
- {
- // That constant is an integer zero after all...
- // Use a MOVR[op] to compute the boolean result
- // Unconditionally set register to 0
- mvec.push_back(BuildMI(V9::SETHI, 2).addZImm(0)
- .addRegDef(setCCInstr));
-
- // Now conditionally move 1 into the register.
- // Mark the register as a use (as well as a def) because the old
- // value will be retained if the condition is false.
- MachineOpCode movOpCode = ChooseMovpregiForSetCC(subtreeRoot);
- mvec.push_back(BuildMI(movOpCode, 3)
- .addReg(subtreeRoot->leftChild()->getValue())
- .addZImm(1)
- .addReg(setCCInstr, MachineOperand::UseAndDef));
-
- break;
- }
- }
- // ELSE FALL THROUGH
- }
-
- case 42: // bool: SetCC(reg, reg):
- {
- // This generates a SUBCC instruction, putting the difference in a
- // result reg. if needed, and/or setting a condition code if needed.
- //
- Instruction* setCCInstr = subtreeRoot->getInstruction();
- Value* leftVal = subtreeRoot->leftChild()->getValue();
- Value* rightVal = subtreeRoot->rightChild()->getValue();
- const Type* opType = leftVal->getType();
- bool isFPCompare = opType->isFloatingPoint();
-
- // If the boolean result of the SetCC is used outside the current basic
- // block (so it must be computed as a boolreg) or is used by anything
- // other than a branch, the boolean must be computed and stored
- // in a result register. We will use a conditional move to do this.
- //
- bool computeBoolVal = (subtreeRoot->parent() == NULL ||
- ! AllUsesAreBranches(setCCInstr));
-
- // A TmpInstruction is created to represent the CC "result".
- // Unlike other instances of TmpInstruction, this one is used
- // by machine code of multiple LLVM instructions, viz.,
- // the SetCC and the branch. Make sure to get the same one!
- // Note that we do this even for FP CC registers even though they
- // are explicit operands, because the type of the operand
- // needs to be a floating point condition code, not an integer
- // condition code. Think of this as casting the bool result to
- // a FP condition code register.
- // Later, we mark the 4th operand as being a CC register, and as a def.
- //
- TmpInstruction* tmpForCC = GetTmpForCC(setCCInstr,
- setCCInstr->getParent()->getParent(),
- leftVal->getType(),
- MachineCodeForInstruction::get(setCCInstr));
-
- // If the operands are signed values smaller than 4 bytes, then they
- // must be sign-extended in order to do a valid 32-bit comparison
- // and get the right result in the 32-bit CC register (%icc).
- //
- Value* leftOpToUse = leftVal;
- Value* rightOpToUse = rightVal;
- if (opType->isIntegral() && opType->isSigned()) {
- unsigned opSize = target.getTargetData().getTypeSize(opType);
- if (opSize < 4) {
- MachineCodeForInstruction& mcfi =
- MachineCodeForInstruction::get(setCCInstr);
-
- // create temporary virtual regs. to hold the sign-extensions
- leftOpToUse = new TmpInstruction(mcfi, leftVal);
- rightOpToUse = new TmpInstruction(mcfi, rightVal);
-
- // sign-extend each operand and put the result in the temporary reg.
- target.getInstrInfo().CreateSignExtensionInstructions
- (target, setCCInstr->getParent()->getParent(),
- leftVal, leftOpToUse, 8*opSize, mvec, mcfi);
- target.getInstrInfo().CreateSignExtensionInstructions
- (target, setCCInstr->getParent()->getParent(),
- rightVal, rightOpToUse, 8*opSize, mvec, mcfi);
- }
- }
-
- if (! isFPCompare) {
- // Integer condition: set CC and discard result.
- mvec.push_back(BuildMI(V9::SUBccr, 4)
- .addReg(leftOpToUse)
- .addReg(rightOpToUse)
- .addMReg(target.getRegInfo()
- .getZeroRegNum(), MachineOperand::Def)
- .addCCReg(tmpForCC, MachineOperand::Def));
- } else {
- // FP condition: dest of FCMP should be some FCCn register
- mvec.push_back(BuildMI(ChooseFcmpInstruction(subtreeRoot), 3)
- .addCCReg(tmpForCC, MachineOperand::Def)
- .addReg(leftOpToUse)
- .addReg(rightOpToUse));
- }
-
- if (computeBoolVal) {
- MachineOpCode movOpCode = (isFPCompare
- ? ChooseMovFpcciInstruction(subtreeRoot)
- : ChooseMovpcciForSetCC(subtreeRoot));
-
- // Unconditionally set register to 0
- M = BuildMI(V9::SETHI, 2).addZImm(0).addRegDef(setCCInstr);
- mvec.push_back(M);
-
- // Now conditionally move 1 into the register.
- // Mark the register as a use (as well as a def) because the old
- // value will be retained if the condition is false.
- M = (BuildMI(movOpCode, 3).addCCReg(tmpForCC).addZImm(1)
- .addReg(setCCInstr, MachineOperand::UseAndDef));
- mvec.push_back(M);
- }
- break;
- }
-
- case 51: // reg: Load(reg)
- case 52: // reg: Load(ptrreg)
- SetOperandsForMemInstr(ChooseLoadInstruction(
- subtreeRoot->getValue()->getType()),
- mvec, subtreeRoot, target);
- break;
-
- case 55: // reg: GetElemPtr(reg)
- case 56: // reg: GetElemPtrIdx(reg,reg)
- // If the GetElemPtr was folded into the user (parent), it will be
- // caught above. For other cases, we have to compute the address.
- SetOperandsForMemInstr(V9::ADDr, mvec, subtreeRoot, target);
- break;
-
- case 57: // reg: Alloca: Implement as 1 instruction:
- { // add %fp, offsetFromFP -> result
- AllocationInst* instr =
- cast<AllocationInst>(subtreeRoot->getInstruction());
- unsigned tsize =
- target.getTargetData().getTypeSize(instr->getAllocatedType());
- assert(tsize != 0);
- CreateCodeForFixedSizeAlloca(target, instr, tsize, 1, mvec);
- break;
- }
-
- case 58: // reg: Alloca(reg): Implement as 3 instructions:
- // mul num, typeSz -> tmp
- // sub %sp, tmp -> %sp
- { // add %sp, frameSizeBelowDynamicArea -> result
- AllocationInst* instr =
- cast<AllocationInst>(subtreeRoot->getInstruction());
- const Type* eltType = instr->getAllocatedType();
-
- // If #elements is constant, use simpler code for fixed-size allocas
- int tsize = (int) target.getTargetData().getTypeSize(eltType);
- Value* numElementsVal = NULL;
- bool isArray = instr->isArrayAllocation();
-
- if (!isArray || isa<Constant>(numElementsVal = instr->getArraySize())) {
- // total size is constant: generate code for fixed-size alloca
- unsigned numElements = isArray?
- cast<ConstantUInt>(numElementsVal)->getValue() : 1;
- CreateCodeForFixedSizeAlloca(target, instr, tsize,
- numElements, mvec);
- } else {
- // total size is not constant.
- CreateCodeForVariableSizeAlloca(target, instr, tsize,
- numElementsVal, mvec);
- }
- break;
- }
-
- case 61: // reg: Call
- { // Generate a direct (CALL) or indirect (JMPL) call.
- // Mark the return-address register, the indirection
- // register (for indirect calls), the operands of the Call,
- // and the return value (if any) as implicit operands
- // of the machine instruction.
- //
- // If this is a varargs function, floating point arguments
- // have to passed in integer registers so insert
- // copy-float-to-int instructions for each float operand.
- //
- CallInst *callInstr = cast<CallInst>(subtreeRoot->getInstruction());
- Value *callee = callInstr->getCalledValue();
- Function* calledFunc = dyn_cast<Function>(callee);
-
- // Check if this is an intrinsic function that needs a special code
- // sequence (e.g., va_start). Indirect calls cannot be special.
- //
- bool specialIntrinsic = false;
- Intrinsic::ID iid;
- if (calledFunc && (iid=(Intrinsic::ID)calledFunc->getIntrinsicID()))
- specialIntrinsic = CodeGenIntrinsic(iid, *callInstr, target, mvec);
-
- // If not, generate the normal call sequence for the function.
- // This can also handle any intrinsics that are just function calls.
- //
- if (! specialIntrinsic) {
- Function* currentFunc = callInstr->getParent()->getParent();
- MachineFunction& MF = MachineFunction::get(currentFunc);
- MachineCodeForInstruction& mcfi =
- MachineCodeForInstruction::get(callInstr);
- const SparcRegInfo& regInfo =
- (SparcRegInfo&) target.getRegInfo();
- const TargetFrameInfo& frameInfo = target.getFrameInfo();
-
- // Create hidden virtual register for return address with type void*
- TmpInstruction* retAddrReg =
- new TmpInstruction(mcfi, PointerType::get(Type::VoidTy), callInstr);
-
- // Generate the machine instruction and its operands.
- // Use CALL for direct function calls; this optimistically assumes
- // the PC-relative address fits in the CALL address field (22 bits).
- // Use JMPL for indirect calls.
- // This will be added to mvec later, after operand copies.
- //
- MachineInstr* callMI;
- if (calledFunc) // direct function call
- callMI = BuildMI(V9::CALL, 1).addPCDisp(callee);
- else // indirect function call
- callMI = (BuildMI(V9::JMPLCALLi,3).addReg(callee)
- .addSImm((int64_t)0).addRegDef(retAddrReg));
-
- const FunctionType* funcType =
- cast<FunctionType>(cast<PointerType>(callee->getType())
- ->getElementType());
- bool isVarArgs = funcType->isVarArg();
- bool noPrototype = isVarArgs && funcType->getNumParams() == 0;
-
- // Use a descriptor to pass information about call arguments
- // to the register allocator. This descriptor will be "owned"
- // and freed automatically when the MachineCodeForInstruction
- // object for the callInstr goes away.
- CallArgsDescriptor* argDesc =
- new CallArgsDescriptor(callInstr, retAddrReg,isVarArgs,noPrototype);
- assert(callInstr->getOperand(0) == callee
- && "This is assumed in the loop below!");
-
- // Insert sign-extension instructions for small signed values,
- // if this is an unknown function (i.e., called via a funcptr)
- // or an external one (i.e., which may not be compiled by llc).
- //
- if (calledFunc == NULL || calledFunc->isExternal()) {
- for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i) {
- Value* argVal = callInstr->getOperand(i);
- const Type* argType = argVal->getType();
- if (argType->isIntegral() && argType->isSigned()) {
- unsigned argSize = target.getTargetData().getTypeSize(argType);
- if (argSize <= 4) {
- // create a temporary virtual reg. to hold the sign-extension
- TmpInstruction* argExtend = new TmpInstruction(mcfi, argVal);
-
- // sign-extend argVal and put the result in the temporary reg.
- target.getInstrInfo().CreateSignExtensionInstructions
- (target, currentFunc, argVal, argExtend,
- 8*argSize, mvec, mcfi);
-
- // replace argVal with argExtend in CallArgsDescriptor
- argDesc->getArgInfo(i-1).replaceArgVal(argExtend);
- }
- }
- }
- }
-
- // Insert copy instructions to get all the arguments into
- // all the places that they need to be.
- //
- for (unsigned i=1, N=callInstr->getNumOperands(); i < N; ++i) {
- int argNo = i-1;
- CallArgInfo& argInfo = argDesc->getArgInfo(argNo);
- Value* argVal = argInfo.getArgVal(); // don't use callInstr arg here
- const Type* argType = argVal->getType();
- unsigned regType = regInfo.getRegTypeForDataType(argType);
- unsigned argSize = target.getTargetData().getTypeSize(argType);
- int regNumForArg = TargetRegInfo::getInvalidRegNum();
- unsigned regClassIDOfArgReg;
-
- // Check for FP arguments to varargs functions.
- // Any such argument in the first $K$ args must be passed in an
- // integer register. If there is no prototype, it must also
- // be passed as an FP register.
- // K = #integer argument registers.
- bool isFPArg = argVal->getType()->isFloatingPoint();
- if (isVarArgs && isFPArg) {
-
- if (noPrototype) {
- // It is a function with no prototype: pass value
- // as an FP value as well as a varargs value. The FP value
- // may go in a register or on the stack. The copy instruction
- // to the outgoing reg/stack is created by the normal argument
- // handling code since this is the "normal" passing mode.
- //
- regNumForArg = regInfo.regNumForFPArg(regType,
- false, false, argNo,
- regClassIDOfArgReg);
- if (regNumForArg == regInfo.getInvalidRegNum())
- argInfo.setUseStackSlot();
- else
- argInfo.setUseFPArgReg();
- }
-
- // If this arg. is in the first $K$ regs, add special copy-
- // float-to-int instructions to pass the value as an int.
- // To check if it is in the first $K$, get the register
- // number for the arg #i. These copy instructions are
- // generated here because they are extra cases and not needed
- // for the normal argument handling (some code reuse is
- // possible though -- later).
- //
- int copyRegNum = regInfo.regNumForIntArg(false, false, argNo,
- regClassIDOfArgReg);
- if (copyRegNum != regInfo.getInvalidRegNum()) {
- // Create a virtual register to represent copyReg. Mark
- // this vreg as being an implicit operand of the call MI
- const Type* loadTy = (argType == Type::FloatTy
- ? Type::IntTy : Type::LongTy);
- TmpInstruction* argVReg = new TmpInstruction(mcfi, loadTy,
- argVal, NULL,
- "argRegCopy");
- callMI->addImplicitRef(argVReg);
-
- // Get a temp stack location to use to copy
- // float-to-int via the stack.
- //
- // FIXME: For now, we allocate permanent space because
- // the stack frame manager does not allow locals to be
- // allocated (e.g., for alloca) after a temp is
- // allocated!
- //
- // int tmpOffset = MF.getInfo()->pushTempValue(argSize);
- int tmpOffset = MF.getInfo()->allocateLocalVar(argVReg);
-
- // Generate the store from FP reg to stack
- unsigned StoreOpcode = ChooseStoreInstruction(argType);
- M = BuildMI(convertOpcodeFromRegToImm(StoreOpcode), 3)
- .addReg(argVal).addMReg(regInfo.getFramePointer())
- .addSImm(tmpOffset);
- mvec.push_back(M);
-
- // Generate the load from stack to int arg reg
- unsigned LoadOpcode = ChooseLoadInstruction(loadTy);
- M = BuildMI(convertOpcodeFromRegToImm(LoadOpcode), 3)
- .addMReg(regInfo.getFramePointer()).addSImm(tmpOffset)
- .addReg(argVReg, MachineOperand::Def);
-
- // Mark operand with register it should be assigned
- // both for copy and for the callMI
- M->SetRegForOperand(M->getNumOperands()-1, copyRegNum);
- callMI->SetRegForImplicitRef(callMI->getNumImplicitRefs()-1,
- copyRegNum);
- mvec.push_back(M);
-
- // Add info about the argument to the CallArgsDescriptor
- argInfo.setUseIntArgReg();
- argInfo.setArgCopy(copyRegNum);
- } else {
- // Cannot fit in first $K$ regs so pass arg on stack
- argInfo.setUseStackSlot();
- }
- } else if (isFPArg) {
- // Get the outgoing arg reg to see if there is one.
- regNumForArg = regInfo.regNumForFPArg(regType, false, false,
- argNo, regClassIDOfArgReg);
- if (regNumForArg == regInfo.getInvalidRegNum())
- argInfo.setUseStackSlot();
- else {
- argInfo.setUseFPArgReg();
- regNumForArg =regInfo.getUnifiedRegNum(regClassIDOfArgReg,
- regNumForArg);
- }
- } else {
- // Get the outgoing arg reg to see if there is one.
- regNumForArg = regInfo.regNumForIntArg(false,false,
- argNo, regClassIDOfArgReg);
- if (regNumForArg == regInfo.getInvalidRegNum())
- argInfo.setUseStackSlot();
- else {
- argInfo.setUseIntArgReg();
- regNumForArg =regInfo.getUnifiedRegNum(regClassIDOfArgReg,
- regNumForArg);
- }
- }
-
- //
- // Now insert copy instructions to stack slot or arg. register
- //
- if (argInfo.usesStackSlot()) {
- // Get the stack offset for this argument slot.
- // FP args on stack are right justified so adjust offset!
- // int arguments are also right justified but they are
- // always loaded as a full double-word so the offset does
- // not need to be adjusted.
- int argOffset = frameInfo.getOutgoingArgOffset(MF, argNo);
- if (argType->isFloatingPoint()) {
- unsigned slotSize = frameInfo.getSizeOfEachArgOnStack();
- assert(argSize <= slotSize && "Insufficient slot size!");
- argOffset += slotSize - argSize;
- }
-
- // Now generate instruction to copy argument to stack
- MachineOpCode storeOpCode =
- (argType->isFloatingPoint()
- ? ((argSize == 4)? V9::STFi : V9::STDFi) : V9::STXi);
-
- M = BuildMI(storeOpCode, 3).addReg(argVal)
- .addMReg(regInfo.getStackPointer()).addSImm(argOffset);
- mvec.push_back(M);
- }
- else if (regNumForArg != regInfo.getInvalidRegNum()) {
-
- // Create a virtual register to represent the arg reg. Mark
- // this vreg as being an implicit operand of the call MI.
- TmpInstruction* argVReg =
- new TmpInstruction(mcfi, argVal, NULL, "argReg");
-
- callMI->addImplicitRef(argVReg);
-
- // Generate the reg-to-reg copy into the outgoing arg reg.
- // -- For FP values, create a FMOVS or FMOVD instruction
- // -- For non-FP values, create an add-with-0 instruction
- if (argType->isFloatingPoint())
- M=(BuildMI(argType==Type::FloatTy? V9::FMOVS :V9::FMOVD,2)
- .addReg(argVal).addReg(argVReg, MachineOperand::Def));
- else
- M = (BuildMI(ChooseAddInstructionByType(argType), 3)
- .addReg(argVal).addSImm((int64_t) 0)
- .addReg(argVReg, MachineOperand::Def));
-
- // Mark the operand with the register it should be assigned
- M->SetRegForOperand(M->getNumOperands()-1, regNumForArg);
- callMI->SetRegForImplicitRef(callMI->getNumImplicitRefs()-1,
- regNumForArg);
-
- mvec.push_back(M);
- }
- else
- assert(argInfo.getArgCopy() != regInfo.getInvalidRegNum() &&
- "Arg. not in stack slot, primary or secondary register?");
- }
-
- // add call instruction and delay slot before copying return value
- mvec.push_back(callMI);
- mvec.push_back(BuildMI(V9::NOP, 0));
-
- // Add the return value as an implicit ref. The call operands
- // were added above. Also, add code to copy out the return value.
- // This is always register-to-register for int or FP return values.
- //
- if (callInstr->getType() != Type::VoidTy) {
- // Get the return value reg.
- const Type* retType = callInstr->getType();
-
- int regNum = (retType->isFloatingPoint()
- ? (unsigned) SparcFloatRegClass::f0
- : (unsigned) SparcIntRegClass::o0);
- unsigned regClassID = regInfo.getRegClassIDOfType(retType);
- regNum = regInfo.getUnifiedRegNum(regClassID, regNum);
-
- // Create a virtual register to represent it and mark
- // this vreg as being an implicit operand of the call MI
- TmpInstruction* retVReg =
- new TmpInstruction(mcfi, callInstr, NULL, "argReg");
-
- callMI->addImplicitRef(retVReg, /*isDef*/ true);
-
- // Generate the reg-to-reg copy from the return value reg.
- // -- For FP values, create a FMOVS or FMOVD instruction
- // -- For non-FP values, create an add-with-0 instruction
- if (retType->isFloatingPoint())
- M = (BuildMI(retType==Type::FloatTy? V9::FMOVS : V9::FMOVD, 2)
- .addReg(retVReg).addReg(callInstr, MachineOperand::Def));
- else
- M = (BuildMI(ChooseAddInstructionByType(retType), 3)
- .addReg(retVReg).addSImm((int64_t) 0)
- .addReg(callInstr, MachineOperand::Def));
-
- // Mark the operand with the register it should be assigned
- // Also mark the implicit ref of the call defining this operand
- M->SetRegForOperand(0, regNum);
- callMI->SetRegForImplicitRef(callMI->getNumImplicitRefs()-1,regNum);
-
- mvec.push_back(M);
- }
-
- // For the CALL instruction, the ret. addr. reg. is also implicit
- if (isa<Function>(callee))
- callMI->addImplicitRef(retAddrReg, /*isDef*/ true);
-
- MF.getInfo()->popAllTempValues(); // free temps used for this inst
- }
-
- break;
- }
-
- case 62: // reg: Shl(reg, reg)
- {
- Value* argVal1 = subtreeRoot->leftChild()->getValue();
- Value* argVal2 = subtreeRoot->rightChild()->getValue();
- Instruction* shlInstr = subtreeRoot->getInstruction();
-
- const Type* opType = argVal1->getType();
- assert((opType->isInteger() || isa<PointerType>(opType)) &&
- "Shl unsupported for other types");
- unsigned opSize = target.getTargetData().getTypeSize(opType);
-
- CreateShiftInstructions(target, shlInstr->getParent()->getParent(),
- (opSize > 4)? V9::SLLXr6:V9::SLLr5,
- argVal1, argVal2, 0, shlInstr, mvec,
- MachineCodeForInstruction::get(shlInstr));
- break;
- }
-
- case 63: // reg: Shr(reg, reg)
- {
- const Type* opType = subtreeRoot->leftChild()->getValue()->getType();
- assert((opType->isInteger() || isa<PointerType>(opType)) &&
- "Shr unsupported for other types");
- unsigned opSize = target.getTargetData().getTypeSize(opType);
- Add3OperandInstr(opType->isSigned()
- ? (opSize > 4? V9::SRAXr6 : V9::SRAr5)
- : (opSize > 4? V9::SRLXr6 : V9::SRLr5),
- subtreeRoot, mvec);
- break;
- }
-
- case 64: // reg: Phi(reg,reg)
- break; // don't forward the value
-
- case 65: // reg: VANext(reg): the va_next(va_list, type) instruction
- { // Increment the va_list pointer register according to the type.
- // All LLVM argument types are <= 64 bits, so use one doubleword.
- Instruction* vaNextI = subtreeRoot->getInstruction();
- assert(target.getTargetData().getTypeSize(vaNextI->getType()) <= 8 &&
- "We assumed that all LLVM parameter types <= 8 bytes!");
- int argSize = target.getFrameInfo().getSizeOfEachArgOnStack();
- mvec.push_back(BuildMI(V9::ADDi, 3).addReg(vaNextI->getOperand(0)).
- addSImm(argSize).addRegDef(vaNextI));
- break;
- }
-
- case 66: // reg: VAArg (reg): the va_arg instruction
- { // Load argument from stack using current va_list pointer value.
- // Use 64-bit load for all non-FP args, and LDDF or double for FP.
- Instruction* vaArgI = subtreeRoot->getInstruction();
- MachineOpCode loadOp = (vaArgI->getType()->isFloatingPoint()
- ? (vaArgI->getType() == Type::FloatTy
- ? V9::LDFi : V9::LDDFi)
- : V9::LDXi);
- mvec.push_back(BuildMI(loadOp, 3).addReg(vaArgI->getOperand(0)).
- addSImm(0).addRegDef(vaArgI));
- break;
- }
-
- case 71: // reg: VReg
- case 72: // reg: Constant
- break; // don't forward the value
-
- default:
- assert(0 && "Unrecognized BURG rule");
- break;
- }
- }
-
- if (forwardOperandNum >= 0) {
- // We did not generate a machine instruction but need to use operand.
- // If user is in the same tree, replace Value in its machine operand.
- // If not, insert a copy instruction which should get coalesced away
- // by register allocation.
- if (subtreeRoot->parent() != NULL)
- ForwardOperand(subtreeRoot, subtreeRoot->parent(), forwardOperandNum);
- else {
- std::vector<MachineInstr*> minstrVec;
- Instruction* instr = subtreeRoot->getInstruction();
- target.getInstrInfo().
- CreateCopyInstructionsByType(target,
- instr->getParent()->getParent(),
- instr->getOperand(forwardOperandNum),
- instr, minstrVec,
- MachineCodeForInstruction::get(instr));
- assert(minstrVec.size() > 0);
- mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end());
- }
- }
-
- if (maskUnsignedResult) {
- // If result is unsigned and smaller than int reg size,
- // we need to clear high bits of result value.
- assert(forwardOperandNum < 0 && "Need mask but no instruction generated");
- Instruction* dest = subtreeRoot->getInstruction();
- if (dest->getType()->isUnsigned()) {
- unsigned destSize=target.getTargetData().getTypeSize(dest->getType());
- if (destSize <= 4) {
- // Mask high 64 - N bits, where N = 4*destSize.
-
- // Use a TmpInstruction to represent the
- // intermediate result before masking. Since those instructions
- // have already been generated, go back and substitute tmpI
- // for dest in the result position of each one of them.
- //
- MachineCodeForInstruction& mcfi = MachineCodeForInstruction::get(dest);
- TmpInstruction *tmpI = new TmpInstruction(mcfi, dest->getType(),
- dest, NULL, "maskHi");
- Value* srlArgToUse = tmpI;
-
- unsigned numSubst = 0;
- for (unsigned i=0, N=mvec.size(); i < N; ++i) {
-
- // Make sure we substitute all occurrences of dest in these instrs.
- // Otherwise, we will have bogus code.
- bool someArgsWereIgnored = false;
-
- // Make sure not to substitute an upwards-exposed use -- that would
- // introduce a use of `tmpI' with no preceding def. Therefore,
- // substitute a use or def-and-use operand only if a previous def
- // operand has already been substituted (i.e., numSusbt > 0).
- //
- numSubst += mvec[i]->substituteValue(dest, tmpI,
- /*defsOnly*/ numSubst == 0,
- /*notDefsAndUses*/ numSubst > 0,
- someArgsWereIgnored);
- assert(!someArgsWereIgnored &&
- "Operand `dest' exists but not replaced: probably bogus!");
- }
- assert(numSubst > 0 && "Operand `dest' not replaced: probably bogus!");
-
- // Left shift 32-N if size (N) is less than 32 bits.
- // Use another tmp. virtual register to represent this result.
- if (destSize < 4) {
- srlArgToUse = new TmpInstruction(mcfi, dest->getType(),
- tmpI, NULL, "maskHi2");
- mvec.push_back(BuildMI(V9::SLLXi6, 3).addReg(tmpI)
- .addZImm(8*(4-destSize))
- .addReg(srlArgToUse, MachineOperand::Def));
- }
-
- // Logical right shift 32-N to get zero extension in top 64-N bits.
- mvec.push_back(BuildMI(V9::SRLi5, 3).addReg(srlArgToUse)
- .addZImm(8*(4-destSize))
- .addReg(dest, MachineOperand::Def));
-
- } else if (destSize < 8) {
- assert(0 && "Unsupported type size: 32 < size < 64 bits");
- }
- }
- }
-}
-
-}
diff --git a/llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h b/llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h
deleted file mode 100644
index b69c5c2b6e4..00000000000
--- a/llvm/lib/Target/Sparc/SparcInstrSelectionSupport.h
+++ /dev/null
@@ -1,227 +0,0 @@
-//===-- llvm/CodeGen/SparcInstrSelectionSupport.h ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// TODO: Need a description here.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARC_INSTR_SELECTION_SUPPORT_h
-#define SPARC_INSTR_SELECTION_SUPPORT_h
-
-#include "llvm/DerivedTypes.h"
-#include "SparcInternals.h"
-
-namespace llvm {
-
-// Choose load instruction opcode based on type of value
-inline MachineOpCode
-ChooseLoadInstruction(const Type *DestTy)
-{
- switch (DestTy->getPrimitiveID()) {
- case Type::BoolTyID:
- case Type::UByteTyID: return V9::LDUBr;
- case Type::SByteTyID: return V9::LDSBr;
- case Type::UShortTyID: return V9::LDUHr;
- case Type::ShortTyID: return V9::LDSHr;
- case Type::UIntTyID: return V9::LDUWr;
- case Type::IntTyID: return V9::LDSWr;
- case Type::PointerTyID:
- case Type::ULongTyID:
- case Type::LongTyID: return V9::LDXr;
- case Type::FloatTyID: return V9::LDFr;
- case Type::DoubleTyID: return V9::LDDFr;
- default: assert(0 && "Invalid type for Load instruction");
- }
-
- return 0;
-}
-
-// Choose store instruction opcode based on type of value
-inline MachineOpCode
-ChooseStoreInstruction(const Type *DestTy)
-{
- switch (DestTy->getPrimitiveID()) {
- case Type::BoolTyID:
- case Type::UByteTyID:
- case Type::SByteTyID: return V9::STBr;
- case Type::UShortTyID:
- case Type::ShortTyID: return V9::STHr;
- case Type::UIntTyID:
- case Type::IntTyID: return V9::STWr;
- case Type::PointerTyID:
- case Type::ULongTyID:
- case Type::LongTyID: return V9::STXr;
- case Type::FloatTyID: return V9::STFr;
- case Type::DoubleTyID: return V9::STDFr;
- default: assert(0 && "Invalid type for Store instruction");
- }
-
- return 0;
-}
-
-
-inline MachineOpCode
-ChooseAddInstructionByType(const Type* resultType)
-{
- MachineOpCode opCode = V9::INVALID_OPCODE;
-
- if (resultType->isIntegral() ||
- isa<PointerType>(resultType) ||
- isa<FunctionType>(resultType) ||
- resultType == Type::LabelTy)
- {
- opCode = V9::ADDr;
- }
- else
- switch(resultType->getPrimitiveID())
- {
- case Type::FloatTyID: opCode = V9::FADDS; break;
- case Type::DoubleTyID: opCode = V9::FADDD; break;
- default: assert(0 && "Invalid type for ADD instruction"); break;
- }
-
- return opCode;
-}
-
-
-// Because the Sparc instruction selector likes to re-write operands to
-// instructions, making them change from a Value* (virtual register) to a
-// Constant* (making an immediate field), we need to change the opcode from a
-// register-based instruction to an immediate-based instruction, hence this
-// mapping.
-static unsigned
-convertOpcodeFromRegToImm(unsigned Opcode) {
- switch (Opcode) {
- /* arithmetic */
- case V9::ADDr: return V9::ADDi;
- case V9::ADDccr: return V9::ADDcci;
- case V9::ADDCr: return V9::ADDCi;
- case V9::ADDCccr: return V9::ADDCcci;
- case V9::SUBr: return V9::SUBi;
- case V9::SUBccr: return V9::SUBcci;
- case V9::SUBCr: return V9::SUBCi;
- case V9::SUBCccr: return V9::SUBCcci;
- case V9::MULXr: return V9::MULXi;
- case V9::SDIVXr: return V9::SDIVXi;
- case V9::UDIVXr: return V9::UDIVXi;
-
- /* logical */
- case V9::ANDr: return V9::ANDi;
- case V9::ANDccr: return V9::ANDcci;
- case V9::ANDNr: return V9::ANDNi;
- case V9::ANDNccr: return V9::ANDNcci;
- case V9::ORr: return V9::ORi;
- case V9::ORccr: return V9::ORcci;
- case V9::ORNr: return V9::ORNi;
- case V9::ORNccr: return V9::ORNcci;
- case V9::XORr: return V9::XORi;
- case V9::XORccr: return V9::XORcci;
- case V9::XNORr: return V9::XNORi;
- case V9::XNORccr: return V9::XNORcci;
-
- /* shift */
- case V9::SLLr5: return V9::SLLi5;
- case V9::SRLr5: return V9::SRLi5;
- case V9::SRAr5: return V9::SRAi5;
- case V9::SLLXr6: return V9::SLLXi6;
- case V9::SRLXr6: return V9::SRLXi6;
- case V9::SRAXr6: return V9::SRAXi6;
-
- /* Conditional move on int comparison with zero */
- case V9::MOVRZr: return V9::MOVRZi;
- case V9::MOVRLEZr: return V9::MOVRLEZi;
- case V9::MOVRLZr: return V9::MOVRLZi;
- case V9::MOVRNZr: return V9::MOVRNZi;
- case V9::MOVRGZr: return V9::MOVRGZi;
- case V9::MOVRGEZr: return V9::MOVRGEZi;
-
-
- /* Conditional move on int condition code */
- case V9::MOVAr: return V9::MOVAi;
- case V9::MOVNr: return V9::MOVNi;
- case V9::MOVNEr: return V9::MOVNEi;
- case V9::MOVEr: return V9::MOVEi;
- case V9::MOVGr: return V9::MOVGi;
- case V9::MOVLEr: return V9::MOVLEi;
- case V9::MOVGEr: return V9::MOVGEi;
- case V9::MOVLr: return V9::MOVLi;
- case V9::MOVGUr: return V9::MOVGUi;
- case V9::MOVLEUr: return V9::MOVLEUi;
- case V9::MOVCCr: return V9::MOVCCi;
- case V9::MOVCSr: return V9::MOVCSi;
- case V9::MOVPOSr: return V9::MOVPOSi;
- case V9::MOVNEGr: return V9::MOVNEGi;
- case V9::MOVVCr: return V9::MOVVCi;
- case V9::MOVVSr: return V9::MOVVSi;
-
- /* Conditional move of int reg on fp condition code */
- case V9::MOVFAr: return V9::MOVFAi;
- case V9::MOVFNr: return V9::MOVFNi;
- case V9::MOVFUr: return V9::MOVFUi;
- case V9::MOVFGr: return V9::MOVFGi;
- case V9::MOVFUGr: return V9::MOVFUGi;
- case V9::MOVFLr: return V9::MOVFLi;
- case V9::MOVFULr: return V9::MOVFULi;
- case V9::MOVFLGr: return V9::MOVFLGi;
- case V9::MOVFNEr: return V9::MOVFNEi;
- case V9::MOVFEr: return V9::MOVFEi;
- case V9::MOVFUEr: return V9::MOVFUEi;
- case V9::MOVFGEr: return V9::MOVFGEi;
- case V9::MOVFUGEr: return V9::MOVFUGEi;
- case V9::MOVFLEr: return V9::MOVFLEi;
- case V9::MOVFULEr: return V9::MOVFULEi;
- case V9::MOVFOr: return V9::MOVFOi;
-
- /* load */
- case V9::LDSBr: return V9::LDSBi;
- case V9::LDSHr: return V9::LDSHi;
- case V9::LDSWr: return V9::LDSWi;
- case V9::LDUBr: return V9::LDUBi;
- case V9::LDUHr: return V9::LDUHi;
- case V9::LDUWr: return V9::LDUWi;
- case V9::LDXr: return V9::LDXi;
- case V9::LDFr: return V9::LDFi;
- case V9::LDDFr: return V9::LDDFi;
- case V9::LDQFr: return V9::LDQFi;
- case V9::LDFSRr: return V9::LDFSRi;
- case V9::LDXFSRr: return V9::LDXFSRi;
-
- /* store */
- case V9::STBr: return V9::STBi;
- case V9::STHr: return V9::STHi;
- case V9::STWr: return V9::STWi;
- case V9::STXr: return V9::STXi;
- case V9::STFr: return V9::STFi;
- case V9::STDFr: return V9::STDFi;
- case V9::STFSRr: return V9::STFSRi;
- case V9::STXFSRr: return V9::STXFSRi;
-
- /* jump & return */
- case V9::JMPLCALLr: return V9::JMPLCALLi;
- case V9::JMPLRETr: return V9::JMPLRETi;
- case V9::RETURNr: return V9::RETURNi;
-
- /* save and restore */
- case V9::SAVEr: return V9::SAVEi;
- case V9::RESTOREr: return V9::RESTOREi;
-
- default:
- // It's already in correct format
- // Or, it's just not handled yet, but an assert() would break LLC
-#if 0
- std::cerr << "Unhandled opcode in convertOpcodeFromRegToImm(): " << Opcode
- << "\n";
-#endif
- return Opcode;
- }
-}
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/SparcInternals.h b/llvm/lib/Target/Sparc/SparcInternals.h
deleted file mode 100644
index aaf39feb60a..00000000000
--- a/llvm/lib/Target/Sparc/SparcInternals.h
+++ /dev/null
@@ -1,134 +0,0 @@
-//===-- SparcInternals.h ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines stuff that is to be private to the Sparc backend, but is
-// shared among different portions of the backend.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARC_INTERNALS_H
-#define SPARC_INTERNALS_H
-
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetSchedInfo.h"
-#include "llvm/Target/TargetFrameInfo.h"
-#include "llvm/Target/TargetCacheInfo.h"
-#include "llvm/Target/TargetRegInfo.h"
-#include "llvm/Type.h"
-#include "SparcRegClassInfo.h"
-#include "Config/sys/types.h"
-
-namespace llvm {
-
-class LiveRange;
-class SparcTargetMachine;
-class Pass;
-
-enum SparcInstrSchedClass {
- SPARC_NONE, /* Instructions with no scheduling restrictions */
- SPARC_IEUN, /* Integer class that can use IEU0 or IEU1 */
- SPARC_IEU0, /* Integer class IEU0 */
- SPARC_IEU1, /* Integer class IEU1 */
- SPARC_FPM, /* FP Multiply or Divide instructions */
- SPARC_FPA, /* All other FP instructions */
- SPARC_CTI, /* Control-transfer instructions */
- SPARC_LD, /* Load instructions */
- SPARC_ST, /* Store instructions */
- SPARC_SINGLE, /* Instructions that must issue by themselves */
-
- SPARC_INV, /* This should stay at the end for the next value */
- SPARC_NUM_SCHED_CLASSES = SPARC_INV
-};
-
-
-//---------------------------------------------------------------------------
-// enum SparcMachineOpCode.
-// const TargetInstrDescriptor SparcMachineInstrDesc[]
-//
-// Purpose:
-// Description of UltraSparc machine instructions.
-//
-//---------------------------------------------------------------------------
-
-namespace V9 {
- enum SparcMachineOpCode {
-#define I(ENUM, OPCODESTRING, NUMOPERANDS, RESULTPOS, MAXIMM, IMMSE, \
- NUMDELAYSLOTS, LATENCY, SCHEDCLASS, INSTFLAGS) \
- ENUM,
-#include "SparcInstr.def"
-
- // End-of-array marker
- INVALID_OPCODE,
- NUM_REAL_OPCODES = PHI, // number of valid opcodes
- NUM_TOTAL_OPCODES = INVALID_OPCODE
- };
-}
-
-// Array of machine instruction descriptions...
-extern const TargetInstrDescriptor SparcMachineInstrDesc[];
-
-//---------------------------------------------------------------------------
-// class SparcSchedInfo
-//
-// Purpose:
-// Interface to instruction scheduling information for UltraSPARC.
-// The parameter values above are based on UltraSPARC IIi.
-//---------------------------------------------------------------------------
-
-class SparcSchedInfo: public TargetSchedInfo {
-public:
- SparcSchedInfo(const TargetMachine &tgt);
-protected:
- virtual void initializeResources();
-};
-
-//---------------------------------------------------------------------------
-// class SparcCacheInfo
-//
-// Purpose:
-// Interface to cache parameters for the UltraSPARC.
-// Just use defaults for now.
-//---------------------------------------------------------------------------
-
-struct SparcCacheInfo: public TargetCacheInfo {
- SparcCacheInfo(const TargetMachine &T) : TargetCacheInfo(T) {}
-};
-
-
-/// createStackSlotsPass - External interface to stack-slots pass that enters 2
-/// empty slots at the top of each function stack
-///
-Pass *createStackSlotsPass(const TargetMachine &TM);
-
-/// Specializes LLVM code for a target machine.
-///
-FunctionPass *createPreSelectionPass(const TargetMachine &TM);
-
-/// Peephole optimization pass operating on machine code
-///
-FunctionPass *createPeepholeOptsPass(const TargetMachine &TM);
-
-/// Writes out assembly code for the module, one function at a time
-///
-FunctionPass *createAsmPrinterPass(std::ostream &Out, const TargetMachine &TM);
-
-/// getPrologEpilogInsertionPass - Inserts prolog/epilog code.
-///
-FunctionPass* createPrologEpilogInsertionPass();
-
-/// getBytecodeAsmPrinterPass - Emits final LLVM bytecode to assembly file.
-///
-Pass* createBytecodeAsmPrinterPass(std::ostream &Out);
-
-FunctionPass *createSparcMachineCodeDestructionPass();
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp b/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp
deleted file mode 100644
index b1387bfa9c0..00000000000
--- a/llvm/lib/Target/Sparc/SparcRegClassInfo.cpp
+++ /dev/null
@@ -1,397 +0,0 @@
-//===-- SparcRegClassInfo.cpp - Register class def'ns for Sparc -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the register classes used by the Sparc target description.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Type.h"
-#include "SparcRegClassInfo.h"
-#include "SparcInternals.h"
-#include "SparcRegInfo.h"
-#include "RegAlloc/RegAllocCommon.h"
-#include "RegAlloc/IGNode.h"
-
-namespace llvm {
-
-//-----------------------------------------------------------------------------
-// Int Register Class - method for coloring a node in the interference graph.
-//
-// Algorithm:
-// Record the colors/suggested colors of all neighbors.
-//
-// If there is a suggested color, try to allocate it
-// If there is no call interf, try to allocate volatile, then non volatile
-// If there is call interf, try to allocate non-volatile. If that fails
-// try to allocate a volatile and insert save across calls
-// If both above fail, spill.
-//
-//-----------------------------------------------------------------------------
-void SparcIntRegClass::colorIGNode(IGNode * Node,
- const std::vector<bool> &IsColorUsedArr) const
-{
- LiveRange *LR = Node->getParentLR();
-
- if (DEBUG_RA) {
- std::cerr << "\nColoring LR [CallInt=" << LR->isCallInterference() <<"]:";
- printSet(*LR);
- }
-
- if (LR->hasSuggestedColor()) {
- unsigned SugCol = LR->getSuggestedColor();
- if (!IsColorUsedArr[SugCol]) {
- if (LR->isSuggestedColorUsable()) {
- // if the suggested color is volatile, we should use it only if
- // there are no call interferences. Otherwise, it will get spilled.
- if (DEBUG_RA)
- std::cerr << "\n -Coloring with sug color: " << SugCol;
-
- LR->setColor(LR->getSuggestedColor());
- return;
- } else if(DEBUG_RA) {
- std::cerr << "\n Couldn't alloc Sug col - LR volatile & calls interf";
- }
- } else if (DEBUG_RA) { // can't allocate the suggested col
- std::cerr << "\n Could NOT allocate the suggested color (already used) ";
- printSet(*LR); std::cerr << "\n";
- }
- }
-
- unsigned SearchStart; // start pos of color in pref-order
- bool ColorFound= false; // have we found a color yet?
-
- //if this Node is between calls
- if (! LR->isCallInterference()) {
- // start with volatiles (we can allocate volatiles safely)
- SearchStart = SparcIntRegClass::StartOfAllRegs;
- } else {
- // start with non volatiles (no non-volatiles)
- SearchStart = SparcIntRegClass::StartOfNonVolatileRegs;
- }
-
- unsigned c=0; // color
-
- // find first unused color
- for (c=SearchStart; c < SparcIntRegClass::NumOfAvailRegs; c++) {
- if (!IsColorUsedArr[c]) {
- ColorFound = true;
- break;
- }
- }
-
- if (ColorFound) {
- LR->setColor(c); // first color found in preferred order
- if (DEBUG_RA) std::cerr << "\n Colored after first search with col " << c;
- }
-
- // if color is not found because of call interference
- // try even finding a volatile color and insert save across calls
- //
- else if (LR->isCallInterference()) {
- // start from 0 - try to find even a volatile this time
- SearchStart = SparcIntRegClass::StartOfAllRegs;
-
- // find first unused volatile color
- for(c=SearchStart; c < SparcIntRegClass::StartOfNonVolatileRegs; c++) {
- if (! IsColorUsedArr[c]) {
- ColorFound = true;
- break;
- }
- }
-
- if (ColorFound) {
- LR->setColor(c);
- // get the live range corresponding to live var
- // since LR span across calls, must save across calls
- //
- LR->markForSaveAcrossCalls();
- if (DEBUG_RA)
- std::cerr << "\n Colored after SECOND search with col " << c;
- }
- }
-
-
- // If we couldn't find a color regardless of call interference - i.e., we
- // don't have either a volatile or non-volatile color left
- //
- if (!ColorFound)
- LR->markForSpill(); // no color found - must spill
-}
-
-//-----------------------------------------------------------------------------
-// Int CC Register Class - method for coloring a node in the interference graph.
-//
-// Algorithm:
-//
-// If (node has any interferences)
-// /* all interference operations can use only one register! */
-// mark the LR for spilling
-// else {
-// if (the LR is a 64-bit comparison) use %xcc
-// else /*32-bit or smaller*/ use %icc
-// }
-//
-// Note: The third name (%ccr) is essentially an assembly mnemonic and
-// depends solely on the opcode, so the name can be chosen in EmitAssembly.
-//-----------------------------------------------------------------------------
-void SparcIntCCRegClass::colorIGNode(IGNode *Node,
- const std::vector<bool> &IsColorUsedArr) const
-{
- if (Node->getNumOfNeighbors() > 0)
- Node->getParentLR()->markForSpill();
-
- // Mark the appropriate register in any case (even if it needs to be spilled)
- // because there is only one possible register, but more importantly, the
- // spill algorithm cannot find it. In particular, we have to choose
- // whether to use %xcc or %icc based on type of value compared
- //
- const LiveRange* ccLR = Node->getParentLR();
- const Type* setCCType = (* ccLR->begin())->getType(); // any Value in LR
- assert(setCCType->isIntegral() || isa<PointerType>(setCCType));
- int ccReg = ((isa<PointerType>(setCCType) || setCCType == Type::LongTy)
- ? xcc : icc);
-
-#ifndef NDEBUG
- // Let's just make sure values of two different types have not been
- // coalesced into this LR.
- for (ValueSet::const_iterator I=ccLR->begin(), E=ccLR->end(); I!=E; ++I) {
- const Type* ccType = (*I)->getType();
- assert((ccReg == xcc && (isa<PointerType>(ccType)
- || ccType == Type::LongTy)) ||
- (ccReg == icc && ccType->isIntegral() && ccType != Type::LongTy)
- && "Comparisons needing different intCC regs coalesced in LR!");
- }
-#endif
-
- Node->setColor(ccReg); // only one int cc reg is available
-}
-
-
-void SparcFloatCCRegClass::colorIGNode(IGNode *Node,
- const std::vector<bool> &IsColorUsedArr) const {
- for(unsigned c = 0; c != 4; ++c)
- if (!IsColorUsedArr[c]) { // find unused color
- Node->setColor(c);
- return;
- }
-
- Node->getParentLR()->markForSpill();
-}
-
-
-
-//-----------------------------------------------------------------------------
-// Float Register Class - method for coloring a node in the interference graph.
-//
-// Algorithm:
-//
-// If the LR is a double try to allocate f32 - f63
-// If the above fails or LR is single precision
-// If the LR does not interfere with a call
-// start allocating from f0
-// Else start allocating from f6
-// If a color is still not found because LR interferes with a call
-// Search in f0 - f6. If found mark for spill across calls.
-// If a color is still not fond, mark for spilling
-//
-//----------------------------------------------------------------------------
-void SparcFloatRegClass::colorIGNode(IGNode * Node,
- const std::vector<bool> &IsColorUsedArr) const
-{
- LiveRange *LR = Node->getParentLR();
-
-#ifndef NDEBUG
- // Check that the correct colors have been are marked for fp-doubles.
- //
- // FIXME: This is old code that is no longer needed. Temporarily converting
- // it into a big assertion just to check that the replacement logic
- // (invoking SparcFloatRegClass::markColorsUsed() directly from
- // RegClass::colorIGNode) works correctly.
- //
- // In fact, this entire function should be identical to
- // SparcIntRegClass::colorIGNode(), and perhaps can be
- // made into a general case in CodeGen/RegAlloc/RegClass.cpp.
- //
- unsigned NumNeighbors = Node->getNumOfNeighbors(); // total # of neighbors
- for(unsigned n=0; n < NumNeighbors; n++) { // for each neigh
- IGNode *NeighIGNode = Node->getAdjIGNode(n);
- LiveRange *NeighLR = NeighIGNode->getParentLR();
-
- if (NeighLR->hasColor()) {
- assert(IsColorUsedArr[ NeighLR->getColor() ]);
- if (NeighLR->getType() == Type::DoubleTy)
- assert(IsColorUsedArr[ NeighLR->getColor()+1 ]);
-
- } else if (NeighLR->hasSuggestedColor() &&
- NeighLR-> isSuggestedColorUsable() ) {
-
- // if the neighbour can use the suggested color
- assert(IsColorUsedArr[ NeighLR->getSuggestedColor() ]);
- if (NeighLR->getType() == Type::DoubleTy)
- assert(IsColorUsedArr[ NeighLR->getSuggestedColor()+1 ]);
- }
- }
-#endif
-
- // **NOTE: We don't check for call interferences in allocating suggested
- // color in this class since ALL registers are volatile. If this fact
- // changes, we should change the following part
- //- see SparcIntRegClass::colorIGNode()
- //
- if( LR->hasSuggestedColor() ) {
- if( ! IsColorUsedArr[ LR->getSuggestedColor() ] ) {
- LR->setColor( LR->getSuggestedColor() );
- return;
- } else if (DEBUG_RA) { // can't allocate the suggested col
- std::cerr << " Could NOT allocate the suggested color for LR ";
- printSet(*LR); std::cerr << "\n";
- }
- }
-
-
- int ColorFound = -1; // have we found a color yet?
- bool isCallInterf = LR->isCallInterference();
-
- // if value is a double - search the double only region (f32 - f63)
- // i.e. we try to allocate f32 - f63 first for doubles since singles
- // cannot go there. By doing that, we provide more space for singles
- // in f0 - f31
- //
- if (LR->getType() == Type::DoubleTy)
- ColorFound = findFloatColor( LR, 32, 64, IsColorUsedArr );
-
- if (ColorFound >= 0) { // if we could find a color
- LR->setColor(ColorFound);
- return;
- } else {
-
- // if we didn't find a color because the LR was single precision or
- // all f32-f63 range is filled, we try to allocate a register from
- // the f0 - f31 region
-
- unsigned SearchStart; // start pos of color in pref-order
-
- //if this Node is between calls (i.e., no call interferences )
- if (! isCallInterf) {
- // start with volatiles (we can allocate volatiles safely)
- SearchStart = SparcFloatRegClass::StartOfAllRegs;
- } else {
- // start with non volatiles (no non-volatiles)
- SearchStart = SparcFloatRegClass::StartOfNonVolatileRegs;
- }
-
- ColorFound = findFloatColor(LR, SearchStart, 32, IsColorUsedArr);
- }
-
- if (ColorFound >= 0) { // if we could find a color
- LR->setColor(ColorFound);
- return;
- } else if (isCallInterf) {
- // We are here because there is a call interference and no non-volatile
- // color could be found.
- // Now try to allocate even a volatile color
- ColorFound = findFloatColor(LR, SparcFloatRegClass::StartOfAllRegs,
- SparcFloatRegClass::StartOfNonVolatileRegs,
- IsColorUsedArr);
- }
-
- if (ColorFound >= 0) {
- LR->setColor(ColorFound); // first color found in preferred order
- LR->markForSaveAcrossCalls();
- } else {
- // we are here because no color could be found
- LR->markForSpill(); // no color found - must spill
- }
-}
-
-//-----------------------------------------------------------------------------
-// This method marks the registers used for a given register number.
-// This marks a single register for Float regs, but the R,R+1 pair
-// for double-precision registers.
-//-----------------------------------------------------------------------------
-
-void SparcFloatRegClass::markColorsUsed(unsigned RegInClass,
- int UserRegType,
- int RegTypeWanted,
- std::vector<bool> &IsColorUsedArr) const
-{
- if (UserRegType == SparcRegInfo::FPDoubleRegType ||
- RegTypeWanted == SparcRegInfo::FPDoubleRegType) {
- // This register is used as or is needed as a double-precision reg.
- // We need to mark the [even,odd] pair corresponding to this reg.
- // Get the even numbered register corresponding to this reg.
- unsigned EvenRegInClass = RegInClass & ~1u;
- assert(EvenRegInClass+1 < NumOfAllRegs &&
- EvenRegInClass+1 < IsColorUsedArr.size());
- IsColorUsedArr[EvenRegInClass] = true;
- IsColorUsedArr[EvenRegInClass+1] = true;
- }
- else {
- assert(RegInClass < NumOfAllRegs && RegInClass < IsColorUsedArr.size());
- assert(UserRegType == RegTypeWanted
- && "Something other than FP single/double types share a reg class?");
- IsColorUsedArr[RegInClass] = true;
- }
-}
-
-// This method finds unused registers of the specified register type,
-// using the given "used" flag array IsColorUsedArr. It checks a single
-// entry in the array directly for float regs, and checks the pair [R,R+1]
-// for double-precision registers
-// It returns -1 if no unused color is found.
-//
-int SparcFloatRegClass::findUnusedColor(int RegTypeWanted,
- const std::vector<bool> &IsColorUsedArr) const
-{
- if (RegTypeWanted == SparcRegInfo::FPDoubleRegType) {
- unsigned NC = 2 * this->getNumOfAvailRegs();
- assert(IsColorUsedArr.size() == NC && "Invalid colors-used array");
- for (unsigned c = 0; c < NC; c+=2)
- if (!IsColorUsedArr[c]) {
- assert(!IsColorUsedArr[c+1] && "Incorrect used regs for FP double!");
- return c;
- }
- return -1;
- }
- else
- return TargetRegClassInfo::findUnusedColor(RegTypeWanted, IsColorUsedArr);
-}
-
-//-----------------------------------------------------------------------------
-// Helper method for coloring a node of Float Reg class.
-// Finds the first available color in the range [Start,End] depending on the
-// type of the Node (i.e., float/double)
-//-----------------------------------------------------------------------------
-
-int SparcFloatRegClass::findFloatColor(const LiveRange *LR,
- unsigned Start,
- unsigned End,
- const std::vector<bool> &IsColorUsedArr) const
-{
- if (LR->getType() == Type::DoubleTy) {
- // find first unused color for a double
- assert(Start % 2 == 0 && "Odd register number could be used for double!");
- for (unsigned c=Start; c < End ; c+= 2)
- if (!IsColorUsedArr[c]) {
- assert(!IsColorUsedArr[c+1] &&
- "Incorrect marking of used regs for Sparc FP double!");
- return c;
- }
- } else {
- // find first unused color for a single
- for (unsigned c = Start; c < End; c++)
- if (!IsColorUsedArr[c])
- return c;
- }
-
- return -1;
-
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/SparcRegClassInfo.h b/llvm/lib/Target/Sparc/SparcRegClassInfo.h
deleted file mode 100644
index cc492e77c72..00000000000
--- a/llvm/lib/Target/Sparc/SparcRegClassInfo.h
+++ /dev/null
@@ -1,224 +0,0 @@
-//===-- SparcRegClassInfo.h - Register class def'ns for Sparc ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the register classes used by the Sparc target description.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARC_REG_CLASS_INFO_H
-#define SPARC_REG_CLASS_INFO_H
-
-#include "llvm/Target/TargetRegInfo.h"
-
-namespace llvm {
-
-//-----------------------------------------------------------------------------
-// Integer Register Class
-//-----------------------------------------------------------------------------
-
-struct SparcIntRegClass : public TargetRegClassInfo {
- SparcIntRegClass(unsigned ID)
- : TargetRegClassInfo(ID, NumOfAvailRegs, NumOfAllRegs) { }
-
- void colorIGNode(IGNode *Node,
- const std::vector<bool> &IsColorUsedArr) const;
-
- inline bool isRegVolatile(int Reg) const {
- return (Reg < (int)StartOfNonVolatileRegs);
- }
-
- inline bool modifiedByCall(int Reg) const {
- return Reg==(int)ModifiedByCall;
- }
-
- enum { // colors possible for a LR (in preferred order)
- // --- following colors are volatile across function calls
- // %g0 can't be used for coloring - always 0
- o0, o1, o2, o3, o4, o5, o7, // %o0-%o5,
-
- // %o6 is sp,
- // all %0's can get modified by a call
-
- // --- following colors are NON-volatile across function calls
- l0, l1, l2, l3, l4, l5, l6, l7, // %l0-%l7
- i0, i1, i2, i3, i4, i5, // %i0-%i5: i's need not be preserved
-
- // %i6 is the fp - so not allocated
- // %i7 is the ret address by convention - can be used for others
-
- // max # of colors reg coloring can allocate (NumOfAvailRegs)
-
- // --- following colors are not available for allocation within this phase
- // --- but can appear for pre-colored ranges
-
- i6, i7, g0, g1, g2, g3, g4, g5, g6, g7, o6,
-
- NumOfAllRegs, // Must be first AFTER registers...
-
- //*** NOTE: If we decide to use some %g regs, they are volatile
- // (see sparc64ABI)
- // Move the %g regs from the end of the enumeration to just above the
- // enumeration of %o0 (change StartOfAllRegs below)
- // change isRegVloatile method below
- // Also change IntRegNames above.
-
- // max # of colors reg coloring can allocate
- NumOfAvailRegs = i6,
-
- StartOfNonVolatileRegs = l0,
- StartOfAllRegs = o0,
-
- ModifiedByCall = o7,
- };
-
- const char * const getRegName(unsigned reg) const;
-};
-
-
-
-
-//-----------------------------------------------------------------------------
-// Float Register Class
-//-----------------------------------------------------------------------------
-
-class SparcFloatRegClass : public TargetRegClassInfo {
- int findFloatColor(const LiveRange *LR, unsigned Start,
- unsigned End,
- const std::vector<bool> &IsColorUsedArr) const;
-public:
- SparcFloatRegClass(unsigned ID)
- : TargetRegClassInfo(ID, NumOfAvailRegs, NumOfAllRegs) {}
-
- // This method marks the registers used for a given register number.
- // This marks a single register for Float regs, but the R,R+1 pair
- // for double-precision registers.
- //
- virtual void markColorsUsed(unsigned RegInClass,
- int UserRegType,
- int RegTypeWanted,
- std::vector<bool> &IsColorUsedArr) const;
-
- // This method finds unused registers of the specified register type,
- // using the given "used" flag array IsColorUsedArr. It checks a single
- // entry in the array directly for float regs, and checks the pair [R,R+1]
- // for double-precision registers
- // It returns -1 if no unused color is found.
- //
- virtual int findUnusedColor(int RegTypeWanted,
- const std::vector<bool> &IsColorUsedArr) const;
-
- void colorIGNode(IGNode *Node,
- const std::vector<bool> &IsColorUsedArr) const;
-
- // according to Sparc 64 ABI, all %fp regs are volatile
- inline bool isRegVolatile(int Reg) const { return true; }
-
- enum {
- f0, f1, f2, f3, f4, f5, f6, f7, f8, f9,
- f10, f11, f12, f13, f14, f15, f16, f17, f18, f19,
- f20, f21, f22, f23, f24, f25, f26, f27, f28, f29,
- f30, f31, f32, f33, f34, f35, f36, f37, f38, f39,
- f40, f41, f42, f43, f44, f45, f46, f47, f48, f49,
- f50, f51, f52, f53, f54, f55, f56, f57, f58, f59,
- f60, f61, f62, f63,
-
- // there are 64 regs alltogether but only 32 regs can be allocated at
- // a time.
- //
- NumOfAvailRegs = 32,
- NumOfAllRegs = 64,
-
- StartOfNonVolatileRegs = f32,
- StartOfAllRegs = f0,
- };
-
- const char * const getRegName(unsigned reg) const;
-};
-
-
-
-
-//-----------------------------------------------------------------------------
-// Int CC Register Class
-// Only one integer cc register is available. However, this register is
-// referred to as %xcc or %icc when instructions like subcc are executed but
-// referred to as %ccr (i.e., %xcc . %icc") when this register is moved
-// into an integer register using RD or WR instrcutions. So, three ids are
-// allocated for the three names.
-//-----------------------------------------------------------------------------
-
-struct SparcIntCCRegClass : public TargetRegClassInfo {
- SparcIntCCRegClass(unsigned ID)
- : TargetRegClassInfo(ID, 1, 3) { }
-
- void colorIGNode(IGNode *Node,
- const std::vector<bool> &IsColorUsedArr) const;
-
- // according to Sparc 64 ABI, %ccr is volatile
- //
- inline bool isRegVolatile(int Reg) const { return true; }
-
- enum {
- xcc, icc, ccr // only one is available - see the note above
- };
-
- const char * const getRegName(unsigned reg) const;
-};
-
-
-//-----------------------------------------------------------------------------
-// Float CC Register Class
-// Only 4 Float CC registers are available for allocation.
-//-----------------------------------------------------------------------------
-
-struct SparcFloatCCRegClass : public TargetRegClassInfo {
- SparcFloatCCRegClass(unsigned ID)
- : TargetRegClassInfo(ID, 4, 5) { }
-
- void colorIGNode(IGNode *Node,
- const std::vector<bool> &IsColorUsedArr) const;
-
- // according to Sparc 64 ABI, all %fp CC regs are volatile
- //
- inline bool isRegVolatile(int Reg) const { return true; }
-
- enum {
- fcc0, fcc1, fcc2, fcc3, fsr // fsr is not used in allocation
- }; // but has a name in getRegName()
-
- const char * const getRegName(unsigned reg) const;
-};
-
-//-----------------------------------------------------------------------------
-// Sparc special register class. These registers are not used for allocation
-// but are used as arguments of some instructions.
-//-----------------------------------------------------------------------------
-
-struct SparcSpecialRegClass : public TargetRegClassInfo {
- SparcSpecialRegClass(unsigned ID)
- : TargetRegClassInfo(ID, 0, 1) { }
-
- void colorIGNode(IGNode *Node,
- const std::vector<bool> &IsColorUsedArr) const {
- assert(0 && "SparcSpecialRegClass should never be used for allocation");
- }
-
- // all currently included special regs are volatile
- inline bool isRegVolatile(int Reg) const { return true; }
-
- enum {
- fsr // floating point state register
- };
-
- const char * const getRegName(unsigned reg) const;
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/SparcRegInfo.cpp b/llvm/lib/Target/Sparc/SparcRegInfo.cpp
deleted file mode 100644
index 33690f8aa49..00000000000
--- a/llvm/lib/Target/Sparc/SparcRegInfo.cpp
+++ /dev/null
@@ -1,978 +0,0 @@
-//===-- SparcRegInfo.cpp - Sparc Target Register Information --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains implementation of Sparc specific helper methods
-// used for register allocation.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/CodeGen/InstrSelection.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/MachineInstrAnnot.h"
-#include "RegAlloc/LiveRangeInfo.h"
-#include "RegAlloc/LiveRange.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Function.h"
-#include "llvm/iTerminators.h"
-#include "llvm/iOther.h"
-#include "SparcInternals.h"
-#include "SparcRegClassInfo.h"
-#include "SparcRegInfo.h"
-#include "SparcTargetMachine.h"
-
-namespace llvm {
-
-enum {
- BadRegClass = ~0
-};
-
-SparcRegInfo::SparcRegInfo(const SparcTargetMachine &tgt)
- : TargetRegInfo(tgt), NumOfIntArgRegs(6), NumOfFloatArgRegs(32)
-{
- MachineRegClassArr.push_back(new SparcIntRegClass(IntRegClassID));
- MachineRegClassArr.push_back(new SparcFloatRegClass(FloatRegClassID));
- MachineRegClassArr.push_back(new SparcIntCCRegClass(IntCCRegClassID));
- MachineRegClassArr.push_back(new SparcFloatCCRegClass(FloatCCRegClassID));
- MachineRegClassArr.push_back(new SparcSpecialRegClass(SpecialRegClassID));
-
- assert(SparcFloatRegClass::StartOfNonVolatileRegs == 32 &&
- "32 Float regs are used for float arg passing");
-}
-
-
-// getZeroRegNum - returns the register that contains always zero.
-// this is the unified register number
-//
-unsigned SparcRegInfo::getZeroRegNum() const {
- return getUnifiedRegNum(SparcRegInfo::IntRegClassID,
- SparcIntRegClass::g0);
-}
-
-// getCallAddressReg - returns the reg used for pushing the address when a
-// method is called. This can be used for other purposes between calls
-//
-unsigned SparcRegInfo::getCallAddressReg() const {
- return getUnifiedRegNum(SparcRegInfo::IntRegClassID,
- SparcIntRegClass::o7);
-}
-
-// Returns the register containing the return address.
-// It should be made sure that this register contains the return
-// value when a return instruction is reached.
-//
-unsigned SparcRegInfo::getReturnAddressReg() const {
- return getUnifiedRegNum(SparcRegInfo::IntRegClassID,
- SparcIntRegClass::i7);
-}
-
-// Register get name implementations...
-
-// Int register names in same order as enum in class SparcIntRegClass
-static const char * const IntRegNames[] = {
- "o0", "o1", "o2", "o3", "o4", "o5", "o7",
- "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
- "i0", "i1", "i2", "i3", "i4", "i5",
- "i6", "i7",
- "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
- "o6"
-};
-
-const char * const SparcIntRegClass::getRegName(unsigned reg) const {
- assert(reg < NumOfAllRegs);
- return IntRegNames[reg];
-}
-
-static const char * const FloatRegNames[] = {
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9",
- "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19",
- "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29",
- "f30", "f31", "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
- "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", "f48", "f49",
- "f50", "f51", "f52", "f53", "f54", "f55", "f56", "f57", "f58", "f59",
- "f60", "f61", "f62", "f63"
-};
-
-const char * const SparcFloatRegClass::getRegName(unsigned reg) const {
- assert (reg < NumOfAllRegs);
- return FloatRegNames[reg];
-}
-
-
-static const char * const IntCCRegNames[] = {
- "xcc", "icc", "ccr"
-};
-
-const char * const SparcIntCCRegClass::getRegName(unsigned reg) const {
- assert(reg < 3);
- return IntCCRegNames[reg];
-}
-
-static const char * const FloatCCRegNames[] = {
- "fcc0", "fcc1", "fcc2", "fcc3"
-};
-
-const char * const SparcFloatCCRegClass::getRegName(unsigned reg) const {
- assert (reg < 5);
- return FloatCCRegNames[reg];
-}
-
-static const char * const SpecialRegNames[] = {
- "fsr"
-};
-
-const char * const SparcSpecialRegClass::getRegName(unsigned reg) const {
- assert (reg < 1);
- return SpecialRegNames[reg];
-}
-
-// Get unified reg number for frame pointer
-unsigned SparcRegInfo::getFramePointer() const {
- return getUnifiedRegNum(SparcRegInfo::IntRegClassID,
- SparcIntRegClass::i6);
-}
-
-// Get unified reg number for stack pointer
-unsigned SparcRegInfo::getStackPointer() const {
- return getUnifiedRegNum(SparcRegInfo::IntRegClassID,
- SparcIntRegClass::o6);
-}
-
-
-//---------------------------------------------------------------------------
-// Finds whether a call is an indirect call
-//---------------------------------------------------------------------------
-
-inline bool
-isVarArgsFunction(const Type *funcType) {
- return cast<FunctionType>(cast<PointerType>(funcType)
- ->getElementType())->isVarArg();
-}
-
-inline bool
-isVarArgsCall(const MachineInstr *CallMI) {
- Value* callee = CallMI->getOperand(0).getVRegValue();
- // const Type* funcType = isa<Function>(callee)? callee->getType()
- // : cast<PointerType>(callee->getType())->getElementType();
- const Type* funcType = callee->getType();
- return isVarArgsFunction(funcType);
-}
-
-
-// Get the register number for the specified argument #argNo,
-//
-// Return value:
-// getInvalidRegNum(), if there is no int register available for the arg.
-// regNum, otherwise (this is NOT the unified reg. num).
-// regClassId is set to the register class ID.
-//
-int
-SparcRegInfo::regNumForIntArg(bool inCallee, bool isVarArgsCall,
- unsigned argNo, unsigned& regClassId) const
-{
- regClassId = IntRegClassID;
- if (argNo >= NumOfIntArgRegs)
- return getInvalidRegNum();
- else
- return argNo + (inCallee? SparcIntRegClass::i0 : SparcIntRegClass::o0);
-}
-
-// Get the register number for the specified FP argument #argNo,
-// Use INT regs for FP args if this is a varargs call.
-//
-// Return value:
-// getInvalidRegNum(), if there is no int register available for the arg.
-// regNum, otherwise (this is NOT the unified reg. num).
-// regClassId is set to the register class ID.
-//
-int
-SparcRegInfo::regNumForFPArg(unsigned regType,
- bool inCallee, bool isVarArgsCall,
- unsigned argNo, unsigned& regClassId) const
-{
- if (isVarArgsCall)
- return regNumForIntArg(inCallee, isVarArgsCall, argNo, regClassId);
- else
- {
- regClassId = FloatRegClassID;
- if (regType == FPSingleRegType)
- return (argNo*2+1 >= NumOfFloatArgRegs)?
- getInvalidRegNum() : SparcFloatRegClass::f0 + (argNo * 2 + 1);
- else if (regType == FPDoubleRegType)
- return (argNo*2 >= NumOfFloatArgRegs)?
- getInvalidRegNum() : SparcFloatRegClass::f0 + (argNo * 2);
- else
- assert(0 && "Illegal FP register type");
- return 0;
- }
-}
-
-
-//---------------------------------------------------------------------------
-// Finds the return address of a call sparc specific call instruction
-//---------------------------------------------------------------------------
-
-// The following 4 methods are used to find the RegType (SparcInternals.h)
-// of a LiveRange, a Value, and for a given register unified reg number.
-//
-int SparcRegInfo::getRegTypeForClassAndType(unsigned regClassID,
- const Type* type) const
-{
- switch (regClassID) {
- case IntRegClassID: return IntRegType;
- case FloatRegClassID:
- if (type == Type::FloatTy) return FPSingleRegType;
- else if (type == Type::DoubleTy) return FPDoubleRegType;
- assert(0 && "Unknown type in FloatRegClass"); return 0;
- case IntCCRegClassID: return IntCCRegType;
- case FloatCCRegClassID: return FloatCCRegType;
- case SpecialRegClassID: return SpecialRegType;
- default: assert( 0 && "Unknown reg class ID"); return 0;
- }
-}
-
-int SparcRegInfo::getRegTypeForDataType(const Type* type) const
-{
- return getRegTypeForClassAndType(getRegClassIDOfType(type), type);
-}
-
-int SparcRegInfo::getRegTypeForLR(const LiveRange *LR) const
-{
- return getRegTypeForClassAndType(LR->getRegClassID(), LR->getType());
-}
-
-int SparcRegInfo::getRegType(int unifiedRegNum) const
-{
- if (unifiedRegNum < 32)
- return IntRegType;
- else if (unifiedRegNum < (32 + 32))
- return FPSingleRegType;
- else if (unifiedRegNum < (64 + 32))
- return FPDoubleRegType;
- else if (unifiedRegNum < (64+32+4))
- return FloatCCRegType;
- else if (unifiedRegNum < (64+32+4+2))
- return IntCCRegType;
- else
- assert(0 && "Invalid unified register number in getRegType");
- return 0;
-}
-
-
-// To find the register class used for a specified Type
-//
-unsigned SparcRegInfo::getRegClassIDOfType(const Type *type,
- bool isCCReg) const {
- Type::PrimitiveID ty = type->getPrimitiveID();
- unsigned res;
-
- // FIXME: Comparing types like this isn't very safe...
- if ((ty && ty <= Type::LongTyID) || (ty == Type::LabelTyID) ||
- (ty == Type::FunctionTyID) || (ty == Type::PointerTyID) )
- res = IntRegClassID; // sparc int reg (ty=0: void)
- else if (ty <= Type::DoubleTyID)
- res = FloatRegClassID; // sparc float reg class
- else {
- //std::cerr << "TypeID: " << ty << "\n";
- assert(0 && "Cannot resolve register class for type");
- return 0;
- }
-
- if (isCCReg)
- return res + 2; // corresponding condition code register
- else
- return res;
-}
-
-unsigned SparcRegInfo::getRegClassIDOfRegType(int regType) const {
- switch(regType) {
- case IntRegType: return IntRegClassID;
- case FPSingleRegType:
- case FPDoubleRegType: return FloatRegClassID;
- case IntCCRegType: return IntCCRegClassID;
- case FloatCCRegType: return FloatCCRegClassID;
- default:
- assert(0 && "Invalid register type in getRegClassIDOfRegType");
- return 0;
- }
-}
-
-//---------------------------------------------------------------------------
-// Suggests a register for the ret address in the RET machine instruction.
-// We always suggest %i7 by convention.
-//---------------------------------------------------------------------------
-void SparcRegInfo::suggestReg4RetAddr(MachineInstr *RetMI,
- LiveRangeInfo& LRI) const {
-
- assert(target.getInstrInfo().isReturn(RetMI->getOpcode()));
-
- // return address is always mapped to i7 so set it immediately
- RetMI->SetRegForOperand(0, getUnifiedRegNum(IntRegClassID,
- SparcIntRegClass::i7));
-
- // Possible Optimization:
- // Instead of setting the color, we can suggest one. In that case,
- // we have to test later whether it received the suggested color.
- // In that case, a LR has to be created at the start of method.
- // It has to be done as follows (remove the setRegVal above):
-
- // MachineOperand & MO = RetMI->getOperand(0);
- // const Value *RetAddrVal = MO.getVRegValue();
- // assert( RetAddrVal && "LR for ret address must be created at start");
- // LiveRange * RetAddrLR = LRI.getLiveRangeForValue( RetAddrVal);
- // RetAddrLR->setSuggestedColor(getUnifiedRegNum( IntRegClassID,
- // SparcIntRegOrdr::i7) );
-}
-
-
-//---------------------------------------------------------------------------
-// Suggests a register for the ret address in the JMPL/CALL machine instr.
-// Sparc ABI dictates that %o7 be used for this purpose.
-//---------------------------------------------------------------------------
-void
-SparcRegInfo::suggestReg4CallAddr(MachineInstr * CallMI,
- LiveRangeInfo& LRI) const
-{
- CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI);
- const Value *RetAddrVal = argDesc->getReturnAddrReg();
- assert(RetAddrVal && "INTERNAL ERROR: Return address value is required");
-
- // A LR must already exist for the return address.
- LiveRange *RetAddrLR = LRI.getLiveRangeForValue(RetAddrVal);
- assert(RetAddrLR && "INTERNAL ERROR: No LR for return address of call!");
-
- unsigned RegClassID = RetAddrLR->getRegClassID();
- RetAddrLR->setColor(getUnifiedRegNum(IntRegClassID, SparcIntRegClass::o7));
-}
-
-
-
-//---------------------------------------------------------------------------
-// This method will suggest colors to incoming args to a method.
-// According to the Sparc ABI, the first 6 incoming args are in
-// %i0 - %i5 (if they are integer) OR in %f0 - %f31 (if they are float).
-// If the arg is passed on stack due to the lack of regs, NOTHING will be
-// done - it will be colored (or spilled) as a normal live range.
-//---------------------------------------------------------------------------
-void SparcRegInfo::suggestRegs4MethodArgs(const Function *Meth,
- LiveRangeInfo& LRI) const
-{
- // Check if this is a varArgs function. needed for choosing regs.
- bool isVarArgs = isVarArgsFunction(Meth->getType());
-
- // Count the arguments, *ignoring* whether they are int or FP args.
- // Use this common arg numbering to pick the right int or fp register.
- unsigned argNo=0;
- for(Function::const_aiterator I = Meth->abegin(), E = Meth->aend();
- I != E; ++I, ++argNo) {
- LiveRange *LR = LRI.getLiveRangeForValue(I);
- assert(LR && "No live range found for method arg");
-
- unsigned regType = getRegTypeForLR(LR);
- unsigned regClassIDOfArgReg = BadRegClass; // for chosen reg (unused)
-
- int regNum = (regType == IntRegType)
- ? regNumForIntArg(/*inCallee*/ true, isVarArgs, argNo, regClassIDOfArgReg)
- : regNumForFPArg(regType, /*inCallee*/ true, isVarArgs, argNo,
- regClassIDOfArgReg);
-
- if (regNum != getInvalidRegNum())
- LR->setSuggestedColor(regNum);
- }
-}
-
-
-//---------------------------------------------------------------------------
-// This method is called after graph coloring to move incoming args to
-// the correct hardware registers if they did not receive the correct
-// (suggested) color through graph coloring.
-//---------------------------------------------------------------------------
-void SparcRegInfo::colorMethodArgs(const Function *Meth,
- LiveRangeInfo &LRI,
- std::vector<MachineInstr*>& InstrnsBefore,
- std::vector<MachineInstr*>& InstrnsAfter) const {
-
- // check if this is a varArgs function. needed for choosing regs.
- bool isVarArgs = isVarArgsFunction(Meth->getType());
- MachineInstr *AdMI;
-
- // for each argument
- // for each argument. count INT and FP arguments separately.
- unsigned argNo=0, intArgNo=0, fpArgNo=0;
- for(Function::const_aiterator I = Meth->abegin(), E = Meth->aend();
- I != E; ++I, ++argNo) {
- // get the LR of arg
- LiveRange *LR = LRI.getLiveRangeForValue(I);
- assert( LR && "No live range found for method arg");
-
- unsigned regType = getRegTypeForLR(LR);
- unsigned RegClassID = LR->getRegClassID();
-
- // Find whether this argument is coming in a register (if not, on stack)
- // Also find the correct register the argument must use (UniArgReg)
- //
- bool isArgInReg = false;
- unsigned UniArgReg = getInvalidRegNum(); // reg that LR MUST be colored with
- unsigned regClassIDOfArgReg = BadRegClass; // reg class of chosen reg
-
- int regNum = (regType == IntRegType)
- ? regNumForIntArg(/*inCallee*/ true, isVarArgs,
- argNo, regClassIDOfArgReg)
- : regNumForFPArg(regType, /*inCallee*/ true, isVarArgs,
- argNo, regClassIDOfArgReg);
-
- if(regNum != getInvalidRegNum()) {
- isArgInReg = true;
- UniArgReg = getUnifiedRegNum( regClassIDOfArgReg, regNum);
- }
-
- if( ! LR->isMarkedForSpill() ) { // if this arg received a register
-
- unsigned UniLRReg = getUnifiedRegNum( RegClassID, LR->getColor() );
-
- // if LR received the correct color, nothing to do
- //
- if( UniLRReg == UniArgReg )
- continue;
-
- // We are here because the LR did not receive the suggested
- // but LR received another register.
- // Now we have to copy the %i reg (or stack pos of arg)
- // to the register the LR was colored with.
-
- // if the arg is coming in UniArgReg register, it MUST go into
- // the UniLRReg register
- //
- if( isArgInReg ) {
- if( regClassIDOfArgReg != RegClassID ) {
- assert(0 && "This could should work but it is not tested yet");
-
- // It is a variable argument call: the float reg must go in a %o reg.
- // We have to move an int reg to a float reg via memory.
- //
- assert(isVarArgs &&
- RegClassID == FloatRegClassID &&
- regClassIDOfArgReg == IntRegClassID &&
- "This should only be an Int register for an FP argument");
-
- int TmpOff = MachineFunction::get(Meth).getInfo()->pushTempValue(
- getSpilledRegSize(regType));
- cpReg2MemMI(InstrnsBefore,
- UniArgReg, getFramePointer(), TmpOff, IntRegType);
-
- cpMem2RegMI(InstrnsBefore,
- getFramePointer(), TmpOff, UniLRReg, regType);
- }
- else {
- cpReg2RegMI(InstrnsBefore, UniArgReg, UniLRReg, regType);
- }
- }
- else {
-
- // Now the arg is coming on stack. Since the LR received a register,
- // we just have to load the arg on stack into that register
- //
- const TargetFrameInfo& frameInfo = target.getFrameInfo();
- int offsetFromFP =
- frameInfo.getIncomingArgOffset(MachineFunction::get(Meth),
- argNo);
-
- // float arguments on stack are right justified so adjust the offset!
- // int arguments are also right justified but they are always loaded as
- // a full double-word so the offset does not need to be adjusted.
- if (regType == FPSingleRegType) {
- unsigned argSize = target.getTargetData().getTypeSize(LR->getType());
- unsigned slotSize = frameInfo.getSizeOfEachArgOnStack();
- assert(argSize <= slotSize && "Insufficient slot size!");
- offsetFromFP += slotSize - argSize;
- }
-
- cpMem2RegMI(InstrnsBefore,
- getFramePointer(), offsetFromFP, UniLRReg, regType);
- }
-
- } // if LR received a color
-
- else {
-
- // Now, the LR did not receive a color. But it has a stack offset for
- // spilling.
- // So, if the arg is coming in UniArgReg register, we can just move
- // that on to the stack pos of LR
-
- if( isArgInReg ) {
-
- if( regClassIDOfArgReg != RegClassID ) {
- assert(0 &&
- "FP arguments to a varargs function should be explicitly "
- "copied to/from int registers by instruction selection!");
-
- // It must be a float arg for a variable argument call, which
- // must come in a %o reg. Move the int reg to the stack.
- //
- assert(isVarArgs && regClassIDOfArgReg == IntRegClassID &&
- "This should only be an Int register for an FP argument");
-
- cpReg2MemMI(InstrnsBefore, UniArgReg,
- getFramePointer(), LR->getSpillOffFromFP(), IntRegType);
- }
- else {
- cpReg2MemMI(InstrnsBefore, UniArgReg,
- getFramePointer(), LR->getSpillOffFromFP(), regType);
- }
- }
-
- else {
-
- // Now the arg is coming on stack. Since the LR did NOT
- // received a register as well, it is allocated a stack position. We
- // can simply change the stack position of the LR. We can do this,
- // since this method is called before any other method that makes
- // uses of the stack pos of the LR (e.g., updateMachineInstr)
- //
- const TargetFrameInfo& frameInfo = target.getFrameInfo();
- int offsetFromFP =
- frameInfo.getIncomingArgOffset(MachineFunction::get(Meth),
- argNo);
-
- // FP arguments on stack are right justified so adjust offset!
- // int arguments are also right justified but they are always loaded as
- // a full double-word so the offset does not need to be adjusted.
- if (regType == FPSingleRegType) {
- unsigned argSize = target.getTargetData().getTypeSize(LR->getType());
- unsigned slotSize = frameInfo.getSizeOfEachArgOnStack();
- assert(argSize <= slotSize && "Insufficient slot size!");
- offsetFromFP += slotSize - argSize;
- }
-
- LR->modifySpillOffFromFP( offsetFromFP );
- }
-
- }
-
- } // for each incoming argument
-
-}
-
-
-
-//---------------------------------------------------------------------------
-// This method is called before graph coloring to suggest colors to the
-// outgoing call args and the return value of the call.
-//---------------------------------------------------------------------------
-void SparcRegInfo::suggestRegs4CallArgs(MachineInstr *CallMI,
- LiveRangeInfo& LRI) const {
- assert ( (target.getInstrInfo()).isCall(CallMI->getOpcode()) );
-
- CallArgsDescriptor* argDesc = CallArgsDescriptor::get(CallMI);
-
- suggestReg4CallAddr(CallMI, LRI);
-
- // First color the return value of the call instruction, if any.
- // The return value will be in %o0 if the value is an integer type,
- // or in %f0 if the value is a float type.
- //
- if (const Value *RetVal = argDesc->getReturnValue()) {
- LiveRange *RetValLR = LRI.getLiveRangeForValue(RetVal);
- assert(RetValLR && "No LR for return Value of call!");
-
- unsigned RegClassID = RetValLR->getRegClassID();
-
- // now suggest a register depending on the register class of ret arg
- if( RegClassID == IntRegClassID )
- RetValLR->setSuggestedColor(SparcIntRegClass::o0);
- else if (RegClassID == FloatRegClassID )
- RetValLR->setSuggestedColor(SparcFloatRegClass::f0 );
- else assert( 0 && "Unknown reg class for return value of call\n");
- }
-
- // Now suggest colors for arguments (operands) of the call instruction.
- // Colors are suggested only if the arg number is smaller than the
- // the number of registers allocated for argument passing.
- // Now, go thru call args - implicit operands of the call MI
-
- unsigned NumOfCallArgs = argDesc->getNumArgs();
-
- for(unsigned argNo=0, i=0, intArgNo=0, fpArgNo=0;
- i < NumOfCallArgs; ++i, ++argNo) {
-
- const Value *CallArg = argDesc->getArgInfo(i).getArgVal();
-
- // get the LR of call operand (parameter)
- LiveRange *const LR = LRI.getLiveRangeForValue(CallArg);
- if (!LR)
- continue; // no live ranges for constants and labels
-
- unsigned regType = getRegTypeForLR(LR);
- unsigned regClassIDOfArgReg = BadRegClass; // chosen reg class (unused)
-
- // Choose a register for this arg depending on whether it is
- // an INT or FP value. Here we ignore whether or not it is a
- // varargs calls, because FP arguments will be explicitly copied
- // to an integer Value and handled under (argCopy != NULL) below.
- int regNum = (regType == IntRegType)
- ? regNumForIntArg(/*inCallee*/ false, /*isVarArgs*/ false,
- argNo, regClassIDOfArgReg)
- : regNumForFPArg(regType, /*inCallee*/ false, /*isVarArgs*/ false,
- argNo, regClassIDOfArgReg);
-
- // If a register could be allocated, use it.
- // If not, do NOTHING as this will be colored as a normal value.
- if(regNum != getInvalidRegNum())
- LR->setSuggestedColor(regNum);
- } // for all call arguments
-}
-
-
-//---------------------------------------------------------------------------
-// this method is called for an LLVM return instruction to identify which
-// values will be returned from this method and to suggest colors.
-//---------------------------------------------------------------------------
-void SparcRegInfo::suggestReg4RetValue(MachineInstr *RetMI,
- LiveRangeInfo& LRI) const {
-
- assert( (target.getInstrInfo()).isReturn( RetMI->getOpcode() ) );
-
- suggestReg4RetAddr(RetMI, LRI);
-
- // To find the return value (if any), we can get the LLVM return instr.
- // from the return address register, which is the first operand
- Value* tmpI = RetMI->getOperand(0).getVRegValue();
- ReturnInst* retI=cast<ReturnInst>(cast<TmpInstruction>(tmpI)->getOperand(0));
- if (const Value *RetVal = retI->getReturnValue())
- if (LiveRange *const LR = LRI.getLiveRangeForValue(RetVal))
- LR->setSuggestedColor(LR->getRegClassID() == IntRegClassID
- ? (unsigned) SparcIntRegClass::i0
- : (unsigned) SparcFloatRegClass::f0);
-}
-
-//---------------------------------------------------------------------------
-// Check if a specified register type needs a scratch register to be
-// copied to/from memory. If it does, the reg. type that must be used
-// for scratch registers is returned in scratchRegType.
-//
-// Only the int CC register needs such a scratch register.
-// The FP CC registers can (and must) be copied directly to/from memory.
-//---------------------------------------------------------------------------
-
-bool
-SparcRegInfo::regTypeNeedsScratchReg(int RegType,
- int& scratchRegType) const
-{
- if (RegType == IntCCRegType)
- {
- scratchRegType = IntRegType;
- return true;
- }
- return false;
-}
-
-//---------------------------------------------------------------------------
-// Copy from a register to register. Register number must be the unified
-// register number.
-//---------------------------------------------------------------------------
-
-void
-SparcRegInfo::cpReg2RegMI(std::vector<MachineInstr*>& mvec,
- unsigned SrcReg,
- unsigned DestReg,
- int RegType) const {
- assert( ((int)SrcReg != getInvalidRegNum()) &&
- ((int)DestReg != getInvalidRegNum()) &&
- "Invalid Register");
-
- MachineInstr * MI = NULL;
-
- switch( RegType ) {
-
- case IntCCRegType:
- if (getRegType(DestReg) == IntRegType) {
- // copy intCC reg to int reg
- MI = (BuildMI(V9::RDCCR, 2)
- .addMReg(getUnifiedRegNum(SparcRegInfo::IntCCRegClassID,
- SparcIntCCRegClass::ccr))
- .addMReg(DestReg,MachineOperand::Def));
- } else {
- // copy int reg to intCC reg
- assert(getRegType(SrcReg) == IntRegType
- && "Can only copy CC reg to/from integer reg");
- MI = (BuildMI(V9::WRCCRr, 3)
- .addMReg(SrcReg)
- .addMReg(SparcIntRegClass::g0)
- .addMReg(getUnifiedRegNum(SparcRegInfo::IntCCRegClassID,
- SparcIntCCRegClass::ccr),
- MachineOperand::Def));
- }
- break;
-
- case FloatCCRegType:
- assert(0 && "Cannot copy FPCC register to any other register");
- break;
-
- case IntRegType:
- MI = BuildMI(V9::ADDr, 3).addMReg(SrcReg).addMReg(getZeroRegNum())
- .addMReg(DestReg, MachineOperand::Def);
- break;
-
- case FPSingleRegType:
- MI = BuildMI(V9::FMOVS, 2).addMReg(SrcReg)
- .addMReg(DestReg, MachineOperand::Def);
- break;
-
- case FPDoubleRegType:
- MI = BuildMI(V9::FMOVD, 2).addMReg(SrcReg)
- .addMReg(DestReg, MachineOperand::Def);
- break;
-
- default:
- assert(0 && "Unknown RegType");
- break;
- }
-
- if (MI)
- mvec.push_back(MI);
-}
-
-//---------------------------------------------------------------------------
-// Copy from a register to memory (i.e., Store). Register number must
-// be the unified register number
-//---------------------------------------------------------------------------
-
-
-void
-SparcRegInfo::cpReg2MemMI(std::vector<MachineInstr*>& mvec,
- unsigned SrcReg,
- unsigned PtrReg,
- int Offset, int RegType,
- int scratchReg) const {
- MachineInstr * MI = NULL;
- int OffReg = -1;
-
- // If the Offset will not fit in the signed-immediate field, find an
- // unused register to hold the offset value. This takes advantage of
- // the fact that all the opcodes used below have the same size immed. field.
- // Use the register allocator, PRA, to find an unused reg. at this MI.
- //
- if (RegType != IntCCRegType) // does not use offset below
- if (! target.getInstrInfo().constantFitsInImmedField(V9::LDXi, Offset)) {
-#ifdef CAN_FIND_FREE_REGISTER_TRANSPARENTLY
- RegClass* RC = PRA.getRegClassByID(this->getRegClassIDOfRegType(RegType));
- OffReg = PRA.getUnusedUniRegAtMI(RC, RegType, MInst, LVSetBef);
-#else
- // Default to using register g4 for holding large offsets
- OffReg = getUnifiedRegNum(SparcRegInfo::IntRegClassID,
- SparcIntRegClass::g4);
-#endif
- assert(OffReg >= 0 && "FIXME: cpReg2MemMI cannot find an unused reg.");
- mvec.push_back(BuildMI(V9::SETSW, 2).addZImm(Offset).addReg(OffReg));
- }
-
- switch (RegType) {
- case IntRegType:
- if (target.getInstrInfo().constantFitsInImmedField(V9::STXi, Offset))
- MI = BuildMI(V9::STXi,3).addMReg(SrcReg).addMReg(PtrReg).addSImm(Offset);
- else
- MI = BuildMI(V9::STXr,3).addMReg(SrcReg).addMReg(PtrReg).addMReg(OffReg);
- break;
-
- case FPSingleRegType:
- if (target.getInstrInfo().constantFitsInImmedField(V9::STFi, Offset))
- MI = BuildMI(V9::STFi, 3).addMReg(SrcReg).addMReg(PtrReg).addSImm(Offset);
- else
- MI = BuildMI(V9::STFr, 3).addMReg(SrcReg).addMReg(PtrReg).addMReg(OffReg);
- break;
-
- case FPDoubleRegType:
- if (target.getInstrInfo().constantFitsInImmedField(V9::STDFi, Offset))
- MI = BuildMI(V9::STDFi,3).addMReg(SrcReg).addMReg(PtrReg).addSImm(Offset);
- else
- MI = BuildMI(V9::STDFr,3).addMReg(SrcReg).addMReg(PtrReg).addSImm(OffReg);
- break;
-
- case IntCCRegType:
- assert(scratchReg >= 0 && "Need scratch reg to store %ccr to memory");
- assert(getRegType(scratchReg) ==IntRegType && "Invalid scratch reg");
- MI = (BuildMI(V9::RDCCR, 2)
- .addMReg(getUnifiedRegNum(SparcRegInfo::IntCCRegClassID,
- SparcIntCCRegClass::ccr))
- .addMReg(scratchReg, MachineOperand::Def));
- mvec.push_back(MI);
-
- cpReg2MemMI(mvec, scratchReg, PtrReg, Offset, IntRegType);
- return;
-
- case FloatCCRegType: {
- unsigned fsrReg = getUnifiedRegNum(SparcRegInfo::SpecialRegClassID,
- SparcSpecialRegClass::fsr);
- if (target.getInstrInfo().constantFitsInImmedField(V9::STXFSRi, Offset))
- MI=BuildMI(V9::STXFSRi,3).addMReg(fsrReg).addMReg(PtrReg).addSImm(Offset);
- else
- MI=BuildMI(V9::STXFSRr,3).addMReg(fsrReg).addMReg(PtrReg).addMReg(OffReg);
- break;
- }
- default:
- assert(0 && "Unknown RegType in cpReg2MemMI");
- }
- mvec.push_back(MI);
-}
-
-
-//---------------------------------------------------------------------------
-// Copy from memory to a reg (i.e., Load) Register number must be the unified
-// register number
-//---------------------------------------------------------------------------
-
-
-void
-SparcRegInfo::cpMem2RegMI(std::vector<MachineInstr*>& mvec,
- unsigned PtrReg,
- int Offset,
- unsigned DestReg,
- int RegType,
- int scratchReg) const {
- MachineInstr * MI = NULL;
- int OffReg = -1;
-
- // If the Offset will not fit in the signed-immediate field, find an
- // unused register to hold the offset value. This takes advantage of
- // the fact that all the opcodes used below have the same size immed. field.
- // Use the register allocator, PRA, to find an unused reg. at this MI.
- //
- if (RegType != IntCCRegType) // does not use offset below
- if (! target.getInstrInfo().constantFitsInImmedField(V9::LDXi, Offset)) {
-#ifdef CAN_FIND_FREE_REGISTER_TRANSPARENTLY
- RegClass* RC = PRA.getRegClassByID(this->getRegClassIDOfRegType(RegType));
- OffReg = PRA.getUnusedUniRegAtMI(RC, RegType, MInst, LVSetBef);
-#else
- // Default to using register g4 for holding large offsets
- OffReg = getUnifiedRegNum(SparcRegInfo::IntRegClassID,
- SparcIntRegClass::g4);
-#endif
- assert(OffReg >= 0 && "FIXME: cpReg2MemMI cannot find an unused reg.");
- mvec.push_back(BuildMI(V9::SETSW, 2).addZImm(Offset).addReg(OffReg));
- }
-
- switch (RegType) {
- case IntRegType:
- if (target.getInstrInfo().constantFitsInImmedField(V9::LDXi, Offset))
- MI = BuildMI(V9::LDXi, 3).addMReg(PtrReg).addSImm(Offset)
- .addMReg(DestReg, MachineOperand::Def);
- else
- MI = BuildMI(V9::LDXr, 3).addMReg(PtrReg).addMReg(OffReg)
- .addMReg(DestReg, MachineOperand::Def);
- break;
-
- case FPSingleRegType:
- if (target.getInstrInfo().constantFitsInImmedField(V9::LDFi, Offset))
- MI = BuildMI(V9::LDFi, 3).addMReg(PtrReg).addSImm(Offset)
- .addMReg(DestReg, MachineOperand::Def);
- else
- MI = BuildMI(V9::LDFr, 3).addMReg(PtrReg).addMReg(OffReg)
- .addMReg(DestReg, MachineOperand::Def);
- break;
-
- case FPDoubleRegType:
- if (target.getInstrInfo().constantFitsInImmedField(V9::LDDFi, Offset))
- MI= BuildMI(V9::LDDFi, 3).addMReg(PtrReg).addSImm(Offset)
- .addMReg(DestReg, MachineOperand::Def);
- else
- MI= BuildMI(V9::LDDFr, 3).addMReg(PtrReg).addMReg(OffReg)
- .addMReg(DestReg, MachineOperand::Def);
- break;
-
- case IntCCRegType:
- assert(scratchReg >= 0 && "Need scratch reg to load %ccr from memory");
- assert(getRegType(scratchReg) ==IntRegType && "Invalid scratch reg");
- cpMem2RegMI(mvec, PtrReg, Offset, scratchReg, IntRegType);
- MI = (BuildMI(V9::WRCCRr, 3)
- .addMReg(scratchReg)
- .addMReg(SparcIntRegClass::g0)
- .addMReg(getUnifiedRegNum(SparcRegInfo::IntCCRegClassID,
- SparcIntCCRegClass::ccr), MachineOperand::Def));
- break;
-
- case FloatCCRegType: {
- unsigned fsrRegNum = getUnifiedRegNum(SparcRegInfo::SpecialRegClassID,
- SparcSpecialRegClass::fsr);
- if (target.getInstrInfo().constantFitsInImmedField(V9::LDXFSRi, Offset))
- MI = BuildMI(V9::LDXFSRi, 3).addMReg(PtrReg).addSImm(Offset)
- .addMReg(fsrRegNum, MachineOperand::UseAndDef);
- else
- MI = BuildMI(V9::LDXFSRr, 3).addMReg(PtrReg).addMReg(OffReg)
- .addMReg(fsrRegNum, MachineOperand::UseAndDef);
- break;
- }
- default:
- assert(0 && "Unknown RegType in cpMem2RegMI");
- }
- mvec.push_back(MI);
-}
-
-
-//---------------------------------------------------------------------------
-// Generate a copy instruction to copy a value to another. Temporarily
-// used by PhiElimination code.
-//---------------------------------------------------------------------------
-
-
-void
-SparcRegInfo::cpValue2Value(Value *Src, Value *Dest,
- std::vector<MachineInstr*>& mvec) const {
- int RegType = getRegTypeForDataType(Src->getType());
- MachineInstr * MI = NULL;
-
- switch( RegType ) {
- case IntRegType:
- MI = BuildMI(V9::ADDr, 3).addReg(Src).addMReg(getZeroRegNum())
- .addRegDef(Dest);
- break;
- case FPSingleRegType:
- MI = BuildMI(V9::FMOVS, 2).addReg(Src).addRegDef(Dest);
- break;
- case FPDoubleRegType:
- MI = BuildMI(V9::FMOVD, 2).addReg(Src).addRegDef(Dest);
- break;
- default:
- assert(0 && "Unknow RegType in CpValu2Value");
- }
-
- mvec.push_back(MI);
-}
-
-
-
-//---------------------------------------------------------------------------
-// Print the register assigned to a LR
-//---------------------------------------------------------------------------
-
-void SparcRegInfo::printReg(const LiveRange *LR) const {
- unsigned RegClassID = LR->getRegClassID();
- std::cerr << " Node ";
-
- if (!LR->hasColor()) {
- std::cerr << " - could not find a color\n";
- return;
- }
-
- // if a color is found
-
- std::cerr << " colored with color "<< LR->getColor();
-
- unsigned uRegName = getUnifiedRegNum(RegClassID, LR->getColor());
-
- std::cerr << "[";
- std::cerr<< getUnifiedRegName(uRegName);
- if (RegClassID == FloatRegClassID && LR->getType() == Type::DoubleTy)
- std::cerr << "+" << getUnifiedRegName(uRegName+1);
- std::cerr << "]\n";
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/SparcV9.td b/llvm/lib/Target/Sparc/SparcV9.td
deleted file mode 100644
index 4cb00102e2b..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9.td
+++ /dev/null
@@ -1,786 +0,0 @@
-//===- SparcV9.td - Target Description for Sparc V9 Target ----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// TODO: Need a description here.
-//
-//===----------------------------------------------------------------------===//
-
-include "../Target.td"
-
-include "SparcV9_Reg.td"
-
-//===----------------------------------------------------------------------===//
-// Instructions
-//===----------------------------------------------------------------------===//
-
-class InstV9 : Instruction { // Sparc instruction baseline
- field bits<32> Inst;
-
- let Namespace = "V9";
-
- bits<2> op;
- let Inst{31-30} = op; // Top two bits are the 'op' field
-
- // Bit attributes specific to Sparc instructions
- bit isPasi = 0; // Does this instruction affect an alternate addr space?
- bit isDeprecated = 0; // Is this instruction deprecated?
- bit isPrivileged = 0; // Is this a privileged instruction?
-}
-
-include "SparcV9_F2.td"
-include "SparcV9_F3.td"
-include "SparcV9_F4.td"
-
-//===----------------------------------------------------------------------===//
-// Instruction list...
-//
-
-// Section A.2: Add - p137
-def ADDr : F3_1<2, 0b000000, "add">; // add rs1, rs2, rd
-def ADDi : F3_2<2, 0b000000, "add">; // add rs1, imm, rd
-def ADDccr : F3_1<2, 0b010000, "addcc">; // addcc rs1, rs2, rd
-def ADDcci : F3_2<2, 0b010000, "addcc">; // addcc rs1, imm, rd
-def ADDCr : F3_1<2, 0b001000, "addC">; // addC rs1, rs2, rd
-def ADDCi : F3_2<2, 0b001000, "addC">; // addC rs1, imm, rd
-def ADDCccr : F3_1<2, 0b011000, "addCcc">; // addCcc rs1, rs2, rd
-def ADDCcci : F3_2<2, 0b011000, "addCcc">; // addCcc rs1, imm, rd
-
-// Section A.3: Branch on Integer Register with Prediction - p138
-let op2 = 0b011 in {
- def BRZ : F2_4<0b001, "brz">; // Branch on rs1 == 0
- def BRLEZ : F2_4<0b010, "brlez">; // Branch on rs1 <= 0
- def BRLZ : F2_4<0b011, "brlz">; // Branch on rs1 < 0
- def BRNZ : F2_4<0b101, "brnz">; // Branch on rs1 != 0
- def BRGZ : F2_4<0b110, "brgz">; // Branch on rs1 > 0
- def BRGEZ : F2_4<0b111, "brgez">; // Branch on rs1 >= 0
-}
-
-// Section A.4: Branch on Floating-Point Condition Codes (FBfcc) p140
-// The following deprecated instructions don't seem to play nice on Sparc
-/*
-let isDeprecated = 1 in {
- let op2 = 0b110 in {
- def FBA : F2_2<0b1000, "fba">; // Branch always
- def FBN : F2_2<0b0000, "fbn">; // Branch never
- def FBU : F2_2<0b0111, "fbu">; // Branch on unordered
- def FBG : F2_2<0b0110, "fbg">; // Branch >
- def FBUG : F2_2<0b0101, "fbug">; // Branch on unordered or >
- def FBL : F2_2<0b0100, "fbl">; // Branch <
- def FBUL : F2_2<0b0011, "fbul">; // Branch on unordered or <
- def FBLG : F2_2<0b0010, "fblg">; // Branch < or >
- def FBNE : F2_2<0b0001, "fbne">; // Branch !=
- def FBE : F2_2<0b1001, "fbe">; // Branch ==
- def FBUE : F2_2<0b1010, "fbue">; // Branch on unordered or ==
- def FBGE : F2_2<0b1011, "fbge">; // Branch > or ==
- def FBUGE : F2_2<0b1100, "fbuge">; // Branch unord or > or ==
- def FBLE : F2_2<0b1101, "fble">; // Branch < or ==
- def FBULE : F2_2<0b1110, "fbule">; // Branch unord or < or ==
- def FBO : F2_2<0b1111, "fbo">; // Branch on ordered
- }
-}
-*/
-
-// We now make these same opcodes represent the FBPfcc instructions
-let op2 = 0b101 in {
- def FBA : F2_3<0b1000, "fba">; // Branch always
- def FBN : F2_3<0b0000, "fbn">; // Branch never
- def FBU : F2_3<0b0111, "fbu">; // Branch on unordered
- def FBG : F2_3<0b0110, "fbg">; // Branch >
- def FBUG : F2_3<0b0101, "fbug">; // Branch on unordered or >
- def FBL : F2_3<0b0100, "fbl">; // Branch <
- def FBUL : F2_3<0b0011, "fbul">; // Branch on unordered or <
- def FBLG : F2_3<0b0010, "fblg">; // Branch < or >
- def FBNE : F2_3<0b0001, "fbne">; // Branch !=
- def FBE : F2_3<0b1001, "fbe">; // Branch ==
- def FBUE : F2_3<0b1010, "fbue">; // Branch on unordered or ==
- def FBGE : F2_3<0b1011, "fbge">; // Branch > or ==
- def FBUGE : F2_3<0b1100, "fbuge">; // Branch unord or > or ==
- def FBLE : F2_3<0b1101, "fble">; // Branch < or ==
- def FBULE : F2_3<0b1110, "fbule">; // Branch unord or < or ==
- def FBO : F2_3<0b1111, "fbo">; // Branch on ordered
-}
-
-// Section A.5: Branch on FP condition codes with prediction - p143
-// Not used in the Sparc backend (directly)
-/*
-let op2 = 0b101 in {
- def FBPA : F2_3<0b1000, "fba">; // Branch always
- def FBPN : F2_3<0b0000, "fbn">; // Branch never
- def FBPU : F2_3<0b0111, "fbu">; // Branch on unordered
- def FBPG : F2_3<0b0110, "fbg">; // Branch >
- def FBPUG : F2_3<0b0101, "fbug">; // Branch on unordered or >
- def FBPL : F2_3<0b0100, "fbl">; // Branch <
- def FBPUL : F2_3<0b0011, "fbul">; // Branch on unordered or <
- def FBPLG : F2_3<0b0010, "fblg">; // Branch < or >
- def FBPNE : F2_3<0b0001, "fbne">; // Branch !=
- def FBPE : F2_3<0b1001, "fbe">; // Branch ==
- def FBPUE : F2_3<0b1010, "fbue">; // Branch on unordered or ==
- def FBPGE : F2_3<0b1011, "fbge">; // Branch > or ==
- def FBPUGE : F2_3<0b1100, "fbuge">; // Branch unord or > or ==
- def FBPLE : F2_3<0b1101, "fble">; // Branch < or ==
- def FBPULE : F2_3<0b1110, "fbule">; // Branch unord or < or ==
- def FBPO : F2_3<0b1111, "fbo">; // Branch on ordered
-}
-*/
-
-// Section A.6: Branch on Integer condition codes (Bicc) - p146
-/*
-let isDeprecated = 1 in {
- let op2 = 0b010 in {
- def BA : F2_2<0b1000, "ba">; // Branch always
- def BN : F2_2<0b0000, "bn">; // Branch never
- def BNE : F2_2<0b1001, "bne">; // Branch !=
- def BE : F2_2<0b0001, "be">; // Branch ==
- def BG : F2_2<0b1010, "bg">; // Branch >
- def BLE : F2_2<0b0010, "ble">; // Branch <=
- def BGE : F2_2<0b1011, "bge">; // Branch >=
- def BL : F2_2<0b0011, "bl">; // Branch <
- def BGU : F2_2<0b1100, "bgu">; // Branch unsigned >
- def BLEU : F2_2<0b0100, "bleu">; // Branch unsigned <=
- def BCC : F2_2<0b1101, "bcc">; // Branch unsigned >=
- def BCS : F2_2<0b0101, "bcs">; // Branch unsigned <=
- def BPOS : F2_2<0b1110, "bpos">; // Branch on positive
- def BNEG : F2_2<0b0110, "bneg">; // Branch on negative
- def BVC : F2_2<0b1111, "bvc">; // Branch on overflow clear
- def BVS : F2_2<0b0111, "bvs">; // Branch on overflow set
- }
-}
-*/
-
-// Using the format of A.7 instructions...
-let op2 = 0b001 in {
- let cc = 0 in { // BA and BN don't read condition codes
- def BA : F2_3<0b1000, "ba">; // Branch always
- def BN : F2_3<0b0000, "bn">; // Branch never
- }
- def BNE : F2_3<0b1001, "bne">; // Branch !=
- def BE : F2_3<0b0001, "be">; // Branch ==
- def BG : F2_3<0b1010, "bg">; // Branch >
- def BLE : F2_3<0b0010, "ble">; // Branch <=
- def BGE : F2_3<0b1011, "bge">; // Branch >=
- def BL : F2_3<0b0011, "bl">; // Branch <
- def BGU : F2_3<0b1100, "bgu">; // Branch unsigned >
- def BLEU : F2_3<0b0100, "bleu">; // Branch unsigned <=
- def BCC : F2_3<0b1101, "bcc">; // Branch unsigned >=
- def BCS : F2_3<0b0101, "bcs">; // Branch unsigned <=
- def BPOS : F2_3<0b1110, "bpos">; // Branch on positive
- def BNEG : F2_3<0b0110, "bneg">; // Branch on negative
- def BVC : F2_3<0b1111, "bvc">; // Branch on overflow clear
- def BVS : F2_3<0b0111, "bvs">; // Branch on overflow set
-}
-
-// Section A.7: Branch on integer condition codes with prediction - p148
-// Not used in the Sparc backend
-/*
-let op2 = 0b001 in {
- def BPA : F2_3<0b1000, "bpa">; // Branch always
- def BPN : F2_3<0b0000, "bpn">; // Branch never
- def BPNE : F2_3<0b1001, "bpne">; // Branch !=
- def BPE : F2_3<0b0001, "bpe">; // Branch ==
- def BPG : F2_3<0b1010, "bpg">; // Branch >
- def BPLE : F2_3<0b0010, "bple">; // Branch <=
- def BPGE : F2_3<0b1011, "bpge">; // Branch >=
- def BPL : F2_3<0b0011, "bpl">; // Branch <
- def BPGU : F2_3<0b1100, "bpgu">; // Branch unsigned >
- def BPLEU : F2_3<0b0100, "bpleu">; // Branch unsigned <=
- def BPCC : F2_3<0b1101, "bpcc">; // Branch unsigned >=
- def BPCS : F2_3<0b0101, "bpcs">; // Branch unsigned <=
- def BPPOS : F2_3<0b1110, "bppos">; // Branch on positive
- def BPNEG : F2_3<0b0110, "bpneg">; // Branch on negative
- def BPVC : F2_3<0b1111, "bpvc">; // Branch on overflow clear
- def BPVS : F2_3<0b0111, "bpvs">; // Branch on overflow set
-}
-*/
-
-// Section A.8: CALL - p151, the only Format #1 instruction
-def CALL : InstV9 {
- bits<30> disp;
- let op = 1;
- let Inst{29-0} = disp;
- let Name = "call";
- let isCall = 1;
-}
-
-// Section A.9: Compare and Swap - p176
-// CASA/CASXA: are for alternate address spaces! Ignore them
-
-
-// Section A.10: Divide (64-bit / 32-bit) - p178
-// Not used in the Sparc backend
-/*
-let isDeprecated = 1 in {
- def UDIVr : F3_1<2, 0b001110, "udiv">; // udiv r, r, r
- def UDIVi : F3_2<2, 0b001110, "udiv">; // udiv r, r, i
- def SDIVr : F3_1<2, 0b001111, "sdiv">; // sdiv r, r, r
- def SDIVi : F3_2<2, 0b001111, "sdiv">; // sdiv r, r, i
- def UDIVCCr : F3_1<2, 0b011110, "udivcc">; // udivcc r, r, r
- def UDIVCCi : F3_2<2, 0b011110, "udivcc">; // udivcc r, r, i
- def SDIVCCr : F3_1<2, 0b011111, "sdivcc">; // sdivcc r, r, r
- def SDIVCCi : F3_2<2, 0b011111, "sdivcc">; // sdivcc r, r, i
-}
-*/
-
-// Section A.11: DONE and RETRY - p181
-// Not used in the Sparc backend
-/*
-let isPrivileged = 1 in {
- def DONE : F3_18<0, "done">; // done
- def RETRY : F3_18<1, "retry">; // retry
-}
-*/
-
-// Section A.12: Floating-Point Add and Subtract - p156
-def FADDS : F3_16<2, 0b110100, 0x41, "fadds">; // fadds frs1, frs2, frd
-def FADDD : F3_16<2, 0b110100, 0x42, "faddd">; // faddd frs1, frs2, frd
-def FADDQ : F3_16<2, 0b110100, 0x43, "faddq">; // faddq frs1, frs2, frd
-def FSUBS : F3_16<2, 0b110100, 0x45, "fsubs">; // fsubs frs1, frs2, frd
-def FSUBD : F3_16<2, 0b110100, 0x46, "fsubd">; // fsubd frs1, frs2, frd
-def FSUBQ : F3_16<2, 0b110100, 0x47, "fsubq">; // fsubq frs1, frs2, frd
-
-// Section A.13: Floating-point compare - p159
-def FCMPS : F3_15<2, 0b110101, 0b001010001, "fcmps">; // fcmps %fcc, r1, r2
-def FCMPD : F3_15<2, 0b110101, 0b001010010, "fcmpd">; // fcmpd %fcc, r1, r2
-def FCMPQ : F3_15<2, 0b110101, 0b001010011, "fcmpq">; // fcmpq %fcc, r1, r2
-// Currently unused in the Sparc backend
-/*
-def FCMPES : F3_15<2, 0b110101, 0b001010101, "fcmpes">; // fcmpes %fcc, r1, r2
-def FCMPED : F3_15<2, 0b110101, 0b001010110, "fcmped">; // fcmped %fcc, r1, r2
-def FCMPEQ : F3_15<2, 0b110101, 0b001010111, "fcmpeq">; // fcmpeq %fcc, r1, r2
-*/
-
-// Section A.14: Convert floating-point to integer - p161
-def FSTOX : F3_14<2, 0b110100, 0b010000001, "fstox">; // fstox rs2, rd
-def FDTOX : F3_14<2, 0b110100, 0b010000010, "fstox">; // fstox rs2, rd
-def FQTOX : F3_14<2, 0b110100, 0b010000011, "fstox">; // fstox rs2, rd
-def FSTOI : F3_14<2, 0b110100, 0b011010001, "fstoi">; // fstoi rs2, rd
-def FDTOI : F3_14<2, 0b110100, 0b011010010, "fdtoi">; // fdtoi rs2, rd
-def FQTOI : F3_14<2, 0b110100, 0b011010011, "fqtoi">; // fqtoi rs2, rd
-
-// Section A.15: Convert between floating-point formats - p162
-def FSTOD : F3_14<2, 0b110100, 0b011001001, "fstod">; // fstod rs2, rd
-def FSTOQ : F3_14<2, 0b110100, 0b011001101, "fstoq">; // fstoq rs2, rd
-def FDTOS : F3_14<2, 0b110100, 0b011000110, "fstos">; // fstos rs2, rd
-def FDTOQ : F3_14<2, 0b110100, 0b011001110, "fdtoq">; // fdtoq rs2, rd
-def FQTOS : F3_14<2, 0b110100, 0b011000111, "fqtos">; // fqtos rs2, rd
-def FQTOD : F3_14<2, 0b110100, 0b011001011, "fqtod">; // fqtod rs2, rd
-
-// Section A.16: Convert integer to floating-point - p163
-def FXTOS : F3_14<2, 0b110100, 0b010000100, "fxtos">; // fxtos rs2, rd
-def FXTOD : F3_14<2, 0b110100, 0b010001000, "fxtod">; // fxtod rs2, rd
-def FXTOQ : F3_14<2, 0b110100, 0b010001100, "fxtoq">; // fxtoq rs2, rd
-def FITOS : F3_14<2, 0b110100, 0b011000100, "fitos">; // fitos rs2, rd
-def FITOD : F3_14<2, 0b110100, 0b011001000, "fitod">; // fitod rs2, rd
-def FITOQ : F3_14<2, 0b110100, 0b011001100, "fitoq">; // fitoq rs2, rd
-
-// Section A.17: Floating-Point Move - p164
-def FMOVS : F3_14<2, 0b110100, 0b000000001, "fmovs">; // fmovs r, r
-def FMOVD : F3_14<2, 0b110100, 0b000000010, "fmovs">; // fmovd r, r
-//def FMOVQ : F3_14<2, 0b110100, 0b000000011, "fmovs">; // fmovq r, r
-def FNEGS : F3_14<2, 0b110100, 0b000000101, "fnegs">; // fnegs r, r
-def FNEGD : F3_14<2, 0b110100, 0b000000110, "fnegs">; // fnegs r, r
-//def FNEGQ : F3_14<2, 0b110100, 0b000000111, "fnegs">; // fnegs r, r
-def FABSS : F3_14<2, 0b110100, 0b000001001, "fabss">; // fabss r, r
-def FABSD : F3_14<2, 0b110100, 0b000001010, "fabss">; // fabss r, r
-//def FABSQ : F3_14<2, 0b110100, 0b000001011, "fabss">; // fabss r, r
-
-// Section A.18: Floating-Point Multiply and Divide - p165
-def FMULS : F3_16<2, 0b110100, 0b001001001, "fmuls">; // fmuls r, r, r
-def FMULD : F3_16<2, 0b110100, 0b001001010, "fmuld">; // fmuld r, r, r
-def FMULQ : F3_16<2, 0b110100, 0b001001011, "fmulq">; // fmulq r, r, r
-def FSMULD : F3_16<2, 0b110100, 0b001101001, "fsmuld">; // fsmuls r, r, r
-def FDMULQ : F3_16<2, 0b110100, 0b001101110, "fdmulq">; // fdmuls r, r, r
-def FDIVS : F3_16<2, 0b110100, 0b001001101, "fdivs">; // fdivs r, r, r
-def FDIVD : F3_16<2, 0b110100, 0b001001110, "fdivs">; // fdivd r, r, r
-def FDIVQ : F3_16<2, 0b110100, 0b001001111, "fdivs">; // fdivq r, r, r
-
-// Section A.19: Floating-Point Square Root - p166
-def FSQRTS : F3_14<2, 0b110100, 0b000101001, "fsqrts">; // fsqrts r, r
-def FSQRTD : F3_14<2, 0b110100, 0b000101010, "fsqrts">; // fsqrts r, r
-def FSQRTQ : F3_14<2, 0b110100, 0b000101011, "fsqrts">; // fsqrts r, r
-
-// A.20: Flush Instruction Memory - p167
-// Not currently used
-
-// A.21: Flush Register Windows - p169
-// Not currently used
-
-// A.22: Illegal instruction Trap - p170
-// Not currently used
-
-// A.23: Implementation-Dependent Instructions - p171
-// Not currently used
-
-// Section A.24: Jump and Link - p172
-// Mimicking the Sparc's instr def...
-def JMPLCALLr : F3_1<2, 0b111000, "jmpl">; // jmpl [rs1+rs2], rd
-def JMPLCALLi : F3_2<2, 0b111000, "jmpl">; // jmpl [rs1+imm], rd
-def JMPLRETr : F3_1<2, 0b111000, "jmpl">; // jmpl [rs1+rs2], rd
-def JMPLRETi : F3_2<2, 0b111000, "jmpl">; // jmpl [rs1+imm], rd
-
-// Section A.25: Load Floating-Point - p173
-def LDFr : F3_1<3, 0b100000, "ld">; // ld [rs1+rs2], rd
-def LDFi : F3_2<3, 0b100000, "ld">; // ld [rs1+imm], rd
-def LDDFr : F3_1<3, 0b100011, "ldd">; // ldd [rs1+rs2], rd
-def LDDFi : F3_2<3, 0b100011, "ldd">; // ldd [rs1+imm], rd
-def LDQFr : F3_1<3, 0b100010, "ldq">; // ldq [rs1+rs2], rd
-def LDQFi : F3_2<3, 0b100010, "ldq">; // ldq [rs1+imm], rd
-let isDeprecated = 1 in {
- let rd = 0 in {
- def LDFSRr : F3_1<3, 0b100001, "ld">; // ld [rs1+rs2], rd
- def LDFSRi : F3_2<3, 0b100001, "ld">; // ld [rs1+imm], rd
- }
-}
-let rd = 1 in {
- def LDXFSRr : F3_1<3, 0b100001, "ldx">; // ldx [rs1+rs2], rd
- def LDXFSRi : F3_2<3, 0b100001, "ldx">; // ldx [rs1+imm], rd
-}
-
-// Section A.27: Load Integer - p178
-def LDSBr : F3_1<3, 0b001001, "ldsb">; // ldsb [rs1+rs2], rd
-def LDSBi : F3_2<3, 0b001001, "ldsb">; // ldsb [rs1+imm], rd
-def LDSHr : F3_1<3, 0b001010, "ldsh">; // ldsh [rs1+rs2], rd
-def LDSHi : F3_2<3, 0b001010, "ldsh">; // ldsh [rs1+imm], rd
-def LDSWr : F3_1<3, 0b001000, "ldsw">; // ldsh [rs1+rs2], rd
-def LDSWi : F3_2<3, 0b001000, "ldsw">; // ldsh [rs1+imm], rd
-def LDUBr : F3_1<3, 0b000001, "ldub">; // ldub [rs1+rs2], rd
-def LDUBi : F3_2<3, 0b000001, "ldub">; // ldub [rs1+imm], rd
-def LDUHr : F3_1<3, 0b000010, "lduh">; // lduh [rs1+rs2], rd
-def LDUHi : F3_2<3, 0b000010, "lduh">; // lduh [rs1+imm], rd
-// synonym: LD
-def LDUWr : F3_1<3, 0b000000, "lduw">; // lduw [rs1+rs2], rd
-def LDUWi : F3_2<3, 0b000000, "lduw">; // lduw [rs1+imm], rd
-def LDXr : F3_1<3, 0b001011, "ldx">; // ldx [rs1+rs2], rd
-def LDXi : F3_2<3, 0b001011, "ldx">; // ldx [rs1+imm], rd
-/*
-let isDeprecated = 1 in {
- def LDDr : F3_1<3, 0b000011, "ldd">; // ldd [rs1+rs2], rd
- def LDDi : F3_2<3, 0b000011, "ldd">; // ldd [rs1+imm], rd
-}
-*/
-
-// Section A.31: Logical operations
-def ANDr : F3_1<2, 0b000001, "and">; // and rs1, rs2, rd
-def ANDi : F3_2<2, 0b000001, "and">; // and rs1, imm, rd
-def ANDccr : F3_1<2, 0b010001, "andcc">; // andcc rs1, rs2, rd
-def ANDcci : F3_2<2, 0b010001, "andcc">; // andcc rs1, imm, rd
-def ANDNr : F3_1<2, 0b000101, "andn">; // andn rs1, rs2, rd
-def ANDNi : F3_2<2, 0b000101, "andn">; // andn rs1, imm, rd
-def ANDNccr : F3_1<2, 0b010101, "andncc">; // andncc rs1, rs2, rd
-def ANDNcci : F3_2<2, 0b010101, "andncc">; // andncc rs1, imm, rd
-
-def ORr : F3_1<2, 0b000010, "or">; // or rs1, rs2, rd
-def ORi : F3_2<2, 0b000010, "or">; // or rs1, imm, rd
-def ORccr : F3_1<2, 0b010010, "orcc">; // orcc rs1, rs2, rd
-def ORcci : F3_2<2, 0b010010, "orcc">; // orcc rs1, imm, rd
-def ORNr : F3_1<2, 0b000110, "orn">; // orn rs1, rs2, rd
-def ORNi : F3_2<2, 0b000110, "orn">; // orn rs1, imm, rd
-def ORNccr : F3_1<2, 0b010110, "orncc">; // orncc rs1, rs2, rd
-def ORNcci : F3_2<2, 0b010110, "orncc">; // orncc rs1, imm, rd
-
-def XORr : F3_1<2, 0b000011, "xor">; // xor rs1, rs2, rd
-def XORi : F3_2<2, 0b000011, "xor">; // xor rs1, imm, rd
-def XORccr : F3_1<2, 0b010011, "xorcc">; // xorcc rs1, rs2, rd
-def XORcci : F3_2<2, 0b010011, "xorcc">; // xorcc rs1, imm, rd
-def XNORr : F3_1<2, 0b000111, "xnor">; // xnor rs1, rs2, rd
-def XNORi : F3_2<2, 0b000111, "xnor">; // xnor rs1, imm, rd
-def XNORccr : F3_1<2, 0b010111, "xnorcc">; // xnorcc rs1, rs2, rd
-def XNORcci : F3_2<2, 0b010111, "xnorcc">; // xnorcc rs1, imm, rd
-
-// Section A.32: Memory Barrier - p186
-// Not currently used in the Sparc backend
-
-// Section A.33: Move Floating-Point Register on Condition (FMOVcc)
-// ======================= Single Floating Point ======================
-// For integer condition codes
-def FMOVSA : F4_7<2, 0b110101, 0b1000, 0b000001, "fmovsa">; // fmovsa cc, r, r
-def FMOVSN : F4_7<2, 0b110101, 0b0000, 0b000001, "fmovsn">; // fmovsn cc, r, r
-def FMOVSNE : F4_7<2, 0b110101, 0b1001, 0b000001, "fmovsne">; // fmovsne cc, r, r
-def FMOVSE : F4_7<2, 0b110101, 0b0000, 0b000001, "fmovse">; // fmovse cc, r, r
-def FMOVSG : F4_7<2, 0b110101, 0b1010, 0b000001, "fmovsg">; // fmovsg cc, r, r
-def FMOVSLE : F4_7<2, 0b110101, 0b0000, 0b000001, "fmovsle">; // fmovsle cc, r, r
-def FMOVSGE : F4_7<2, 0b110101, 0b1011, 0b000001, "fmovsge">; // fmovsge cc, r, r
-def FMOVSL : F4_7<2, 0b110101, 0b0011, 0b000001, "fmovsl">; // fmovsl cc, r, r
-def FMOVSGU : F4_7<2, 0b110101, 0b1100, 0b000001, "fmovsgu">; // fmovsgu cc, r, r
-def FMOVSLEU : F4_7<2, 0b110101, 0b0100, 0b000001, "fmovsleu">; // fmovsleu cc, r, r
-def FMOVSCC : F4_7<2, 0b110101, 0b1101, 0b000001, "fmovscc">; // fmovscc cc, r, r
-def FMOVSCS : F4_7<2, 0b110101, 0b0101, 0b000001, "fmovscs">; // fmovscs cc, r, r
-def FMOVSPOS : F4_7<2, 0b110101, 0b1110, 0b000001, "fmovspos">; // fmovspos cc, r, r
-def FMOVSNEG : F4_7<2, 0b110101, 0b0110, 0b000001, "fmovsneg">; // fmovsneg cc, r, r
-def FMOVSVC : F4_7<2, 0b110101, 0b1111, 0b000001, "fmovsvc">; // fmovsvc cc, r, r
-def FMOVSVS : F4_7<2, 0b110101, 0b0111, 0b000001, "fmovsvs">; // fmovsvs cc, r, r
-
-// For floating-point condition codes
-def FMOVSFA : F4_7<2, 0b110101, 0b0100, 0b000001, "fmovsfa">; // fmovsfa cc,r,r
-def FMOVSFN : F4_7<2, 0b110101, 0b0000, 0b000001, "fmovsfn">; // fmovsfa cc,r,r
-def FMOVSFU : F4_7<2, 0b110101, 0b0111, 0b000001, "fmovsfu">; // fmovsfu cc,r,r
-def FMOVSFG : F4_7<2, 0b110101, 0b0110, 0b000001, "fmovsfg">; // fmovsfg cc,r,r
-def FMOVSFUG : F4_7<2, 0b110101, 0b0101, 0b000001, "fmovsfug">; // fmovsfug cc,r,r
-def FMOVSFL : F4_7<2, 0b110101, 0b0100, 0b000001, "fmovsfl">; // fmovsfl cc,r,r
-def FMOVSFUL : F4_7<2, 0b110101, 0b0011, 0b000001, "fmovsful">; // fmovsful cc,r,r
-def FMOVSFLG : F4_7<2, 0b110101, 0b0010, 0b000001, "fmovsflg">; // fmovsflg cc,r,r
-def FMOVSFNE : F4_7<2, 0b110101, 0b0001, 0b000001, "fmovsfne">; // fmovsfne cc,r,r
-def FMOVSFE : F4_7<2, 0b110101, 0b1001, 0b000001, "fmovsfe">; // fmovsfe cc,r,r
-def FMOVSFUE : F4_7<2, 0b110101, 0b1010, 0b000001, "fmovsfue">; // fmovsfue cc,r,r
-def FMOVSFGE : F4_7<2, 0b110101, 0b1011, 0b000001, "fmovsge">; // fmovsge cc,r,r
-def FMOVSFUGE : F4_7<2, 0b110101, 0b1100, 0b000001, "fmovsfuge">;// fmovsfuge cc,r,r
-def FMOVSFLE : F4_7<2, 0b110101, 0b1101, 0b000001, "fmovsfle">; // fmovsfle cc,r,r
-def FMOVSFULE : F4_7<2, 0b110101, 0b1110, 0b000001, "fmovsfule">;// fmovsfule cc,r,r
-def FMOVSFO : F4_7<2, 0b110101, 0b1111, 0b000001, "fmovsfo">; // fmovsfo cc,r,r
-
-// ======================= Double Floating Point ======================
-// For integer condition codes
-def FMOVDA : F4_7<2, 0b110101, 0b1000, 0b000010, "fmovda">; // fmovda cc, r, r
-def FMOVDN : F4_7<2, 0b110101, 0b0000, 0b000010, "fmovdn">; // fmovdn cc, r, r
-def FMOVDNE : F4_7<2, 0b110101, 0b1001, 0b000010, "fmovdne">; // fmovdne cc, r, r
-def FMOVDE : F4_7<2, 0b110101, 0b0000, 0b000010, "fmovde">; // fmovde cc, r, r
-def FMOVDG : F4_7<2, 0b110101, 0b1010, 0b000010, "fmovdg">; // fmovdg cc, r, r
-def FMOVDLE : F4_7<2, 0b110101, 0b0000, 0b000010, "fmovdle">; // fmovdle cc, r, r
-def FMOVDGE : F4_7<2, 0b110101, 0b1011, 0b000010, "fmovdge">; // fmovdge cc, r, r
-def FMOVDL : F4_7<2, 0b110101, 0b0011, 0b000010, "fmovdl">; // fmovdl cc, r, r
-def FMOVDGU : F4_7<2, 0b110101, 0b1100, 0b000010, "fmovdgu">; // fmovdgu cc, r, r
-def FMOVDLEU : F4_7<2, 0b110101, 0b0100, 0b000010, "fmovdleu">; // fmovdleu cc, r, r
-def FMOVDCC : F4_7<2, 0b110101, 0b1101, 0b000010, "fmovdcc">; // fmovdcc cc, r, r
-def FMOVDCS : F4_7<2, 0b110101, 0b0101, 0b000010, "fmovdcs">; // fmovdcs cc, r, r
-def FMOVDPOS : F4_7<2, 0b110101, 0b1110, 0b000010, "fmovdpos">; // fmovdpos cc, r, r
-def FMOVDNEG : F4_7<2, 0b110101, 0b0110, 0b000010, "fmovdneg">; // fmovdneg cc, r, r
-def FMOVDVC : F4_7<2, 0b110101, 0b1111, 0b000010, "fmovdvc">; // fmovdvc cc, r, r
-def FMOVDVS : F4_7<2, 0b110101, 0b0111, 0b000010, "fmovdvs">; // fmovdvs cc, r, r
-
-// For floating-point condition codes
-def FMOVDFA : F4_7<2, 0b110101, 0b0100, 0b000010, "fmovdfa">; // fmovdfa cc,r,r
-def FMOVDFN : F4_7<2, 0b110101, 0b0000, 0b000010, "fmovdfn">; // fmovdfa cc,r,r
-def FMOVDFU : F4_7<2, 0b110101, 0b0111, 0b000010, "fmovdfu">; // fmovdfu cc,r,r
-def FMOVDFG : F4_7<2, 0b110101, 0b0110, 0b000010, "fmovdfg">; // fmovdfg cc,r,r
-def FMOVDFUG : F4_7<2, 0b110101, 0b0101, 0b000010, "fmovdfug">; // fmovdfug cc,r,r
-def FMOVDFL : F4_7<2, 0b110101, 0b0100, 0b000010, "fmovdfl">; // fmovdfl cc,r,r
-def FMOVDFUL : F4_7<2, 0b110101, 0b0011, 0b000010, "fmovdful">; // fmovdful cc,r,r
-def FMOVDFLG : F4_7<2, 0b110101, 0b0010, 0b000010, "fmovdflg">; // fmovdflg cc,r,r
-def FMOVDFNE : F4_7<2, 0b110101, 0b0001, 0b000010, "fmovdfne">; // fmovdfne cc,r,r
-def FMOVDFE : F4_7<2, 0b110101, 0b1001, 0b000010, "fmovdfe">; // fmovdfe cc,r,r
-def FMOVDFUE : F4_7<2, 0b110101, 0b1010, 0b000010, "fmovdfue">; // fmovdfue cc,r,r
-def FMOVDFGE : F4_7<2, 0b110101, 0b1011, 0b000010, "fmovdge">; // fmovdge cc,r,r
-def FMOVDFUGE : F4_7<2, 0b110101, 0b1100, 0b000010, "fmovdfuge">;// fmovdfuge cc,r,r
-def FMOVDFLE : F4_7<2, 0b110101, 0b1101, 0b000010, "fmovdfle">; // fmovdfle cc,r,r
-def FMOVDFULE : F4_7<2, 0b110101, 0b1110, 0b000010, "fmovdfule">;// fmovdfule cc,r,r
-def FMOVDFO : F4_7<2, 0b110101, 0b1111, 0b000010, "fmovdfo">; // fmovdfo cc,r,r
-
-// ======================= Quad Floating Point ======================
-// For integer condition codes
-def FMOVQA : F4_7<2, 0b110101, 0b1000, 0b000011, "fmovqa">; // fmovqa cc, r, r
-def FMOVQN : F4_7<2, 0b110101, 0b0000, 0b000011, "fmovqn">; // fmovqn cc, r, r
-def FMOVQNE : F4_7<2, 0b110101, 0b1001, 0b000011, "fmovqne">; // fmovqne cc, r, r
-def FMOVQE : F4_7<2, 0b110101, 0b0000, 0b000011, "fmovqe">; // fmovqe cc, r, r
-def FMOVQG : F4_7<2, 0b110101, 0b1010, 0b000011, "fmovqg">; // fmovqg cc, r, r
-def FMOVQLE : F4_7<2, 0b110101, 0b0000, 0b000011, "fmovqle">; // fmovqle cc, r, r
-def FMOVQGE : F4_7<2, 0b110101, 0b1011, 0b000011, "fmovqge">; // fmovqge cc, r, r
-def FMOVQL : F4_7<2, 0b110101, 0b0011, 0b000011, "fmovql">; // fmovql cc, r, r
-def FMOVQGU : F4_7<2, 0b110101, 0b1100, 0b000011, "fmovqgu">; // fmovqgu cc, r, r
-def FMOVQLEU : F4_7<2, 0b110101, 0b0100, 0b000011, "fmovqleu">; // fmovqleu cc, r, r
-def FMOVQCC : F4_7<2, 0b110101, 0b1101, 0b000011, "fmovqcc">; // fmovqcc cc, r, r
-def FMOVQCS : F4_7<2, 0b110101, 0b0101, 0b000011, "fmovqcs">; // fmovqcs cc, r, r
-def FMOVQPOS : F4_7<2, 0b110101, 0b1110, 0b000011, "fmovqpos">; // fmovqpos cc, r, r
-def FMOVQNEG : F4_7<2, 0b110101, 0b0110, 0b000011, "fmovqneg">; // fmovqneg cc, r, r
-def FMOVQVC : F4_7<2, 0b110101, 0b1111, 0b000011, "fmovqvc">; // fmovqvc cc, r, r
-def FMOVQVS : F4_7<2, 0b110101, 0b0111, 0b000011, "fmovqvs">; // fmovqvs cc, r, r
-
-// For floating-point condition codes
-def FMOVQFA : F4_7<2, 0b110101, 0b0100, 0b000011, "fmovqfa">; // fmovqfa cc,r,r
-def FMOVQFN : F4_7<2, 0b110101, 0b0000, 0b000011, "fmovqfn">; // fmovqfa cc,r,r
-def FMOVQFU : F4_7<2, 0b110101, 0b0111, 0b000011, "fmovqfu">; // fmovqfu cc,r,r
-def FMOVQFG : F4_7<2, 0b110101, 0b0110, 0b000011, "fmovqfg">; // fmovqfg cc,r,r
-def FMOVQFUG : F4_7<2, 0b110101, 0b0101, 0b000011, "fmovqfug">; // fmovqfug cc,r,r
-def FMOVQFL : F4_7<2, 0b110101, 0b0100, 0b000011, "fmovqfl">; // fmovqfl cc,r,r
-def FMOVQFUL : F4_7<2, 0b110101, 0b0011, 0b000011, "fmovqful">; // fmovqful cc,r,r
-def FMOVQFLG : F4_7<2, 0b110101, 0b0010, 0b000011, "fmovqflg">; // fmovqflg cc,r,r
-def FMOVQFNE : F4_7<2, 0b110101, 0b0001, 0b000011, "fmovqfne">; // fmovqfne cc,r,r
-def FMOVQFE : F4_7<2, 0b110101, 0b1001, 0b000011, "fmovqfe">; // fmovqfe cc,r,r
-def FMOVQFUE : F4_7<2, 0b110101, 0b1010, 0b000011, "fmovqfue">; // fmovqfue cc,r,r
-def FMOVQFGE : F4_7<2, 0b110101, 0b1011, 0b000011, "fmovqge">; // fmovqge cc,r,r
-def FMOVQFUGE : F4_7<2, 0b110101, 0b1100, 0b000011, "fmovqfuge">;// fmovqfuge cc,r,r
-def FMOVQFLE : F4_7<2, 0b110101, 0b1101, 0b000011, "fmovqfle">; // fmovqfle cc,r,r
-def FMOVQFULE : F4_7<2, 0b110101, 0b1110, 0b000011, "fmovqfule">;// fmovqfule cc,r,r
-def FMOVQFO : F4_7<2, 0b110101, 0b1111, 0b000011, "fmovqfo">; // fmovqfo cc,r,r
-
-// Section A.34: Move FP Register on Integer Register condition (FMOVr) - p192
-def FMOVRSZ : F4_6<2, 0b110101, 0b001, 0b00101, "fmovrsz">; //fmovsrz r,r,rd
-def FMOVRSLEZ : F4_6<2, 0b110101, 0b010, 0b00101, "fmovrslez">;//fmovsrz r,r,rd
-def FMOVRSLZ : F4_6<2, 0b110101, 0b011, 0b00101, "fmovrslz">; //fmovsrz r,r,rd
-def FMOVRSNZ : F4_6<2, 0b110101, 0b101, 0b00101, "fmovrsne">; //fmovsrz r,r,rd
-def FMOVRSGZ : F4_6<2, 0b110101, 0b110, 0b00101, "fmovrsgz">; //fmovsrz r,r,rd
-def FMOVRSGEZ : F4_6<2, 0b110101, 0b111, 0b00101, "fmovrsgez">;//fmovsrz r,r,rd
-
-def FMOVRDZ : F4_6<2, 0b110101, 0b001, 0b00110, "fmovrdz">; //fmovsrz r,r,rd
-def FMOVRDLEZ : F4_6<2, 0b110101, 0b010, 0b00110, "fmovrdlez">;//fmovsrz r,r,rd
-def FMOVRDLZ : F4_6<2, 0b110101, 0b011, 0b00110, "fmovrdlz">; //fmovsrz r,r,rd
-def FMOVRDNZ : F4_6<2, 0b110101, 0b101, 0b00110, "fmovrdne">; //fmovsrz r,r,rd
-def FMOVRDGZ : F4_6<2, 0b110101, 0b110, 0b00110, "fmovrdgz">; //fmovsrz r,r,rd
-def FMOVRDGEZ : F4_6<2, 0b110101, 0b111, 0b00110, "fmovrdgez">;//fmovsrz r,r,rd
-
-def FMOVRQZ : F4_6<2, 0b110101, 0b001, 0b00111, "fmovrqz">; //fmovsrz r,r,rd
-def FMOVRQLEZ : F4_6<2, 0b110101, 0b010, 0b00111, "fmovrqlez">;//fmovsrz r,r,rd
-def FMOVRQLZ : F4_6<2, 0b110101, 0b011, 0b00111, "fmovrqlz">; //fmovsrz r,r,rd
-def FMOVRQNZ : F4_6<2, 0b110101, 0b101, 0b00111, "fmovrqne">; //fmovsrz r,r,rd
-def FMOVRQGZ : F4_6<2, 0b110101, 0b110, 0b00111, "fmovrqgz">; //fmovsrz r,r,rd
-def FMOVRQGEZ : F4_6<2, 0b110101, 0b111, 0b00111, "fmovrqgez">;//fmovsrz r,r,rd
-
-
-// Section A.35: Move Integer Register on Condition (MOVcc) - p194
-// For integer condition codes
-def MOVAr : F4_3<2, 0b101100, 0b1000, "mova">; // mova i/xcc, rs2, rd
-def MOVAi : F4_4<2, 0b101100, 0b1000, "mova">; // mova i/xcc, imm, rd
-def MOVNr : F4_3<2, 0b101100, 0b0000, "movn">; // movn i/xcc, rs2, rd
-def MOVNi : F4_4<2, 0b101100, 0b0000, "movn">; // movn i/xcc, imm, rd
-def MOVNEr : F4_3<2, 0b101100, 0b1001, "movne">; // movne i/xcc, rs2, rd
-def MOVNEi : F4_4<2, 0b101100, 0b1001, "movne">; // movne i/xcc, imm, rd
-def MOVEr : F4_3<2, 0b101100, 0b0001, "move">; // move i/xcc, rs2, rd
-def MOVEi : F4_4<2, 0b101100, 0b0001, "move">; // move i/xcc, imm, rd
-def MOVGr : F4_3<2, 0b101100, 0b1010, "movg">; // movg i/xcc, rs2, rd
-def MOVGi : F4_4<2, 0b101100, 0b1010, "movg">; // movg i/xcc, imm, rd
-def MOVLEr : F4_3<2, 0b101100, 0b0010, "movle">; // movle i/xcc, rs2, rd
-def MOVLEi : F4_4<2, 0b101100, 0b0010, "movle">; // movle i/xcc, imm, rd
-def MOVGEr : F4_3<2, 0b101100, 0b1011, "movge">; // movge i/xcc, rs2, rd
-def MOVGEi : F4_4<2, 0b101100, 0b1011, "movge">; // movge i/xcc, imm, rd
-def MOVLr : F4_3<2, 0b101100, 0b0011, "movl">; // movl i/xcc, rs2, rd
-def MOVLi : F4_4<2, 0b101100, 0b0011, "movl">; // movl i/xcc, imm, rd
-def MOVGUr : F4_3<2, 0b101100, 0b1100, "movgu">; // movgu i/xcc, rs2, rd
-def MOVGUi : F4_4<2, 0b101100, 0b1100, "movgu">; // movgu i/xcc, imm, rd
-def MOVLEUr : F4_3<2, 0b101100, 0b0100, "movleu">; // movleu i/xcc, rs2, rd
-def MOVLEUi : F4_4<2, 0b101100, 0b0100, "movleu">; // movleu i/xcc, imm, rd
-def MOVCCr : F4_3<2, 0b101100, 0b1101, "movcc">; // movcc i/xcc, rs2, rd
-def MOVCCi : F4_4<2, 0b101100, 0b1101, "movcc">; // movcc i/xcc, imm, rd
-def MOVCSr : F4_3<2, 0b101100, 0b0101, "movcs">; // movcs i/xcc, rs2, rd
-def MOVCSi : F4_4<2, 0b101100, 0b0101, "movcs">; // movcs i/xcc, imm, rd
-def MOVPOSr : F4_3<2, 0b101100, 0b1110, "movpos">; // movpos i/xcc, rs2, rd
-def MOVPOSi : F4_4<2, 0b101100, 0b1110, "movpos">; // movpos i/xcc, imm, rd
-def MOVNEGr : F4_3<2, 0b101100, 0b0110, "movneg">; // movneg i/xcc, rs2, rd
-def MOVNEGi : F4_4<2, 0b101100, 0b0110, "movneg">; // movneg i/xcc, imm, rd
-def MOVVCr : F4_3<2, 0b101100, 0b1111, "movvc">; // movvc i/xcc, rs2, rd
-def MOVVCi : F4_4<2, 0b101100, 0b1111, "movvc">; // movvc i/xcc, imm, rd
-def MOVVSr : F4_3<2, 0b101100, 0b0111, "movvs">; // movvs i/xcc, rs2, rd
-def MOVVSi : F4_4<2, 0b101100, 0b0111, "movvs">; // movvs i/xcc, imm, rd
-
-// For floating-point condition codes
-def MOVFAr : F4_3<2, 0b101100, 0b1000, "movfa">; // movfa i/xcc, rs2, rd
-def MOVFAi : F4_4<2, 0b101100, 0b1000, "movfa">; // movfa i/xcc, imm, rd
-def MOVFNr : F4_3<2, 0b101100, 0b0000, "movfn">; // movfn i/xcc, rs2, rd
-def MOVFNi : F4_4<2, 0b101100, 0b0000, "movfn">; // movfn i/xcc, imm, rd
-def MOVFUr : F4_3<2, 0b101100, 0b0111, "movfu">; // movfu i/xcc, rs2, rd
-def MOVFUi : F4_4<2, 0b101100, 0b0111, "movfu">; // movfu i/xcc, imm, rd
-def MOVFGr : F4_3<2, 0b101100, 0b0110, "movfg">; // movfg i/xcc, rs2, rd
-def MOVFGi : F4_4<2, 0b101100, 0b0110, "movfg">; // movfg i/xcc, imm, rd
-def MOVFUGr : F4_3<2, 0b101100, 0b0101, "movfug">; // movfug i/xcc, rs2, rd
-def MOVFUGi : F4_4<2, 0b101100, 0b0101, "movfug">; // movfug i/xcc, imm, rd
-def MOVFLr : F4_3<2, 0b101100, 0b0100, "movfl">; // movfl i/xcc, rs2, rd
-def MOVFLi : F4_4<2, 0b101100, 0b0100, "movfl">; // movfl i/xcc, imm, rd
-def MOVFULr : F4_3<2, 0b101100, 0b0011, "movful">; // movful i/xcc, rs2, rd
-def MOVFULi : F4_4<2, 0b101100, 0b0011, "movful">; // movful i/xcc, imm, rd
-def MOVFLGr : F4_3<2, 0b101100, 0b0010, "movflg">; // movflg i/xcc, rs2, rd
-def MOVFLGi : F4_4<2, 0b101100, 0b0010, "movflg">; // movflg i/xcc, imm, rd
-def MOVFNEr : F4_3<2, 0b101100, 0b0001, "movfne">; // movfne i/xcc, rs2, rd
-def MOVFNEi : F4_4<2, 0b101100, 0b0001, "movfne">; // movfne i/xcc, imm, rd
-def MOVFEr : F4_3<2, 0b101100, 0b1001, "movfe">; // movfe i/xcc, rs2, rd
-def MOVFEi : F4_4<2, 0b101100, 0b1001, "movfe">; // movfe i/xcc, imm, rd
-def MOVFUEr : F4_3<2, 0b101100, 0b1010, "movfue">; // movfue i/xcc, rs2, rd
-def MOVFUEi : F4_4<2, 0b101100, 0b1010, "movfue">; // movfue i/xcc, imm, rd
-def MOVFGEr : F4_3<2, 0b101100, 0b1011, "movfge">; // movfge i/xcc, rs2, rd
-def MOVFGEi : F4_4<2, 0b101100, 0b1011, "movfge">; // movfge i/xcc, imm, rd
-def MOVFUGEr : F4_3<2, 0b101100, 0b1100, "movfuge">; // movfuge i/xcc, rs2, rd
-def MOVFUGEi : F4_4<2, 0b101100, 0b1100, "movfuge">; // movfuge i/xcc, imm, rd
-def MOVFLEr : F4_3<2, 0b101100, 0b1101, "movfle">; // movfle i/xcc, rs2, rd
-def MOVFLEi : F4_4<2, 0b101100, 0b1101, "movfle">; // movfle i/xcc, imm, rd
-def MOVFULEr : F4_3<2, 0b101100, 0b1110, "movfule">; // movfule i/xcc, rs2, rd
-def MOVFULEi : F4_4<2, 0b101100, 0b1110, "movfule">; // movfule i/xcc, imm, rd
-def MOVFOr : F4_3<2, 0b101100, 0b1111, "movfo">; // movfo i/xcc, rs2, rd
-def MOVFOi : F4_4<2, 0b101100, 0b1111, "movfo">; // movfo i/xcc, imm, rd
-
-// Section A.36: Move Integer Register on Register Condition (MOVR) - p198
-def MOVRZr : F3_5<2, 0b101111, 0b001, "movrz">; // movrz rs1, rs2, rd
-def MOVRZi : F3_6<2, 0b101111, 0b001, "movrz">; // movrz rs1, imm, rd
-def MOVRLEZr : F3_5<2, 0b101111, 0b010, "movrlez">; // movrlez rs1, rs2, rd
-def MOVRLEZi : F3_6<2, 0b101111, 0b010, "movrlez">; // movrlez rs1, imm, rd
-def MOVRLZr : F3_5<2, 0b101111, 0b011, "movrlz">; // movrlz rs1, rs2, rd
-def MOVRLZi : F3_6<2, 0b101111, 0b011, "movrlz">; // movrlz rs1, imm, rd
-def MOVRNZr : F3_5<2, 0b101111, 0b101, "movrnz">; // movrnz rs1, rs2, rd
-def MOVRNZi : F3_6<2, 0b101111, 0b101, "movrnz">; // movrnz rs1, imm, rd
-def MOVRGZr : F3_5<2, 0b101111, 0b110, "movrgz">; // movrgz rs1, rs2, rd
-def MOVRGZi : F3_6<2, 0b101111, 0b110, "movrgz">; // movrgz rs1, imm, rd
-def MOVRGEZr : F3_5<2, 0b101111, 0b111, "movrgez">; // movrgez rs1, rs2, rd
-def MOVRGEZi : F3_6<2, 0b101111, 0b111, "movrgez">; // movrgez rs1, imm, rd
-
-// Section A.37: Multiply and Divide (64-bit) - p199
-def MULXr : F3_1<2, 0b001001, "mulx">; // mulx r, r, r
-def MULXi : F3_2<2, 0b001001, "mulx">; // mulx r, i, r
-def SDIVXr : F3_1<2, 0b101101, "sdivx">; // sdivx r, r, r
-def SDIVXi : F3_2<2, 0b101101, "sdivx">; // sdivx r, i, r
-def UDIVXr : F3_1<2, 0b001101, "udivx">; // udivx r, r, r
-def UDIVXi : F3_2<2, 0b001101, "udivx">; // udivx r, i, r
-
-// Section A.38: Multiply (32-bit) - p200
-// Not used in the Sparc backend
-/*
-let Inst{13} = 0 in {
- def UMULr : F3_1<2, 0b001010, "umul">; // umul r, r, r
- def SMULr : F3_1<2, 0b001011, "smul">; // smul r, r, r
- def UMULCCr : F3_1<2, 0b011010, "umulcc">; // mulcc r, r, r
- def SMULCCr : F3_1<2, 0b011011, "smulcc">; // smulcc r, r, r
-}
-let Inst{13} = 1 in {
- def UMULi : F3_1<2, 0b001010, "umul">; // umul r, i, r
- def SMULi : F3_1<2, 0b001011, "smul">; // smul r, i, r
- def UMULCCi : F3_1<2, 0b011010, "umulcc">; // umulcc r, i, r
- def SMULCCi : F3_1<2, 0b011011, "smulcc">; // smulcc r, i, r
-}
-*/
-
-// Section A.39: Multiply Step - p202
-// Not currently used in the Sparc backend
-
-// Section A.40: No operation - p204
-// NOP is really a pseudo-instruction (special case of SETHI)
-let op2 = 0b100 in {
- let rd = 0 in {
- let imm = 0 in {
- def NOP : F2_1<"nop">; // nop
- }
- }
-}
-
-// Section A.41: Population Count - p205
-// Not currently used in the Sparc backend
-
-// Section A.42: Prefetch Data - p206
-// Not currently used in the Sparc backend
-
-// Section A.43: Read Privileged Register - p211
-// Not currently used in the Sparc backend
-
-// Section A.44: Read State Register
-// The only instr from this section currently used is RDCCR
-let rs1 = 2 in {
- def RDCCR : F3_17<2, 0b101000, "rd">; // rd %ccr, r
-}
-
-// Section A.45: RETURN - p216
-let isReturn = 1 in {
- def RETURNr : F3_3<2, 0b111001, "return">; // return
- def RETURNi : F3_4<2, 0b111001, "return">; // return
-}
-
-// Section A.46: SAVE and RESTORE - p217
-def SAVEr : F3_1<2, 0b111100, "save">; // save r, r, r
-def SAVEi : F3_2<2, 0b111100, "save">; // save r, i, r
-def RESTOREr : F3_1<2, 0b111101, "restore">; // restore r, r, r
-def RESTOREi : F3_2<2, 0b111101, "restore">; // restore r, i, r
-
-// Section A.47: SAVED and RESTORED - p219
-// Not currently used in Sparc backend
-
-// Section A.48: SETHI - p220
-let op2 = 0b100 in {
- def SETHI : F2_1<"sethi">; // sethi
-}
-
-// Section A.49: Shift - p221
-// Not currently used in the Sparc backend
-/*
- uses 5 least significant bits of rs2
-let x = 0 in {
- def SLLr5 : F3_11<2, 0b100101, "sll">; // sll r, r, r
- def SRLr5 : F3_11<2, 0b100110, "srl">; // srl r, r, r
- def SRAr5 : F3_11<2, 0b100111, "sra">; // sra r, r, r
- def SLLXr5 : F3_11<2, 0b100101, "sllx">; // sllx r, r, r
- def SRLXr5 : F3_11<2, 0b100110, "srlx">; // srlx r, r, r
- def SRAXr5 : F3_11<2, 0b100111, "srax">; // srax r, r, r
-}
-*/
-
-// uses 6 least significant bits of rs2
-let x = 0 in {
- def SLLr5 : F3_11<2, 0b100101, "sll">; // sll r, r, r
- def SRLr5 : F3_11<2, 0b100110, "srl">; // srl r, r, r
- def SRAr5 : F3_11<2, 0b100111, "sra">; // sra r, r, r
-}
-let x = 1 in {
- def SLLXr6 : F3_11<2, 0b100101, "sllx">; // sllx r, r, r
- def SRLXr6 : F3_11<2, 0b100110, "srlx">; // srlx r, r, r
- def SRAXr6 : F3_11<2, 0b100111, "srax">; // srax r, r, r
-}
-
-def SLLi5 : F3_12<2, 0b100101, "sll">; // sll r, shcnt32, r
-def SRLi5 : F3_12<2, 0b100110, "srl">; // srl r, shcnt32, r
-def SRAi5 : F3_12<2, 0b100111, "sra">; // sra r, shcnt32, r
-def SLLXi6 : F3_13<2, 0b100101, "sllx">; // sllx r, shcnt64, r
-def SRLXi6 : F3_13<2, 0b100110, "srlx">; // srlx r, shcnt64, r
-def SRAXi6 : F3_13<2, 0b100111, "srax">; // srax r, shcnt64, r
-
-// Section A.50: Sofware-Initiated Reset - p223
-// Not currently used in the Sparc backend
-
-// Section A.51: Store Barrier - p224
-// Not currently used in the Sparc backend
-
-// Section A.52: Store Floating-point - p225
-// Store instructions all want their rd register first
-def STFr : F3_1rd<3, 0b100100, "st">; // st r, [r+r]
-def STFi : F3_2rd<3, 0b100100, "st">; // st r, [r+i]
-def STDFr : F3_1rd<3, 0b100111, "std">; // std r, [r+r]
-def STDFi : F3_2rd<3, 0b100111, "std">; // std r, [r+i]
-
-// Not currently used in the Sparc backend
-/*
-def STQFr : F3_1rd<3, 0b100110, "stq">; // stq r, [r+r]
-def STQFi : F3_2rd<3, 0b100110, "stq">; // stq r, [r+i]
-*/
-
-// FIXME: An encoding needs to be chosen here, because STFSRx expect rd=0,
-// while STXFSRx expect rd=1, but assembly syntax dictates %fsr as first arg.
-// These are being disabled because they aren't used in the Sparc backend.
-/*
-let isDeprecated = 1 in {
- def STFSRr : F3_1<3, 0b100101, "st">; // st %fsr, [r+r]
- def STFSRi : F3_2<3, 0b100101, "st">; // st %fsr, [r+i]
-}
-*/
-def STXFSRr : F3_1<3, 0b100101, "stx">; // stx %fsr, [r+r]
-def STXFSRi : F3_2<3, 0b100101, "stx">; // stx %fsr, [r+i]
-
-// Section A.53: Store Floating-Point into Alternate Space - p227
-// Not currently used in the Sparc backend
-
-// Section A.54: Store Integer - p229
-// Store instructions all want their rd register first
-def STBr : F3_1rd<3, 0b000101, "stb">; // stb r, [r+r]
-def STBi : F3_2rd<3, 0b000101, "stb">; // stb r, [r+i]
-def STHr : F3_1rd<3, 0b000110, "sth">; // sth r, [r+r]
-def STHi : F3_2rd<3, 0b000110, "sth">; // sth r, [r+i]
-def STWr : F3_1rd<3, 0b000100, "stw">; // stw r, [r+r]
-def STWi : F3_2rd<3, 0b000100, "stw">; // stw r, [r+i]
-def STXr : F3_1rd<3, 0b001110, "stx">; // stx r, [r+r]
-def STXi : F3_2rd<3, 0b001110, "stx">; // stx r, [r+i]
-
-// Section A.55: Store Integer into Alternate Space - p231
-// Not currently used in the Sparc backend
-
-// Section A.56: Subtract - p233
-def SUBr : F3_1<2, 0b000100, "sub">; // sub r, r, r
-def SUBi : F3_2<2, 0b000100, "sub">; // sub r, i, r
-def SUBccr : F3_1<2, 0b010100, "subcc">; // subcc r, r, r
-def SUBcci : F3_2<2, 0b010100, "subcc">; // subcc r, i, r
-def SUBCr : F3_1<2, 0b001100, "subc">; // subc r, r, r
-def SUBCi : F3_2<2, 0b001100, "subc">; // subc r, i, r
-def SUBCccr : F3_1<2, 0b011100, "subccc">; // subccc r, r, r
-def SUBCcci : F3_2<2, 0b011100, "subccc">; // subccc r, i, r
-
-// FIXME: More...?
-
-// Section A.63: Write State Register - p244
-let rd = 2 in {
- def WRCCRr : F3_1<2, 0b110000, "wr">; // wr r, r, %y/ccr/etc
- def WRCCRi : F3_2<2, 0b110000, "wr">; // wr r, i, %y/ccr/etc
-}
diff --git a/llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp b/llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp
deleted file mode 100644
index f2368d654b5..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9CodeEmitter.cpp
+++ /dev/null
@@ -1,823 +0,0 @@
-//===-- SparcV9CodeEmitter.cpp --------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// SPARC-specific backend for emitting machine code to memory.
-//
-// This module also contains the code for lazily resolving the targets
-// of call instructions, including the callback used to redirect calls
-// to functions for which the code has not yet been generated into the
-// JIT compiler.
-//
-// This file #includes SparcV9CodeEmitter.inc, which contains the code
-// for getBinaryCodeForInstr(), a method that converts a MachineInstr
-// into the corresponding binary machine code word.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Constants.h"
-#include "llvm/Function.h"
-#include "llvm/GlobalVariable.h"
-#include "llvm/PassManager.h"
-#include "llvm/CodeGen/MachineCodeEmitter.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetData.h"
-#include "Support/Debug.h"
-#include "Support/hash_set"
-#include "Support/Statistic.h"
-#include "SparcInternals.h"
-#include "SparcTargetMachine.h"
-#include "SparcRegInfo.h"
-#include "SparcV9CodeEmitter.h"
-#include "Config/alloca.h"
-
-namespace llvm {
-
-namespace {
- Statistic<> OverwrittenCalls("call-ovwr", "Number of over-written calls");
- Statistic<> UnmodifiedCalls("call-skip", "Number of unmodified calls");
- Statistic<> CallbackCalls("callback", "Number CompilationCallback() calls");
-}
-
-bool SparcTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
- MachineCodeEmitter &MCE) {
- MachineCodeEmitter *M = &MCE;
- DEBUG(M = MachineCodeEmitter::createFilePrinterEmitter(MCE));
- PM.add(new SparcV9CodeEmitter(*this, *M));
- PM.add(createSparcMachineCodeDestructionPass()); //Free stuff no longer needed
- return false;
-}
-
-namespace {
- class JITResolver {
- SparcV9CodeEmitter &SparcV9;
- MachineCodeEmitter &MCE;
-
- /// LazyCodeGenMap - Keep track of call sites for functions that are to be
- /// lazily resolved.
- ///
- std::map<uint64_t, Function*> LazyCodeGenMap;
-
- /// LazyResolverMap - Keep track of the lazy resolver created for a
- /// particular function so that we can reuse them if necessary.
- ///
- std::map<Function*, uint64_t> LazyResolverMap;
-
- public:
- enum CallType { ShortCall, FarCall };
-
- private:
- /// We need to keep track of whether we used a simple call or a far call
- /// (many instructions) in sequence. This means we need to keep track of
- /// what type of stub we generate.
- static std::map<uint64_t, CallType> LazyCallFlavor;
-
- public:
- JITResolver(SparcV9CodeEmitter &V9,
- MachineCodeEmitter &mce) : SparcV9(V9), MCE(mce) {}
- uint64_t getLazyResolver(Function *F);
- uint64_t addFunctionReference(uint64_t Address, Function *F);
- void deleteFunctionReference(uint64_t Address);
- void addCallFlavor(uint64_t Address, CallType Flavor) {
- LazyCallFlavor[Address] = Flavor;
- }
-
- // Utility functions for accessing data from static callback
- uint64_t getCurrentPCValue() {
- return MCE.getCurrentPCValue();
- }
- unsigned getBinaryCodeForInstr(MachineInstr &MI) {
- return SparcV9.getBinaryCodeForInstr(MI);
- }
-
- inline void insertFarJumpAtAddr(int64_t Value, uint64_t Addr);
- void insertJumpAtAddr(int64_t Value, uint64_t &Addr);
-
- private:
- uint64_t emitStubForFunction(Function *F);
- static void SaveRegisters(uint64_t DoubleFP[], uint64_t CC[],
- uint64_t Globals[]);
- static void RestoreRegisters(uint64_t DoubleFP[], uint64_t CC[],
- uint64_t Globals[]);
- static void CompilationCallback();
- uint64_t resolveFunctionReference(uint64_t RetAddr);
-
- };
-
- JITResolver *TheJITResolver;
- std::map<uint64_t, JITResolver::CallType> JITResolver::LazyCallFlavor;
-}
-
-/// addFunctionReference - This method is called when we need to emit the
-/// address of a function that has not yet been emitted, so we don't know the
-/// address. Instead, we emit a call to the CompilationCallback method, and
-/// keep track of where we are.
-///
-uint64_t JITResolver::addFunctionReference(uint64_t Address, Function *F) {
- LazyCodeGenMap[Address] = F;
- return (intptr_t)&JITResolver::CompilationCallback;
-}
-
-/// deleteFunctionReference - If we are emitting a far call, we already added a
-/// reference to the function, but it is now incorrect, since the address to the
-/// JIT resolver is too far away to be a simple call instruction. This is used
-/// to remove the address from the map.
-///
-void JITResolver::deleteFunctionReference(uint64_t Address) {
- std::map<uint64_t, Function*>::iterator I = LazyCodeGenMap.find(Address);
- assert(I != LazyCodeGenMap.end() && "Not in map!");
- LazyCodeGenMap.erase(I);
-}
-
-uint64_t JITResolver::resolveFunctionReference(uint64_t RetAddr) {
- std::map<uint64_t, Function*>::iterator I = LazyCodeGenMap.find(RetAddr);
- assert(I != LazyCodeGenMap.end() && "Not in map!");
- Function *F = I->second;
- LazyCodeGenMap.erase(I);
- return MCE.forceCompilationOf(F);
-}
-
-uint64_t JITResolver::getLazyResolver(Function *F) {
- std::map<Function*, uint64_t>::iterator I = LazyResolverMap.lower_bound(F);
- if (I != LazyResolverMap.end() && I->first == F) return I->second;
-
- uint64_t Stub = emitStubForFunction(F);
- LazyResolverMap.insert(I, std::make_pair(F, Stub));
- return Stub;
-}
-
-void JITResolver::insertJumpAtAddr(int64_t JumpTarget, uint64_t &Addr) {
- DEBUG(std::cerr << "Emitting a jump to 0x" << std::hex << JumpTarget << "\n");
-
- // If the target function is close enough to fit into the 19bit disp of
- // BA, we should use this version, as it's much cheaper to generate.
- int64_t BranchTarget = (JumpTarget-Addr) >> 2;
- if (BranchTarget >= (1 << 19) || BranchTarget <= -(1 << 19)) {
- TheJITResolver->insertFarJumpAtAddr(JumpTarget, Addr);
- } else {
- // ba <target>
- MachineInstr *I = BuildMI(V9::BA, 1).addSImm(BranchTarget);
- *((unsigned*)(intptr_t)Addr) = getBinaryCodeForInstr(*I);
- Addr += 4;
- delete I;
-
- // nop
- I = BuildMI(V9::NOP, 0);
- *((unsigned*)(intptr_t)Addr) = getBinaryCodeForInstr(*I);
- delete I;
- }
-}
-
-void JITResolver::insertFarJumpAtAddr(int64_t Target, uint64_t Addr) {
- static const unsigned
- o6 = SparcIntRegClass::o6, g0 = SparcIntRegClass::g0,
- g1 = SparcIntRegClass::g1, g5 = SparcIntRegClass::g5;
-
- MachineInstr* BinaryCode[] = {
- //
- // Get address to branch into %g1, using %g5 as a temporary
- //
- // sethi %uhi(Target), %g5 ;; get upper 22 bits of Target into %g5
- BuildMI(V9::SETHI, 2).addSImm(Target >> 42).addReg(g5),
- // or %g5, %ulo(Target), %g5 ;; get 10 lower bits of upper word into %g5
- BuildMI(V9::ORi, 3).addReg(g5).addSImm((Target >> 32) & 0x03ff).addReg(g5),
- // sllx %g5, 32, %g5 ;; shift those 10 bits to the upper word
- BuildMI(V9::SLLXi6, 3).addReg(g5).addSImm(32).addReg(g5),
- // sethi %hi(Target), %g1 ;; extract bits 10-31 into the dest reg
- BuildMI(V9::SETHI, 2).addSImm((Target >> 10) & 0x03fffff).addReg(g1),
- // or %g5, %g1, %g1 ;; get upper word (in %g5) into %g1
- BuildMI(V9::ORr, 3).addReg(g5).addReg(g1).addReg(g1),
- // or %g1, %lo(Target), %g1 ;; get lowest 10 bits of Target into %g1
- BuildMI(V9::ORi, 3).addReg(g1).addSImm(Target & 0x03ff).addReg(g1),
- // jmpl %g1, %g0, %g0 ;; indirect branch on %g1
- BuildMI(V9::JMPLRETr, 3).addReg(g1).addReg(g0).addReg(g0),
- // nop ;; delay slot
- BuildMI(V9::NOP, 0)
- };
-
- for (unsigned i=0, e=sizeof(BinaryCode)/sizeof(BinaryCode[0]); i!=e; ++i) {
- *((unsigned*)(intptr_t)Addr) = getBinaryCodeForInstr(*BinaryCode[i]);
- delete BinaryCode[i];
- Addr += 4;
- }
-}
-
-void JITResolver::SaveRegisters(uint64_t DoubleFP[], uint64_t CC[],
- uint64_t Globals[]) {
-#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
-
- __asm__ __volatile__ (// Save condition-code registers
- "stx %%fsr, %0;\n\t"
- "rd %%fprs, %1;\n\t"
- "rd %%ccr, %2;\n\t"
- : "=m"(CC[0]), "=r"(CC[1]), "=r"(CC[2]));
-
- __asm__ __volatile__ (// Save globals g1 and g5
- "stx %%g1, %0;\n\t"
- "stx %%g5, %0;\n\t"
- : "=m"(Globals[0]), "=m"(Globals[1]));
-
- // GCC says: `asm' only allows up to thirty parameters!
- __asm__ __volatile__ (// Save Single/Double FP registers, part 1
- "std %%f0, %0;\n\t" "std %%f2, %1;\n\t"
- "std %%f4, %2;\n\t" "std %%f6, %3;\n\t"
- "std %%f8, %4;\n\t" "std %%f10, %5;\n\t"
- "std %%f12, %6;\n\t" "std %%f14, %7;\n\t"
- "std %%f16, %8;\n\t" "std %%f18, %9;\n\t"
- "std %%f20, %10;\n\t" "std %%f22, %11;\n\t"
- "std %%f24, %12;\n\t" "std %%f26, %13;\n\t"
- "std %%f28, %14;\n\t" "std %%f30, %15;\n\t"
- : "=m"(DoubleFP[ 0]), "=m"(DoubleFP[ 1]),
- "=m"(DoubleFP[ 2]), "=m"(DoubleFP[ 3]),
- "=m"(DoubleFP[ 4]), "=m"(DoubleFP[ 5]),
- "=m"(DoubleFP[ 6]), "=m"(DoubleFP[ 7]),
- "=m"(DoubleFP[ 8]), "=m"(DoubleFP[ 9]),
- "=m"(DoubleFP[10]), "=m"(DoubleFP[11]),
- "=m"(DoubleFP[12]), "=m"(DoubleFP[13]),
- "=m"(DoubleFP[14]), "=m"(DoubleFP[15]));
-
- __asm__ __volatile__ (// Save Double FP registers, part 2
- "std %%f32, %0;\n\t" "std %%f34, %1;\n\t"
- "std %%f36, %2;\n\t" "std %%f38, %3;\n\t"
- "std %%f40, %4;\n\t" "std %%f42, %5;\n\t"
- "std %%f44, %6;\n\t" "std %%f46, %7;\n\t"
- "std %%f48, %8;\n\t" "std %%f50, %9;\n\t"
- "std %%f52, %10;\n\t" "std %%f54, %11;\n\t"
- "std %%f56, %12;\n\t" "std %%f58, %13;\n\t"
- "std %%f60, %14;\n\t" "std %%f62, %15;\n\t"
- : "=m"(DoubleFP[16]), "=m"(DoubleFP[17]),
- "=m"(DoubleFP[18]), "=m"(DoubleFP[19]),
- "=m"(DoubleFP[20]), "=m"(DoubleFP[21]),
- "=m"(DoubleFP[22]), "=m"(DoubleFP[23]),
- "=m"(DoubleFP[24]), "=m"(DoubleFP[25]),
- "=m"(DoubleFP[26]), "=m"(DoubleFP[27]),
- "=m"(DoubleFP[28]), "=m"(DoubleFP[29]),
- "=m"(DoubleFP[30]), "=m"(DoubleFP[31]));
-#endif
-}
-
-
-void JITResolver::RestoreRegisters(uint64_t DoubleFP[], uint64_t CC[],
- uint64_t Globals[])
-{
-#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
-
- __asm__ __volatile__ (// Restore condition-code registers
- "ldx %0, %%fsr;\n\t"
- "wr %1, 0, %%fprs;\n\t"
- "wr %2, 0, %%ccr;\n\t"
- :: "m"(CC[0]), "r"(CC[1]), "r"(CC[2]));
-
- __asm__ __volatile__ (// Restore globals g1 and g5
- "ldx %0, %%g1;\n\t"
- "ldx %0, %%g5;\n\t"
- :: "m"(Globals[0]), "m"(Globals[1]));
-
- // GCC says: `asm' only allows up to thirty parameters!
- __asm__ __volatile__ (// Restore Single/Double FP registers, part 1
- "ldd %0, %%f0;\n\t" "ldd %1, %%f2;\n\t"
- "ldd %2, %%f4;\n\t" "ldd %3, %%f6;\n\t"
- "ldd %4, %%f8;\n\t" "ldd %5, %%f10;\n\t"
- "ldd %6, %%f12;\n\t" "ldd %7, %%f14;\n\t"
- "ldd %8, %%f16;\n\t" "ldd %9, %%f18;\n\t"
- "ldd %10, %%f20;\n\t" "ldd %11, %%f22;\n\t"
- "ldd %12, %%f24;\n\t" "ldd %13, %%f26;\n\t"
- "ldd %14, %%f28;\n\t" "ldd %15, %%f30;\n\t"
- :: "m"(DoubleFP[0]), "m"(DoubleFP[1]),
- "m"(DoubleFP[2]), "m"(DoubleFP[3]),
- "m"(DoubleFP[4]), "m"(DoubleFP[5]),
- "m"(DoubleFP[6]), "m"(DoubleFP[7]),
- "m"(DoubleFP[8]), "m"(DoubleFP[9]),
- "m"(DoubleFP[10]), "m"(DoubleFP[11]),
- "m"(DoubleFP[12]), "m"(DoubleFP[13]),
- "m"(DoubleFP[14]), "m"(DoubleFP[15]));
-
- __asm__ __volatile__ (// Restore Double FP registers, part 2
- "ldd %0, %%f32;\n\t" "ldd %1, %%f34;\n\t"
- "ldd %2, %%f36;\n\t" "ldd %3, %%f38;\n\t"
- "ldd %4, %%f40;\n\t" "ldd %5, %%f42;\n\t"
- "ldd %6, %%f44;\n\t" "ldd %7, %%f46;\n\t"
- "ldd %8, %%f48;\n\t" "ldd %9, %%f50;\n\t"
- "ldd %10, %%f52;\n\t" "ldd %11, %%f54;\n\t"
- "ldd %12, %%f56;\n\t" "ldd %13, %%f58;\n\t"
- "ldd %14, %%f60;\n\t" "ldd %15, %%f62;\n\t"
- :: "m"(DoubleFP[16]), "m"(DoubleFP[17]),
- "m"(DoubleFP[18]), "m"(DoubleFP[19]),
- "m"(DoubleFP[20]), "m"(DoubleFP[21]),
- "m"(DoubleFP[22]), "m"(DoubleFP[23]),
- "m"(DoubleFP[24]), "m"(DoubleFP[25]),
- "m"(DoubleFP[26]), "m"(DoubleFP[27]),
- "m"(DoubleFP[28]), "m"(DoubleFP[29]),
- "m"(DoubleFP[30]), "m"(DoubleFP[31]));
-#endif
-}
-
-void JITResolver::CompilationCallback() {
- // Local space to save the registers
- uint64_t DoubleFP[32];
- uint64_t CC[3];
- uint64_t Globals[2];
-
- SaveRegisters(DoubleFP, CC, Globals);
- ++CallbackCalls;
-
- uint64_t CameFrom = (uint64_t)(intptr_t)__builtin_return_address(0);
- uint64_t CameFrom1 = (uint64_t)(intptr_t)__builtin_return_address(1);
- int64_t Target = (int64_t)TheJITResolver->resolveFunctionReference(CameFrom);
- DEBUG(std::cerr << "In callback! Addr=0x" << std::hex << CameFrom << "\n");
- register int64_t returnAddr = 0;
-#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
- __asm__ __volatile__ ("add %%i7, %%g0, %0" : "=r" (returnAddr) : );
- DEBUG(std::cerr << "Read i7 (return addr) = "
- << std::hex << returnAddr << ", value: "
- << std::hex << *(unsigned*)returnAddr << "\n");
-#endif
-
- // If we can rewrite the ORIGINAL caller, we eliminate the whole need for a
- // trampoline function stub!!
- unsigned OrigCallInst = *((unsigned*)(intptr_t)CameFrom1);
- int64_t OrigTarget = (Target-CameFrom1) >> 2;
- if ((OrigCallInst & (1 << 30)) &&
- (OrigTarget <= (1 << 30) && OrigTarget >= -(1 << 30)))
- {
- // The original call instruction was CALL <immed>, which means we can
- // overwrite it directly, since the offset will fit into 30 bits
- MachineInstr *C = BuildMI(V9::CALL, 1).addSImm(OrigTarget);
- *((unsigned*)(intptr_t)CameFrom1)=TheJITResolver->getBinaryCodeForInstr(*C);
- delete C;
- ++OverwrittenCalls;
- } else {
- ++UnmodifiedCalls;
- }
-
- // Rewrite the call target so that we don't fault every time we execute it.
- //
-
- static const unsigned o6 = SparcIntRegClass::o6;
-
- // Subtract enough to overwrite up to the 'save' instruction
- // This depends on whether we made a short call (1 instruction) or the
- // farCall (7 instructions)
- uint64_t Offset = (LazyCallFlavor[CameFrom] == ShortCall) ? 4 : 28;
- uint64_t CodeBegin = CameFrom - Offset;
-
- // FIXME FIXME FIXME FIXME: __builtin_frame_address doesn't work if frame
- // pointer elimination has been performed. Having a variable sized alloca
- // disables frame pointer elimination currently, even if it's dead. This is
- // a gross hack.
- alloca(42+Offset);
- // FIXME FIXME FIXME FIXME
-
- // Make sure that what we're about to overwrite is indeed "save"
- MachineInstr *SV =BuildMI(V9::SAVEi, 3).addReg(o6).addSImm(-192).addReg(o6);
- unsigned SaveInst = TheJITResolver->getBinaryCodeForInstr(*SV);
- delete SV;
- unsigned CodeInMem = *(unsigned*)(intptr_t)CodeBegin;
- if (CodeInMem != SaveInst) {
- std::cerr << "About to overwrite smthg not a save instr!";
- abort();
- }
- // Overwrite it
- TheJITResolver->insertJumpAtAddr(Target, CodeBegin);
-
- // Flush the I-Cache: FLUSH clears out a doubleword at a given address
- // Self-modifying code MUST clear out the I-Cache to be portable
-#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
- for (int i = -Offset, e = 32-((int64_t)Offset); i < e; i += 8)
- __asm__ __volatile__ ("flush %%i7 + %0" : : "r" (i));
-#endif
-
- // Change the return address to re-execute the restore, then the jump.
- DEBUG(std::cerr << "Callback returning to: 0x"
- << std::hex << (CameFrom-Offset-12) << "\n");
-#if defined(sparc) || defined(__sparc__) || defined(__sparcv9)
- __asm__ __volatile__ ("sub %%i7, %0, %%i7" : : "r" (Offset+12));
-#endif
-
- RestoreRegisters(DoubleFP, CC, Globals);
-}
-
-/// emitStubForFunction - This method is used by the JIT when it needs to emit
-/// the address of a function for a function whose code has not yet been
-/// generated. In order to do this, it generates a stub which jumps to the lazy
-/// function compiler, which will eventually get fixed to call the function
-/// directly.
-///
-uint64_t JITResolver::emitStubForFunction(Function *F) {
- MCE.startFunctionStub(*F, 44);
-
- DEBUG(std::cerr << "Emitting stub at addr: 0x"
- << std::hex << MCE.getCurrentPCValue() << "\n");
-
- unsigned o6 = SparcIntRegClass::o6, g0 = SparcIntRegClass::g0;
-
- // restore %g0, 0, %g0
- MachineInstr *R = BuildMI(V9::RESTOREi, 3).addMReg(g0).addSImm(0)
- .addMReg(g0, MachineOperand::Def);
- SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*R));
- delete R;
-
- // save %sp, -192, %sp
- MachineInstr *SV = BuildMI(V9::SAVEi, 3).addReg(o6).addSImm(-192).addReg(o6);
- SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*SV));
- delete SV;
-
- int64_t CurrPC = MCE.getCurrentPCValue();
- int64_t Addr = (int64_t)addFunctionReference(CurrPC, F);
- int64_t CallTarget = (Addr-CurrPC) >> 2;
- if (CallTarget >= (1 << 29) || CallTarget <= -(1 << 29)) {
- // Since this is a far call, the actual address of the call is shifted
- // by the number of instructions it takes to calculate the exact address
- deleteFunctionReference(CurrPC);
- SparcV9.emitFarCall(Addr, F);
- } else {
- // call CallTarget ;; invoke the callback
- MachineInstr *Call = BuildMI(V9::CALL, 1).addSImm(CallTarget);
- SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Call));
- delete Call;
-
- // nop ;; call delay slot
- MachineInstr *Nop = BuildMI(V9::NOP, 0);
- SparcV9.emitWord(SparcV9.getBinaryCodeForInstr(*Nop));
- delete Nop;
-
- addCallFlavor(CurrPC, ShortCall);
- }
-
- SparcV9.emitWord(0xDEADBEEF); // marker so that we know it's really a stub
- return (intptr_t)MCE.finishFunctionStub(*F)+4; /* 1 instr past the restore */
-}
-
-SparcV9CodeEmitter::SparcV9CodeEmitter(TargetMachine &tm,
- MachineCodeEmitter &M): TM(tm), MCE(M)
-{
- TheJITResolver = new JITResolver(*this, M);
-}
-
-SparcV9CodeEmitter::~SparcV9CodeEmitter() {
- delete TheJITResolver;
-}
-
-void SparcV9CodeEmitter::emitWord(unsigned Val) {
- // Output the constant in big endian byte order...
- unsigned byteVal;
- for (int i = 3; i >= 0; --i) {
- byteVal = Val >> 8*i;
- MCE.emitByte(byteVal & 255);
- }
-}
-
-unsigned
-SparcV9CodeEmitter::getRealRegNum(unsigned fakeReg,
- MachineInstr &MI) {
- const TargetRegInfo &RI = TM.getRegInfo();
- unsigned regClass, regType = RI.getRegType(fakeReg);
- // At least map fakeReg into its class
- fakeReg = RI.getClassRegNum(fakeReg, regClass);
-
- switch (regClass) {
- case SparcRegInfo::IntRegClassID: {
- // Sparc manual, p31
- static const unsigned IntRegMap[] = {
- // "o0", "o1", "o2", "o3", "o4", "o5", "o7",
- 8, 9, 10, 11, 12, 13, 15,
- // "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
- 16, 17, 18, 19, 20, 21, 22, 23,
- // "i0", "i1", "i2", "i3", "i4", "i5", "i6", "i7",
- 24, 25, 26, 27, 28, 29, 30, 31,
- // "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
- 0, 1, 2, 3, 4, 5, 6, 7,
- // "o6"
- 14
- };
-
- return IntRegMap[fakeReg];
- break;
- }
- case SparcRegInfo::FloatRegClassID: {
- DEBUG(std::cerr << "FP reg: " << fakeReg << "\n");
- if (regType == SparcRegInfo::FPSingleRegType) {
- // only numbered 0-31, hence can already fit into 5 bits (and 6)
- DEBUG(std::cerr << "FP single reg, returning: " << fakeReg << "\n");
- } else if (regType == SparcRegInfo::FPDoubleRegType) {
- // FIXME: This assumes that we only have 5-bit register fields!
- // From Sparc Manual, page 40.
- // The bit layout becomes: b[4], b[3], b[2], b[1], b[5]
- fakeReg |= (fakeReg >> 5) & 1;
- fakeReg &= 0x1f;
- DEBUG(std::cerr << "FP double reg, returning: " << fakeReg << "\n");
- }
- return fakeReg;
- }
- case SparcRegInfo::IntCCRegClassID: {
- /* xcc, icc, ccr */
- static const unsigned IntCCReg[] = { 6, 4, 2 };
-
- assert(fakeReg < sizeof(IntCCReg)/sizeof(IntCCReg[0])
- && "CC register out of bounds for IntCCReg map");
- DEBUG(std::cerr << "IntCC reg: " << IntCCReg[fakeReg] << "\n");
- return IntCCReg[fakeReg];
- }
- case SparcRegInfo::FloatCCRegClassID: {
- /* These are laid out %fcc0 - %fcc3 => 0 - 3, so are correct */
- DEBUG(std::cerr << "FP CC reg: " << fakeReg << "\n");
- return fakeReg;
- }
- default:
- assert(0 && "Invalid unified register number in getRegType");
- return fakeReg;
- }
-}
-
-
-// WARNING: if the call used the delay slot to do meaningful work, that's not
-// being accounted for, and the behavior will be incorrect!!
-inline void SparcV9CodeEmitter::emitFarCall(uint64_t Target, Function *F) {
- static const unsigned o6 = SparcIntRegClass::o6,
- o7 = SparcIntRegClass::o7, g0 = SparcIntRegClass::g0,
- g1 = SparcIntRegClass::g1, g5 = SparcIntRegClass::g5;
-
- MachineInstr* BinaryCode[] = {
- //
- // Get address to branch into %g1, using %g5 as a temporary
- //
- // sethi %uhi(Target), %g5 ;; get upper 22 bits of Target into %g5
- BuildMI(V9::SETHI, 2).addSImm(Target >> 42).addReg(g5),
- // or %g5, %ulo(Target), %g5 ;; get 10 lower bits of upper word into %1
- BuildMI(V9::ORi, 3).addReg(g5).addSImm((Target >> 32) & 0x03ff).addReg(g5),
- // sllx %g5, 32, %g5 ;; shift those 10 bits to the upper word
- BuildMI(V9::SLLXi6, 3).addReg(g5).addSImm(32).addReg(g5),
- // sethi %hi(Target), %g1 ;; extract bits 10-31 into the dest reg
- BuildMI(V9::SETHI, 2).addSImm((Target >> 10) & 0x03fffff).addReg(g1),
- // or %g5, %g1, %g1 ;; get upper word (in %g5) into %g1
- BuildMI(V9::ORr, 3).addReg(g5).addReg(g1).addReg(g1),
- // or %g1, %lo(Target), %g1 ;; get lowest 10 bits of Target into %g1
- BuildMI(V9::ORi, 3).addReg(g1).addSImm(Target & 0x03ff).addReg(g1),
- // jmpl %g1, %g0, %o7 ;; indirect call on %g1
- BuildMI(V9::JMPLRETr, 3).addReg(g1).addReg(g0).addReg(o7),
- // nop ;; delay slot
- BuildMI(V9::NOP, 0)
- };
-
- for (unsigned i=0, e=sizeof(BinaryCode)/sizeof(BinaryCode[0]); i!=e; ++i) {
- // This is where we save the return address in the LazyResolverMap!!
- if (i == 6 && F != 0) { // Do this right before the JMPL
- uint64_t CurrPC = MCE.getCurrentPCValue();
- TheJITResolver->addFunctionReference(CurrPC, F);
- // Remember that this is a far call, to subtract appropriate offset later
- TheJITResolver->addCallFlavor(CurrPC, JITResolver::FarCall);
- }
-
- emitWord(getBinaryCodeForInstr(*BinaryCode[i]));
- delete BinaryCode[i];
- }
-}
-
-void SparcJITInfo::replaceMachineCodeForFunction (void *Old, void *New) {
- assert (TheJITResolver &&
- "Can only call replaceMachineCodeForFunction from within JIT");
- uint64_t Target = (uint64_t)(intptr_t)New;
- uint64_t CodeBegin = (uint64_t)(intptr_t)Old;
- TheJITResolver->insertJumpAtAddr(Target, CodeBegin);
-}
-
-int64_t SparcV9CodeEmitter::getMachineOpValue(MachineInstr &MI,
- MachineOperand &MO) {
- int64_t rv = 0; // Return value; defaults to 0 for unhandled cases
- // or things that get fixed up later by the JIT.
- if (MO.isPCRelativeDisp()) {
- DEBUG(std::cerr << "PCRelativeDisp: ");
- Value *V = MO.getVRegValue();
- if (BasicBlock *BB = dyn_cast<BasicBlock>(V)) {
- DEBUG(std::cerr << "Saving reference to BB (VReg)\n");
- unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
- BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI)));
- } else if (const Constant *C = dyn_cast<Constant>(V)) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(C)) {
- rv = CI->getRawValue() - MCE.getCurrentPCValue();
- } else {
- std::cerr << "Cannot have non-integral const in instruction: "
- << *C;
- abort();
- }
- } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
- // same as MO.isGlobalAddress()
- DEBUG(std::cerr << "GlobalValue: ");
- // external function calls, etc.?
- if (Function *F = dyn_cast<Function>(GV)) {
- DEBUG(std::cerr << "Function: ");
- // NOTE: This results in stubs being generated even for
- // external, native functions, which is not optimal. See PR103.
- rv = (int64_t)MCE.getGlobalValueAddress(F);
- if (rv == 0) {
- DEBUG(std::cerr << "not yet generated\n");
- // Function has not yet been code generated!
- TheJITResolver->addFunctionReference(MCE.getCurrentPCValue(), F);
- // Delayed resolution...
- rv = TheJITResolver->getLazyResolver(F);
- } else {
- DEBUG(std::cerr << "already generated: 0x" << std::hex << rv << "\n");
- }
- } else {
- rv = (int64_t)MCE.getGlobalValueAddress(GV);
- DEBUG(std::cerr << "Global addr: 0x" << std::hex << rv << "\n");
- }
- // The real target of the call is Addr = PC + (rv * 4)
- // So undo that: give the instruction (Addr - PC) / 4
- if (MI.getOpcode() == V9::CALL) {
- int64_t CurrPC = MCE.getCurrentPCValue();
- DEBUG(std::cerr << "rv addr: 0x" << std::hex << rv << "\n"
- << "curr PC: 0x" << std::hex << CurrPC << "\n");
- int64_t CallInstTarget = (rv - CurrPC) >> 2;
- if (CallInstTarget >= (1<<29) || CallInstTarget <= -(1<<29)) {
- DEBUG(std::cerr << "Making far call!\n");
- // address is out of bounds for the 30-bit call,
- // make an indirect jump-and-link
- emitFarCall(rv);
- // this invalidates the instruction so that the call with an incorrect
- // address will not be emitted
- rv = 0;
- } else {
- // The call fits into 30 bits, so just return the corrected address
- rv = CallInstTarget;
- }
- DEBUG(std::cerr << "returning addr: 0x" << rv << "\n");
- }
- } else {
- std::cerr << "ERROR: PC relative disp unhandled:" << MO << "\n";
- abort();
- }
- } else if (MO.isRegister() || MO.getType() == MachineOperand::MO_CCRegister)
- {
- // This is necessary because the Sparc backend doesn't actually lay out
- // registers in the real fashion -- it skips those that it chooses not to
- // allocate, i.e. those that are the FP, SP, etc.
- unsigned fakeReg = MO.getReg();
- unsigned realRegByClass = getRealRegNum(fakeReg, MI);
- DEBUG(std::cerr << MO << ": Reg[" << std::dec << fakeReg << "] => "
- << realRegByClass << " (LLC: "
- << TM.getRegInfo().getUnifiedRegName(fakeReg) << ")\n");
- rv = realRegByClass;
- } else if (MO.isImmediate()) {
- rv = MO.getImmedValue();
- DEBUG(std::cerr << "immed: " << rv << "\n");
- } else if (MO.isGlobalAddress()) {
- DEBUG(std::cerr << "GlobalAddress: not PC-relative\n");
- rv = (int64_t)
- (intptr_t)getGlobalAddress(cast<GlobalValue>(MO.getVRegValue()),
- MI, MO.isPCRelative());
- } else if (MO.isMachineBasicBlock()) {
- // Duplicate code of the above case for VirtualRegister, BasicBlock...
- // It should really hit this case, but Sparc backend uses VRegs instead
- DEBUG(std::cerr << "Saving reference to MBB\n");
- const BasicBlock *BB = MO.getMachineBasicBlock()->getBasicBlock();
- unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue();
- BBRefs.push_back(std::make_pair(BB, std::make_pair(CurrPC, &MI)));
- } else if (MO.isExternalSymbol()) {
- // Sparc backend doesn't generate this (yet...)
- std::cerr << "ERROR: External symbol unhandled: " << MO << "\n";
- abort();
- } else if (MO.isFrameIndex()) {
- // Sparc backend doesn't generate this (yet...)
- int FrameIndex = MO.getFrameIndex();
- std::cerr << "ERROR: Frame index unhandled.\n";
- abort();
- } else if (MO.isConstantPoolIndex()) {
- unsigned Index = MO.getConstantPoolIndex();
- rv = MCE.getConstantPoolEntryAddress(Index);
- } else {
- std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n";
- abort();
- }
-
- // Finally, deal with the various bitfield-extracting functions that
- // are used in SPARC assembly. (Some of these make no sense in combination
- // with some of the above; we'll trust that the instruction selector
- // will not produce nonsense, and not check for valid combinations here.)
- if (MO.isLoBits32()) { // %lo(val) == %lo() in Sparc ABI doc
- return rv & 0x03ff;
- } else if (MO.isHiBits32()) { // %lm(val) == %hi() in Sparc ABI doc
- return (rv >> 10) & 0x03fffff;
- } else if (MO.isLoBits64()) { // %hm(val) == %ulo() in Sparc ABI doc
- return (rv >> 32) & 0x03ff;
- } else if (MO.isHiBits64()) { // %hh(val) == %uhi() in Sparc ABI doc
- return rv >> 42;
- } else { // (unadorned) val
- return rv;
- }
-}
-
-unsigned SparcV9CodeEmitter::getValueBit(int64_t Val, unsigned bit) {
- Val >>= bit;
- return (Val & 1);
-}
-
-bool SparcV9CodeEmitter::runOnMachineFunction(MachineFunction &MF) {
- MCE.startFunction(MF);
- DEBUG(std::cerr << "Starting function " << MF.getFunction()->getName()
- << ", address: " << "0x" << std::hex
- << (long)MCE.getCurrentPCValue() << "\n");
-
- MCE.emitConstantPool(MF.getConstantPool());
- for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
- emitBasicBlock(*I);
- MCE.finishFunction(MF);
-
- DEBUG(std::cerr << "Finishing fn " << MF.getFunction()->getName() << "\n");
-
- // Resolve branches to BasicBlocks for the entire function
- for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
- long Location = BBLocations[BBRefs[i].first];
- unsigned *Ref = BBRefs[i].second.first;
- MachineInstr *MI = BBRefs[i].second.second;
- DEBUG(std::cerr << "Fixup @ " << std::hex << Ref << " to 0x" << Location
- << " in instr: " << std::dec << *MI);
- for (unsigned ii = 0, ee = MI->getNumOperands(); ii != ee; ++ii) {
- MachineOperand &op = MI->getOperand(ii);
- if (op.isPCRelativeDisp()) {
- // the instruction's branch target is made such that it branches to
- // PC + (branchTarget * 4), so undo that arithmetic here:
- // Location is the target of the branch
- // Ref is the location of the instruction, and hence the PC
- int64_t branchTarget = (Location - (long)Ref) >> 2;
- // Save the flags.
- bool loBits32=false, hiBits32=false, loBits64=false, hiBits64=false;
- if (op.isLoBits32()) { loBits32=true; }
- if (op.isHiBits32()) { hiBits32=true; }
- if (op.isLoBits64()) { loBits64=true; }
- if (op.isHiBits64()) { hiBits64=true; }
- MI->SetMachineOperandConst(ii, MachineOperand::MO_SignExtendedImmed,
- branchTarget);
- if (loBits32) { MI->setOperandLo32(ii); }
- else if (hiBits32) { MI->setOperandHi32(ii); }
- else if (loBits64) { MI->setOperandLo64(ii); }
- else if (hiBits64) { MI->setOperandHi64(ii); }
- DEBUG(std::cerr << "Rewrote BB ref: ");
- unsigned fixedInstr = SparcV9CodeEmitter::getBinaryCodeForInstr(*MI);
- *Ref = fixedInstr;
- break;
- }
- }
- }
- BBRefs.clear();
- BBLocations.clear();
-
- return false;
-}
-
-void SparcV9CodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) {
- currBB = MBB.getBasicBlock();
- BBLocations[currBB] = MCE.getCurrentPCValue();
- for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){
- unsigned binCode = getBinaryCodeForInstr(*I);
- if (binCode == (1 << 30)) {
- // this is an invalid call: the addr is out of bounds. that means a code
- // sequence has already been emitted, and this is a no-op
- DEBUG(std::cerr << "Call supressed: already emitted far call.\n");
- } else {
- emitWord(binCode);
- }
- }
-}
-
-void* SparcV9CodeEmitter::getGlobalAddress(GlobalValue *V, MachineInstr &MI,
- bool isPCRelative)
-{
- if (isPCRelative) { // must be a call, this is a major hack!
- // Try looking up the function to see if it is already compiled!
- if (void *Addr = (void*)(intptr_t)MCE.getGlobalValueAddress(V)) {
- intptr_t CurByte = MCE.getCurrentPCValue();
- // The real target of the call is Addr = PC + (target * 4)
- // CurByte is the PC, Addr we just received
- return (void*) (((long)Addr - (long)CurByte) >> 2);
- } else {
- if (Function *F = dyn_cast<Function>(V)) {
- // Function has not yet been code generated!
- TheJITResolver->addFunctionReference(MCE.getCurrentPCValue(),
- cast<Function>(V));
- // Delayed resolution...
- return
- (void*)(intptr_t)TheJITResolver->getLazyResolver(cast<Function>(V));
- } else {
- std::cerr << "Unhandled global: " << *V << "\n";
- abort();
- }
- }
- } else {
- return (void*)(intptr_t)MCE.getGlobalValueAddress(V);
- }
-}
-
-#include "SparcV9CodeEmitter.inc"
-
-} // End llvm namespace
-
diff --git a/llvm/lib/Target/Sparc/SparcV9CodeEmitter.h b/llvm/lib/Target/Sparc/SparcV9CodeEmitter.h
deleted file mode 100644
index d21345ec041..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9CodeEmitter.h
+++ /dev/null
@@ -1,88 +0,0 @@
-//===-- SparcV9CodeEmitter.h ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// TODO: Need a description here.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARCV9CODEEMITTER_H
-#define SPARCV9CODEEMITTER_H
-
-#include "llvm/BasicBlock.h"
-#include "llvm/CodeGen/MachineCodeEmitter.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/Target/TargetMachine.h"
-
-namespace llvm {
-
-class GlobalValue;
-class MachineInstr;
-class MachineOperand;
-
-class SparcV9CodeEmitter : public MachineFunctionPass {
- TargetMachine &TM;
- MachineCodeEmitter &MCE;
- const BasicBlock *currBB;
-
- // Tracks which instruction references which BasicBlock
- std::vector<std::pair<const BasicBlock*,
- std::pair<unsigned*,MachineInstr*> > > BBRefs;
- // Tracks where each BasicBlock starts
- std::map<const BasicBlock*, long> BBLocations;
-
-public:
- SparcV9CodeEmitter(TargetMachine &T, MachineCodeEmitter &M);
- ~SparcV9CodeEmitter();
-
- /// runOnMachineFunction - emits the given machine function to memory.
- ///
- bool runOnMachineFunction(MachineFunction &F);
-
- /// emitWord - writes out the given 32-bit value to memory at the current PC.
- ///
- void emitWord(unsigned Val);
-
- /// getBinaryCodeForInstr - This function, generated by the
- /// CodeEmitterGenerator using TableGen, produces the binary encoding for
- /// machine instructions.
- ///
- unsigned getBinaryCodeForInstr(MachineInstr &MI);
-
- /// emitFarCall - produces a code sequence to make a call to a destination
- /// that does not fit in the 30 bits that a call instruction allows.
- /// If the function F is non-null, this also saves the return address in
- /// the LazyResolver map of the JITResolver.
- void emitFarCall(uint64_t Addr, Function *F = 0);
-
-private:
- /// getMachineOpValue -
- ///
- int64_t getMachineOpValue(MachineInstr &MI, MachineOperand &MO);
-
- /// emitBasicBlock -
- ///
- void emitBasicBlock(MachineBasicBlock &MBB);
-
- /// getValueBit -
- ///
- unsigned getValueBit(int64_t Val, unsigned bit);
-
- /// getGlobalAddress -
- ///
- void* getGlobalAddress(GlobalValue *V, MachineInstr &MI,
- bool isPCRelative);
- /// emitFarCall -
- ///
- unsigned getRealRegNum(unsigned fakeReg, MachineInstr &MI);
-
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/SparcV9FrameInfo.cpp b/llvm/lib/Target/Sparc/SparcV9FrameInfo.cpp
deleted file mode 100644
index d283e942bb4..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9FrameInfo.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-//===-- Sparc.cpp - General implementation file for the Sparc Target ------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Interface to stack frame layout info for the UltraSPARC. Starting offsets
-// for each area of the stack frame are aligned at a multiple of
-// getStackFrameSizeAlignment().
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/Target/TargetFrameInfo.h"
-#include "SparcFrameInfo.h"
-
-using namespace llvm;
-
-int
-SparcFrameInfo::getFirstAutomaticVarOffset(MachineFunction&, bool& pos) const {
- pos = false; // static stack area grows downwards
- return StaticAreaOffsetFromFP;
-}
-
-int
-SparcFrameInfo::getRegSpillAreaOffset(MachineFunction& mcInfo, bool& pos) const
-{
- // ensure no more auto vars are added
- mcInfo.getInfo()->freezeAutomaticVarsArea();
-
- pos = false; // static stack area grows downwards
- unsigned autoVarsSize = mcInfo.getInfo()->getAutomaticVarsSize();
- return StaticAreaOffsetFromFP - autoVarsSize;
-}
-
-int SparcFrameInfo::getTmpAreaOffset(MachineFunction& mcInfo, bool& pos) const {
- MachineFunctionInfo *MFI = mcInfo.getInfo();
- MFI->freezeAutomaticVarsArea(); // ensure no more auto vars are added
- MFI->freezeSpillsArea(); // ensure no more spill slots are added
-
- pos = false; // static stack area grows downwards
- unsigned autoVarsSize = MFI->getAutomaticVarsSize();
- unsigned spillAreaSize = MFI->getRegSpillsSize();
- int offset = autoVarsSize + spillAreaSize;
- return StaticAreaOffsetFromFP - offset;
-}
-
-int
-SparcFrameInfo::getDynamicAreaOffset(MachineFunction& mcInfo, bool& pos) const {
- // Dynamic stack area grows downwards starting at top of opt-args area.
- // The opt-args, required-args, and register-save areas are empty except
- // during calls and traps, so they are shifted downwards on each
- // dynamic-size alloca.
- pos = false;
- unsigned optArgsSize = mcInfo.getInfo()->getMaxOptionalArgsSize();
- if (int extra = optArgsSize % getStackFrameSizeAlignment())
- optArgsSize += (getStackFrameSizeAlignment() - extra);
- int offset = optArgsSize + FirstOptionalOutgoingArgOffsetFromSP;
- assert((offset - OFFSET) % getStackFrameSizeAlignment() == 0);
- return offset;
-}
diff --git a/llvm/lib/Target/Sparc/SparcV9FrameInfo.h b/llvm/lib/Target/Sparc/SparcV9FrameInfo.h
deleted file mode 100644
index 903859675ce..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9FrameInfo.h
+++ /dev/null
@@ -1,174 +0,0 @@
-//===-- SparcFrameInfo.h - Define TargetFrameInfo for Sparc -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Interface to stack frame layout info for the UltraSPARC.
-// Starting offsets for each area of the stack frame are aligned at
-// a multiple of getStackFrameSizeAlignment().
-//
-//----------------------------------------------------------------------------
-
-#ifndef SPARC_FRAMEINFO_H
-#define SPARC_FRAMEINFO_H
-
-#include "llvm/Target/TargetFrameInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetRegInfo.h"
-
-namespace llvm {
-
-class SparcFrameInfo: public TargetFrameInfo {
- const TargetMachine &target;
-public:
- SparcFrameInfo(const TargetMachine &TM)
- : TargetFrameInfo(StackGrowsDown, StackFrameSizeAlignment, 0), target(TM) {}
-
-public:
- // These methods provide constant parameters of the frame layout.
- //
- int getStackFrameSizeAlignment() const { return StackFrameSizeAlignment;}
- int getMinStackFrameSize() const { return MinStackFrameSize; }
- int getNumFixedOutgoingArgs() const { return NumFixedOutgoingArgs; }
- int getSizeOfEachArgOnStack() const { return SizeOfEachArgOnStack; }
- bool argsOnStackHaveFixedSize() const { return true; }
-
- // This method adjusts a stack offset to meet alignment rules of target.
- // The fixed OFFSET (0x7ff) must be subtracted and the result aligned.
- virtual int adjustAlignment(int unalignedOffset, bool growUp,
- unsigned int align) const {
- return unalignedOffset + (growUp? +1:-1)*((unalignedOffset-OFFSET) % align);
- }
-
- // These methods compute offsets using the frame contents for a
- // particular function. The frame contents are obtained from the
- // MachineCodeInfoForMethod object for the given function.
- //
- int getFirstIncomingArgOffset(MachineFunction& mcInfo, bool& growUp) const {
- growUp = true; // arguments area grows upwards
- return FirstIncomingArgOffsetFromFP;
- }
- int getFirstOutgoingArgOffset(MachineFunction& mcInfo, bool& growUp) const {
- growUp = true; // arguments area grows upwards
- return FirstOutgoingArgOffsetFromSP;
- }
- int getFirstOptionalOutgoingArgOffset(MachineFunction& mcInfo,
- bool& growUp) const {
- growUp = true; // arguments area grows upwards
- return FirstOptionalOutgoingArgOffsetFromSP;
- }
-
- int getFirstAutomaticVarOffset(MachineFunction& mcInfo, bool& growUp) const;
- int getRegSpillAreaOffset(MachineFunction& mcInfo, bool& growUp) const;
- int getTmpAreaOffset(MachineFunction& mcInfo, bool& growUp) const;
- int getDynamicAreaOffset(MachineFunction& mcInfo, bool& growUp) const;
-
- //
- // These methods specify the base register used for each stack area
- // (generally FP or SP)
- //
- virtual int getIncomingArgBaseRegNum() const {
- return (int) target.getRegInfo().getFramePointer();
- }
- virtual int getOutgoingArgBaseRegNum() const {
- return (int) target.getRegInfo().getStackPointer();
- }
- virtual int getOptionalOutgoingArgBaseRegNum() const {
- return (int) target.getRegInfo().getStackPointer();
- }
- virtual int getAutomaticVarBaseRegNum() const {
- return (int) target.getRegInfo().getFramePointer();
- }
- virtual int getRegSpillAreaBaseRegNum() const {
- return (int) target.getRegInfo().getFramePointer();
- }
- virtual int getDynamicAreaBaseRegNum() const {
- return (int) target.getRegInfo().getStackPointer();
- }
-
- virtual int getIncomingArgOffset(MachineFunction& mcInfo,
- unsigned argNum) const {
- assert(argsOnStackHaveFixedSize());
-
- unsigned relativeOffset = argNum * getSizeOfEachArgOnStack();
- bool growUp; // do args grow up or down
- int firstArg = getFirstIncomingArgOffset(mcInfo, growUp);
- return growUp ? firstArg + relativeOffset : firstArg - relativeOffset;
- }
-
- virtual int getOutgoingArgOffset(MachineFunction& mcInfo,
- unsigned argNum) const {
- assert(argsOnStackHaveFixedSize());
- //assert(((int) argNum - this->getNumFixedOutgoingArgs())
- // <= (int) mcInfo.getInfo()->getMaxOptionalNumArgs());
-
- unsigned relativeOffset = argNum * getSizeOfEachArgOnStack();
- bool growUp; // do args grow up or down
- int firstArg = getFirstOutgoingArgOffset(mcInfo, growUp);
- return growUp ? firstArg + relativeOffset : firstArg - relativeOffset;
- }
-
-private:
- /*----------------------------------------------------------------------
- This diagram shows the stack frame layout used by llc on Sparc V9.
- Note that only the location of automatic variables, spill area,
- temporary storage, and dynamically allocated stack area are chosen
- by us. The rest conform to the Sparc V9 ABI.
- All stack addresses are offset by OFFSET = 0x7ff (2047).
-
- Alignment assumptions and other invariants:
- (1) %sp+OFFSET and %fp+OFFSET are always aligned on 16-byte boundary
- (2) Variables in automatic, spill, temporary, or dynamic regions
- are aligned according to their size as in all memory accesses.
- (3) Everything below the dynamically allocated stack area is only used
- during a call to another function, so it is never needed when
- the current function is active. This is why space can be allocated
- dynamically by incrementing %sp any time within the function.
-
- STACK FRAME LAYOUT:
-
- ...
- %fp+OFFSET+176 Optional extra incoming arguments# 1..N
- %fp+OFFSET+168 Incoming argument #6
- ... ...
- %fp+OFFSET+128 Incoming argument #1
- ... ...
- ---%fp+OFFSET-0--------Bottom of caller's stack frame--------------------
- %fp+OFFSET-8 Automatic variables <-- ****TOP OF STACK FRAME****
- Spill area
- Temporary storage
- ...
-
- %sp+OFFSET+176+8N Bottom of dynamically allocated stack area
- %sp+OFFSET+168+8N Optional extra outgoing argument# N
- ... ...
- %sp+OFFSET+176 Optional extra outgoing argument# 1
- %sp+OFFSET+168 Outgoing argument #6
- ... ...
- %sp+OFFSET+128 Outgoing argument #1
- %sp+OFFSET+120 Save area for %i7
- ... ...
- %sp+OFFSET+0 Save area for %l0 <-- ****BOTTOM OF STACK FRAME****
-
- *----------------------------------------------------------------------*/
-
- // All stack addresses must be offset by 0x7ff (2047) on Sparc V9.
- static const int OFFSET = (int) 0x7ff;
- static const int StackFrameSizeAlignment = 16;
- static const int MinStackFrameSize = 176;
- static const int NumFixedOutgoingArgs = 6;
- static const int SizeOfEachArgOnStack = 8;
- static const int FirstIncomingArgOffsetFromFP = 128 + OFFSET;
- static const int FirstOptionalIncomingArgOffsetFromFP = 176 + OFFSET;
- static const int StaticAreaOffsetFromFP = 0 + OFFSET;
- static const int FirstOutgoingArgOffsetFromSP = 128 + OFFSET;
- static const int FirstOptionalOutgoingArgOffsetFromSP = 176 + OFFSET;
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/SparcV9InstrInfo.h b/llvm/lib/Target/Sparc/SparcV9InstrInfo.h
deleted file mode 100644
index 0be2544c607..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9InstrInfo.h
+++ /dev/null
@@ -1,201 +0,0 @@
-//===-- SparcInstrInfo.h - Define TargetInstrInfo for Sparc -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class contains information about individual instructions.
-// Most information is stored in the SparcMachineInstrDesc array above.
-// Other information is computed on demand, and most such functions
-// default to member functions in base class TargetInstrInfo.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARC_INSTRINFO_H
-#define SPARC_INSTRINFO_H
-
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "SparcInternals.h"
-
-namespace llvm {
-
-struct SparcInstrInfo : public TargetInstrInfo {
- SparcInstrInfo();
-
- // All immediate constants are in position 1 except the
- // store instructions and SETxx.
- //
- virtual int getImmedConstantPos(MachineOpCode opCode) const {
- bool ignore;
- if (this->maxImmedConstant(opCode, ignore) != 0) {
- // 1st store opcode
- assert(! this->isStore((MachineOpCode) V9::STBr - 1));
- // last store opcode
- assert(! this->isStore((MachineOpCode) V9::STXFSRi + 1));
-
- if (opCode == V9::SETSW || opCode == V9::SETUW ||
- opCode == V9::SETX || opCode == V9::SETHI)
- return 0;
- if (opCode >= V9::STBr && opCode <= V9::STXFSRi)
- return 2;
- return 1;
- }
- else
- return -1;
- }
-
- /// createNOPinstr - returns the target's implementation of NOP, which is
- /// usually a pseudo-instruction, implemented by a degenerate version of
- /// another instruction, e.g. X86: xchg ax, ax; SparcV9: sethi 0, g0
- ///
- MachineInstr* createNOPinstr() const {
- return BuildMI(V9::SETHI, 2).addZImm(0).addReg(SparcIntRegClass::g0);
- }
-
- /// isNOPinstr - not having a special NOP opcode, we need to know if a given
- /// instruction is interpreted as an `official' NOP instr, i.e., there may be
- /// more than one way to `do nothing' but only one canonical way to slack off.
- ///
- bool isNOPinstr(const MachineInstr &MI) const {
- // Make sure the instruction is EXACTLY `sethi g0, 0'
- if (MI.getOpcode() == V9::SETHI && MI.getNumOperands() == 2) {
- const MachineOperand &op0 = MI.getOperand(0), &op1 = MI.getOperand(1);
- if (op0.isImmediate() && op0.getImmedValue() == 0 &&
- op1.getType() == MachineOperand::MO_MachineRegister &&
- op1.getMachineRegNum() == SparcIntRegClass::g0)
- {
- return true;
- }
- }
- return false;
- }
-
- virtual bool hasResultInterlock(MachineOpCode opCode) const
- {
- // All UltraSPARC instructions have interlocks (note that delay slots
- // are not considered here).
- // However, instructions that use the result of an FCMP produce a
- // 9-cycle stall if they are issued less than 3 cycles after the FCMP.
- // Force the compiler to insert a software interlock (i.e., gap of
- // 2 other groups, including NOPs if necessary).
- return (opCode == V9::FCMPS || opCode == V9::FCMPD || opCode == V9::FCMPQ);
- }
-
- //-------------------------------------------------------------------------
- // Queries about representation of LLVM quantities (e.g., constants)
- //-------------------------------------------------------------------------
-
- virtual bool ConstantMayNotFitInImmedField(const Constant* CV,
- const Instruction* I) const;
-
- //-------------------------------------------------------------------------
- // Code generation support for creating individual machine instructions
- //-------------------------------------------------------------------------
-
- // Get certain common op codes for the current target. This and all the
- // Create* methods below should be moved to a machine code generation class
- //
- virtual MachineOpCode getNOPOpCode() const { return V9::NOP; }
-
- // Get the value of an integral constant in the form that must
- // be put into the machine register. The specified constant is interpreted
- // as (i.e., converted if necessary to) the specified destination type. The
- // result is always returned as an uint64_t, since the representation of
- // int64_t and uint64_t are identical. The argument can be any known const.
- //
- // isValidConstant is set to true if a valid constant was found.
- //
- virtual uint64_t ConvertConstantToIntType(const TargetMachine &target,
- const Value *V,
- const Type *destType,
- bool &isValidConstant) const;
-
- // Create an instruction sequence to put the constant `val' into
- // the virtual register `dest'. `val' may be a Constant or a
- // GlobalValue, viz., the constant address of a global variable or function.
- // The generated instructions are returned in `mvec'.
- // Any temp. registers (TmpInstruction) created are recorded in mcfi.
- // Any stack space required is allocated via mcff.
- //
- virtual void CreateCodeToLoadConst(const TargetMachine& target,
- Function* F,
- Value* val,
- Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const;
-
- // Create an instruction sequence to copy an integer value `val'
- // to a floating point value `dest' by copying to memory and back.
- // val must be an integral type. dest must be a Float or Double.
- // The generated instructions are returned in `mvec'.
- // Any temp. registers (TmpInstruction) created are recorded in mcfi.
- // Any stack space required is allocated via mcff.
- //
- virtual void CreateCodeToCopyIntToFloat(const TargetMachine& target,
- Function* F,
- Value* val,
- Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const;
-
- // Similarly, create an instruction sequence to copy an FP value
- // `val' to an integer value `dest' by copying to memory and back.
- // The generated instructions are returned in `mvec'.
- // Any temp. registers (TmpInstruction) created are recorded in mcfi.
- // Any stack space required is allocated via mcff.
- //
- virtual void CreateCodeToCopyFloatToInt(const TargetMachine& target,
- Function* F,
- Value* val,
- Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const;
-
- // Create instruction(s) to copy src to dest, for arbitrary types
- // The generated instructions are returned in `mvec'.
- // Any temp. registers (TmpInstruction) created are recorded in mcfi.
- // Any stack space required is allocated via mcff.
- //
- virtual void CreateCopyInstructionsByType(const TargetMachine& target,
- Function* F,
- Value* src,
- Instruction* dest,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const;
-
- // Create instruction sequence to produce a sign-extended register value
- // from an arbitrary sized value (sized in bits, not bytes).
- // The generated instructions are appended to `mvec'.
- // Any temp. registers (TmpInstruction) created are recorded in mcfi.
- // Any stack space required is allocated via mcff.
- //
- virtual void CreateSignExtensionInstructions(const TargetMachine& target,
- Function* F,
- Value* srcVal,
- Value* destVal,
- unsigned int numLowBits,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const;
-
- // Create instruction sequence to produce a zero-extended register value
- // from an arbitrary sized value (sized in bits, not bytes).
- // The generated instructions are appended to `mvec'.
- // Any temp. registers (TmpInstruction) created are recorded in mcfi.
- // Any stack space required is allocated via mcff.
- //
- virtual void CreateZeroExtensionInstructions(const TargetMachine& target,
- Function* F,
- Value* srcVal,
- Value* destVal,
- unsigned int numLowBits,
- std::vector<MachineInstr*>& mvec,
- MachineCodeForInstruction& mcfi) const;
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/SparcV9JITInfo.h b/llvm/lib/Target/Sparc/SparcV9JITInfo.h
deleted file mode 100644
index b667c5599e4..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9JITInfo.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//===- SparcJITInfo.h - Sparc implementation of the JIT interface -*-C++-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the Sparc implementation of the TargetJITInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARCJITINFO_H
-#define SPARCJITINFO_H
-
-#include "llvm/Target/TargetJITInfo.h"
-
-namespace llvm {
- class TargetMachine;
-
- class SparcJITInfo : public TargetJITInfo {
- TargetMachine &TM;
- public:
- SparcJITInfo(TargetMachine &tm) : TM(tm) {}
-
- /// addPassesToJITCompile - Add passes to the specified pass manager to
- /// implement a fast dynamic compiler for this target. Return true if this
- /// is not supported for this target.
- ///
- virtual void addPassesToJITCompile(FunctionPassManager &PM);
-
- /// replaceMachineCodeForFunction - Make it so that calling the function
- /// whose machine code is at OLD turns into a call to NEW, perhaps by
- /// overwriting OLD with a branch to NEW. This is used for self-modifying
- /// code.
- ///
- virtual void replaceMachineCodeForFunction (void *Old, void *New);
-
- /// getJITStubForFunction - Create or return a stub for the specified
- /// function. This stub acts just like the specified function, except that
- /// it allows the "address" of the function to be taken without having to
- /// generate code for it.
- //virtual void *getJITStubForFunction(Function *F, MachineCodeEmitter &MCE);
- };
-}
-
-#endif
diff --git a/llvm/lib/Target/Sparc/SparcV9RegInfo.h b/llvm/lib/Target/Sparc/SparcV9RegInfo.h
deleted file mode 100644
index 3dd9e683e03..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9RegInfo.h
+++ /dev/null
@@ -1,193 +0,0 @@
-//===-- SparcRegInfo.h - Define TargetRegInfo for Sparc ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This class implements the virtual class TargetRegInfo for Sparc.
-//
-//----------------------------------------------------------------------------
-
-#ifndef SPARC_REGINFO_H
-#define SPARC_REGINFO_H
-
-#include "llvm/Target/TargetRegInfo.h"
-
-namespace llvm {
-
-class SparcTargetMachine;
-
-class SparcRegInfo : public TargetRegInfo {
-
-private:
-
- // Number of registers used for passing int args (usually 6: %o0 - %o5)
- //
- unsigned const NumOfIntArgRegs;
-
- // Number of registers used for passing float args (usually 32: %f0 - %f31)
- //
- unsigned const NumOfFloatArgRegs;
-
- // The following methods are used to color special live ranges (e.g.
- // function args and return values etc.) with specific hardware registers
- // as required. See SparcRegInfo.cpp for the implementation.
- //
- void suggestReg4RetAddr(MachineInstr *RetMI,
- LiveRangeInfo &LRI) const;
-
- void suggestReg4CallAddr(MachineInstr *CallMI, LiveRangeInfo &LRI) const;
-
- // Helper used by the all the getRegType() functions.
- int getRegTypeForClassAndType(unsigned regClassID, const Type* type) const;
-
-public:
- // Type of registers available in Sparc. There can be several reg types
- // in the same class. For instace, the float reg class has Single/Double
- // types
- //
- enum RegTypes {
- IntRegType,
- FPSingleRegType,
- FPDoubleRegType,
- IntCCRegType,
- FloatCCRegType,
- SpecialRegType
- };
-
- // The actual register classes in the Sparc
- //
- // **** WARNING: If this enum order is changed, also modify
- // getRegisterClassOfValue method below since it assumes this particular
- // order for efficiency.
- //
- enum RegClassIDs {
- IntRegClassID, // Integer
- FloatRegClassID, // Float (both single/double)
- IntCCRegClassID, // Int Condition Code
- FloatCCRegClassID, // Float Condition code
- SpecialRegClassID // Special (unallocated) registers
- };
-
- SparcRegInfo(const SparcTargetMachine &tgt);
-
- // To find the register class used for a specified Type
- //
- unsigned getRegClassIDOfType(const Type *type,
- bool isCCReg = false) const;
-
- // To find the register class to which a specified register belongs
- //
- unsigned getRegClassIDOfRegType(int regType) const;
-
- // getZeroRegNum - returns the register that contains always zero this is the
- // unified register number
- //
- virtual unsigned getZeroRegNum() const;
-
- // getCallAddressReg - returns the reg used for pushing the address when a
- // function is called. This can be used for other purposes between calls
- //
- unsigned getCallAddressReg() const;
-
- // Returns the register containing the return address.
- // It should be made sure that this register contains the return
- // value when a return instruction is reached.
- //
- unsigned getReturnAddressReg() const;
-
- // Number of registers used for passing int args (usually 6: %o0 - %o5)
- // and float args (usually 32: %f0 - %f31)
- //
- unsigned const getNumOfIntArgRegs() const { return NumOfIntArgRegs; }
- unsigned const getNumOfFloatArgRegs() const { return NumOfFloatArgRegs; }
-
- // Compute which register can be used for an argument, if any
- //
- int regNumForIntArg(bool inCallee, bool isVarArgsCall,
- unsigned argNo, unsigned& regClassId) const;
-
- int regNumForFPArg(unsigned RegType, bool inCallee, bool isVarArgsCall,
- unsigned argNo, unsigned& regClassId) const;
-
- // The following methods are used to color special live ranges (e.g.
- // function args and return values etc.) with specific hardware registers
- // as required. See SparcRegInfo.cpp for the implementation for Sparc.
- //
- void suggestRegs4MethodArgs(const Function *Meth,
- LiveRangeInfo& LRI) const;
-
- void suggestRegs4CallArgs(MachineInstr *CallMI,
- LiveRangeInfo& LRI) const;
-
- void suggestReg4RetValue(MachineInstr *RetMI,
- LiveRangeInfo& LRI) const;
-
- void colorMethodArgs(const Function *Meth, LiveRangeInfo& LRI,
- std::vector<MachineInstr*>& InstrnsBefore,
- std::vector<MachineInstr*>& InstrnsAfter) const;
-
- // method used for printing a register for debugging purposes
- //
- void printReg(const LiveRange *LR) const;
-
- // returns the # of bytes of stack space allocated for each register
- // type. For Sparc, currently we allocate 8 bytes on stack for all
- // register types. We can optimize this later if necessary to save stack
- // space (However, should make sure that stack alignment is correct)
- //
- inline int getSpilledRegSize(int RegType) const {
- return 8;
- }
-
- // To obtain the return value and the indirect call address (if any)
- // contained in a CALL machine instruction
- //
- const Value * getCallInstRetVal(const MachineInstr *CallMI) const;
- const Value * getCallInstIndirectAddrVal(const MachineInstr *CallMI) const;
-
- // The following methods are used to generate "copy" machine instructions
- // for an architecture.
- //
- // The function regTypeNeedsScratchReg() can be used to check whether a
- // scratch register is needed to copy a register of type `regType' to
- // or from memory. If so, such a scratch register can be provided by
- // the caller (e.g., if it knows which regsiters are free); otherwise
- // an arbitrary one will be chosen and spilled by the copy instructions.
- //
- bool regTypeNeedsScratchReg(int RegType,
- int& scratchRegClassId) const;
-
- void cpReg2RegMI(std::vector<MachineInstr*>& mvec,
- unsigned SrcReg, unsigned DestReg,
- int RegType) const;
-
- void cpReg2MemMI(std::vector<MachineInstr*>& mvec,
- unsigned SrcReg, unsigned DestPtrReg,
- int Offset, int RegType, int scratchReg = -1) const;
-
- void cpMem2RegMI(std::vector<MachineInstr*>& mvec,
- unsigned SrcPtrReg, int Offset, unsigned DestReg,
- int RegType, int scratchReg = -1) const;
-
- void cpValue2Value(Value *Src, Value *Dest,
- std::vector<MachineInstr*>& mvec) const;
-
- // Get the register type for a register identified different ways.
- // Note that getRegTypeForLR(LR) != getRegTypeForDataType(LR->getType())!
- // The reg class of a LR depends both on the Value types in it and whether
- // they are CC registers or not (for example).
- int getRegTypeForDataType(const Type* type) const;
- int getRegTypeForLR(const LiveRange *LR) const;
- int getRegType(int unifiedRegNum) const;
-
- virtual unsigned getFramePointer() const;
- virtual unsigned getStackPointer() const;
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/SparcV9TargetMachine.h b/llvm/lib/Target/Sparc/SparcV9TargetMachine.h
deleted file mode 100644
index be50174de72..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9TargetMachine.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===-- SparcTargetMachine.h - Define TargetMachine for Sparc ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares the top-level UltraSPARC target machine.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARC_TARGETMACHINE_H
-#define SPARC_TARGETMACHINE_H
-
-#include "llvm/Target/TargetFrameInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "SparcInstrInfo.h"
-#include "SparcInternals.h"
-#include "SparcRegInfo.h"
-#include "SparcFrameInfo.h"
-#include "SparcJITInfo.h"
-
-namespace llvm {
- class PassManager;
-
-class SparcTargetMachine : public TargetMachine {
- SparcInstrInfo instrInfo;
- SparcSchedInfo schedInfo;
- SparcRegInfo regInfo;
- SparcFrameInfo frameInfo;
- SparcCacheInfo cacheInfo;
- SparcJITInfo jitInfo;
-public:
- SparcTargetMachine(IntrinsicLowering *IL);
-
- virtual const TargetInstrInfo &getInstrInfo() const { return instrInfo; }
- virtual const TargetSchedInfo &getSchedInfo() const { return schedInfo; }
- virtual const TargetRegInfo &getRegInfo() const { return regInfo; }
- virtual const TargetFrameInfo &getFrameInfo() const { return frameInfo; }
- virtual const TargetCacheInfo &getCacheInfo() const { return cacheInfo; }
- virtual TargetJITInfo *getJITInfo() { return &jitInfo; }
-
- virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
- virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM,
- MachineCodeEmitter &MCE);
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/llvm/lib/Target/Sparc/SparcV9_F2.td b/llvm/lib/Target/Sparc/SparcV9_F2.td
deleted file mode 100644
index cfaf5d87a95..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9_F2.td
+++ /dev/null
@@ -1,71 +0,0 @@
-//===- SparcV9_F2.td - Format 2 instructions: Sparc V9 Target -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Format #2 classes
-//
-class F2 : InstV9 { // Format 2 instructions
- bits<3> op2;
- let op = 0; // Op = 0
- let Inst{24-22} = op2;
-}
-
-// Format 2.1 instructions
-class F2_1<string name> : F2 {
- bits<22> imm;
- bits<5> rd;
-
- let Name = name;
- let Inst{29-25} = rd;
- let Inst{21-0} = imm;
-}
-
-class F2_br : F2 { // Format 2 Branch instruction
- let isBranch = 1; // All instances are branch instructions
-}
-
-class F2_2<bits<4> cond, string name> : F2_br { // Format 2.2 instructions
- bits<22> disp;
- bit annul = 0; // currently unused by Sparc backend
-
- let Name = name;
- let Inst{29} = annul;
- let Inst{28-25} = cond;
- let Inst{21-0} = disp;
-}
-
-class F2_3<bits<4> cond, string name> : F2_br { // Format 2.3 instructions
- bits<2> cc;
- bits<19> disp;
- bit predict = 1;
- bit annul = 0; // currently unused by Sparc backend
-
- let Name = name;
- let Inst{29} = annul;
- let Inst{28-25} = cond;
- let Inst{21-20} = cc;
- let Inst{19} = predict;
- let Inst{18-0} = disp;
-}
-
-class F2_4<bits<3> rcond, string name> : F2_br { // Format 2.4 instructions
- bits<5> rs1;
- bits<16> disp;
- bit predict = 1;
- bit annul = 0; // currently unused by Sparc backend
-
- let Name = name;
- let Inst{29} = annul;
- let Inst{28} = 0;
- let Inst{27-25} = rcond;
- let Inst{21-20} = disp{15-14};
- let Inst{19} = predict;
- let Inst{18-14} = rs1;
- let Inst{13-0 } = disp{13-0};
-}
diff --git a/llvm/lib/Target/Sparc/SparcV9_F3.td b/llvm/lib/Target/Sparc/SparcV9_F3.td
deleted file mode 100644
index 718b0dea064..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9_F3.td
+++ /dev/null
@@ -1,267 +0,0 @@
-//===- SparcV9_F3.td - Format 3 Instructions: Sparc V9 Target -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Format #3 classes
-//
-
-// F3 - Common superclass of all F3 instructions. All instructions have an op3
-// field.
-class F3 : InstV9 {
- bits<6> op3;
- let op{1} = 1; // Op = 2 or 3
- let Inst{24-19} = op3;
-}
-
-// F3_rs1 - Common class of instructions that have an rs1 field
-class F3_rs1 : F3 {
- bits<5> rs1;
- let Inst{18-14} = rs1;
-}
-
-// F3_rs1rs2 - Common class of instructions that only have rs1 and rs2 fields
-class F3_rs1rs2 : F3_rs1 {
- bits<5> rs2;
- let Inst{4-0} = rs2;
-}
-
-// F3_rs1rs2 - Common class of instructions that only have rs1 and rs2 fields
-class F3_rs1rs2rd : F3_rs1rs2 {
- bits<5> rd;
- let Inst{29-25} = rd;
-}
-
-// F3_rs1simm13 - Common class of instructions that only have rs1 and simm13
-class F3_rs1simm13 : F3_rs1 {
- bits<13> simm13;
- let Inst{12-0} = simm13;
-}
-
-class F3_rs1simm13rd : F3_rs1simm13 {
- bits<5> rd;
- let Inst{29-25} = rd;
-}
-
-// F3_rs1rd - Common class of instructions that have an rs1 and rd fields
-class F3_rs1rd : F3_rs1 {
- bits<5> rd;
- let Inst{29-25} = rd;
-}
-
-// F3_rs2 - Common class of instructions that don't use an rs1
-class F3_rs2 : F3 {
- bits<5> rs2;
- let Inst{4-0} = rs2;
-}
-
-// F3_rs2rd - Common class of instructions that use rs2 and rd, but not rs1
-class F3_rs2rd : F3_rs2 {
- bits<5> rd;
- let Inst{29-25} = rd;
-}
-
-// F3_rd - Common class of instructions that have an rd field
-class F3_rd : F3 {
- bits<5> rd;
- let Inst{29-25} = rd;
-}
-
-// F3_rdrs1 - Common class of instructions that have rd and rs1 fields
-class F3_rdrs1 : F3_rd {
- bits<5> rs1;
- let Inst{18-14} = rs1;
-}
-
-// F3_rdrs1simm13 - Common class of instructions that have rd, rs1, and simm13
-class F3_rdrs1simm13 : F3_rdrs1 {
- bits<13> simm13;
- let Inst{12-0} = simm13;
-}
-
-// F3_rdrs1rs2 - Common class of instructions that have rd, rs1, and rs2 fields
-class F3_rdrs1rs2 : F3_rdrs1 {
- bits<5> rs2;
- let Inst{4-0} = rs2;
-}
-
-
-// Specific F3 classes...
-//
-
-class F3_1<bits<2> opVal, bits<6> op3val, string name> : F3_rs1rs2rd {
- let op = opVal;
- let op3 = op3val;
- let Name = name;
- let Inst{13} = 0; // i field = 0
- let Inst{12-5} = 0; // don't care
-}
-
-// The store instructions seem to like to see rd first, then rs1 and rs2
-class F3_1rd<bits<2> opVal, bits<6> op3val, string name> : F3_rdrs1rs2 {
- let op = opVal;
- let op3 = op3val;
- let Name = name;
- let Inst{13} = 0; // i field = 0
- let Inst{12-5} = 0; // don't care
-}
-
-class F3_2<bits<2> opVal, bits<6> op3val, string name> : F3_rs1simm13rd {
- let op = opVal;
- let op3 = op3val;
- let Name = name;
- let Inst{13} = 1; // i field = 1
-}
-
-// The store instructions seem to like to see rd first, then rs1 and imm
-class F3_2rd<bits<2> opVal, bits<6> op3val, string name> : F3_rdrs1simm13 {
- let op = opVal;
- let op3 = op3val;
- let Name = name;
- let Inst{13} = 1; // i field = 1
-}
-
-class F3_3<bits<2> opVal, bits<6> op3val, string name> : F3_rs1rs2 {
- let op = opVal;
- let op3 = op3val;
- let Name = name;
- let Inst{29-25} = 0; // don't care
- let Inst{13} = 0; // i field = 0
- let Inst{12-5} = 0; // don't care
-}
-
-class F3_4<bits<2> opVal, bits<6> op3Val, string name> : F3_rs1simm13 {
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{29-25} = 0; // don't care
- let Inst{13} = 1; // i field = 1
- let Inst{12-0} = simm13;
-}
-
-class F3_5<bits<2> opVal, bits<6> op3Val, bits<3> rcondVal,
- string name> : F3_rs1rs2rd {
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{13} = 0; // i field = 0
- let Inst{12-10} = rcondVal; // rcond field
- let Inst{9-5} = 0; // don't care
-}
-
-class F3_6<bits<2> opVal, bits<6> op3Val, bits<3> rcondVal,
- string name> : F3_rs1 {
- bits<10> simm10;
- bits<5> rd;
-
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{29-25} = rd;
- let Inst{13} = 1; // i field = 1
- let Inst{12-10} = rcondVal; // rcond field
- let Inst{9-0} = simm10;
-}
-
-//FIXME: classes 7-10 not defined!!
-
-class F3_11<bits<2> opVal, bits<6> op3Val, string name> : F3_rs1rs2rd {
- bit x;
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{13} = 0; // i field = 0
- let Inst{12} = x;
- let Inst{11-5} = 0; // don't care
-}
-
-class F3_12<bits<2> opVal, bits<6> op3Val, string name> : F3_rs1 {
- bits<5> shcnt;
- bits<5> rd;
-
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{29-25} = rd;
- let Inst{13} = 1; // i field = 1
- let Inst{12} = 0; // x field = 0
- let Inst{11-5} = 0; // don't care
- let Inst{4-0} = shcnt;
-}
-
-class F3_13<bits<2> opVal, bits<6> op3Val, string name> : F3_rs1 {
- bits<6> shcnt;
- bits<5> rd;
-
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{29-25} = rd;
- let Inst{13} = 1; // i field = 1
- let Inst{12} = 1; // x field = 1
- let Inst{11-6} = 0; // don't care
- let Inst{5-0} = shcnt;
-}
-
-class F3_14<bits<2> opVal, bits<6> op3Val,
- bits<9> opfVal, string name> : F3_rs2rd {
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{18-14} = 0; // don't care
- let Inst{13-5} = opfVal;
-}
-
-class F3_15<bits<2> opVal, bits<6> op3Val,
- bits<9> opfVal, string name> : F3 {
- bits<2> cc;
- bits<5> rs1;
- bits<5> rs2;
-
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{29-27} = 0; // defined to be zero
- let Inst{26-25} = cc;
- let Inst{18-14} = rs1;
- let Inst{13-5} = opfVal;
- let Inst{4-0} = rs2;
-}
-
-class F3_16<bits<2> opVal, bits<6> op3Val,
- bits<9> opfval, string name> : F3_rs1rs2rd {
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{13-5} = opfval;
-}
-
-class F3_17<bits<2> opVal, bits<6> op3Val, string name> : F3_rs1rd {
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{13-0} = 0; // don't care
-}
-
-class F3_18<bits<5> fcn, string name> : F3 {
- let op = 2;
- let op3 = 0b111110;
- let Name = name;
- let Inst{29-25} = fcn;
- let Inst{18-0 } = 0; // don't care;
-}
-
-class F3_19<bits<2> opVal, bits<6> op3Val, string name> : F3_rd {
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{18-0} = 0; // don't care
-}
-
-// FIXME: class F3_20
-// FIXME: class F3_21
diff --git a/llvm/lib/Target/Sparc/SparcV9_F4.td b/llvm/lib/Target/Sparc/SparcV9_F4.td
deleted file mode 100644
index 19e52e108a2..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9_F4.td
+++ /dev/null
@@ -1,141 +0,0 @@
-//===- SparcV9_F4.td - Format 4 instructions: Sparc V9 Target -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-//----------------------- F4 classes -----------------------------------------
-
-// F4 - Common superclass of all F4 instructions. All instructions have an op3
-// field.
-class F4 : InstV9 {
- bits<6> op3;
- let Inst{24-19} = op3;
-}
-
-// F4_rs1 - Common class of instructions that use an rs1 field
-class F4_rs1 : F4 {
- bits<5> rs1;
- let Inst{18-14} = rs1;
-}
-
-// F4_rs1rs2 - Common class of instructions that have rs1 and rs2 fields
-class F4_rs1rs2 : F4_rs1 {
- bits<5> rs2;
- let Inst{4-0} = rs2;
-}
-
-// F4_rs1rs2rd - Common class of instructions that have 3 register operands
-class F4_rs1rs2rd : F4_rs1rs2 {
- bits<5> rd;
- let Inst{29-25} = rd;
-}
-
-// F4_rs1rs2rd - Common class of instructions that have 2 reg and 1 imm operand
-class F4_rs1simm11rd : F4_rs1 {
- bits<11> simm11;
- bits<5> rd;
-
- let Inst{10-0} = simm11;
- let Inst{29-25} = rd;
-}
-
-// F4_cc - Common class of instructions that have a cond field
-class F4_cond : F4 {
- bits<4> cond;
- let Inst{17-14} = cond;
-}
-
-// F4_cc - Common class of instructions that have cc register as first operand
-class F4_condcc : F4_cond {
- bits<3> cc;
- let Inst{18} = cc{2};
- let Inst{12} = cc{1};
- let Inst{11} = cc{0};
-}
-
-// Actual F4 instruction classes
-//
-class F4_1<bits<2> opVal, bits<6> op3Val, string name> : F4_rs1rs2rd {
- bits<2> cc;
-
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{13} = 0; // i bit
- let Inst{12-11} = cc;
- let Inst{10-5} = 0; // don't care
-}
-
-class F4_2<bits<2> opVal, bits<6> op3Val, string name> : F4_rs1simm11rd {
- bits<2> cc;
-
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{13} = 1; // i bit
- let Inst{12-11} = cc;
-}
-
-class F4_3<bits<2> opVal, bits<6> op3Val, bits<4> condVal,
- string name> : F4_condcc {
- bits<5> rs2;
- bits<5> rd;
-
- let op = opVal;
- let op3 = op3Val;
- let cond = condVal;
- let Name = name;
- let Inst{29-25} = rd;
- let Inst{13} = 0; // i bit
- let Inst{10-5} = 0; // don't care
- let Inst{4-0} = rs2;
-}
-
-class F4_4<bits<2> opVal, bits<6> op3Val, bits<4> condVal,
- string name> : F4_condcc {
- bits<11> simm11;
- bits<5> rd;
-
- let op = opVal;
- let op3 = op3Val;
- let cond = condVal;
- let Name = name;
- let Inst{29-25} = rd;
- let Inst{13} = 1; // i bit
- let Inst{10-0} = simm11;
-}
-
-// FIXME: class F4_5
-
-class F4_6<bits<2> opVal, bits<6> op3Val, bits<3> rcondVal,
- bits<5> opf_lowVal, string name> : F4_rs1rs2rd {
- let op = opVal;
- let op3 = op3Val;
- let Name = name;
- let Inst{13} = 0;
- let Inst{12-10} = rcondVal;
- let Inst{9-5} = opf_lowVal;
-}
-
-class F4_7<bits<2> opVal, bits<6> op3Val, bits<4> condVal,
- bits<6> opf_lowVal, string name> : F4_cond {
- bits<3> cc;
- bits<5> rs2;
- bits<5> rd;
-
- let op = opVal;
- let op3 = op3Val;
- let cond = condVal;
- let Name = name;
- let Inst{29-25} = rd;
- let Inst{18} = 0;
- let Inst{13-11} = cc;
- let Inst{10-5} = opf_lowVal;
- let Inst{4-0} = rs2;
-}
-
-// FIXME: F4 classes 8-9
diff --git a/llvm/lib/Target/Sparc/SparcV9_Reg.td b/llvm/lib/Target/Sparc/SparcV9_Reg.td
deleted file mode 100644
index 6d5ad1d55a0..00000000000
--- a/llvm/lib/Target/Sparc/SparcV9_Reg.td
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- SparcV9_Reg.td - Sparc V9 Register definitions ---------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Declarations that describe the Sparc register file
-//===----------------------------------------------------------------------===//
-
-// Ri - One of the 32 64 bit integer registers
-class Ri<bits<5> num> : Register {
- field bits<5> Num = num; // Numbers are identified with a 5 bit ID
-}
-
-let Namespace = "SparcV9" in {
- def G0 : Ri< 0>; def G1 : Ri< 1>; def G2 : Ri< 2>; def G3 : Ri< 3>;
- def G4 : Ri< 4>; def G5 : Ri< 5>; def G6 : Ri< 6>; def G7 : Ri< 7>;
- def O0 : Ri< 8>; def O1 : Ri< 9>; def O2 : Ri<10>; def O3 : Ri<11>;
- def O4 : Ri<12>; def O5 : Ri<13>; def O6 : Ri<14>; def O7 : Ri<15>;
- def L0 : Ri<16>; def L1 : Ri<17>; def L2 : Ri<18>; def L3 : Ri<19>;
- def L4 : Ri<20>; def L5 : Ri<21>; def L6 : Ri<22>; def L7 : Ri<23>;
- def I0 : Ri<24>; def I1 : Ri<25>; def I2 : Ri<26>; def I3 : Ri<27>;
- def I4 : Ri<28>; def I5 : Ri<29>; def I6 : Ri<30>; def I7 : Ri<31>;
- // Floating-point registers?
- // ...
-}
-
-
-// For fun, specify a register class.
-//
-// FIXME: the register order should be defined in terms of the preferred
-// allocation order...
-//
-def IntRegs : RegisterClass<i64, 8, [G0, G1, G2, G3, G4, G5, G6, G7,
- O0, O1, O2, O3, O4, O5, O6, O7,
- L0, L1, L2, L3, L4, L5, L6, L7,
- I0, I1, I2, I3, I4, I5, I6, I7]>;
diff --git a/llvm/lib/Target/Sparc/StackSlots.cpp b/llvm/lib/Target/Sparc/StackSlots.cpp
deleted file mode 100644
index 5fd0ba19271..00000000000
--- a/llvm/lib/Target/Sparc/StackSlots.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- StackSlots.cpp - Specialize LLVM code for target machine ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass adds 2 empty slots at the top of function stack. These two slots
-// are later used during code reoptimization for spilling the register values
-// when rewriting branches.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcInternals.h"
-#include "llvm/Constant.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Function.h"
-#include "llvm/CodeGen/MachineFunctionInfo.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-
-namespace llvm {
-
-namespace {
- class StackSlots : public MachineFunctionPass {
- const TargetMachine &Target;
- public:
- StackSlots(const TargetMachine &T) : Target(T) {}
-
- const char *getPassName() const {
- return "Stack Slot Insertion for profiling code";
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesCFG();
- }
-
- bool runOnMachineFunction(MachineFunction &MF) {
- const Type *PtrInt = PointerType::get(Type::IntTy);
- unsigned Size = Target.getTargetData().getTypeSize(PtrInt);
-
- Value *V = Constant::getNullValue(Type::IntTy);
- MF.getInfo()->allocateLocalVar(V, 2*Size);
- return true;
- }
- };
-}
-
-Pass *createStackSlotsPass(const TargetMachine &Target) {
- return new StackSlots(Target);
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/Sparc/UltraSparcSchedInfo.cpp b/llvm/lib/Target/Sparc/UltraSparcSchedInfo.cpp
deleted file mode 100644
index 016587458ba..00000000000
--- a/llvm/lib/Target/Sparc/UltraSparcSchedInfo.cpp
+++ /dev/null
@@ -1,773 +0,0 @@
-//===-- UltraSparcSchedInfo.cpp -------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Describe the scheduling characteristics of the UltraSparc
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcInternals.h"
-
-using namespace llvm;
-
-/*---------------------------------------------------------------------------
-Scheduling guidelines for SPARC IIi:
-
-I-Cache alignment rules (pg 326)
--- Align a branch target instruction so that it's entire group is within
- the same cache line (may be 1-4 instructions).
-** Don't let a branch that is predicted taken be the last instruction
- on an I-cache line: delay slot will need an entire line to be fetched
--- Make a FP instruction or a branch be the 4th instruction in a group.
- For branches, there are tradeoffs in reordering to make this happen
- (see pg. 327).
-** Don't put a branch in a group that crosses a 32-byte boundary!
- An artificial branch is inserted after every 32 bytes, and having
- another branch will force the group to be broken into 2 groups.
-
-iTLB rules:
--- Don't let a loop span two memory pages, if possible
-
-Branch prediction performance:
--- Don't make the branch in a delay slot the target of a branch
--- Try not to have 2 predicted branches within a group of 4 instructions
- (because each such group has a single branch target field).
--- Try to align branches in slots 0, 2, 4 or 6 of a cache line (to avoid
- the wrong prediction bits being used in some cases).
-
-D-Cache timing constraints:
--- Signed int loads of less than 64 bits have 3 cycle latency, not 2
--- All other loads that hit in D-Cache have 2 cycle latency
--- All loads are returned IN ORDER, so a D-Cache miss will delay a later hit
--- Mis-aligned loads or stores cause a trap. In particular, replace
- mis-aligned FP double precision l/s with 2 single-precision l/s.
--- Simulations of integer codes show increase in avg. group size of
- 33% when code (including esp. non-faulting loads) is moved across
- one branch, and 50% across 2 branches.
-
-E-Cache timing constraints:
--- Scheduling for E-cache (D-Cache misses) is effective (due to load buffering)
-
-Store buffer timing constraints:
--- Stores can be executed in same cycle as instruction producing the value
--- Stores are buffered and have lower priority for E-cache until
- highwater mark is reached in the store buffer (5 stores)
-
-Pipeline constraints:
--- Shifts can only use IEU0.
--- CC setting instructions can only use IEU1.
--- Several other instructions must only use IEU1:
- EDGE(?), ARRAY(?), CALL, JMPL, BPr, PST, and FCMP.
--- Two instructions cannot store to the same register file in a single cycle
- (single write port per file).
-
-Issue and grouping constraints:
--- FP and branch instructions must use slot 4.
--- Shift instructions cannot be grouped with other IEU0-specific instructions.
--- CC setting instructions cannot be grouped with other IEU1-specific instrs.
--- Several instructions must be issued in a single-instruction group:
- MOVcc or MOVr, MULs/x and DIVs/x, SAVE/RESTORE, many others
--- A CALL or JMPL breaks a group, ie, is not combined with subsequent instrs.
---
---
-
-Branch delay slot scheduling rules:
--- A CTI couple (two back-to-back CTI instructions in the dynamic stream)
- has a 9-instruction penalty: the entire pipeline is flushed when the
- second instruction reaches stage 9 (W-Writeback).
--- Avoid putting multicycle instructions, and instructions that may cause
- load misses, in the delay slot of an annulling branch.
--- Avoid putting WR, SAVE..., RESTORE and RETURN instructions in the
- delay slot of an annulling branch.
-
- *--------------------------------------------------------------------------- */
-
-//---------------------------------------------------------------------------
-// List of CPUResources for UltraSPARC IIi.
-//---------------------------------------------------------------------------
-
-static const CPUResource AllIssueSlots( "All Instr Slots", 4);
-static const CPUResource IntIssueSlots( "Int Instr Slots", 3);
-static const CPUResource First3IssueSlots("Instr Slots 0-3", 3);
-static const CPUResource LSIssueSlots( "Load-Store Instr Slot", 1);
-static const CPUResource CTIIssueSlots( "Ctrl Transfer Instr Slot", 1);
-static const CPUResource FPAIssueSlots( "FP Instr Slot 1", 1);
-static const CPUResource FPMIssueSlots( "FP Instr Slot 2", 1);
-
-// IEUN instructions can use either Alu and should use IAluN.
-// IEU0 instructions must use Alu 1 and should use both IAluN and IAlu0.
-// IEU1 instructions must use Alu 2 and should use both IAluN and IAlu1.
-static const CPUResource IAluN("Int ALU 1or2", 2);
-static const CPUResource IAlu0("Int ALU 1", 1);
-static const CPUResource IAlu1("Int ALU 2", 1);
-
-static const CPUResource LSAluC1("Load/Store Unit Addr Cycle", 1);
-static const CPUResource LSAluC2("Load/Store Unit Issue Cycle", 1);
-static const CPUResource LdReturn("Load Return Unit", 1);
-
-static const CPUResource FPMAluC1("FP Mul/Div Alu Cycle 1", 1);
-static const CPUResource FPMAluC2("FP Mul/Div Alu Cycle 2", 1);
-static const CPUResource FPMAluC3("FP Mul/Div Alu Cycle 3", 1);
-
-static const CPUResource FPAAluC1("FP Other Alu Cycle 1", 1);
-static const CPUResource FPAAluC2("FP Other Alu Cycle 2", 1);
-static const CPUResource FPAAluC3("FP Other Alu Cycle 3", 1);
-
-static const CPUResource IRegReadPorts("Int Reg ReadPorts", INT_MAX); // CHECK
-static const CPUResource IRegWritePorts("Int Reg WritePorts", 2); // CHECK
-static const CPUResource FPRegReadPorts("FP Reg Read Ports", INT_MAX);// CHECK
-static const CPUResource FPRegWritePorts("FP Reg Write Ports", 1); // CHECK
-
-static const CPUResource CTIDelayCycle( "CTI delay cycle", 1);
-static const CPUResource FCMPDelayCycle("FCMP delay cycle", 1);
-
-
-
-//---------------------------------------------------------------------------
-// const InstrClassRUsage SparcRUsageDesc[]
-//
-// Purpose:
-// Resource usage information for instruction in each scheduling class.
-// The InstrRUsage Objects for individual classes are specified first.
-// Note that fetch and decode are decoupled from the execution pipelines
-// via an instr buffer, so they are not included in the cycles below.
-//---------------------------------------------------------------------------
-
-static const InstrClassRUsage NoneClassRUsage = {
- SPARC_NONE,
- /*totCycles*/ 7,
-
- /* maxIssueNum */ 4,
- /* isSingleIssue */ false,
- /* breaksGroup */ false,
- /* numBubbles */ 0,
-
- /*numSlots*/ 4,
- /* feasibleSlots[] */ { 0, 1, 2, 3 },
-
- /*numEntries*/ 0,
- /* V[] */ {
- /*Cycle G */
- /*Ccle E */
- /*Cycle C */
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle W */
- }
-};
-
-static const InstrClassRUsage IEUNClassRUsage = {
- SPARC_IEUN,
- /*totCycles*/ 7,
-
- /* maxIssueNum */ 3,
- /* isSingleIssue */ false,
- /* breaksGroup */ false,
- /* numBubbles */ 0,
-
- /*numSlots*/ 3,
- /* feasibleSlots[] */ { 0, 1, 2 },
-
- /*numEntries*/ 4,
- /* V[] */ {
- /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
- { IntIssueSlots.rid, 0, 1 },
- /*Cycle E */ { IAluN.rid, 1, 1 },
- /*Cycle C */
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle W */ { IRegWritePorts.rid, 6, 1 }
- }
-};
-
-static const InstrClassRUsage IEU0ClassRUsage = {
- SPARC_IEU0,
- /*totCycles*/ 7,
-
- /* maxIssueNum */ 1,
- /* isSingleIssue */ false,
- /* breaksGroup */ false,
- /* numBubbles */ 0,
-
- /*numSlots*/ 3,
- /* feasibleSlots[] */ { 0, 1, 2 },
-
- /*numEntries*/ 5,
- /* V[] */ {
- /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
- { IntIssueSlots.rid, 0, 1 },
- /*Cycle E */ { IAluN.rid, 1, 1 },
- { IAlu0.rid, 1, 1 },
- /*Cycle C */
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle W */ { IRegWritePorts.rid, 6, 1 }
- }
-};
-
-static const InstrClassRUsage IEU1ClassRUsage = {
- SPARC_IEU1,
- /*totCycles*/ 7,
-
- /* maxIssueNum */ 1,
- /* isSingleIssue */ false,
- /* breaksGroup */ false,
- /* numBubbles */ 0,
-
- /*numSlots*/ 3,
- /* feasibleSlots[] */ { 0, 1, 2 },
-
- /*numEntries*/ 5,
- /* V[] */ {
- /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
- { IntIssueSlots.rid, 0, 1 },
- /*Cycle E */ { IAluN.rid, 1, 1 },
- { IAlu1.rid, 1, 1 },
- /*Cycle C */
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle W */ { IRegWritePorts.rid, 6, 1 }
- }
-};
-
-static const InstrClassRUsage FPMClassRUsage = {
- SPARC_FPM,
- /*totCycles*/ 7,
-
- /* maxIssueNum */ 1,
- /* isSingleIssue */ false,
- /* breaksGroup */ false,
- /* numBubbles */ 0,
-
- /*numSlots*/ 4,
- /* feasibleSlots[] */ { 0, 1, 2, 3 },
-
- /*numEntries*/ 7,
- /* V[] */ {
- /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
- { FPMIssueSlots.rid, 0, 1 },
- /*Cycle E */ { FPRegReadPorts.rid, 1, 1 },
- /*Cycle C */ { FPMAluC1.rid, 2, 1 },
- /*Cycle N1*/ { FPMAluC2.rid, 3, 1 },
- /*Cycle N1*/ { FPMAluC3.rid, 4, 1 },
- /*Cycle N1*/
- /*Cycle W */ { FPRegWritePorts.rid, 6, 1 }
- }
-};
-
-static const InstrClassRUsage FPAClassRUsage = {
- SPARC_FPA,
- /*totCycles*/ 7,
-
- /* maxIssueNum */ 1,
- /* isSingleIssue */ false,
- /* breaksGroup */ false,
- /* numBubbles */ 0,
-
- /*numSlots*/ 4,
- /* feasibleSlots[] */ { 0, 1, 2, 3 },
-
- /*numEntries*/ 7,
- /* V[] */ {
- /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
- { FPAIssueSlots.rid, 0, 1 },
- /*Cycle E */ { FPRegReadPorts.rid, 1, 1 },
- /*Cycle C */ { FPAAluC1.rid, 2, 1 },
- /*Cycle N1*/ { FPAAluC2.rid, 3, 1 },
- /*Cycle N1*/ { FPAAluC3.rid, 4, 1 },
- /*Cycle N1*/
- /*Cycle W */ { FPRegWritePorts.rid, 6, 1 }
- }
-};
-
-static const InstrClassRUsage LDClassRUsage = {
- SPARC_LD,
- /*totCycles*/ 7,
-
- /* maxIssueNum */ 1,
- /* isSingleIssue */ false,
- /* breaksGroup */ false,
- /* numBubbles */ 0,
-
- /*numSlots*/ 3,
- /* feasibleSlots[] */ { 0, 1, 2, },
-
- /*numEntries*/ 6,
- /* V[] */ {
- /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
- { First3IssueSlots.rid, 0, 1 },
- { LSIssueSlots.rid, 0, 1 },
- /*Cycle E */ { LSAluC1.rid, 1, 1 },
- /*Cycle C */ { LSAluC2.rid, 2, 1 },
- { LdReturn.rid, 2, 1 },
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle W */ { IRegWritePorts.rid, 6, 1 }
- }
-};
-
-static const InstrClassRUsage STClassRUsage = {
- SPARC_ST,
- /*totCycles*/ 7,
-
- /* maxIssueNum */ 1,
- /* isSingleIssue */ false,
- /* breaksGroup */ false,
- /* numBubbles */ 0,
-
- /*numSlots*/ 3,
- /* feasibleSlots[] */ { 0, 1, 2 },
-
- /*numEntries*/ 4,
- /* V[] */ {
- /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
- { First3IssueSlots.rid, 0, 1 },
- { LSIssueSlots.rid, 0, 1 },
- /*Cycle E */ { LSAluC1.rid, 1, 1 },
- /*Cycle C */ { LSAluC2.rid, 2, 1 }
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle W */
- }
-};
-
-static const InstrClassRUsage CTIClassRUsage = {
- SPARC_CTI,
- /*totCycles*/ 7,
-
- /* maxIssueNum */ 1,
- /* isSingleIssue */ false,
- /* breaksGroup */ false,
- /* numBubbles */ 0,
-
- /*numSlots*/ 4,
- /* feasibleSlots[] */ { 0, 1, 2, 3 },
-
- /*numEntries*/ 4,
- /* V[] */ {
- /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
- { CTIIssueSlots.rid, 0, 1 },
- /*Cycle E */ { IAlu0.rid, 1, 1 },
- /*Cycles E-C */ { CTIDelayCycle.rid, 1, 2 }
- /*Cycle C */
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle W */
- }
-};
-
-static const InstrClassRUsage SingleClassRUsage = {
- SPARC_SINGLE,
- /*totCycles*/ 7,
-
- /* maxIssueNum */ 1,
- /* isSingleIssue */ true,
- /* breaksGroup */ false,
- /* numBubbles */ 0,
-
- /*numSlots*/ 1,
- /* feasibleSlots[] */ { 0 },
-
- /*numEntries*/ 5,
- /* V[] */ {
- /*Cycle G */ { AllIssueSlots.rid, 0, 1 },
- { AllIssueSlots.rid, 0, 1 },
- { AllIssueSlots.rid, 0, 1 },
- { AllIssueSlots.rid, 0, 1 },
- /*Cycle E */ { IAlu0.rid, 1, 1 }
- /*Cycle C */
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle N1*/
- /*Cycle W */
- }
-};
-
-
-static const InstrClassRUsage SparcRUsageDesc[] = {
- NoneClassRUsage,
- IEUNClassRUsage,
- IEU0ClassRUsage,
- IEU1ClassRUsage,
- FPMClassRUsage,
- FPAClassRUsage,
- CTIClassRUsage,
- LDClassRUsage,
- STClassRUsage,
- SingleClassRUsage
-};
-
-
-
-//---------------------------------------------------------------------------
-// const InstrIssueDelta SparcInstrIssueDeltas[]
-//
-// Purpose:
-// Changes to issue restrictions information in InstrClassRUsage for
-// instructions that differ from other instructions in their class.
-//---------------------------------------------------------------------------
-
-static const InstrIssueDelta SparcInstrIssueDeltas[] = {
-
- // opCode, isSingleIssue, breaksGroup, numBubbles
-
- // Special cases for single-issue only
- // Other single issue cases are below.
-//{ V9::LDDA, true, true, 0 },
-//{ V9::STDA, true, true, 0 },
-//{ V9::LDDF, true, true, 0 },
-//{ V9::LDDFA, true, true, 0 },
- { V9::ADDCr, true, true, 0 },
- { V9::ADDCi, true, true, 0 },
- { V9::ADDCccr, true, true, 0 },
- { V9::ADDCcci, true, true, 0 },
- { V9::SUBCr, true, true, 0 },
- { V9::SUBCi, true, true, 0 },
- { V9::SUBCccr, true, true, 0 },
- { V9::SUBCcci, true, true, 0 },
-//{ V9::LDSTUB, true, true, 0 },
-//{ V9::SWAP, true, true, 0 },
-//{ V9::SWAPA, true, true, 0 },
-//{ V9::CAS, true, true, 0 },
-//{ V9::CASA, true, true, 0 },
-//{ V9::CASX, true, true, 0 },
-//{ V9::CASXA, true, true, 0 },
-//{ V9::LDFSR, true, true, 0 },
-//{ V9::LDFSRA, true, true, 0 },
-//{ V9::LDXFSR, true, true, 0 },
-//{ V9::LDXFSRA, true, true, 0 },
-//{ V9::STFSR, true, true, 0 },
-//{ V9::STFSRA, true, true, 0 },
-//{ V9::STXFSR, true, true, 0 },
-//{ V9::STXFSRA, true, true, 0 },
-//{ V9::SAVED, true, true, 0 },
-//{ V9::RESTORED, true, true, 0 },
-//{ V9::FLUSH, true, true, 9 },
-//{ V9::FLUSHW, true, true, 9 },
-//{ V9::ALIGNADDR, true, true, 0 },
- { V9::RETURNr, true, true, 0 },
- { V9::RETURNi, true, true, 0 },
-//{ V9::DONE, true, true, 0 },
-//{ V9::RETRY, true, true, 0 },
-//{ V9::TCC, true, true, 0 },
-//{ V9::SHUTDOWN, true, true, 0 },
-
- // Special cases for breaking group *before*
- // CURRENTLY NOT SUPPORTED!
- { V9::CALL, false, false, 0 },
- { V9::JMPLCALLr, false, false, 0 },
- { V9::JMPLCALLi, false, false, 0 },
- { V9::JMPLRETr, false, false, 0 },
- { V9::JMPLRETi, false, false, 0 },
-
- // Special cases for breaking the group *after*
- { V9::MULXr, true, true, (4+34)/2 },
- { V9::MULXi, true, true, (4+34)/2 },
- { V9::FDIVS, false, true, 0 },
- { V9::FDIVD, false, true, 0 },
- { V9::FDIVQ, false, true, 0 },
- { V9::FSQRTS, false, true, 0 },
- { V9::FSQRTD, false, true, 0 },
- { V9::FSQRTQ, false, true, 0 },
-//{ V9::FCMP{LE,GT,NE,EQ}, false, true, 0 },
-
- // Instructions that introduce bubbles
-//{ V9::MULScc, true, true, 2 },
-//{ V9::SMULcc, true, true, (4+18)/2 },
-//{ V9::UMULcc, true, true, (4+19)/2 },
- { V9::SDIVXr, true, true, 68 },
- { V9::SDIVXi, true, true, 68 },
- { V9::UDIVXr, true, true, 68 },
- { V9::UDIVXi, true, true, 68 },
-//{ V9::SDIVcc, true, true, 36 },
-//{ V9::UDIVcc, true, true, 37 },
- { V9::WRCCRr, true, true, 4 },
- { V9::WRCCRi, true, true, 4 },
-//{ V9::WRPR, true, true, 4 },
-//{ V9::RDCCR, true, true, 0 }, // no bubbles after, but see below
-//{ V9::RDPR, true, true, 0 },
-};
-
-
-
-
-//---------------------------------------------------------------------------
-// const InstrRUsageDelta SparcInstrUsageDeltas[]
-//
-// Purpose:
-// Changes to resource usage information in InstrClassRUsage for
-// instructions that differ from other instructions in their class.
-//---------------------------------------------------------------------------
-
-static const InstrRUsageDelta SparcInstrUsageDeltas[] = {
-
- // MachineOpCode, Resource, Start cycle, Num cycles
-
- //
- // JMPL counts as a load/store instruction for issue!
- //
- { V9::JMPLCALLr, LSIssueSlots.rid, 0, 1 },
- { V9::JMPLCALLi, LSIssueSlots.rid, 0, 1 },
- { V9::JMPLRETr, LSIssueSlots.rid, 0, 1 },
- { V9::JMPLRETi, LSIssueSlots.rid, 0, 1 },
-
- //
- // Many instructions cannot issue for the next 2 cycles after an FCMP
- // We model that with a fake resource FCMPDelayCycle.
- //
- { V9::FCMPS, FCMPDelayCycle.rid, 1, 3 },
- { V9::FCMPD, FCMPDelayCycle.rid, 1, 3 },
- { V9::FCMPQ, FCMPDelayCycle.rid, 1, 3 },
-
- { V9::MULXr, FCMPDelayCycle.rid, 1, 1 },
- { V9::MULXi, FCMPDelayCycle.rid, 1, 1 },
- { V9::SDIVXr, FCMPDelayCycle.rid, 1, 1 },
- { V9::SDIVXi, FCMPDelayCycle.rid, 1, 1 },
- { V9::UDIVXr, FCMPDelayCycle.rid, 1, 1 },
- { V9::UDIVXi, FCMPDelayCycle.rid, 1, 1 },
-//{ V9::SMULcc, FCMPDelayCycle.rid, 1, 1 },
-//{ V9::UMULcc, FCMPDelayCycle.rid, 1, 1 },
-//{ V9::SDIVcc, FCMPDelayCycle.rid, 1, 1 },
-//{ V9::UDIVcc, FCMPDelayCycle.rid, 1, 1 },
- { V9::STDFr, FCMPDelayCycle.rid, 1, 1 },
- { V9::STDFi, FCMPDelayCycle.rid, 1, 1 },
- { V9::FMOVRSZ, FCMPDelayCycle.rid, 1, 1 },
- { V9::FMOVRSLEZ,FCMPDelayCycle.rid, 1, 1 },
- { V9::FMOVRSLZ, FCMPDelayCycle.rid, 1, 1 },
- { V9::FMOVRSNZ, FCMPDelayCycle.rid, 1, 1 },
- { V9::FMOVRSGZ, FCMPDelayCycle.rid, 1, 1 },
- { V9::FMOVRSGEZ,FCMPDelayCycle.rid, 1, 1 },
-
- //
- // Some instructions are stalled in the GROUP stage if a CTI is in
- // the E or C stage. We model that with a fake resource CTIDelayCycle.
- //
- { V9::LDDFr, CTIDelayCycle.rid, 1, 1 },
- { V9::LDDFi, CTIDelayCycle.rid, 1, 1 },
-//{ V9::LDDA, CTIDelayCycle.rid, 1, 1 },
-//{ V9::LDDSTUB, CTIDelayCycle.rid, 1, 1 },
-//{ V9::LDDSTUBA, CTIDelayCycle.rid, 1, 1 },
-//{ V9::SWAP, CTIDelayCycle.rid, 1, 1 },
-//{ V9::SWAPA, CTIDelayCycle.rid, 1, 1 },
-//{ V9::CAS, CTIDelayCycle.rid, 1, 1 },
-//{ V9::CASA, CTIDelayCycle.rid, 1, 1 },
-//{ V9::CASX, CTIDelayCycle.rid, 1, 1 },
-//{ V9::CASXA, CTIDelayCycle.rid, 1, 1 },
-
- //
- // Signed int loads of less than dword size return data in cycle N1 (not C)
- // and put all loads in consecutive cycles into delayed load return mode.
- //
- { V9::LDSBr, LdReturn.rid, 2, -1 },
- { V9::LDSBr, LdReturn.rid, 3, 1 },
- { V9::LDSBi, LdReturn.rid, 2, -1 },
- { V9::LDSBi, LdReturn.rid, 3, 1 },
-
- { V9::LDSHr, LdReturn.rid, 2, -1 },
- { V9::LDSHr, LdReturn.rid, 3, 1 },
- { V9::LDSHi, LdReturn.rid, 2, -1 },
- { V9::LDSHi, LdReturn.rid, 3, 1 },
-
- { V9::LDSWr, LdReturn.rid, 2, -1 },
- { V9::LDSWr, LdReturn.rid, 3, 1 },
- { V9::LDSWi, LdReturn.rid, 2, -1 },
- { V9::LDSWi, LdReturn.rid, 3, 1 },
-
- //
- // RDPR from certain registers and RD from any register are not dispatchable
- // until four clocks after they reach the head of the instr. buffer.
- // Together with their single-issue requirement, this means all four issue
- // slots are effectively blocked for those cycles, plus the issue cycle.
- // This does not increase the latency of the instruction itself.
- //
- { V9::RDCCR, AllIssueSlots.rid, 0, 5 },
- { V9::RDCCR, AllIssueSlots.rid, 0, 5 },
- { V9::RDCCR, AllIssueSlots.rid, 0, 5 },
- { V9::RDCCR, AllIssueSlots.rid, 0, 5 },
-
-#undef EXPLICIT_BUBBLES_NEEDED
-#ifdef EXPLICIT_BUBBLES_NEEDED
- //
- // MULScc inserts one bubble.
- // This means it breaks the current group (captured in UltraSparcSchedInfo)
- // *and occupies all issue slots for the next cycle
- //
-//{ V9::MULScc, AllIssueSlots.rid, 2, 2-1 },
-//{ V9::MULScc, AllIssueSlots.rid, 2, 2-1 },
-//{ V9::MULScc, AllIssueSlots.rid, 2, 2-1 },
-//{ V9::MULScc, AllIssueSlots.rid, 2, 2-1 },
-
- //
- // SMULcc inserts between 4 and 18 bubbles, depending on #leading 0s in rs1.
- // We just model this with a simple average.
- //
-//{ V9::SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 },
-//{ V9::SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 },
-//{ V9::SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 },
-//{ V9::SMULcc, AllIssueSlots.rid, 2, ((4+18)/2)-1 },
-
- // SMULcc inserts between 4 and 19 bubbles, depending on #leading 0s in rs1.
-//{ V9::UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 },
-//{ V9::UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 },
-//{ V9::UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 },
-//{ V9::UMULcc, AllIssueSlots.rid, 2, ((4+19)/2)-1 },
-
- //
- // MULX inserts between 4 and 34 bubbles, depending on #leading 0s in rs1.
- //
- { V9::MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 },
- { V9::MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 },
- { V9::MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 },
- { V9::MULX, AllIssueSlots.rid, 2, ((4+34)/2)-1 },
-
- //
- // SDIVcc inserts 36 bubbles.
- //
-//{ V9::SDIVcc, AllIssueSlots.rid, 2, 36-1 },
-//{ V9::SDIVcc, AllIssueSlots.rid, 2, 36-1 },
-//{ V9::SDIVcc, AllIssueSlots.rid, 2, 36-1 },
-//{ V9::SDIVcc, AllIssueSlots.rid, 2, 36-1 },
-
- // UDIVcc inserts 37 bubbles.
-//{ V9::UDIVcc, AllIssueSlots.rid, 2, 37-1 },
-//{ V9::UDIVcc, AllIssueSlots.rid, 2, 37-1 },
-//{ V9::UDIVcc, AllIssueSlots.rid, 2, 37-1 },
-//{ V9::UDIVcc, AllIssueSlots.rid, 2, 37-1 },
-
- //
- // SDIVX inserts 68 bubbles.
- //
- { V9::SDIVX, AllIssueSlots.rid, 2, 68-1 },
- { V9::SDIVX, AllIssueSlots.rid, 2, 68-1 },
- { V9::SDIVX, AllIssueSlots.rid, 2, 68-1 },
- { V9::SDIVX, AllIssueSlots.rid, 2, 68-1 },
-
- //
- // UDIVX inserts 68 bubbles.
- //
- { V9::UDIVX, AllIssueSlots.rid, 2, 68-1 },
- { V9::UDIVX, AllIssueSlots.rid, 2, 68-1 },
- { V9::UDIVX, AllIssueSlots.rid, 2, 68-1 },
- { V9::UDIVX, AllIssueSlots.rid, 2, 68-1 },
-
- //
- // WR inserts 4 bubbles.
- //
-//{ V9::WR, AllIssueSlots.rid, 2, 68-1 },
-//{ V9::WR, AllIssueSlots.rid, 2, 68-1 },
-//{ V9::WR, AllIssueSlots.rid, 2, 68-1 },
-//{ V9::WR, AllIssueSlots.rid, 2, 68-1 },
-
- //
- // WRPR inserts 4 bubbles.
- //
-//{ V9::WRPR, AllIssueSlots.rid, 2, 68-1 },
-//{ V9::WRPR, AllIssueSlots.rid, 2, 68-1 },
-//{ V9::WRPR, AllIssueSlots.rid, 2, 68-1 },
-//{ V9::WRPR, AllIssueSlots.rid, 2, 68-1 },
-
- //
- // DONE inserts 9 bubbles.
- //
-//{ V9::DONE, AllIssueSlots.rid, 2, 9-1 },
-//{ V9::DONE, AllIssueSlots.rid, 2, 9-1 },
-//{ V9::DONE, AllIssueSlots.rid, 2, 9-1 },
-//{ V9::DONE, AllIssueSlots.rid, 2, 9-1 },
-
- //
- // RETRY inserts 9 bubbles.
- //
-//{ V9::RETRY, AllIssueSlots.rid, 2, 9-1 },
-//{ V9::RETRY, AllIssueSlots.rid, 2, 9-1 },
-//{ V9::RETRY, AllIssueSlots.rid, 2, 9-1 },
-//{ V9::RETRY, AllIssueSlots.rid, 2, 9-1 },
-
-#endif /*EXPLICIT_BUBBLES_NEEDED */
-};
-
-// Additional delays to be captured in code:
-// 1. RDPR from several state registers (page 349)
-// 2. RD from *any* register (page 349)
-// 3. Writes to TICK, PSTATE, TL registers and FLUSH{W} instr (page 349)
-// 4. Integer store can be in same group as instr producing value to store.
-// 5. BICC and BPICC can be in the same group as instr producing CC (pg 350)
-// 6. FMOVr cannot be in the same or next group as an IEU instr (pg 351).
-// 7. The second instr. of a CTI group inserts 9 bubbles (pg 351)
-// 8. WR{PR}, SVAE, SAVED, RESTORE, RESTORED, RETURN, RETRY, and DONE that
-// follow an annulling branch cannot be issued in the same group or in
-// the 3 groups following the branch.
-// 9. A predicted annulled load does not stall dependent instructions.
-// Other annulled delay slot instructions *do* stall dependents, so
-// nothing special needs to be done for them during scheduling.
-//10. Do not put a load use that may be annulled in the same group as the
-// branch. The group will stall until the load returns.
-//11. Single-prec. FP loads lock 2 registers, for dependency checking.
-//
-//
-// Additional delays we cannot or will not capture:
-// 1. If DCTI is last word of cache line, it is delayed until next line can be
-// fetched. Also, other DCTI alignment-related delays (pg 352)
-// 2. Load-after-store is delayed by 7 extra cycles if load hits in D-Cache.
-// Also, several other store-load and load-store conflicts (pg 358)
-// 3. MEMBAR, LD{X}FSR, LDD{A} and a bunch of other load stalls (pg 358)
-// 4. There can be at most 8 outstanding buffered store instructions
-// (including some others like MEMBAR, LDSTUB, CAS{AX}, and FLUSH)
-
-
-
-//---------------------------------------------------------------------------
-// class SparcSchedInfo
-//
-// Purpose:
-// Scheduling information for the UltraSPARC.
-// Primarily just initializes machine-dependent parameters in
-// class TargetSchedInfo.
-//---------------------------------------------------------------------------
-
-/*ctor*/
-SparcSchedInfo::SparcSchedInfo(const TargetMachine& tgt)
- : TargetSchedInfo(tgt,
- (unsigned int) SPARC_NUM_SCHED_CLASSES,
- SparcRUsageDesc,
- SparcInstrUsageDeltas,
- SparcInstrIssueDeltas,
- sizeof(SparcInstrUsageDeltas)/sizeof(InstrRUsageDelta),
- sizeof(SparcInstrIssueDeltas)/sizeof(InstrIssueDelta))
-{
- maxNumIssueTotal = 4;
- longestIssueConflict = 0; // computed from issuesGaps[]
-
- branchMispredictPenalty = 4; // 4 for SPARC IIi
- branchTargetUnknownPenalty = 2; // 2 for SPARC IIi
- l1DCacheMissPenalty = 8; // 7 or 9 for SPARC IIi
- l1ICacheMissPenalty = 8; // ? for SPARC IIi
-
- inOrderLoads = true; // true for SPARC IIi
- inOrderIssue = true; // true for SPARC IIi
- inOrderExec = false; // false for most architectures
- inOrderRetire= true; // true for most architectures
-
- // must be called after above parameters are initialized.
- initializeResources();
-}
-
-void
-SparcSchedInfo::initializeResources()
-{
- // Compute TargetSchedInfo::instrRUsages and TargetSchedInfo::issueGaps
- TargetSchedInfo::initializeResources();
-
- // Machine-dependent fixups go here. None for now.
-}
OpenPOWER on IntegriCloud