summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCVS to SVN Conversion <nobody@llvm.org>2004-08-06 16:21:48 +0000
committerCVS to SVN Conversion <nobody@llvm.org>2004-08-06 16:21:48 +0000
commita27fe0174c8fb506a6bb8ec33eac2d825443cf2a (patch)
tree7ecceb08af6d54e50e756677434e58e609d73e64
parent5064097632cae9d8bb02b30d2e1b8ae5e7a1e7bb (diff)
downloadllvm-a27fe0174c8fb506a6bb8ec33eac2d825443cf2a.tar.gz
This commit was manufactured by cvs2svn to create branch 'release_13'.
llvm-svn: 15548
-rw-r--r--llvm/docs/ReleaseNotes.html29
-rw-r--r--llvm/lib/Target/PowerPC/PPC32AsmPrinter.cpp735
-rw-r--r--llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp43
-rw-r--r--llvm/lib/Target/PowerPC/PPC32ISelSimple.cpp3343
-rw-r--r--llvm/lib/Target/SparcV8/DelaySlotFiller.cpp112
-rw-r--r--llvm/lib/Target/SparcV8/InstSelectSimple.cpp1151
-rw-r--r--llvm/lib/Target/SparcV8/Makefile46
-rw-r--r--llvm/lib/Target/SparcV8/README.txt20
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8.h41
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8.td37
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8AsmPrinter.cpp632
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8CodeEmitter.cpp43
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8InstrInfo.cpp41
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8InstrInfo.h54
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8InstrInfo.td242
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8InstrInfo_F2.td44
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8InstrInfo_F3.td61
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8JITInfo.h49
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8RegisterInfo.cpp165
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8RegisterInfo.h58
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8RegisterInfo.td111
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8TargetMachine.cpp134
-rw-r--r--llvm/lib/Target/SparcV8/SparcV8TargetMachine.h57
23 files changed, 11 insertions, 7237 deletions
diff --git a/llvm/docs/ReleaseNotes.html b/llvm/docs/ReleaseNotes.html
index 82d357a3996c..aa7c73dc558b 100644
--- a/llvm/docs/ReleaseNotes.html
+++ b/llvm/docs/ReleaseNotes.html
@@ -73,8 +73,7 @@ href="http://llvm.cs.uiuc.edu/releases/">releases page</a>.</p>
release primarily improves the <a href="#codequality">performance of the
code</a> produced by all aspects of the LLVM compiler, adds many <a
href="#newfeatures">new features</a>, <a href="#bugfix">fixes a few
-bugs</a>, speeds up the compiler, and introduces a new (experimental)
-PowerPC code generator.</p>
+bugs</a>, and speeds up the compiler.</p>
<p> At this time, LLVM is known to correctly compile and run all C &amp; C++
SPEC CPU95 &amp; 2000 benchmarks, the Olden benchmarks, and the Ptrdist
@@ -150,8 +149,6 @@ tablegen description of the target (before they were hand coded).</li>
<li>All LLVM tools will now respond to the
<a href="http://llvm.cs.uiuc.edu/PR413"><tt>--version</tt> option</a> which
will tell you the version of LLVM on which the tool is based.</li>
-<li>An experimental PowerPC backend has been added, capable of compiling several
-SPEC benchmarks.</li>
</ol>
</div>
@@ -201,15 +198,13 @@ produced when linking C++ programs has been fixed.</li>
Bytecode Reader</a></li>
<li><a href="http://llvm.cs.uiuc.edu/PR392">Global Vars Have (Somewhat) Limited
Type Range</a></li>
-<li><a href="http://llvm.cs.uiuc.edu/PR341">operator&lt;&lt; on a Value* now
-prints the address of the object instead of its contents.</a></li>
+<li><a href="http://llvm.cs.uiuc.edu/PR341">operator&lt;&lt; on a Value* now prints the address of the object instead of its contents.</a></li>
<li><a href="http://llvm.cs.uiuc.edu/PR402">Bytecode Enhancements
-Needed</a></li>
-<li><a href="http://llvm.cs.uiuc.edu/PR404">[loopsimplify] Loop simplify is
-really slow on 252.eon</a></li>
-<li><a href="Http://llvm.cs.uiuc.edu/PR122">[code-cleanup] SymbolTable class
-cleanup, Type should not derive from Value, eliminate ConstantPointerRef
-class</a>.</li>
+ Needed</a></li>
+<li><a href="http://llvm.cs.uiuc.edu/PR404">[loopsimplify] Loop simplify is really slow on 252.eon</a></li>
+<li><a href="Http://llvm.cs.uiuc.edu/PR122">[code-cleanup] SymbolTable
+ class cleanup, Type should not derive from Value, eliminate
+ ConstantPointerRef class</a>.</li>
<li>The memory footprint of the LLVM IR has been reduced substantially.</li>
<li>The LLVM linker and many core classes have been sped up substantially.</li>
</ol>
@@ -350,12 +345,12 @@ initialized unsigned bitfields</a></li>
<li>Intel and AMD machines running Red Hat Linux and FreeBSD (and probably
other unix-like systems).</li>
<li>Sun UltraSPARC workstations running Solaris 8.</li>
+<li>PowerPC-based Mac OS X boxes, running 10.3 and above (C backend and
+ interpreter only, no native codegen is available yet).</li>
<li>Intel and AMD machines running on Win32 with the Cygwin libraries.</li>
-<li>PowerPC-based Mac OS X boxes, running 10.2 and above. Note that no JIT
-support is available yet, and LLC support is beta. The C backend can be used
-to produce stable code for this platform.</li>
</ul>
+
<p>The core LLVM infrastructure uses
<a href="http://www.gnu.org/software/autoconf/">GNU autoconf</a> to adapt itself
to the machine and operating system on which it is built. However, minor
@@ -401,11 +396,9 @@ useful to some people. In particular, if you would like to work on one of these
components, please contact us on the llvmdev list.</p>
<ul>
-<li>The PowerPC backend is incomplete and is known to miscompile several SPEC
-benchmarks. The file <tt>llvm/lib/Target/PowerPC/README.txt</tt> has
-details.</li>
<li>The following passes are incomplete or buggy: <tt>-pgmdep, -memdep,
-ipmodref, -cee</tt></li>
+
<li>The <tt>-pre</tt> pass is incomplete (there are cases it doesn't handle that
it should) and not thoroughly tested.</li>
<li>The <tt>llvm-ar</tt> tool is incomplete and probably buggy.</li>
diff --git a/llvm/lib/Target/PowerPC/PPC32AsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPC32AsmPrinter.cpp
deleted file mode 100644
index 62deac0a5bb6..000000000000
--- a/llvm/lib/Target/PowerPC/PPC32AsmPrinter.cpp
+++ /dev/null
@@ -1,735 +0,0 @@
-//===-- PowerPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly --===//
-//
-// 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 printer that converts from our internal representation
-// of machine-dependent LLVM code to PowerPC assembly language. This printer is
-// the output mechanism used by `llc'.
-//
-// Documentation at http://developer.apple.com/documentation/DeveloperTools/
-// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "asmprinter"
-#include "PowerPC.h"
-#include "PowerPCInstrInfo.h"
-#include "PowerPCTargetMachine.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/Assembly/Writer.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/Mangler.h"
-#include "Support/CommandLine.h"
-#include "Support/Debug.h"
-#include "Support/Statistic.h"
-#include "Support/StringExtras.h"
-#include <set>
-
-namespace llvm {
-
-namespace {
- Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
-
- struct Printer : public MachineFunctionPass {
- /// Output stream on which we're printing assembly code.
- ///
- std::ostream &O;
-
- /// Target machine description which we query for reg. names, data
- /// layout, etc.
- ///
- PowerPCTargetMachine &TM;
-
- /// Name-mangler for global names.
- ///
- Mangler *Mang;
- std::set<std::string> FnStubs, GVStubs, LinkOnceStubs;
- std::set<std::string> Strings;
-
- Printer(std::ostream &o, TargetMachine &tm) : O(o),
- TM(reinterpret_cast<PowerPCTargetMachine&>(tm)), LabelNumber(0) {}
-
- /// Cache of mangled name for current function. This is
- /// recalculated at the beginning of each call to
- /// runOnMachineFunction().
- ///
- std::string CurrentFnName;
-
- /// Unique incrementer for label values for referencing Global values.
- ///
- unsigned LabelNumber;
-
- virtual const char *getPassName() const {
- return "PowerPC Assembly Printer";
- }
-
- void printMachineInstruction(const MachineInstr *MI);
- void printOp(const MachineOperand &MO, bool elideOffsetKeyword = false);
- void printImmOp(const MachineOperand &MO, unsigned ArgType);
- void printConstantPool(MachineConstantPool *MCP);
- bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
- void emitGlobalConstant(const Constant* CV);
- void emitConstantValueOnly(const Constant *CV);
- };
-} // end of anonymous namespace
-
-/// createPPCCodePrinterPass - Returns a pass that prints the PPC
-/// assembly code for a MachineFunction to the given output stream,
-/// using the given target machine description. This should work
-/// regardless of whether the function is in SSA form.
-///
-FunctionPass *createPPCCodePrinterPass(std::ostream &o,TargetMachine &tm) {
- return new Printer(o, tm);
-}
-
-/// isStringCompatible - Can we treat the specified array as a string?
-/// Only if it is an array of ubytes or non-negative sbytes.
-///
-static bool isStringCompatible(const ConstantArray *CVA) {
- const Type *ETy = cast<ArrayType>(CVA->getType())->getElementType();
- if (ETy == Type::UByteTy) return true;
- if (ETy != Type::SByteTy) return false;
-
- for (unsigned i = 0; i < CVA->getNumOperands(); ++i)
- if (cast<ConstantSInt>(CVA->getOperand(i))->getValue() < 0)
- return false;
-
- return true;
-}
-
-/// toOctal - Convert the low order bits of X into an octal digit.
-///
-static inline char toOctal(int X) {
- return (X&7)+'0';
-}
-
-/// getAsCString - Return the specified array as a C compatible
-/// string, only if the predicate isStringCompatible is true.
-///
-static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
- assert(isStringCompatible(CVA) && "Array is not string compatible!");
-
- O << "\"";
- for (unsigned i = 0; i < CVA->getNumOperands(); ++i) {
- unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
-
- if (C == '"') {
- O << "\\\"";
- } else if (C == '\\') {
- O << "\\\\";
- } else if (isprint(C)) {
- O << C;
- } else {
- switch (C) {
- case '\b': O << "\\b"; break;
- case '\f': O << "\\f"; break;
- case '\n': O << "\\n"; break;
- case '\r': O << "\\r"; break;
- case '\t': O << "\\t"; break;
- default:
- O << '\\';
- O << toOctal(C >> 6);
- O << toOctal(C >> 3);
- O << toOctal(C >> 0);
- break;
- }
- }
- }
- O << "\"";
-}
-
-// Print out the specified constant, without a storage class. Only the
-// constants valid in constant expressions can occur here.
-void Printer::emitConstantValueOnly(const Constant *CV) {
- if (CV->isNullValue())
- O << "0";
- else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
- assert(CB == ConstantBool::True);
- O << "1";
- } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
- O << CI->getValue();
- else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
- O << CI->getValue();
- else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
- // This is a constant address for a global variable or function. Use the
- // name of the variable or function as the address value.
- O << Mang->getValueName(GV);
- else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
- const TargetData &TD = TM.getTargetData();
- switch (CE->getOpcode()) {
- case Instruction::GetElementPtr: {
- // generate a symbolic expression for the byte address
- const Constant *ptrVal = CE->getOperand(0);
- std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
- if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
- O << "(";
- emitConstantValueOnly(ptrVal);
- O << ") + " << Offset;
- } else {
- emitConstantValueOnly(ptrVal);
- }
- break;
- }
- case Instruction::Cast: {
- // Support only non-converting or widening casts for now, that is, ones
- // that do not involve a change in value. This assertion is really gross,
- // and may not even be a complete check.
- Constant *Op = CE->getOperand(0);
- const Type *OpTy = Op->getType(), *Ty = CE->getType();
-
- // Remember, kids, pointers on x86 can be losslessly converted back and
- // forth into 32-bit or wider integers, regardless of signedness. :-P
- assert(((isa<PointerType>(OpTy)
- && (Ty == Type::LongTy || Ty == Type::ULongTy
- || Ty == Type::IntTy || Ty == Type::UIntTy))
- || (isa<PointerType>(Ty)
- && (OpTy == Type::LongTy || OpTy == Type::ULongTy
- || OpTy == Type::IntTy || OpTy == Type::UIntTy))
- || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
- && OpTy->isLosslesslyConvertibleTo(Ty))))
- && "FIXME: Don't yet support this kind of constant cast expr");
- O << "(";
- emitConstantValueOnly(Op);
- O << ")";
- break;
- }
- case Instruction::Add:
- O << "(";
- emitConstantValueOnly(CE->getOperand(0));
- O << ") + (";
- emitConstantValueOnly(CE->getOperand(1));
- O << ")";
- break;
- default:
- assert(0 && "Unsupported operator!");
- }
- } else {
- assert(0 && "Unknown constant value!");
- }
-}
-
-// Print a constant value or values, with the appropriate storage class as a
-// prefix.
-void Printer::emitGlobalConstant(const Constant *CV) {
- const TargetData &TD = TM.getTargetData();
-
- if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
- if (isStringCompatible(CVA)) {
- O << "\t.ascii ";
- printAsCString(O, CVA);
- O << "\n";
- } else { // Not a string. Print the values in successive locations
- for (unsigned i=0, e = CVA->getNumOperands(); i != e; i++)
- emitGlobalConstant(CVA->getOperand(i));
- }
- return;
- } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
- // Print the fields in successive locations. Pad to align if needed!
- const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
- unsigned sizeSoFar = 0;
- for (unsigned i = 0, e = CVS->getNumOperands(); i != e; i++) {
- const Constant* field = CVS->getOperand(i);
-
- // Check if padding is needed and insert one or more 0s.
- unsigned fieldSize = TD.getTypeSize(field->getType());
- unsigned padSize = ((i == e-1? cvsLayout->StructSize
- : cvsLayout->MemberOffsets[i+1])
- - cvsLayout->MemberOffsets[i]) - fieldSize;
- sizeSoFar += fieldSize + padSize;
-
- // Now print the actual field value
- emitGlobalConstant(field);
-
- // Insert the field padding unless it's zero bytes...
- if (padSize)
- O << "\t.space\t " << padSize << "\n";
- }
- assert(sizeSoFar == cvsLayout->StructSize &&
- "Layout of constant struct may be incorrect!");
- return;
- } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
- // FP Constants are printed as integer constants to avoid losing
- // precision...
- double Val = CFP->getValue();
- switch (CFP->getType()->getTypeID()) {
- default: assert(0 && "Unknown floating point type!");
- case Type::FloatTyID: {
- union FU { // Abide by C TBAA rules
- float FVal;
- unsigned UVal;
- } U;
- U.FVal = Val;
- O << ".long\t" << U.UVal << "\t; float " << Val << "\n";
- return;
- }
- case Type::DoubleTyID: {
- union DU { // Abide by C TBAA rules
- double FVal;
- uint64_t UVal;
- struct {
- uint32_t MSWord;
- uint32_t LSWord;
- } T;
- } U;
- U.FVal = Val;
-
- O << ".long\t" << U.T.MSWord << "\t; double most significant word "
- << Val << "\n";
- O << ".long\t" << U.T.LSWord << "\t; double least significant word "
- << Val << "\n";
- return;
- }
- }
- } else if (CV->getType() == Type::ULongTy || CV->getType() == Type::LongTy) {
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
- union DU { // Abide by C TBAA rules
- int64_t UVal;
- struct {
- uint32_t MSWord;
- uint32_t LSWord;
- } T;
- } U;
- U.UVal = CI->getRawValue();
-
- O << ".long\t" << U.T.MSWord << "\t; Double-word most significant word "
- << U.UVal << "\n";
- O << ".long\t" << U.T.LSWord << "\t; Double-word least significant word "
- << U.UVal << "\n";
- return;
- }
- }
-
- const Type *type = CV->getType();
- O << "\t";
- switch (type->getTypeID()) {
- case Type::UByteTyID: case Type::SByteTyID:
- O << ".byte";
- break;
- case Type::UShortTyID: case Type::ShortTyID:
- O << ".short";
- break;
- case Type::BoolTyID:
- case Type::PointerTyID:
- case Type::UIntTyID: case Type::IntTyID:
- O << ".long";
- break;
- case Type::ULongTyID: case Type::LongTyID:
- assert (0 && "Should have already output double-word constant.");
- case Type::FloatTyID: case Type::DoubleTyID:
- assert (0 && "Should have already output floating point constant.");
- default:
- if (CV == Constant::getNullValue(type)) { // Zero initializer?
- O << ".space\t" << TD.getTypeSize(type) << "\n";
- return;
- }
- std::cerr << "Can't handle printing: " << *CV;
- abort();
- break;
- }
- O << "\t";
- emitConstantValueOnly(CV);
- O << "\n";
-}
-
-/// printConstantPool - Print to the current output stream assembly
-/// representations of the constants in the constant pool MCP. This is
-/// used to print out constants which have been "spilled to memory" by
-/// the code generator.
-///
-void Printer::printConstantPool(MachineConstantPool *MCP) {
- const std::vector<Constant*> &CP = MCP->getConstants();
- const TargetData &TD = TM.getTargetData();
-
- if (CP.empty()) return;
-
- for (unsigned i = 0, e = CP.size(); i != e; ++i) {
- O << "\t.const\n";
- O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
- << "\n";
- O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t;"
- << *CP[i] << "\n";
- emitGlobalConstant(CP[i]);
- }
-}
-
-/// runOnMachineFunction - This uses the printMachineInstruction()
-/// method to print assembly for each instruction.
-///
-bool Printer::runOnMachineFunction(MachineFunction &MF) {
- O << "\n\n";
- // What's my mangled name?
- CurrentFnName = Mang->getValueName(MF.getFunction());
-
- // Print out constants referenced by the function
- printConstantPool(MF.getConstantPool());
-
- // Print out labels for the function.
- O << "\t.text\n";
- O << "\t.globl\t" << CurrentFnName << "\n";
- O << "\t.align 2\n";
- O << CurrentFnName << ":\n";
-
- // Print out code for the function.
- for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
- I != E; ++I) {
- // Print a label for the basic block.
- O << ".LBB" << CurrentFnName << "_" << I->getNumber() << ":\t; "
- << I->getBasicBlock()->getName() << "\n";
- for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II) {
- // Print the assembly for the instruction.
- O << "\t";
- printMachineInstruction(II);
- }
- }
- ++LabelNumber;
-
- // We didn't modify anything.
- return false;
-}
-
-void Printer::printOp(const MachineOperand &MO,
- bool elideOffsetKeyword /* = false */) {
- const MRegisterInfo &RI = *TM.getRegisterInfo();
- int new_symbol;
-
- switch (MO.getType()) {
- case MachineOperand::MO_VirtualRegister:
- if (Value *V = MO.getVRegValueOrNull()) {
- O << "<" << V->getName() << ">";
- return;
- }
- // FALLTHROUGH
- case MachineOperand::MO_MachineRegister:
- case MachineOperand::MO_CCRegister:
- O << LowercaseString(RI.get(MO.getReg()).Name);
- return;
-
- case MachineOperand::MO_SignExtendedImmed:
- case MachineOperand::MO_UnextendedImmed:
- std::cerr << "printOp() does not handle immediate values\n";
- abort();
- return;
-
- case MachineOperand::MO_PCRelativeDisp:
- std::cerr << "Shouldn't use addPCDisp() when building PPC MachineInstrs";
- abort();
- return;
-
- case MachineOperand::MO_MachineBasicBlock: {
- MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
- O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
- << "_" << MBBOp->getNumber() << "\t; "
- << MBBOp->getBasicBlock()->getName();
- return;
- }
-
- case MachineOperand::MO_ConstantPoolIndex:
- O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex();
- return;
-
- case MachineOperand::MO_ExternalSymbol:
- O << MO.getSymbolName();
- return;
-
- case MachineOperand::MO_GlobalAddress:
- if (!elideOffsetKeyword) {
- GlobalValue *GV = MO.getGlobal();
- std::string Name = Mang->getValueName(GV);
-
- // Dynamically-resolved functions need a stub for the function
- Function *F = dyn_cast<Function>(GV);
- if (F && F->isExternal() &&
- TM.CalledFunctions.find(F) != TM.CalledFunctions.end()) {
- FnStubs.insert(Name);
- O << "L" << Name << "$stub";
- return;
- }
-
- // External global variables need a non-lazily-resolved stub
- if (!GV->hasInternalLinkage() &&
- TM.AddressTaken.find(GV) != TM.AddressTaken.end()) {
- GVStubs.insert(Name);
- O << "L" << Name << "$non_lazy_ptr";
- return;
- }
-
- O << Mang->getValueName(GV);
- }
- return;
-
- default:
- O << "<unknown operand type: " << MO.getType() << ">";
- return;
- }
-}
-
-void Printer::printImmOp(const MachineOperand &MO, unsigned ArgType) {
- int Imm = MO.getImmedValue();
- if (ArgType == PPC32II::Simm16 || ArgType == PPC32II::Disimm16) {
- O << (short)Imm;
- } else if (ArgType == PPC32II::Zimm16) {
- O << (unsigned short)Imm;
- } else {
- O << Imm;
- }
-}
-
-/// printMachineInstruction -- Print out a single PPC32 LLVM instruction
-/// MI in Darwin syntax to the current output stream.
-///
-void Printer::printMachineInstruction(const MachineInstr *MI) {
- unsigned Opcode = MI->getOpcode();
- const TargetInstrInfo &TII = *TM.getInstrInfo();
- const TargetInstrDescriptor &Desc = TII.get(Opcode);
- unsigned i;
-
- unsigned ArgCount = MI->getNumOperands();
- unsigned ArgType[] = {
- (Desc.TSFlags >> PPC32II::Arg0TypeShift) & PPC32II::ArgTypeMask,
- (Desc.TSFlags >> PPC32II::Arg1TypeShift) & PPC32II::ArgTypeMask,
- (Desc.TSFlags >> PPC32II::Arg2TypeShift) & PPC32II::ArgTypeMask,
- (Desc.TSFlags >> PPC32II::Arg3TypeShift) & PPC32II::ArgTypeMask,
- (Desc.TSFlags >> PPC32II::Arg4TypeShift) & PPC32II::ArgTypeMask
- };
- assert(((Desc.TSFlags & PPC32II::VMX) == 0) &&
- "Instruction requires VMX support");
- assert(((Desc.TSFlags & PPC32II::PPC64) == 0) &&
- "Instruction requires 64 bit support");
- ++EmittedInsts;
-
- // CALLpcrel and CALLindirect are handled specially here to print only the
- // appropriate number of args that the assembler expects. This is because
- // may have many arguments appended to record the uses of registers that are
- // holding arguments to the called function.
- if (Opcode == PPC32::COND_BRANCH) {
- std::cerr << "Error: untranslated conditional branch psuedo instruction!\n";
- abort();
- } else if (Opcode == PPC32::IMPLICIT_DEF) {
- O << "; IMPLICIT DEF ";
- printOp(MI->getOperand(0));
- O << "\n";
- return;
- } else if (Opcode == PPC32::CALLpcrel) {
- O << TII.getName(Opcode) << " ";
- printOp(MI->getOperand(0));
- O << "\n";
- return;
- } else if (Opcode == PPC32::CALLindirect) {
- O << TII.getName(Opcode) << " ";
- printImmOp(MI->getOperand(0), ArgType[0]);
- O << ", ";
- printImmOp(MI->getOperand(1), ArgType[0]);
- O << "\n";
- return;
- } else if (Opcode == PPC32::MovePCtoLR) {
- // FIXME: should probably be converted to cout.width and cout.fill
- O << "bl \"L0000" << LabelNumber << "$pb\"\n";
- O << "\"L0000" << LabelNumber << "$pb\":\n";
- O << "\tmflr ";
- printOp(MI->getOperand(0));
- O << "\n";
- return;
- }
-
- O << TII.getName(Opcode) << " ";
- if (Opcode == PPC32::LOADLoDirect || Opcode == PPC32::LOADLoIndirect) {
- printOp(MI->getOperand(0));
- O << ", lo16(";
- printOp(MI->getOperand(2));
- O << "-\"L0000" << LabelNumber << "$pb\")";
- O << "(";
- if (MI->getOperand(1).getReg() == PPC32::R0)
- O << "0";
- else
- printOp(MI->getOperand(1));
- O << ")\n";
- } else if (Opcode == PPC32::LOADHiAddr) {
- printOp(MI->getOperand(0));
- O << ", ";
- if (MI->getOperand(1).getReg() == PPC32::R0)
- O << "0";
- else
- printOp(MI->getOperand(1));
- O << ", ha16(" ;
- printOp(MI->getOperand(2));
- O << "-\"L0000" << LabelNumber << "$pb\")\n";
- } else if (ArgCount == 3 && ArgType[1] == PPC32II::Disimm16) {
- printOp(MI->getOperand(0));
- O << ", ";
- printImmOp(MI->getOperand(1), ArgType[1]);
- O << "(";
- if (MI->getOperand(2).hasAllocatedReg() &&
- MI->getOperand(2).getReg() == PPC32::R0)
- O << "0";
- else
- printOp(MI->getOperand(2));
- O << ")\n";
- } else {
- for (i = 0; i < ArgCount; ++i) {
- // addi and friends
- if (i == 1 && ArgCount == 3 && ArgType[2] == PPC32II::Simm16 &&
- MI->getOperand(1).hasAllocatedReg() &&
- MI->getOperand(1).getReg() == PPC32::R0) {
- O << "0";
- // for long branch support, bc $+8
- } else if (i == 1 && ArgCount == 2 && MI->getOperand(1).isImmediate() &&
- TII.isBranch(MI->getOpcode())) {
- O << "$+8";
- assert(8 == MI->getOperand(i).getImmedValue()
- && "branch off PC not to pc+8?");
- //printOp(MI->getOperand(i));
- } else if (MI->getOperand(i).isImmediate()) {
- printImmOp(MI->getOperand(i), ArgType[i]);
- } else {
- printOp(MI->getOperand(i));
- }
- if (ArgCount - 1 == i)
- O << "\n";
- else
- O << ", ";
- }
- }
-}
-
-bool Printer::doInitialization(Module &M) {
- Mang = new Mangler(M, true);
- return false; // success
-}
-
-// SwitchSection - Switch to the specified section of the executable if we are
-// not already in it!
-//
-static void SwitchSection(std::ostream &OS, std::string &CurSection,
- const char *NewSection) {
- if (CurSection != NewSection) {
- CurSection = NewSection;
- if (!CurSection.empty())
- OS << "\t" << NewSection << "\n";
- }
-}
-
-bool Printer::doFinalization(Module &M) {
- const TargetData &TD = TM.getTargetData();
- std::string CurSection;
-
- // Print out module-level global variables here.
- for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
- if (I->hasInitializer()) { // External global require no code
- O << "\n\n";
- std::string name = Mang->getValueName(I);
- Constant *C = I->getInitializer();
- unsigned Size = TD.getTypeSize(C->getType());
- unsigned Align = TD.getTypeAlignment(C->getType());
-
- if (C->isNullValue() && /* FIXME: Verify correct */
- (I->hasInternalLinkage() || I->hasWeakLinkage())) {
- SwitchSection(O, CurSection, ".data");
- if (I->hasInternalLinkage())
- O << ".lcomm " << name << "," << TD.getTypeSize(C->getType())
- << "," << (unsigned)TD.getTypeAlignment(C->getType());
- else
- O << ".comm " << name << "," << TD.getTypeSize(C->getType());
- O << "\t\t; ";
- WriteAsOperand(O, I, true, true, &M);
- O << "\n";
- } else {
- switch (I->getLinkage()) {
- case GlobalValue::LinkOnceLinkage:
- O << ".section __TEXT,__textcoal_nt,coalesced,no_toc\n"
- << ".weak_definition " << name << '\n'
- << ".private_extern " << name << '\n'
- << ".section __DATA,__datacoal_nt,coalesced,no_toc\n";
- LinkOnceStubs.insert(name);
- break;
- case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
- // Nonnull linkonce -> weak
- O << "\t.weak " << name << "\n";
- SwitchSection(O, CurSection, "");
- O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
- break;
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << "\t.globl " << name << "\n";
- // FALL THROUGH
- case GlobalValue::InternalLinkage:
- SwitchSection(O, CurSection, ".data");
- break;
- }
-
- O << "\t.align " << Align << "\n";
- O << name << ":\t\t\t\t; ";
- WriteAsOperand(O, I, true, true, &M);
- O << " = ";
- WriteAsOperand(O, C, false, false, &M);
- O << "\n";
- emitGlobalConstant(C);
- }
- }
-
- // Output stubs for link-once variables
- if (LinkOnceStubs.begin() != LinkOnceStubs.end())
- O << ".data\n.align 2\n";
- for (std::set<std::string>::iterator i = LinkOnceStubs.begin(),
- e = LinkOnceStubs.end(); i != e; ++i) {
- O << *i << "$non_lazy_ptr:\n"
- << "\t.long\t" << *i << '\n';
- }
-
- // Output stubs for dynamically-linked functions
- for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
- i != e; ++i)
- {
- O << ".data\n";
- O << ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n";
- O << "\t.align 2\n";
- O << "L" << *i << "$stub:\n";
- O << "\t.indirect_symbol " << *i << "\n";
- O << "\tmflr r0\n";
- O << "\tbcl 20,31,L0$" << *i << "\n";
- O << "L0$" << *i << ":\n";
- O << "\tmflr r11\n";
- O << "\taddis r11,r11,ha16(L" << *i << "$lazy_ptr-L0$" << *i << ")\n";
- O << "\tmtlr r0\n";
- O << "\tlwzu r12,lo16(L" << *i << "$lazy_ptr-L0$" << *i << ")(r11)\n";
- O << "\tmtctr r12\n";
- O << "\tbctr\n";
- O << ".data\n";
- O << ".lazy_symbol_pointer\n";
- O << "L" << *i << "$lazy_ptr:\n";
- O << "\t.indirect_symbol " << *i << "\n";
- O << "\t.long dyld_stub_binding_helper\n";
- }
-
- O << "\n";
-
- // Output stubs for external global variables
- if (GVStubs.begin() != GVStubs.end())
- O << ".data\n.non_lazy_symbol_pointer\n";
- for (std::set<std::string>::iterator i = GVStubs.begin(), e = GVStubs.end();
- i != e; ++i) {
- O << "L" << *i << "$non_lazy_ptr:\n";
- O << "\t.indirect_symbol " << *i << "\n";
- O << "\t.long\t0\n";
- }
-
- delete Mang;
- return false; // success
-}
-
-} // End llvm namespace
diff --git a/llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp b/llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp
deleted file mode 100644
index 3c423e5cef6b..000000000000
--- a/llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===-- PowerPCCodeEmitter.cpp - JIT Code Emitter for PowerPC -----*- 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.
-//
-//===----------------------------------------------------------------------===//
-//
-//
-//===----------------------------------------------------------------------===//
-
-#include "PowerPCTargetMachine.h"
-
-namespace llvm {
-
-/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
-/// machine code emitted. This uses a MachineCodeEmitter object to handle
-/// actually outputting the machine code and resolving things like the address
-/// of functions. This method should returns true if machine code emission is
-/// not supported.
-///
-bool PowerPCTargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
- MachineCodeEmitter &MCE) {
- return true;
- // It should go something like this:
- // PM.add(new Emitter(MCE)); // Machine code emitter pass for PowerPC
- // Delete machine code for this function after emitting it:
- // PM.add(createMachineCodeDeleter());
-}
-
-void *PowerPCJITInfo::getJITStubForFunction(Function *F,
- MachineCodeEmitter &MCE) {
- assert (0 && "PowerPCJITInfo::getJITStubForFunction not implemented");
- return 0;
-}
-
-void PowerPCJITInfo::replaceMachineCodeForFunction (void *Old, void *New) {
- assert (0 && "PowerPCJITInfo::replaceMachineCodeForFunction not implemented");
-}
-
-} // end llvm namespace
-
diff --git a/llvm/lib/Target/PowerPC/PPC32ISelSimple.cpp b/llvm/lib/Target/PowerPC/PPC32ISelSimple.cpp
deleted file mode 100644
index 35272380d69d..000000000000
--- a/llvm/lib/Target/PowerPC/PPC32ISelSimple.cpp
+++ /dev/null
@@ -1,3343 +0,0 @@
-//===-- InstSelectSimple.cpp - A simple instruction selector for PowerPC --===//
-//
-// 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.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "isel"
-#include "PowerPC.h"
-#include "PowerPCInstrBuilder.h"
-#include "PowerPCInstrInfo.h"
-#include "PowerPCTargetMachine.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Function.h"
-#include "llvm/Instructions.h"
-#include "llvm/Pass.h"
-#include "llvm/CodeGen/IntrinsicLowering.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/SSARegMap.h"
-#include "llvm/Target/MRegisterInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/GetElementPtrTypeIterator.h"
-#include "llvm/Support/InstVisitor.h"
-#include "Support/Debug.h"
-#include "Support/Statistic.h"
-#include <vector>
-using namespace llvm;
-
-namespace {
- Statistic<> GEPFolds("ppc-codegen", "Number of GEPs folded");
-
- /// TypeClass - Used by the PowerPC backend to group LLVM types by their basic
- /// PPC Representation.
- ///
- enum TypeClass {
- cByte, cShort, cInt, cFP32, cFP64, cLong
- };
-}
-
-/// getClass - Turn a primitive type into a "class" number which is based on the
-/// size of the type, and whether or not it is floating point.
-///
-static inline TypeClass getClass(const Type *Ty) {
- switch (Ty->getTypeID()) {
- case Type::SByteTyID:
- case Type::UByteTyID: return cByte; // Byte operands are class #0
- case Type::ShortTyID:
- case Type::UShortTyID: return cShort; // Short operands are class #1
- case Type::IntTyID:
- case Type::UIntTyID:
- case Type::PointerTyID: return cInt; // Ints and pointers are class #2
-
- case Type::FloatTyID: return cFP32; // Single float is #3
- case Type::DoubleTyID: return cFP64; // Double Point is #4
-
- case Type::LongTyID:
- case Type::ULongTyID: return cLong; // Longs are class #5
- default:
- assert(0 && "Invalid type to getClass!");
- return cByte; // not reached
- }
-}
-
-// getClassB - Just like getClass, but treat boolean values as ints.
-static inline TypeClass getClassB(const Type *Ty) {
- if (Ty == Type::BoolTy) return cInt;
- return getClass(Ty);
-}
-
-namespace {
- struct ISel : public FunctionPass, InstVisitor<ISel> {
- PowerPCTargetMachine &TM;
- MachineFunction *F; // The function we are compiling into
- MachineBasicBlock *BB; // The current MBB we are compiling
- int VarArgsFrameIndex; // FrameIndex for start of varargs area
-
- std::map<Value*, unsigned> RegMap; // Mapping between Values and SSA Regs
-
- // External functions used in the Module
- Function *fmodfFn, *fmodFn, *__moddi3Fn, *__divdi3Fn, *__umoddi3Fn,
- *__udivdi3Fn, *__fixsfdiFn, *__fixdfdiFn, *__floatdisfFn, *__floatdidfFn,
- *mallocFn, *freeFn;
-
- // MBBMap - Mapping between LLVM BB -> Machine BB
- std::map<const BasicBlock*, MachineBasicBlock*> MBBMap;
-
- // AllocaMap - Mapping from fixed sized alloca instructions to the
- // FrameIndex for the alloca.
- std::map<AllocaInst*, unsigned> AllocaMap;
-
- // A Reg to hold the base address used for global loads and stores, and a
- // flag to set whether or not we need to emit it for this function.
- unsigned GlobalBaseReg;
- bool GlobalBaseInitialized;
-
- ISel(TargetMachine &tm) : TM(reinterpret_cast<PowerPCTargetMachine&>(tm)),
- F(0), BB(0) {}
-
- bool doInitialization(Module &M) {
- // Add external functions that we may call
- Type *d = Type::DoubleTy;
- Type *f = Type::FloatTy;
- Type *l = Type::LongTy;
- Type *ul = Type::ULongTy;
- Type *voidPtr = PointerType::get(Type::SByteTy);
- // float fmodf(float, float);
- fmodfFn = M.getOrInsertFunction("fmodf", f, f, f, 0);
- // double fmod(double, double);
- fmodFn = M.getOrInsertFunction("fmod", d, d, d, 0);
- // long __moddi3(long, long);
- __moddi3Fn = M.getOrInsertFunction("__moddi3", l, l, l, 0);
- // long __divdi3(long, long);
- __divdi3Fn = M.getOrInsertFunction("__divdi3", l, l, l, 0);
- // unsigned long __umoddi3(unsigned long, unsigned long);
- __umoddi3Fn = M.getOrInsertFunction("__umoddi3", ul, ul, ul, 0);
- // unsigned long __udivdi3(unsigned long, unsigned long);
- __udivdi3Fn = M.getOrInsertFunction("__udivdi3", ul, ul, ul, 0);
- // long __fixsfdi(float)
- __fixdfdiFn = M.getOrInsertFunction("__fixsfdi", l, f, 0);
- // long __fixdfdi(double)
- __fixdfdiFn = M.getOrInsertFunction("__fixdfdi", l, d, 0);
- // float __floatdisf(long)
- __floatdisfFn = M.getOrInsertFunction("__floatdisf", f, l, 0);
- // double __floatdidf(long)
- __floatdidfFn = M.getOrInsertFunction("__floatdidf", d, l, 0);
- // void* malloc(size_t)
- mallocFn = M.getOrInsertFunction("malloc", voidPtr, Type::UIntTy, 0);
- // void free(void*)
- freeFn = M.getOrInsertFunction("free", Type::VoidTy, voidPtr, 0);
- return false;
- }
-
- /// runOnFunction - Top level implementation of instruction selection for
- /// the entire function.
- ///
- bool runOnFunction(Function &Fn) {
- // First pass over the function, lower any unknown intrinsic functions
- // with the IntrinsicLowering class.
- LowerUnknownIntrinsicFunctionCalls(Fn);
-
- F = &MachineFunction::construct(&Fn, TM);
-
- // Create all of the machine basic blocks for the function...
- for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
- F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I));
-
- BB = &F->front();
-
- // Make sure we re-emit a set of the global base reg if necessary
- GlobalBaseInitialized = false;
-
- // Copy incoming arguments off of the stack...
- LoadArgumentsToVirtualRegs(Fn);
-
- // Instruction select everything except PHI nodes
- visit(Fn);
-
- // Select the PHI nodes
- SelectPHINodes();
-
- RegMap.clear();
- MBBMap.clear();
- AllocaMap.clear();
- F = 0;
- // We always build a machine code representation for the function
- return true;
- }
-
- virtual const char *getPassName() const {
- return "PowerPC Simple Instruction Selection";
- }
-
- /// visitBasicBlock - This method is called when we are visiting a new basic
- /// block. This simply creates a new MachineBasicBlock to emit code into
- /// and adds it to the current MachineFunction. Subsequent visit* for
- /// instructions will be invoked for all instructions in the basic block.
- ///
- void visitBasicBlock(BasicBlock &LLVM_BB) {
- BB = MBBMap[&LLVM_BB];
- }
-
- /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
- /// function, lowering any calls to unknown intrinsic functions into the
- /// equivalent LLVM code.
- ///
- void LowerUnknownIntrinsicFunctionCalls(Function &F);
-
- /// LoadArgumentsToVirtualRegs - Load all of the arguments to this function
- /// from the stack into virtual registers.
- ///
- void LoadArgumentsToVirtualRegs(Function &F);
-
- /// SelectPHINodes - Insert machine code to generate phis. This is tricky
- /// because we have to generate our sources into the source basic blocks,
- /// not the current one.
- ///
- void SelectPHINodes();
-
- // Visitation methods for various instructions. These methods simply emit
- // fixed PowerPC code for each instruction.
-
- // Control flow operators
- void visitReturnInst(ReturnInst &RI);
- void visitBranchInst(BranchInst &BI);
-
- struct ValueRecord {
- Value *Val;
- unsigned Reg;
- const Type *Ty;
- ValueRecord(unsigned R, const Type *T) : Val(0), Reg(R), Ty(T) {}
- ValueRecord(Value *V) : Val(V), Reg(0), Ty(V->getType()) {}
- };
-
- // This struct is for recording the necessary operations to emit the GEP
- struct CollapsedGepOp {
- bool isMul;
- Value *index;
- ConstantSInt *size;
- CollapsedGepOp(bool mul, Value *i, ConstantSInt *s) :
- isMul(mul), index(i), size(s) {}
- };
-
- void doCall(const ValueRecord &Ret, MachineInstr *CallMI,
- const std::vector<ValueRecord> &Args, bool isVarArg);
- void visitCallInst(CallInst &I);
- void visitIntrinsicCall(Intrinsic::ID ID, CallInst &I);
-
- // Arithmetic operators
- void visitSimpleBinary(BinaryOperator &B, unsigned OpcodeClass);
- void visitAdd(BinaryOperator &B) { visitSimpleBinary(B, 0); }
- void visitSub(BinaryOperator &B) { visitSimpleBinary(B, 1); }
- void visitMul(BinaryOperator &B);
-
- void visitDiv(BinaryOperator &B) { visitDivRem(B); }
- void visitRem(BinaryOperator &B) { visitDivRem(B); }
- void visitDivRem(BinaryOperator &B);
-
- // Bitwise operators
- void visitAnd(BinaryOperator &B) { visitSimpleBinary(B, 2); }
- void visitOr (BinaryOperator &B) { visitSimpleBinary(B, 3); }
- void visitXor(BinaryOperator &B) { visitSimpleBinary(B, 4); }
-
- // Comparison operators...
- void visitSetCondInst(SetCondInst &I);
- unsigned EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
- MachineBasicBlock *MBB,
- MachineBasicBlock::iterator MBBI);
- void visitSelectInst(SelectInst &SI);
-
-
- // Memory Instructions
- void visitLoadInst(LoadInst &I);
- void visitStoreInst(StoreInst &I);
- void visitGetElementPtrInst(GetElementPtrInst &I);
- void visitAllocaInst(AllocaInst &I);
- void visitMallocInst(MallocInst &I);
- void visitFreeInst(FreeInst &I);
-
- // Other operators
- void visitShiftInst(ShiftInst &I);
- void visitPHINode(PHINode &I) {} // PHI nodes handled by second pass
- void visitCastInst(CastInst &I);
- void visitVANextInst(VANextInst &I);
- void visitVAArgInst(VAArgInst &I);
-
- void visitInstruction(Instruction &I) {
- std::cerr << "Cannot instruction select: " << I;
- abort();
- }
-
- /// promote32 - Make a value 32-bits wide, and put it somewhere.
- ///
- void promote32(unsigned targetReg, const ValueRecord &VR);
-
- /// emitGEPOperation - Common code shared between visitGetElementPtrInst and
- /// constant expression GEP support.
- ///
- void emitGEPOperation(MachineBasicBlock *BB, MachineBasicBlock::iterator IP,
- Value *Src, User::op_iterator IdxBegin,
- User::op_iterator IdxEnd, unsigned TargetReg,
- bool CollapseRemainder, ConstantSInt **Remainder);
-
- /// emitCastOperation - Common code shared between visitCastInst and
- /// constant expression cast support.
- ///
- void emitCastOperation(MachineBasicBlock *BB,MachineBasicBlock::iterator IP,
- Value *Src, const Type *DestTy, unsigned TargetReg);
-
- /// emitSimpleBinaryOperation - Common code shared between visitSimpleBinary
- /// and constant expression support.
- ///
- void emitSimpleBinaryOperation(MachineBasicBlock *BB,
- MachineBasicBlock::iterator IP,
- Value *Op0, Value *Op1,
- unsigned OperatorClass, unsigned TargetReg);
-
- /// emitBinaryFPOperation - This method handles emission of floating point
- /// Add (0), Sub (1), Mul (2), and Div (3) operations.
- void emitBinaryFPOperation(MachineBasicBlock *BB,
- MachineBasicBlock::iterator IP,
- Value *Op0, Value *Op1,
- unsigned OperatorClass, unsigned TargetReg);
-
- void emitMultiply(MachineBasicBlock *BB, MachineBasicBlock::iterator IP,
- Value *Op0, Value *Op1, unsigned TargetReg);
-
- void doMultiply(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- unsigned DestReg, Value *Op0, Value *Op1);
-
- /// doMultiplyConst - This method will multiply the value in Op0Reg by the
- /// value of the ContantInt *CI
- void doMultiplyConst(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- unsigned DestReg, Value *Op0, ConstantInt *CI);
-
- void emitDivRemOperation(MachineBasicBlock *BB,
- MachineBasicBlock::iterator IP,
- Value *Op0, Value *Op1, bool isDiv,
- unsigned TargetReg);
-
- /// emitSetCCOperation - Common code shared between visitSetCondInst and
- /// constant expression support.
- ///
- void emitSetCCOperation(MachineBasicBlock *BB,
- MachineBasicBlock::iterator IP,
- Value *Op0, Value *Op1, unsigned Opcode,
- unsigned TargetReg);
-
- /// emitShiftOperation - Common code shared between visitShiftInst and
- /// constant expression support.
- ///
- void emitShiftOperation(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Value *Op, Value *ShiftAmount, bool isLeftShift,
- const Type *ResultTy, unsigned DestReg);
-
- /// emitSelectOperation - Common code shared between visitSelectInst and the
- /// constant expression support.
- ///
- void emitSelectOperation(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Value *Cond, Value *TrueVal, Value *FalseVal,
- unsigned DestReg);
-
- /// copyGlobalBaseToRegister - Output the instructions required to put the
- /// base address to use for accessing globals into a register.
- ///
- void ISel::copyGlobalBaseToRegister(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- unsigned R);
-
- /// copyConstantToRegister - Output the instructions required to put the
- /// specified constant into the specified register.
- ///
- void copyConstantToRegister(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator MBBI,
- Constant *C, unsigned Reg);
-
- void emitUCOM(MachineBasicBlock *MBB, MachineBasicBlock::iterator MBBI,
- unsigned LHS, unsigned RHS);
-
- /// makeAnotherReg - This method returns the next register number we haven't
- /// yet used.
- ///
- /// Long values are handled somewhat specially. They are always allocated
- /// as pairs of 32 bit integer values. The register number returned is the
- /// high 32 bits of the long value, and the regNum+1 is the low 32 bits.
- ///
- unsigned makeAnotherReg(const Type *Ty) {
- assert(dynamic_cast<const PowerPCRegisterInfo*>(TM.getRegisterInfo()) &&
- "Current target doesn't have PPC reg info??");
- const PowerPCRegisterInfo *MRI =
- static_cast<const PowerPCRegisterInfo*>(TM.getRegisterInfo());
- if (Ty == Type::LongTy || Ty == Type::ULongTy) {
- const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy);
- // Create the lower part
- F->getSSARegMap()->createVirtualRegister(RC);
- // Create the upper part.
- return F->getSSARegMap()->createVirtualRegister(RC)-1;
- }
-
- // Add the mapping of regnumber => reg class to MachineFunction
- const TargetRegisterClass *RC = MRI->getRegClassForType(Ty);
- return F->getSSARegMap()->createVirtualRegister(RC);
- }
-
- /// getReg - This method turns an LLVM value into a register number.
- ///
- unsigned getReg(Value &V) { return getReg(&V); } // Allow references
- unsigned getReg(Value *V) {
- // Just append to the end of the current bb.
- MachineBasicBlock::iterator It = BB->end();
- return getReg(V, BB, It);
- }
- unsigned getReg(Value *V, MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IPt);
-
- /// canUseAsImmediateForOpcode - This method returns whether a ConstantInt
- /// is okay to use as an immediate argument to a certain binary operation
- bool canUseAsImmediateForOpcode(ConstantInt *CI, unsigned Opcode);
-
- /// getFixedSizedAllocaFI - Return the frame index for a fixed sized alloca
- /// that is to be statically allocated with the initial stack frame
- /// adjustment.
- unsigned getFixedSizedAllocaFI(AllocaInst *AI);
- };
-}
-
-/// dyn_castFixedAlloca - If the specified value is a fixed size alloca
-/// instruction in the entry block, return it. Otherwise, return a null
-/// pointer.
-static AllocaInst *dyn_castFixedAlloca(Value *V) {
- if (AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
- BasicBlock *BB = AI->getParent();
- if (isa<ConstantUInt>(AI->getArraySize()) && BB ==&BB->getParent()->front())
- return AI;
- }
- return 0;
-}
-
-/// getReg - This method turns an LLVM value into a register number.
-///
-unsigned ISel::getReg(Value *V, MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IPt) {
- if (Constant *C = dyn_cast<Constant>(V)) {
- unsigned Reg = makeAnotherReg(V->getType());
- copyConstantToRegister(MBB, IPt, C, Reg);
- return Reg;
- } else if (AllocaInst *AI = dyn_castFixedAlloca(V)) {
- unsigned Reg = makeAnotherReg(V->getType());
- unsigned FI = getFixedSizedAllocaFI(AI);
- addFrameReference(BuildMI(*MBB, IPt, PPC32::ADDI, 2, Reg), FI, 0, false);
- return Reg;
- }
-
- unsigned &Reg = RegMap[V];
- if (Reg == 0) {
- Reg = makeAnotherReg(V->getType());
- RegMap[V] = Reg;
- }
-
- return Reg;
-}
-
-/// canUseAsImmediateForOpcode - This method returns whether a ConstantInt
-/// is okay to use as an immediate argument to a certain binary operator.
-///
-/// Operator is one of: 0 for Add, 1 for Sub, 2 for And, 3 for Or, 4 for Xor.
-bool ISel::canUseAsImmediateForOpcode(ConstantInt *CI, unsigned Operator) {
- ConstantSInt *Op1Cs;
- ConstantUInt *Op1Cu;
-
- // ADDI, Compare, and non-indexed Load take SIMM
- bool cond1 = (Operator == 0)
- && (Op1Cs = dyn_cast<ConstantSInt>(CI))
- && (Op1Cs->getValue() <= 32767)
- && (Op1Cs->getValue() >= -32768);
-
- // SUBI takes -SIMM since it is a mnemonic for ADDI
- bool cond2 = (Operator == 1)
- && (Op1Cs = dyn_cast<ConstantSInt>(CI))
- && (Op1Cs->getValue() <= 32768)
- && (Op1Cs->getValue() >= -32767);
-
- // ANDIo, ORI, and XORI take unsigned values
- bool cond3 = (Operator >= 2)
- && (Op1Cs = dyn_cast<ConstantSInt>(CI))
- && (Op1Cs->getValue() >= 0)
- && (Op1Cs->getValue() <= 32767);
-
- // ADDI and SUBI take SIMMs, so we have to make sure the UInt would fit
- bool cond4 = (Operator < 2)
- && (Op1Cu = dyn_cast<ConstantUInt>(CI))
- && (Op1Cu->getValue() <= 32767);
-
- // ANDIo, ORI, and XORI take UIMMs, so they can be larger
- bool cond5 = (Operator >= 2)
- && (Op1Cu = dyn_cast<ConstantUInt>(CI))
- && (Op1Cu->getValue() <= 65535);
-
- if (cond1 || cond2 || cond3 || cond4 || cond5)
- return true;
-
- return false;
-}
-
-/// getFixedSizedAllocaFI - Return the frame index for a fixed sized alloca
-/// that is to be statically allocated with the initial stack frame
-/// adjustment.
-unsigned ISel::getFixedSizedAllocaFI(AllocaInst *AI) {
- // Already computed this?
- std::map<AllocaInst*, unsigned>::iterator I = AllocaMap.lower_bound(AI);
- if (I != AllocaMap.end() && I->first == AI) return I->second;
-
- const Type *Ty = AI->getAllocatedType();
- ConstantUInt *CUI = cast<ConstantUInt>(AI->getArraySize());
- unsigned TySize = TM.getTargetData().getTypeSize(Ty);
- TySize *= CUI->getValue(); // Get total allocated size...
- unsigned Alignment = TM.getTargetData().getTypeAlignment(Ty);
-
- // Create a new stack object using the frame manager...
- int FrameIdx = F->getFrameInfo()->CreateStackObject(TySize, Alignment);
- AllocaMap.insert(I, std::make_pair(AI, FrameIdx));
- return FrameIdx;
-}
-
-
-/// copyGlobalBaseToRegister - Output the instructions required to put the
-/// base address to use for accessing globals into a register.
-///
-void ISel::copyGlobalBaseToRegister(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- unsigned R) {
- if (!GlobalBaseInitialized) {
- // Insert the set of GlobalBaseReg into the first MBB of the function
- MachineBasicBlock &FirstMBB = F->front();
- MachineBasicBlock::iterator MBBI = FirstMBB.begin();
- GlobalBaseReg = makeAnotherReg(Type::IntTy);
- BuildMI(FirstMBB, MBBI, PPC32::IMPLICIT_DEF, 0, PPC32::LR);
- BuildMI(FirstMBB, MBBI, PPC32::MovePCtoLR, 0, GlobalBaseReg);
- GlobalBaseInitialized = true;
- }
- // Emit our copy of GlobalBaseReg to the destination register in the
- // current MBB
- BuildMI(*MBB, IP, PPC32::OR, 2, R).addReg(GlobalBaseReg)
- .addReg(GlobalBaseReg);
-}
-
-/// copyConstantToRegister - Output the instructions required to put the
-/// specified constant into the specified register.
-///
-void ISel::copyConstantToRegister(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Constant *C, unsigned R) {
- if (C->getType()->isIntegral()) {
- unsigned Class = getClassB(C->getType());
-
- if (Class == cLong) {
- if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(C)) {
- uint64_t uval = CUI->getValue();
- unsigned hiUVal = uval >> 32;
- unsigned loUVal = uval;
- ConstantUInt *CUHi = ConstantUInt::get(Type::UIntTy, hiUVal);
- ConstantUInt *CULo = ConstantUInt::get(Type::UIntTy, loUVal);
- copyConstantToRegister(MBB, IP, CUHi, R);
- copyConstantToRegister(MBB, IP, CULo, R+1);
- return;
- } else if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(C)) {
- int64_t sval = CSI->getValue();
- int hiSVal = sval >> 32;
- int loSVal = sval;
- ConstantSInt *CSHi = ConstantSInt::get(Type::IntTy, hiSVal);
- ConstantSInt *CSLo = ConstantSInt::get(Type::IntTy, loSVal);
- copyConstantToRegister(MBB, IP, CSHi, R);
- copyConstantToRegister(MBB, IP, CSLo, R+1);
- return;
- } else {
- std::cerr << "Unhandled long constant type!\n";
- abort();
- }
- }
-
- assert(Class <= cInt && "Type not handled yet!");
-
- // Handle bool
- if (C->getType() == Type::BoolTy) {
- BuildMI(*MBB, IP, PPC32::LI, 1, R).addSImm(C == ConstantBool::True);
- return;
- }
-
- // Handle int
- if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(C)) {
- unsigned uval = CUI->getValue();
- if (uval < 32768) {
- BuildMI(*MBB, IP, PPC32::LI, 1, R).addSImm(uval);
- } else {
- unsigned Temp = makeAnotherReg(Type::IntTy);
- BuildMI(*MBB, IP, PPC32::LIS, 1, Temp).addSImm(uval >> 16);
- BuildMI(*MBB, IP, PPC32::ORI, 2, R).addReg(Temp).addImm(uval);
- }
- return;
- } else if (ConstantSInt *CSI = dyn_cast<ConstantSInt>(C)) {
- int sval = CSI->getValue();
- if (sval < 32768 && sval >= -32768) {
- BuildMI(*MBB, IP, PPC32::LI, 1, R).addSImm(sval);
- } else {
- unsigned Temp = makeAnotherReg(Type::IntTy);
- BuildMI(*MBB, IP, PPC32::LIS, 1, Temp).addSImm(sval >> 16);
- BuildMI(*MBB, IP, PPC32::ORI, 2, R).addReg(Temp).addImm(sval);
- }
- return;
- }
-
- std::cerr << "Unhandled integer constant!\n";
- abort();
- } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
- // We need to spill the constant to memory...
- MachineConstantPool *CP = F->getConstantPool();
- unsigned CPI = CP->getConstantPoolIndex(CFP);
- const Type *Ty = CFP->getType();
-
- assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
-
- // Load addr of constant to reg; constant is located at base + distance
- unsigned GlobalBase = makeAnotherReg(Type::IntTy);
- unsigned Reg1 = makeAnotherReg(Type::IntTy);
- unsigned Reg2 = makeAnotherReg(Type::IntTy);
- // Move value at base + distance into return reg
- copyGlobalBaseToRegister(MBB, IP, GlobalBase);
- BuildMI(*MBB, IP, PPC32::LOADHiAddr, 2, Reg1).addReg(GlobalBase)
- .addConstantPoolIndex(CPI);
- BuildMI(*MBB, IP, PPC32::LOADLoDirect, 2, Reg2).addReg(Reg1)
- .addConstantPoolIndex(CPI);
-
- unsigned LoadOpcode = (Ty == Type::FloatTy) ? PPC32::LFS : PPC32::LFD;
- BuildMI(*MBB, IP, LoadOpcode, 2, R).addSImm(0).addReg(Reg2);
- } else if (isa<ConstantPointerNull>(C)) {
- // Copy zero (null pointer) to the register.
- BuildMI(*MBB, IP, PPC32::LI, 1, R).addSImm(0);
- } else if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
- // GV is located at base + distance
- unsigned GlobalBase = makeAnotherReg(Type::IntTy);
- unsigned TmpReg = makeAnotherReg(GV->getType());
- unsigned Opcode = (GV->hasWeakLinkage() || GV->isExternal()) ?
- PPC32::LOADLoIndirect : PPC32::LOADLoDirect;
-
- // Move value at base + distance into return reg
- copyGlobalBaseToRegister(MBB, IP, GlobalBase);
- BuildMI(*MBB, IP, PPC32::LOADHiAddr, 2, TmpReg).addReg(GlobalBase)
- .addGlobalAddress(GV);
- BuildMI(*MBB, IP, Opcode, 2, R).addReg(TmpReg).addGlobalAddress(GV);
-
- // Add the GV to the list of things whose addresses have been taken.
- TM.AddressTaken.insert(GV);
- } else {
- std::cerr << "Offending constant: " << *C << "\n";
- assert(0 && "Type not handled yet!");
- }
-}
-
-/// LoadArgumentsToVirtualRegs - Load all of the arguments to this function from
-/// the stack into virtual registers.
-void ISel::LoadArgumentsToVirtualRegs(Function &Fn) {
- unsigned ArgOffset = 24;
- unsigned GPR_remaining = 8;
- unsigned FPR_remaining = 13;
- unsigned GPR_idx = 0, FPR_idx = 0;
- static const unsigned GPR[] = {
- PPC32::R3, PPC32::R4, PPC32::R5, PPC32::R6,
- PPC32::R7, PPC32::R8, PPC32::R9, PPC32::R10,
- };
- static const unsigned FPR[] = {
- PPC32::F1, PPC32::F2, PPC32::F3, PPC32::F4, PPC32::F5, PPC32::F6, PPC32::F7,
- PPC32::F8, PPC32::F9, PPC32::F10, PPC32::F11, PPC32::F12, PPC32::F13
- };
-
- MachineFrameInfo *MFI = F->getFrameInfo();
-
- for (Function::aiterator I = Fn.abegin(), E = Fn.aend(); I != E; ++I) {
- bool ArgLive = !I->use_empty();
- unsigned Reg = ArgLive ? getReg(*I) : 0;
- int FI; // Frame object index
-
- switch (getClassB(I->getType())) {
- case cByte:
- if (ArgLive) {
- FI = MFI->CreateFixedObject(4, ArgOffset);
- if (GPR_remaining > 0) {
- BuildMI(BB, PPC32::IMPLICIT_DEF, 0, GPR[GPR_idx]);
- BuildMI(BB, PPC32::OR, 2, Reg).addReg(GPR[GPR_idx])
- .addReg(GPR[GPR_idx]);
- } else {
- addFrameReference(BuildMI(BB, PPC32::LBZ, 2, Reg), FI);
- }
- }
- break;
- case cShort:
- if (ArgLive) {
- FI = MFI->CreateFixedObject(4, ArgOffset);
- if (GPR_remaining > 0) {
- BuildMI(BB, PPC32::IMPLICIT_DEF, 0, GPR[GPR_idx]);
- BuildMI(BB, PPC32::OR, 2, Reg).addReg(GPR[GPR_idx])
- .addReg(GPR[GPR_idx]);
- } else {
- addFrameReference(BuildMI(BB, PPC32::LHZ, 2, Reg), FI);
- }
- }
- break;
- case cInt:
- if (ArgLive) {
- FI = MFI->CreateFixedObject(4, ArgOffset);
- if (GPR_remaining > 0) {
- BuildMI(BB, PPC32::IMPLICIT_DEF, 0, GPR[GPR_idx]);
- BuildMI(BB, PPC32::OR, 2, Reg).addReg(GPR[GPR_idx])
- .addReg(GPR[GPR_idx]);
- } else {
- addFrameReference(BuildMI(BB, PPC32::LWZ, 2, Reg), FI);
- }
- }
- break;
- case cLong:
- if (ArgLive) {
- FI = MFI->CreateFixedObject(8, ArgOffset);
- if (GPR_remaining > 1) {
- BuildMI(BB, PPC32::IMPLICIT_DEF, 0, GPR[GPR_idx]);
- BuildMI(BB, PPC32::IMPLICIT_DEF, 0, GPR[GPR_idx+1]);
- BuildMI(BB, PPC32::OR, 2, Reg).addReg(GPR[GPR_idx])
- .addReg(GPR[GPR_idx]);
- BuildMI(BB, PPC32::OR, 2, Reg+1).addReg(GPR[GPR_idx+1])
- .addReg(GPR[GPR_idx+1]);
- } else {
- addFrameReference(BuildMI(BB, PPC32::LWZ, 2, Reg), FI);
- addFrameReference(BuildMI(BB, PPC32::LWZ, 2, Reg+1), FI, 4);
- }
- }
- // longs require 4 additional bytes and use 2 GPRs
- ArgOffset += 4;
- if (GPR_remaining > 1) {
- GPR_remaining--;
- GPR_idx++;
- }
- break;
- case cFP32:
- if (ArgLive) {
- FI = MFI->CreateFixedObject(4, ArgOffset);
-
- if (FPR_remaining > 0) {
- BuildMI(BB, PPC32::IMPLICIT_DEF, 0, FPR[FPR_idx]);
- BuildMI(BB, PPC32::FMR, 1, Reg).addReg(FPR[FPR_idx]);
- FPR_remaining--;
- FPR_idx++;
- } else {
- addFrameReference(BuildMI(BB, PPC32::LFS, 2, Reg), FI);
- }
- }
- break;
- case cFP64:
- if (ArgLive) {
- FI = MFI->CreateFixedObject(8, ArgOffset);
-
- if (FPR_remaining > 0) {
- BuildMI(BB, PPC32::IMPLICIT_DEF, 0, FPR[FPR_idx]);
- BuildMI(BB, PPC32::FMR, 1, Reg).addReg(FPR[FPR_idx]);
- FPR_remaining--;
- FPR_idx++;
- } else {
- addFrameReference(BuildMI(BB, PPC32::LFD, 2, Reg), FI);
- }
- }
-
- // doubles require 4 additional bytes and use 2 GPRs of param space
- ArgOffset += 4;
- if (GPR_remaining > 0) {
- GPR_remaining--;
- GPR_idx++;
- }
- break;
- default:
- assert(0 && "Unhandled argument type!");
- }
- ArgOffset += 4; // Each argument takes at least 4 bytes on the stack...
- if (GPR_remaining > 0) {
- GPR_remaining--; // uses up 2 GPRs
- GPR_idx++;
- }
- }
-
- // If the function takes variable number of arguments, add a frame offset for
- // the start of the first vararg value... this is used to expand
- // llvm.va_start.
- if (Fn.getFunctionType()->isVarArg())
- VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset);
-}
-
-
-/// SelectPHINodes - Insert machine code to generate phis. This is tricky
-/// because we have to generate our sources into the source basic blocks, not
-/// the current one.
-///
-void ISel::SelectPHINodes() {
- const TargetInstrInfo &TII = *TM.getInstrInfo();
- const Function &LF = *F->getFunction(); // The LLVM function...
- for (Function::const_iterator I = LF.begin(), E = LF.end(); I != E; ++I) {
- const BasicBlock *BB = I;
- MachineBasicBlock &MBB = *MBBMap[I];
-
- // Loop over all of the PHI nodes in the LLVM basic block...
- MachineBasicBlock::iterator PHIInsertPoint = MBB.begin();
- for (BasicBlock::const_iterator I = BB->begin();
- PHINode *PN = const_cast<PHINode*>(dyn_cast<PHINode>(I)); ++I) {
-
- // Create a new machine instr PHI node, and insert it.
- unsigned PHIReg = getReg(*PN);
- MachineInstr *PhiMI = BuildMI(MBB, PHIInsertPoint,
- PPC32::PHI, PN->getNumOperands(), PHIReg);
-
- MachineInstr *LongPhiMI = 0;
- if (PN->getType() == Type::LongTy || PN->getType() == Type::ULongTy)
- LongPhiMI = BuildMI(MBB, PHIInsertPoint,
- PPC32::PHI, PN->getNumOperands(), PHIReg+1);
-
- // PHIValues - Map of blocks to incoming virtual registers. We use this
- // so that we only initialize one incoming value for a particular block,
- // even if the block has multiple entries in the PHI node.
- //
- std::map<MachineBasicBlock*, unsigned> PHIValues;
-
- for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
- MachineBasicBlock *PredMBB = 0;
- for (MachineBasicBlock::pred_iterator PI = MBB.pred_begin (),
- PE = MBB.pred_end (); PI != PE; ++PI)
- if (PN->getIncomingBlock(i) == (*PI)->getBasicBlock()) {
- PredMBB = *PI;
- break;
- }
- assert (PredMBB && "Couldn't find incoming machine-cfg edge for phi");
-
- unsigned ValReg;
- std::map<MachineBasicBlock*, unsigned>::iterator EntryIt =
- PHIValues.lower_bound(PredMBB);
-
- if (EntryIt != PHIValues.end() && EntryIt->first == PredMBB) {
- // We already inserted an initialization of the register for this
- // predecessor. Recycle it.
- ValReg = EntryIt->second;
- } else {
- // Get the incoming value into a virtual register.
- //
- Value *Val = PN->getIncomingValue(i);
-
- // If this is a constant or GlobalValue, we may have to insert code
- // into the basic block to compute it into a virtual register.
- if ((isa<Constant>(Val) && !isa<ConstantExpr>(Val)) ||
- isa<GlobalValue>(Val)) {
- // Simple constants get emitted at the end of the basic block,
- // before any terminator instructions. We "know" that the code to
- // move a constant into a register will never clobber any flags.
- ValReg = getReg(Val, PredMBB, PredMBB->getFirstTerminator());
- } else {
- // Because we don't want to clobber any values which might be in
- // physical registers with the computation of this constant (which
- // might be arbitrarily complex if it is a constant expression),
- // just insert the computation at the top of the basic block.
- MachineBasicBlock::iterator PI = PredMBB->begin();
-
- // Skip over any PHI nodes though!
- while (PI != PredMBB->end() && PI->getOpcode() == PPC32::PHI)
- ++PI;
-
- ValReg = getReg(Val, PredMBB, PI);
- }
-
- // Remember that we inserted a value for this PHI for this predecessor
- PHIValues.insert(EntryIt, std::make_pair(PredMBB, ValReg));
- }
-
- PhiMI->addRegOperand(ValReg);
- PhiMI->addMachineBasicBlockOperand(PredMBB);
- if (LongPhiMI) {
- LongPhiMI->addRegOperand(ValReg+1);
- LongPhiMI->addMachineBasicBlockOperand(PredMBB);
- }
- }
-
- // Now that we emitted all of the incoming values for the PHI node, make
- // sure to reposition the InsertPoint after the PHI that we just added.
- // This is needed because we might have inserted a constant into this
- // block, right after the PHI's which is before the old insert point!
- PHIInsertPoint = LongPhiMI ? LongPhiMI : PhiMI;
- ++PHIInsertPoint;
- }
- }
-}
-
-
-// canFoldSetCCIntoBranchOrSelect - Return the setcc instruction if we can fold
-// it into the conditional branch or select instruction which is the only user
-// of the cc instruction. This is the case if the conditional branch is the
-// only user of the setcc, and if the setcc is in the same basic block as the
-// conditional branch.
-//
-static SetCondInst *canFoldSetCCIntoBranchOrSelect(Value *V) {
- if (SetCondInst *SCI = dyn_cast<SetCondInst>(V))
- if (SCI->hasOneUse()) {
- Instruction *User = cast<Instruction>(SCI->use_back());
- if ((isa<BranchInst>(User) || isa<SelectInst>(User)) &&
- SCI->getParent() == User->getParent())
- return SCI;
- }
- return 0;
-}
-
-
-// canFoldGEPIntoLoadOrStore - Return the GEP instruction if we can fold it into
-// the load or store instruction that is the only user of the GEP.
-//
-static GetElementPtrInst *canFoldGEPIntoLoadOrStore(Value *V) {
- if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(V))
- if (GEPI->hasOneUse()) {
- Instruction *User = cast<Instruction>(GEPI->use_back());
- if (isa<StoreInst>(User) &&
- GEPI->getParent() == User->getParent() &&
- User->getOperand(0) != GEPI &&
- User->getOperand(1) == GEPI) {
- ++GEPFolds;
- return GEPI;
- }
- if (isa<LoadInst>(User) &&
- GEPI->getParent() == User->getParent() &&
- User->getOperand(0) == GEPI) {
- ++GEPFolds;
- return GEPI;
- }
- }
- return 0;
-}
-
-
-// Return a fixed numbering for setcc instructions which does not depend on the
-// order of the opcodes.
-//
-static unsigned getSetCCNumber(unsigned Opcode) {
- switch (Opcode) {
- default: assert(0 && "Unknown setcc instruction!");
- case Instruction::SetEQ: return 0;
- case Instruction::SetNE: return 1;
- case Instruction::SetLT: return 2;
- case Instruction::SetGE: return 3;
- case Instruction::SetGT: return 4;
- case Instruction::SetLE: return 5;
- }
-}
-
-static unsigned getPPCOpcodeForSetCCNumber(unsigned Opcode) {
- switch (Opcode) {
- default: assert(0 && "Unknown setcc instruction!");
- case Instruction::SetEQ: return PPC32::BEQ;
- case Instruction::SetNE: return PPC32::BNE;
- case Instruction::SetLT: return PPC32::BLT;
- case Instruction::SetGE: return PPC32::BGE;
- case Instruction::SetGT: return PPC32::BGT;
- case Instruction::SetLE: return PPC32::BLE;
- }
-}
-
-/// emitUCOM - emits an unordered FP compare.
-void ISel::emitUCOM(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
- unsigned LHS, unsigned RHS) {
- BuildMI(*MBB, IP, PPC32::FCMPU, 2, PPC32::CR0).addReg(LHS).addReg(RHS);
-}
-
-/// EmitComparison - emits a comparison of the two operands, returning the
-/// extended setcc code to use. The result is in CR0.
-///
-unsigned ISel::EmitComparison(unsigned OpNum, Value *Op0, Value *Op1,
- MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP) {
- // The arguments are already supposed to be of the same type.
- const Type *CompTy = Op0->getType();
- unsigned Class = getClassB(CompTy);
- unsigned Op0r = getReg(Op0, MBB, IP);
-
- // Before we do a comparison, we have to make sure that we're truncating our
- // registers appropriately.
- if (Class == cByte) {
- unsigned TmpReg = makeAnotherReg(CompTy);
- if (CompTy->isSigned())
- BuildMI(*MBB, IP, PPC32::EXTSB, 1, TmpReg).addReg(Op0r);
- else
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, TmpReg).addReg(Op0r).addImm(0)
- .addImm(24).addImm(31);
- Op0r = TmpReg;
- } else if (Class == cShort) {
- unsigned TmpReg = makeAnotherReg(CompTy);
- if (CompTy->isSigned())
- BuildMI(*MBB, IP, PPC32::EXTSH, 1, TmpReg).addReg(Op0r);
- else
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, TmpReg).addReg(Op0r).addImm(0)
- .addImm(16).addImm(31);
- Op0r = TmpReg;
- }
-
- // Use crand for lt, gt and crandc for le, ge
- unsigned CROpcode = (OpNum == 2 || OpNum == 4) ? PPC32::CRAND : PPC32::CRANDC;
- // ? cr1[lt] : cr1[gt]
- unsigned CR1field = (OpNum == 2 || OpNum == 3) ? 4 : 5;
- // ? cr0[lt] : cr0[gt]
- unsigned CR0field = (OpNum == 2 || OpNum == 5) ? 0 : 1;
- unsigned Opcode = CompTy->isSigned() ? PPC32::CMPW : PPC32::CMPLW;
- unsigned OpcodeImm = CompTy->isSigned() ? PPC32::CMPWI : PPC32::CMPLWI;
-
- // Special case handling of: cmp R, i
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
- if (Class == cByte || Class == cShort || Class == cInt) {
- unsigned Op1v = CI->getRawValue() & 0xFFFF;
-
- // Treat compare like ADDI for the purposes of immediate suitability
- if (canUseAsImmediateForOpcode(CI, 0)) {
- BuildMI(*MBB, IP, OpcodeImm, 2, PPC32::CR0).addReg(Op0r).addSImm(Op1v);
- } else {
- unsigned Op1r = getReg(Op1, MBB, IP);
- BuildMI(*MBB, IP, Opcode, 2, PPC32::CR0).addReg(Op0r).addReg(Op1r);
- }
- return OpNum;
- } else {
- assert(Class == cLong && "Unknown integer class!");
- unsigned LowCst = CI->getRawValue();
- unsigned HiCst = CI->getRawValue() >> 32;
- if (OpNum < 2) { // seteq, setne
- unsigned LoLow = makeAnotherReg(Type::IntTy);
- unsigned LoTmp = makeAnotherReg(Type::IntTy);
- unsigned HiLow = makeAnotherReg(Type::IntTy);
- unsigned HiTmp = makeAnotherReg(Type::IntTy);
- unsigned FinalTmp = makeAnotherReg(Type::IntTy);
-
- BuildMI(*MBB, IP, PPC32::XORI, 2, LoLow).addReg(Op0r+1)
- .addImm(LowCst & 0xFFFF);
- BuildMI(*MBB, IP, PPC32::XORIS, 2, LoTmp).addReg(LoLow)
- .addImm(LowCst >> 16);
- BuildMI(*MBB, IP, PPC32::XORI, 2, HiLow).addReg(Op0r)
- .addImm(HiCst & 0xFFFF);
- BuildMI(*MBB, IP, PPC32::XORIS, 2, HiTmp).addReg(HiLow)
- .addImm(HiCst >> 16);
- BuildMI(*MBB, IP, PPC32::ORo, 2, FinalTmp).addReg(LoTmp).addReg(HiTmp);
- return OpNum;
- } else {
- unsigned ConstReg = makeAnotherReg(CompTy);
- copyConstantToRegister(MBB, IP, CI, ConstReg);
-
- // cr0 = r3 ccOpcode r5 or (r3 == r5 AND r4 ccOpcode r6)
- BuildMI(*MBB, IP, Opcode, 2, PPC32::CR0).addReg(Op0r)
- .addReg(ConstReg);
- BuildMI(*MBB, IP, Opcode, 2, PPC32::CR1).addReg(Op0r+1)
- .addReg(ConstReg+1);
- BuildMI(*MBB, IP, PPC32::CRAND, 3).addImm(2).addImm(2).addImm(CR1field);
- BuildMI(*MBB, IP, PPC32::CROR, 3).addImm(CR0field).addImm(CR0field)
- .addImm(2);
- return OpNum;
- }
- }
- }
-
- unsigned Op1r = getReg(Op1, MBB, IP);
-
- switch (Class) {
- default: assert(0 && "Unknown type class!");
- case cByte:
- case cShort:
- case cInt:
- BuildMI(*MBB, IP, Opcode, 2, PPC32::CR0).addReg(Op0r).addReg(Op1r);
- break;
-
- case cFP32:
- case cFP64:
- emitUCOM(MBB, IP, Op0r, Op1r);
- break;
-
- case cLong:
- if (OpNum < 2) { // seteq, setne
- unsigned LoTmp = makeAnotherReg(Type::IntTy);
- unsigned HiTmp = makeAnotherReg(Type::IntTy);
- unsigned FinalTmp = makeAnotherReg(Type::IntTy);
- BuildMI(*MBB, IP, PPC32::XOR, 2, HiTmp).addReg(Op0r).addReg(Op1r);
- BuildMI(*MBB, IP, PPC32::XOR, 2, LoTmp).addReg(Op0r+1).addReg(Op1r+1);
- BuildMI(*MBB, IP, PPC32::ORo, 2, FinalTmp).addReg(LoTmp).addReg(HiTmp);
- break; // Allow the sete or setne to be generated from flags set by OR
- } else {
- unsigned TmpReg1 = makeAnotherReg(Type::IntTy);
- unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
-
- // cr0 = r3 ccOpcode r5 or (r3 == r5 AND r4 ccOpcode r6)
- BuildMI(*MBB, IP, Opcode, 2, PPC32::CR0).addReg(Op0r).addReg(Op1r);
- BuildMI(*MBB, IP, Opcode, 2, PPC32::CR1).addReg(Op0r+1).addReg(Op1r+1);
- BuildMI(*MBB, IP, PPC32::CRAND, 3).addImm(2).addImm(2).addImm(CR1field);
- BuildMI(*MBB, IP, PPC32::CROR, 3).addImm(CR0field).addImm(CR0field)
- .addImm(2);
- return OpNum;
- }
- }
- return OpNum;
-}
-
-/// visitSetCondInst - emit code to calculate the condition via
-/// EmitComparison(), and possibly store a 0 or 1 to a register as a result
-///
-void ISel::visitSetCondInst(SetCondInst &I) {
- if (canFoldSetCCIntoBranchOrSelect(&I))
- return;
-
- unsigned DestReg = getReg(I);
- unsigned OpNum = I.getOpcode();
- const Type *Ty = I.getOperand (0)->getType();
-
- EmitComparison(OpNum, I.getOperand(0), I.getOperand(1), BB, BB->end());
-
- unsigned Opcode = getPPCOpcodeForSetCCNumber(OpNum);
- MachineBasicBlock *thisMBB = BB;
- const BasicBlock *LLVM_BB = BB->getBasicBlock();
- ilist<MachineBasicBlock>::iterator It = BB;
- ++It;
-
- // thisMBB:
- // ...
- // cmpTY cr0, r1, r2
- // bCC copy1MBB
- // b copy0MBB
-
- // FIXME: we wouldn't need copy0MBB (we could fold it into thisMBB)
- // if we could insert other, non-terminator instructions after the
- // bCC. But MBB->getFirstTerminator() can't understand this.
- MachineBasicBlock *copy1MBB = new MachineBasicBlock(LLVM_BB);
- F->getBasicBlockList().insert(It, copy1MBB);
- BuildMI(BB, Opcode, 2).addReg(PPC32::CR0).addMBB(copy1MBB);
- MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
- F->getBasicBlockList().insert(It, copy0MBB);
- BuildMI(BB, PPC32::B, 1).addMBB(copy0MBB);
- MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
- F->getBasicBlockList().insert(It, sinkMBB);
- // Update machine-CFG edges
- BB->addSuccessor(copy1MBB);
- BB->addSuccessor(copy0MBB);
-
- // copy1MBB:
- // %TrueValue = li 1
- // b sinkMBB
- BB = copy1MBB;
- unsigned TrueValue = makeAnotherReg(I.getType());
- BuildMI(BB, PPC32::LI, 1, TrueValue).addSImm(1);
- BuildMI(BB, PPC32::B, 1).addMBB(sinkMBB);
- // Update machine-CFG edges
- BB->addSuccessor(sinkMBB);
-
- // copy0MBB:
- // %FalseValue = li 0
- // fallthrough
- BB = copy0MBB;
- unsigned FalseValue = makeAnotherReg(I.getType());
- BuildMI(BB, PPC32::LI, 1, FalseValue).addSImm(0);
- // Update machine-CFG edges
- BB->addSuccessor(sinkMBB);
-
- // sinkMBB:
- // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, copy1MBB ]
- // ...
- BB = sinkMBB;
- BuildMI(BB, PPC32::PHI, 4, DestReg).addReg(FalseValue)
- .addMBB(copy0MBB).addReg(TrueValue).addMBB(copy1MBB);
-}
-
-void ISel::visitSelectInst(SelectInst &SI) {
- unsigned DestReg = getReg(SI);
- MachineBasicBlock::iterator MII = BB->end();
- emitSelectOperation(BB, MII, SI.getCondition(), SI.getTrueValue(),
- SI.getFalseValue(), DestReg);
-}
-
-/// emitSelect - Common code shared between visitSelectInst and the constant
-/// expression support.
-/// FIXME: this is most likely broken in one or more ways. Namely, PowerPC has
-/// no select instruction. FSEL only works for comparisons against zero.
-void ISel::emitSelectOperation(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Value *Cond, Value *TrueVal, Value *FalseVal,
- unsigned DestReg) {
- unsigned SelectClass = getClassB(TrueVal->getType());
- unsigned Opcode;
-
- // See if we can fold the setcc into the select instruction, or if we have
- // to get the register of the Cond value
- if (SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(Cond)) {
- // We successfully folded the setcc into the select instruction.
- unsigned OpNum = getSetCCNumber(SCI->getOpcode());
- OpNum = EmitComparison(OpNum, SCI->getOperand(0),SCI->getOperand(1),MBB,IP);
- Opcode = getPPCOpcodeForSetCCNumber(SCI->getOpcode());
- } else {
- unsigned CondReg = getReg(Cond, MBB, IP);
- BuildMI(*MBB, IP, PPC32::CMPI, 2, PPC32::CR0).addReg(CondReg).addSImm(0);
- Opcode = getPPCOpcodeForSetCCNumber(Instruction::SetNE);
- }
-
- // thisMBB:
- // ...
- // cmpTY cr0, r1, r2
- // bCC copy1MBB
- // b copy0MBB
-
- MachineBasicBlock *thisMBB = BB;
- const BasicBlock *LLVM_BB = BB->getBasicBlock();
- ilist<MachineBasicBlock>::iterator It = BB;
- ++It;
-
- // FIXME: we wouldn't need copy0MBB (we could fold it into thisMBB)
- // if we could insert other, non-terminator instructions after the
- // bCC. But MBB->getFirstTerminator() can't understand this.
- MachineBasicBlock *copy1MBB = new MachineBasicBlock(LLVM_BB);
- F->getBasicBlockList().insert(It, copy1MBB);
- BuildMI(BB, Opcode, 2).addReg(PPC32::CR0).addMBB(copy1MBB);
- MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB);
- F->getBasicBlockList().insert(It, copy0MBB);
- BuildMI(BB, PPC32::B, 1).addMBB(copy0MBB);
- MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB);
- F->getBasicBlockList().insert(It, sinkMBB);
- // Update machine-CFG edges
- BB->addSuccessor(copy1MBB);
- BB->addSuccessor(copy0MBB);
-
- // copy1MBB:
- // %TrueValue = ...
- // b sinkMBB
- BB = copy1MBB;
- unsigned TrueValue = getReg(TrueVal, BB, BB->begin());
- BuildMI(BB, PPC32::B, 1).addMBB(sinkMBB);
- // Update machine-CFG edges
- BB->addSuccessor(sinkMBB);
-
- // copy0MBB:
- // %FalseValue = ...
- // fallthrough
- BB = copy0MBB;
- unsigned FalseValue = getReg(FalseVal, BB, BB->begin());
- // Update machine-CFG edges
- BB->addSuccessor(sinkMBB);
-
- // sinkMBB:
- // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, copy1MBB ]
- // ...
- BB = sinkMBB;
- BuildMI(BB, PPC32::PHI, 4, DestReg).addReg(FalseValue)
- .addMBB(copy0MBB).addReg(TrueValue).addMBB(copy1MBB);
- // For a register pair representing a long value, define the second reg
- if (getClass(TrueVal->getType()) == cLong)
- BuildMI(BB, PPC32::LI, 1, DestReg+1).addImm(0);
- return;
-}
-
-
-
-/// promote32 - Emit instructions to turn a narrow operand into a 32-bit-wide
-/// operand, in the specified target register.
-///
-void ISel::promote32(unsigned targetReg, const ValueRecord &VR) {
- bool isUnsigned = VR.Ty->isUnsigned() || VR.Ty == Type::BoolTy;
-
- Value *Val = VR.Val;
- const Type *Ty = VR.Ty;
- if (Val) {
- if (Constant *C = dyn_cast<Constant>(Val)) {
- Val = ConstantExpr::getCast(C, Type::IntTy);
- Ty = Type::IntTy;
- }
-
- // If this is a simple constant, just emit a load directly to avoid the copy
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Val)) {
- int TheVal = CI->getRawValue() & 0xFFFFFFFF;
-
- if (TheVal < 32768 && TheVal >= -32768) {
- BuildMI(BB, PPC32::LI, 1, targetReg).addSImm(TheVal);
- } else {
- unsigned TmpReg = makeAnotherReg(Type::IntTy);
- BuildMI(BB, PPC32::LIS, 1, TmpReg).addSImm(TheVal >> 16);
- BuildMI(BB, PPC32::ORI, 2, targetReg).addReg(TmpReg)
- .addImm(TheVal & 0xFFFF);
- }
- return;
- }
- }
-
- // Make sure we have the register number for this value...
- unsigned Reg = Val ? getReg(Val) : VR.Reg;
- switch (getClassB(Ty)) {
- case cByte:
- // Extend value into target register (8->32)
- if (isUnsigned)
- BuildMI(BB, PPC32::RLWINM, 4, targetReg).addReg(Reg).addZImm(0)
- .addZImm(24).addZImm(31);
- else
- BuildMI(BB, PPC32::EXTSB, 1, targetReg).addReg(Reg);
- break;
- case cShort:
- // Extend value into target register (16->32)
- if (isUnsigned)
- BuildMI(BB, PPC32::RLWINM, 4, targetReg).addReg(Reg).addZImm(0)
- .addZImm(16).addZImm(31);
- else
- BuildMI(BB, PPC32::EXTSH, 1, targetReg).addReg(Reg);
- break;
- case cInt:
- // Move value into target register (32->32)
- BuildMI(BB, PPC32::OR, 2, targetReg).addReg(Reg).addReg(Reg);
- break;
- default:
- assert(0 && "Unpromotable operand class in promote32");
- }
-}
-
-/// visitReturnInst - implemented with BLR
-///
-void ISel::visitReturnInst(ReturnInst &I) {
- // Only do the processing if this is a non-void return
- if (I.getNumOperands() > 0) {
- Value *RetVal = I.getOperand(0);
- switch (getClassB(RetVal->getType())) {
- case cByte: // integral return values: extend or move into r3 and return
- case cShort:
- case cInt:
- promote32(PPC32::R3, ValueRecord(RetVal));
- break;
- case cFP32:
- case cFP64: { // Floats & Doubles: Return in f1
- unsigned RetReg = getReg(RetVal);
- BuildMI(BB, PPC32::FMR, 1, PPC32::F1).addReg(RetReg);
- break;
- }
- case cLong: {
- unsigned RetReg = getReg(RetVal);
- BuildMI(BB, PPC32::OR, 2, PPC32::R3).addReg(RetReg).addReg(RetReg);
- BuildMI(BB, PPC32::OR, 2, PPC32::R4).addReg(RetReg+1).addReg(RetReg+1);
- break;
- }
- default:
- visitInstruction(I);
- }
- }
- BuildMI(BB, PPC32::BLR, 1).addImm(0);
-}
-
-// getBlockAfter - Return the basic block which occurs lexically after the
-// specified one.
-static inline BasicBlock *getBlockAfter(BasicBlock *BB) {
- Function::iterator I = BB; ++I; // Get iterator to next block
- return I != BB->getParent()->end() ? &*I : 0;
-}
-
-/// visitBranchInst - Handle conditional and unconditional branches here. Note
-/// that since code layout is frozen at this point, that if we are trying to
-/// jump to a block that is the immediate successor of the current block, we can
-/// just make a fall-through (but we don't currently).
-///
-void ISel::visitBranchInst(BranchInst &BI) {
- // Update machine-CFG edges
- BB->addSuccessor(MBBMap[BI.getSuccessor(0)]);
- if (BI.isConditional())
- BB->addSuccessor(MBBMap[BI.getSuccessor(1)]);
-
- BasicBlock *NextBB = getBlockAfter(BI.getParent()); // BB after current one
-
- if (!BI.isConditional()) { // Unconditional branch?
- if (BI.getSuccessor(0) != NextBB)
- BuildMI(BB, PPC32::B, 1).addMBB(MBBMap[BI.getSuccessor(0)]);
- return;
- }
-
- // See if we can fold the setcc into the branch itself...
- SetCondInst *SCI = canFoldSetCCIntoBranchOrSelect(BI.getCondition());
- if (SCI == 0) {
- // Nope, cannot fold setcc into this branch. Emit a branch on a condition
- // computed some other way...
- unsigned condReg = getReg(BI.getCondition());
- BuildMI(BB, PPC32::CMPLI, 3, PPC32::CR0).addImm(0).addReg(condReg)
- .addImm(0);
- if (BI.getSuccessor(1) == NextBB) {
- if (BI.getSuccessor(0) != NextBB)
- BuildMI(BB, PPC32::COND_BRANCH, 3).addReg(PPC32::CR0).addImm(PPC32::BNE)
- .addMBB(MBBMap[BI.getSuccessor(0)])
- .addMBB(MBBMap[BI.getSuccessor(1)]);
- } else {
- BuildMI(BB, PPC32::COND_BRANCH, 3).addReg(PPC32::CR0).addImm(PPC32::BEQ)
- .addMBB(MBBMap[BI.getSuccessor(1)])
- .addMBB(MBBMap[BI.getSuccessor(0)]);
- if (BI.getSuccessor(0) != NextBB)
- BuildMI(BB, PPC32::B, 1).addMBB(MBBMap[BI.getSuccessor(0)]);
- }
- return;
- }
-
- unsigned OpNum = getSetCCNumber(SCI->getOpcode());
- unsigned Opcode = getPPCOpcodeForSetCCNumber(SCI->getOpcode());
- MachineBasicBlock::iterator MII = BB->end();
- OpNum = EmitComparison(OpNum, SCI->getOperand(0), SCI->getOperand(1), BB,MII);
-
- if (BI.getSuccessor(0) != NextBB) {
- BuildMI(BB, PPC32::COND_BRANCH, 3).addReg(PPC32::CR0).addImm(Opcode)
- .addMBB(MBBMap[BI.getSuccessor(0)])
- .addMBB(MBBMap[BI.getSuccessor(1)]);
- if (BI.getSuccessor(1) != NextBB)
- BuildMI(BB, PPC32::B, 1).addMBB(MBBMap[BI.getSuccessor(1)]);
- } else {
- // Change to the inverse condition...
- if (BI.getSuccessor(1) != NextBB) {
- Opcode = PowerPCInstrInfo::invertPPCBranchOpcode(Opcode);
- BuildMI(BB, PPC32::COND_BRANCH, 3).addReg(PPC32::CR0).addImm(Opcode)
- .addMBB(MBBMap[BI.getSuccessor(1)])
- .addMBB(MBBMap[BI.getSuccessor(0)]);
- }
- }
-}
-
-/// doCall - This emits an abstract call instruction, setting up the arguments
-/// and the return value as appropriate. For the actual function call itself,
-/// it inserts the specified CallMI instruction into the stream.
-///
-/// FIXME: See Documentation at the following URL for "correct" behavior
-/// <http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/2rt_powerpc_abi/chapter_9_section_5.html>
-void ISel::doCall(const ValueRecord &Ret, MachineInstr *CallMI,
- const std::vector<ValueRecord> &Args, bool isVarArg) {
- // Count how many bytes are to be pushed on the stack, including the linkage
- // area, and parameter passing area.
- unsigned NumBytes = 24;
- unsigned ArgOffset = 24;
-
- if (!Args.empty()) {
- for (unsigned i = 0, e = Args.size(); i != e; ++i)
- switch (getClassB(Args[i].Ty)) {
- case cByte: case cShort: case cInt:
- NumBytes += 4; break;
- case cLong:
- NumBytes += 8; break;
- case cFP32:
- NumBytes += 4; break;
- case cFP64:
- NumBytes += 8; break;
- break;
- default: assert(0 && "Unknown class!");
- }
-
- // Just to be safe, we'll always reserve the full 32 bytes worth of
- // argument passing space in case any called code gets funky on us.
- if (NumBytes < 24 + 32) NumBytes = 24 + 32;
-
- // Adjust the stack pointer for the new arguments...
- // These functions are automatically eliminated by the prolog/epilog pass
- BuildMI(BB, PPC32::ADJCALLSTACKDOWN, 1).addImm(NumBytes);
-
- // Arguments go on the stack in reverse order, as specified by the ABI.
- // Offset to the paramater area on the stack is 24.
- int GPR_remaining = 8, FPR_remaining = 13;
- unsigned GPR_idx = 0, FPR_idx = 0;
- static const unsigned GPR[] = {
- PPC32::R3, PPC32::R4, PPC32::R5, PPC32::R6,
- PPC32::R7, PPC32::R8, PPC32::R9, PPC32::R10,
- };
- static const unsigned FPR[] = {
- PPC32::F1, PPC32::F2, PPC32::F3, PPC32::F4, PPC32::F5, PPC32::F6,
- PPC32::F7, PPC32::F8, PPC32::F9, PPC32::F10, PPC32::F11, PPC32::F12,
- PPC32::F13
- };
-
- for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- unsigned ArgReg;
- switch (getClassB(Args[i].Ty)) {
- case cByte:
- case cShort:
- // Promote arg to 32 bits wide into a temporary register...
- ArgReg = makeAnotherReg(Type::UIntTy);
- promote32(ArgReg, Args[i]);
-
- // Reg or stack?
- if (GPR_remaining > 0) {
- BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx]).addReg(ArgReg)
- .addReg(ArgReg);
- CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
- }
- if (GPR_remaining <= 0 || isVarArg) {
- BuildMI(BB, PPC32::STW, 3).addReg(ArgReg).addSImm(ArgOffset)
- .addReg(PPC32::R1);
- }
- break;
- case cInt:
- ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
-
- // Reg or stack?
- if (GPR_remaining > 0) {
- BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx]).addReg(ArgReg)
- .addReg(ArgReg);
- CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
- }
- if (GPR_remaining <= 0 || isVarArg) {
- BuildMI(BB, PPC32::STW, 3).addReg(ArgReg).addSImm(ArgOffset)
- .addReg(PPC32::R1);
- }
- break;
- case cLong:
- ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
-
- // Reg or stack? Note that PPC calling conventions state that long args
- // are passed rN = hi, rN+1 = lo, opposite of LLVM.
- if (GPR_remaining > 1) {
- BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx]).addReg(ArgReg)
- .addReg(ArgReg);
- BuildMI(BB, PPC32::OR, 2, GPR[GPR_idx+1]).addReg(ArgReg+1)
- .addReg(ArgReg+1);
- CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
- CallMI->addRegOperand(GPR[GPR_idx+1], MachineOperand::Use);
- }
- if (GPR_remaining <= 1 || isVarArg) {
- BuildMI(BB, PPC32::STW, 3).addReg(ArgReg).addSImm(ArgOffset)
- .addReg(PPC32::R1);
- BuildMI(BB, PPC32::STW, 3).addReg(ArgReg+1).addSImm(ArgOffset+4)
- .addReg(PPC32::R1);
- }
-
- ArgOffset += 4; // 8 byte entry, not 4.
- GPR_remaining -= 1; // uses up 2 GPRs
- GPR_idx += 1;
- break;
- case cFP32:
- ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
- // Reg or stack?
- if (FPR_remaining > 0) {
- BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
- CallMI->addRegOperand(FPR[FPR_idx], MachineOperand::Use);
- FPR_remaining--;
- FPR_idx++;
-
- // If this is a vararg function, and there are GPRs left, also
- // pass the float in an int. Otherwise, put it on the stack.
- if (isVarArg) {
- BuildMI(BB, PPC32::STFS, 3).addReg(ArgReg).addSImm(ArgOffset)
- .addReg(PPC32::R1);
- if (GPR_remaining > 0) {
- BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx])
- .addSImm(ArgOffset).addReg(ArgReg);
- CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
- }
- }
- } else {
- BuildMI(BB, PPC32::STFS, 3).addReg(ArgReg).addSImm(ArgOffset)
- .addReg(PPC32::R1);
- }
- break;
- case cFP64:
- ArgReg = Args[i].Val ? getReg(Args[i].Val) : Args[i].Reg;
- // Reg or stack?
- if (FPR_remaining > 0) {
- BuildMI(BB, PPC32::FMR, 1, FPR[FPR_idx]).addReg(ArgReg);
- CallMI->addRegOperand(FPR[FPR_idx], MachineOperand::Use);
- FPR_remaining--;
- FPR_idx++;
- // For vararg functions, must pass doubles via int regs as well
- if (isVarArg) {
- BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addSImm(ArgOffset)
- .addReg(PPC32::R1);
-
- // Doubles can be split across reg + stack for varargs
- if (GPR_remaining > 0) {
- BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx]).addSImm(ArgOffset)
- .addReg(PPC32::R1);
- CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use);
- }
- if (GPR_remaining > 1) {
- BuildMI(BB, PPC32::LWZ, 2, GPR[GPR_idx+1])
- .addSImm(ArgOffset+4).addReg(PPC32::R1);
- CallMI->addRegOperand(GPR[GPR_idx+1], MachineOperand::Use);
- }
- }
- } else {
- BuildMI(BB, PPC32::STFD, 3).addReg(ArgReg).addSImm(ArgOffset)
- .addReg(PPC32::R1);
- }
- // Doubles use 8 bytes, and 2 GPRs worth of param space
- ArgOffset += 4;
- GPR_remaining--;
- GPR_idx++;
- break;
-
- default: assert(0 && "Unknown class!");
- }
- ArgOffset += 4;
- GPR_remaining--;
- GPR_idx++;
- }
- } else {
- BuildMI(BB, PPC32::ADJCALLSTACKDOWN, 1).addImm(0);
- }
-
- BuildMI(BB, PPC32::IMPLICIT_DEF, 0, PPC32::LR);
- BB->push_back(CallMI);
-
- // These functions are automatically eliminated by the prolog/epilog pass
- BuildMI(BB, PPC32::ADJCALLSTACKUP, 1).addImm(NumBytes);
-
- // If there is a return value, scavenge the result from the location the call
- // leaves it in...
- //
- if (Ret.Ty != Type::VoidTy) {
- unsigned DestClass = getClassB(Ret.Ty);
- switch (DestClass) {
- case cByte:
- case cShort:
- case cInt:
- // Integral results are in r3
- BuildMI(BB, PPC32::OR, 2, Ret.Reg).addReg(PPC32::R3).addReg(PPC32::R3);
- break;
- case cFP32: // Floating-point return values live in f1
- case cFP64:
- BuildMI(BB, PPC32::FMR, 1, Ret.Reg).addReg(PPC32::F1);
- break;
- case cLong: // Long values are in r3:r4
- BuildMI(BB, PPC32::OR, 2, Ret.Reg).addReg(PPC32::R3).addReg(PPC32::R3);
- BuildMI(BB, PPC32::OR, 2, Ret.Reg+1).addReg(PPC32::R4).addReg(PPC32::R4);
- break;
- default: assert(0 && "Unknown class!");
- }
- }
-}
-
-
-/// visitCallInst - Push args on stack and do a procedure call instruction.
-void ISel::visitCallInst(CallInst &CI) {
- MachineInstr *TheCall;
- Function *F = CI.getCalledFunction();
- if (F) {
- // Is it an intrinsic function call?
- if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) {
- visitIntrinsicCall(ID, CI); // Special intrinsics are not handled here
- return;
- }
- // Emit a CALL instruction with PC-relative displacement.
- TheCall = BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(F, true);
- // Add it to the set of functions called to be used by the Printer
- TM.CalledFunctions.insert(F);
- } else { // Emit an indirect call through the CTR
- unsigned Reg = getReg(CI.getCalledValue());
- BuildMI(BB, PPC32::MTCTR, 1).addReg(Reg);
- TheCall = BuildMI(PPC32::CALLindirect, 2).addZImm(20).addZImm(0);
- }
-
- std::vector<ValueRecord> Args;
- for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i)
- Args.push_back(ValueRecord(CI.getOperand(i)));
-
- unsigned DestReg = CI.getType() != Type::VoidTy ? getReg(CI) : 0;
- bool isVarArg = F ? F->getFunctionType()->isVarArg() : true;
- doCall(ValueRecord(DestReg, CI.getType()), TheCall, Args, isVarArg);
-}
-
-
-/// dyncastIsNan - Return the operand of an isnan operation if this is an isnan.
-///
-static Value *dyncastIsNan(Value *V) {
- if (CallInst *CI = dyn_cast<CallInst>(V))
- if (Function *F = CI->getCalledFunction())
- if (F->getIntrinsicID() == Intrinsic::isunordered)
- return CI->getOperand(1);
- return 0;
-}
-
-/// isOnlyUsedByUnorderedComparisons - Return true if this value is only used by
-/// or's whos operands are all calls to the isnan predicate.
-static bool isOnlyUsedByUnorderedComparisons(Value *V) {
- assert(dyncastIsNan(V) && "The value isn't an isnan call!");
-
- // Check all uses, which will be or's of isnans if this predicate is true.
- for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
- Instruction *I = cast<Instruction>(*UI);
- if (I->getOpcode() != Instruction::Or) return false;
- if (I->getOperand(0) != V && !dyncastIsNan(I->getOperand(0))) return false;
- if (I->getOperand(1) != V && !dyncastIsNan(I->getOperand(1))) return false;
- }
-
- return true;
-}
-
-/// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
-/// function, lowering any calls to unknown intrinsic functions into the
-/// equivalent LLVM code.
-///
-void ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
- 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()) {
- case Intrinsic::not_intrinsic:
- case Intrinsic::vastart:
- case Intrinsic::vacopy:
- case Intrinsic::vaend:
- case Intrinsic::returnaddress:
- case Intrinsic::frameaddress:
- // FIXME: should lower these ourselves
- // case Intrinsic::isunordered:
- // case Intrinsic::memcpy: -> doCall(). system memcpy almost
- // guaranteed to be faster than anything we generate ourselves
- // We directly implement these intrinsics
- break;
- case Intrinsic::readio: {
- // On PPC, memory operations are in-order. Lower this intrinsic
- // into a volatile load.
- Instruction *Before = CI->getPrev();
- LoadInst * LI = new LoadInst(CI->getOperand(1), "", true, CI);
- CI->replaceAllUsesWith(LI);
- BB->getInstList().erase(CI);
- break;
- }
- case Intrinsic::writeio: {
- // On PPC, memory operations are in-order. Lower this intrinsic
- // into a volatile store.
- Instruction *Before = CI->getPrev();
- StoreInst *SI = new StoreInst(CI->getOperand(1),
- CI->getOperand(2), true, CI);
- CI->replaceAllUsesWith(SI);
- BB->getInstList().erase(CI);
- break;
- }
- default:
- // All other intrinsic calls we must lower.
- Instruction *Before = CI->getPrev();
- TM.getIntrinsicLowering().LowerIntrinsicCall(CI);
- if (Before) { // Move iterator to instruction after call
- I = Before; ++I;
- } else {
- I = BB->begin();
- }
- }
-}
-
-void ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
- unsigned TmpReg1, TmpReg2, TmpReg3;
- switch (ID) {
- case Intrinsic::vastart:
- // Get the address of the first vararg value...
- TmpReg1 = getReg(CI);
- addFrameReference(BuildMI(BB, PPC32::ADDI, 2, TmpReg1), VarArgsFrameIndex,
- 0, false);
- return;
-
- case Intrinsic::vacopy:
- TmpReg1 = getReg(CI);
- TmpReg2 = getReg(CI.getOperand(1));
- BuildMI(BB, PPC32::OR, 2, TmpReg1).addReg(TmpReg2).addReg(TmpReg2);
- return;
- case Intrinsic::vaend: return;
-
- case Intrinsic::returnaddress:
- TmpReg1 = getReg(CI);
- if (cast<Constant>(CI.getOperand(1))->isNullValue()) {
- MachineFrameInfo *MFI = F->getFrameInfo();
- unsigned NumBytes = MFI->getStackSize();
-
- BuildMI(BB, PPC32::LWZ, 2, TmpReg1).addSImm(NumBytes+8)
- .addReg(PPC32::R1);
- } else {
- // Values other than zero are not implemented yet.
- BuildMI(BB, PPC32::LI, 1, TmpReg1).addSImm(0);
- }
- return;
-
- case Intrinsic::frameaddress:
- TmpReg1 = getReg(CI);
- if (cast<Constant>(CI.getOperand(1))->isNullValue()) {
- BuildMI(BB, PPC32::OR, 2, TmpReg1).addReg(PPC32::R1).addReg(PPC32::R1);
- } else {
- // Values other than zero are not implemented yet.
- BuildMI(BB, PPC32::LI, 1, TmpReg1).addSImm(0);
- }
- return;
-
-#if 0
- // This may be useful for supporting isunordered
- case Intrinsic::isnan:
- // If this is only used by 'isunordered' style comparisons, don't emit it.
- if (isOnlyUsedByUnorderedComparisons(&CI)) return;
- TmpReg1 = getReg(CI.getOperand(1));
- emitUCOM(BB, BB->end(), TmpReg1, TmpReg1);
- TmpReg2 = makeAnotherReg(Type::IntTy);
- BuildMI(BB, PPC32::MFCR, TmpReg2);
- TmpReg3 = getReg(CI);
- BuildMI(BB, PPC32::RLWINM, 4, TmpReg3).addReg(TmpReg2).addImm(4).addImm(31).addImm(31);
- return;
-#endif
-
- default: assert(0 && "Error: unknown intrinsics should have been lowered!");
- }
-}
-
-/// visitSimpleBinary - Implement simple binary operators for integral types...
-/// OperatorClass is one of: 0 for Add, 1 for Sub, 2 for And, 3 for Or, 4 for
-/// Xor.
-///
-void ISel::visitSimpleBinary(BinaryOperator &B, unsigned OperatorClass) {
- unsigned DestReg = getReg(B);
- MachineBasicBlock::iterator MI = BB->end();
- Value *Op0 = B.getOperand(0), *Op1 = B.getOperand(1);
- unsigned Class = getClassB(B.getType());
-
- emitSimpleBinaryOperation(BB, MI, Op0, Op1, OperatorClass, DestReg);
-}
-
-/// emitBinaryFPOperation - This method handles emission of floating point
-/// Add (0), Sub (1), Mul (2), and Div (3) operations.
-void ISel::emitBinaryFPOperation(MachineBasicBlock *BB,
- MachineBasicBlock::iterator IP,
- Value *Op0, Value *Op1,
- unsigned OperatorClass, unsigned DestReg) {
-
- // Special case: op Reg, <const fp>
- if (ConstantFP *Op1C = dyn_cast<ConstantFP>(Op1)) {
- // Create a constant pool entry for this constant.
- MachineConstantPool *CP = F->getConstantPool();
- unsigned CPI = CP->getConstantPoolIndex(Op1C);
- const Type *Ty = Op1->getType();
- assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
-
- static const unsigned OpcodeTab[][4] = {
- { PPC32::FADDS, PPC32::FSUBS, PPC32::FMULS, PPC32::FDIVS }, // Float
- { PPC32::FADD, PPC32::FSUB, PPC32::FMUL, PPC32::FDIV }, // Double
- };
-
- unsigned Opcode = OpcodeTab[Ty != Type::FloatTy][OperatorClass];
- unsigned Op1Reg = getReg(Op1C, BB, IP);
- unsigned Op0r = getReg(Op0, BB, IP);
- BuildMI(*BB, IP, Opcode, 2, DestReg).addReg(Op0r).addReg(Op1Reg);
- return;
- }
-
- // Special case: R1 = op <const fp>, R2
- if (ConstantFP *Op0C = dyn_cast<ConstantFP>(Op0))
- if (Op0C->isExactlyValue(-0.0) && OperatorClass == 1) {
- // -0.0 - X === -X
- unsigned op1Reg = getReg(Op1, BB, IP);
- BuildMI(*BB, IP, PPC32::FNEG, 1, DestReg).addReg(op1Reg);
- return;
- } else {
- // R1 = op CST, R2 --> R1 = opr R2, CST
-
- // Create a constant pool entry for this constant.
- MachineConstantPool *CP = F->getConstantPool();
- unsigned CPI = CP->getConstantPoolIndex(Op0C);
- const Type *Ty = Op0C->getType();
- assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
-
- static const unsigned OpcodeTab[][4] = {
- { PPC32::FADDS, PPC32::FSUBS, PPC32::FMULS, PPC32::FDIVS }, // Float
- { PPC32::FADD, PPC32::FSUB, PPC32::FMUL, PPC32::FDIV }, // Double
- };
-
- unsigned Opcode = OpcodeTab[Ty != Type::FloatTy][OperatorClass];
- unsigned Op0Reg = getReg(Op0C, BB, IP);
- unsigned Op1Reg = getReg(Op1, BB, IP);
- BuildMI(*BB, IP, Opcode, 2, DestReg).addReg(Op0Reg).addReg(Op1Reg);
- return;
- }
-
- // General case.
- static const unsigned OpcodeTab[] = {
- PPC32::FADD, PPC32::FSUB, PPC32::FMUL, PPC32::FDIV
- };
-
- unsigned Opcode = OpcodeTab[OperatorClass];
- unsigned Op0r = getReg(Op0, BB, IP);
- unsigned Op1r = getReg(Op1, BB, IP);
- BuildMI(*BB, IP, Opcode, 2, DestReg).addReg(Op0r).addReg(Op1r);
-}
-
-/// emitSimpleBinaryOperation - Implement simple binary operators for integral
-/// types... OperatorClass is one of: 0 for Add, 1 for Sub, 2 for And, 3 for
-/// Or, 4 for Xor.
-///
-/// emitSimpleBinaryOperation - Common code shared between visitSimpleBinary
-/// and constant expression support.
-///
-void ISel::emitSimpleBinaryOperation(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Value *Op0, Value *Op1,
- unsigned OperatorClass, unsigned DestReg) {
- unsigned Class = getClassB(Op0->getType());
-
- // Arithmetic and Bitwise operators
- static const unsigned OpcodeTab[] = {
- PPC32::ADD, PPC32::SUB, PPC32::AND, PPC32::OR, PPC32::XOR
- };
- static const unsigned ImmOpcodeTab[] = {
- PPC32::ADDI, PPC32::SUBI, PPC32::ANDIo, PPC32::ORI, PPC32::XORI
- };
- static const unsigned RImmOpcodeTab[] = {
- PPC32::ADDI, PPC32::SUBFIC, PPC32::ANDIo, PPC32::ORI, PPC32::XORI
- };
-
- // Otherwise, code generate the full operation with a constant.
- static const unsigned BottomTab[] = {
- PPC32::ADDC, PPC32::SUBC, PPC32::AND, PPC32::OR, PPC32::XOR
- };
- static const unsigned TopTab[] = {
- PPC32::ADDE, PPC32::SUBFE, PPC32::AND, PPC32::OR, PPC32::XOR
- };
-
- if (Class == cFP32 || Class == cFP64) {
- assert(OperatorClass < 2 && "No logical ops for FP!");
- emitBinaryFPOperation(MBB, IP, Op0, Op1, OperatorClass, DestReg);
- return;
- }
-
- if (Op0->getType() == Type::BoolTy) {
- if (OperatorClass == 3)
- // If this is an or of two isnan's, emit an FP comparison directly instead
- // of or'ing two isnan's together.
- if (Value *LHS = dyncastIsNan(Op0))
- if (Value *RHS = dyncastIsNan(Op1)) {
- unsigned Op0Reg = getReg(RHS, MBB, IP), Op1Reg = getReg(LHS, MBB, IP);
- unsigned TmpReg = makeAnotherReg(Type::IntTy);
- emitUCOM(MBB, IP, Op0Reg, Op1Reg);
- BuildMI(*MBB, IP, PPC32::MFCR, TmpReg);
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(TmpReg).addImm(4)
- .addImm(31).addImm(31);
- return;
- }
- }
-
- // Special case: op <const int>, Reg
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0)) {
- // sub 0, X -> subfic
- if (OperatorClass == 1 && canUseAsImmediateForOpcode(CI, 0)) {
- unsigned Op1r = getReg(Op1, MBB, IP);
- int imm = CI->getRawValue() & 0xFFFF;
-
- if (Class == cLong) {
- BuildMI(*MBB, IP, PPC32::SUBFIC, 2, DestReg+1).addReg(Op1r+1)
- .addSImm(imm);
- BuildMI(*MBB, IP, PPC32::SUBFZE, 1, DestReg).addReg(Op1r);
- } else {
- BuildMI(*MBB, IP, PPC32::SUBFIC, 2, DestReg).addReg(Op1r).addSImm(imm);
- }
- return;
- }
-
- // If it is easy to do, swap the operands and emit an immediate op
- if (Class != cLong && OperatorClass != 1 &&
- canUseAsImmediateForOpcode(CI, OperatorClass)) {
- unsigned Op1r = getReg(Op1, MBB, IP);
- int imm = CI->getRawValue() & 0xFFFF;
-
- if (OperatorClass < 2)
- BuildMI(*MBB, IP, RImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op1r)
- .addSImm(imm);
- else
- BuildMI(*MBB, IP, RImmOpcodeTab[OperatorClass], 2, DestReg).addReg(Op1r)
- .addZImm(imm);
- return;
- }
- }
-
- // Special case: op Reg, <const int>
- if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
- unsigned Op0r = getReg(Op0, MBB, IP);
-
- // xor X, -1 -> not X
- if (OperatorClass == 4 && Op1C->isAllOnesValue()) {
- BuildMI(*MBB, IP, PPC32::NOR, 2, DestReg).addReg(Op0r).addReg(Op0r);
- if (Class == cLong) // Invert the low part too
- BuildMI(*MBB, IP, PPC32::NOR, 2, DestReg+1).addReg(Op0r+1)
- .addReg(Op0r+1);
- return;
- }
-
- if (Class != cLong) {
- if (canUseAsImmediateForOpcode(Op1C, OperatorClass)) {
- int immediate = Op1C->getRawValue() & 0xFFFF;
-
- if (OperatorClass < 2)
- BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2,DestReg).addReg(Op0r)
- .addSImm(immediate);
- else
- BuildMI(*MBB, IP, ImmOpcodeTab[OperatorClass], 2,DestReg).addReg(Op0r)
- .addZImm(immediate);
- } else {
- unsigned Op1r = getReg(Op1, MBB, IP);
- BuildMI(*MBB, IP, OpcodeTab[OperatorClass], 2, DestReg).addReg(Op0r)
- .addReg(Op1r);
- }
- return;
- }
-
- unsigned Op1r = getReg(Op1, MBB, IP);
-
- BuildMI(*MBB, IP, BottomTab[OperatorClass], 2, DestReg+1).addReg(Op0r+1)
- .addReg(Op1r+1);
- BuildMI(*MBB, IP, TopTab[OperatorClass], 2, DestReg).addReg(Op0r)
- .addReg(Op1r);
- return;
- }
-
- // We couldn't generate an immediate variant of the op, load both halves into
- // registers and emit the appropriate opcode.
- unsigned Op0r = getReg(Op0, MBB, IP);
- unsigned Op1r = getReg(Op1, MBB, IP);
-
- if (Class != cLong) {
- unsigned Opcode = OpcodeTab[OperatorClass];
- BuildMI(*MBB, IP, Opcode, 2, DestReg).addReg(Op0r).addReg(Op1r);
- } else {
- BuildMI(*MBB, IP, BottomTab[OperatorClass], 2, DestReg+1).addReg(Op0r+1)
- .addReg(Op1r+1);
- BuildMI(*MBB, IP, TopTab[OperatorClass], 2, DestReg).addReg(Op0r)
- .addReg(Op1r);
- }
- return;
-}
-
-// ExactLog2 - This function solves for (Val == 1 << (N-1)) and returns N. It
-// returns zero when the input is not exactly a power of two.
-static unsigned ExactLog2(unsigned Val) {
- if (Val == 0 || (Val & (Val-1))) return 0;
- unsigned Count = 0;
- while (Val != 1) {
- Val >>= 1;
- ++Count;
- }
- return Count;
-}
-
-/// doMultiply - Emit appropriate instructions to multiply together the
-/// Values Op0 and Op1, and put the result in DestReg.
-///
-void ISel::doMultiply(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- unsigned DestReg, Value *Op0, Value *Op1) {
- unsigned Class0 = getClass(Op0->getType());
- unsigned Class1 = getClass(Op1->getType());
-
- unsigned Op0r = getReg(Op0, MBB, IP);
- unsigned Op1r = getReg(Op1, MBB, IP);
-
- // 64 x 64 -> 64
- if (Class0 == cLong && Class1 == cLong) {
- unsigned Tmp1 = makeAnotherReg(Type::IntTy);
- unsigned Tmp2 = makeAnotherReg(Type::IntTy);
- unsigned Tmp3 = makeAnotherReg(Type::IntTy);
- unsigned Tmp4 = makeAnotherReg(Type::IntTy);
- BuildMI(*MBB, IP, PPC32::MULHWU, 2, Tmp1).addReg(Op0r+1).addReg(Op1r+1);
- BuildMI(*MBB, IP, PPC32::MULLW, 2, DestReg+1).addReg(Op0r+1).addReg(Op1r+1);
- BuildMI(*MBB, IP, PPC32::MULLW, 2, Tmp2).addReg(Op0r+1).addReg(Op1r);
- BuildMI(*MBB, IP, PPC32::ADD, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
- BuildMI(*MBB, IP, PPC32::MULLW, 2, Tmp4).addReg(Op0r).addReg(Op1r+1);
- BuildMI(*MBB, IP, PPC32::ADD, 2, DestReg).addReg(Tmp3).addReg(Tmp4);
- return;
- }
-
- // 64 x 32 or less, promote 32 to 64 and do a 64 x 64
- if (Class0 == cLong && Class1 <= cInt) {
- unsigned Tmp0 = makeAnotherReg(Type::IntTy);
- unsigned Tmp1 = makeAnotherReg(Type::IntTy);
- unsigned Tmp2 = makeAnotherReg(Type::IntTy);
- unsigned Tmp3 = makeAnotherReg(Type::IntTy);
- unsigned Tmp4 = makeAnotherReg(Type::IntTy);
- if (Op1->getType()->isSigned())
- BuildMI(*MBB, IP, PPC32::SRAWI, 2, Tmp0).addReg(Op1r).addImm(31);
- else
- BuildMI(*MBB, IP, PPC32::LI, 2, Tmp0).addSImm(0);
- BuildMI(*MBB, IP, PPC32::MULHWU, 2, Tmp1).addReg(Op0r+1).addReg(Op1r);
- BuildMI(*MBB, IP, PPC32::MULLW, 2, DestReg+1).addReg(Op0r+1).addReg(Op1r);
- BuildMI(*MBB, IP, PPC32::MULLW, 2, Tmp2).addReg(Op0r+1).addReg(Tmp0);
- BuildMI(*MBB, IP, PPC32::ADD, 2, Tmp3).addReg(Tmp1).addReg(Tmp2);
- BuildMI(*MBB, IP, PPC32::MULLW, 2, Tmp4).addReg(Op0r).addReg(Op1r);
- BuildMI(*MBB, IP, PPC32::ADD, 2, DestReg).addReg(Tmp3).addReg(Tmp4);
- return;
- }
-
- // 32 x 32 -> 32
- if (Class0 <= cInt && Class1 <= cInt) {
- BuildMI(*MBB, IP, PPC32::MULLW, 2, DestReg).addReg(Op0r).addReg(Op1r);
- return;
- }
-
- assert(0 && "doMultiply cannot operate on unknown type!");
-}
-
-/// doMultiplyConst - This method will multiply the value in Op0 by the
-/// value of the ContantInt *CI
-void ISel::doMultiplyConst(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- unsigned DestReg, Value *Op0, ConstantInt *CI) {
- unsigned Class = getClass(Op0->getType());
-
- // Mul op0, 0 ==> 0
- if (CI->isNullValue()) {
- BuildMI(*MBB, IP, PPC32::LI, 1, DestReg).addSImm(0);
- if (Class == cLong)
- BuildMI(*MBB, IP, PPC32::LI, 1, DestReg+1).addSImm(0);
- return;
- }
-
- // Mul op0, 1 ==> op0
- if (CI->equalsInt(1)) {
- unsigned Op0r = getReg(Op0, MBB, IP);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(Op0r).addReg(Op0r);
- if (Class == cLong)
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(Op0r+1).addReg(Op0r+1);
- return;
- }
-
- // If the element size is exactly a power of 2, use a shift to get it.
- if (unsigned Shift = ExactLog2(CI->getRawValue())) {
- ConstantUInt *ShiftCI = ConstantUInt::get(Type::UByteTy, Shift);
- emitShiftOperation(MBB, IP, Op0, ShiftCI, true, Op0->getType(), DestReg);
- return;
- }
-
- // If 32 bits or less and immediate is in right range, emit mul by immediate
- if (Class == cByte || Class == cShort || Class == cInt) {
- if (canUseAsImmediateForOpcode(CI, 0)) {
- unsigned Op0r = getReg(Op0, MBB, IP);
- unsigned imm = CI->getRawValue() & 0xFFFF;
- BuildMI(*MBB, IP, PPC32::MULLI, 2, DestReg).addReg(Op0r).addSImm(imm);
- return;
- }
- }
-
- doMultiply(MBB, IP, DestReg, Op0, CI);
-}
-
-void ISel::visitMul(BinaryOperator &I) {
- unsigned ResultReg = getReg(I);
-
- Value *Op0 = I.getOperand(0);
- Value *Op1 = I.getOperand(1);
-
- MachineBasicBlock::iterator IP = BB->end();
- emitMultiply(BB, IP, Op0, Op1, ResultReg);
-}
-
-void ISel::emitMultiply(MachineBasicBlock *MBB, MachineBasicBlock::iterator IP,
- Value *Op0, Value *Op1, unsigned DestReg) {
- TypeClass Class = getClass(Op0->getType());
-
- switch (Class) {
- case cByte:
- case cShort:
- case cInt:
- case cLong:
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Op1)) {
- doMultiplyConst(MBB, IP, DestReg, Op0, CI);
- } else {
- doMultiply(MBB, IP, DestReg, Op0, Op1);
- }
- return;
- case cFP32:
- case cFP64:
- emitBinaryFPOperation(MBB, IP, Op0, Op1, 2, DestReg);
- return;
- break;
- }
-}
-
-
-/// visitDivRem - Handle division and remainder instructions... these
-/// instruction both require the same instructions to be generated, they just
-/// select the result from a different register. Note that both of these
-/// instructions work differently for signed and unsigned operands.
-///
-void ISel::visitDivRem(BinaryOperator &I) {
- unsigned ResultReg = getReg(I);
- Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
-
- MachineBasicBlock::iterator IP = BB->end();
- emitDivRemOperation(BB, IP, Op0, Op1, I.getOpcode() == Instruction::Div,
- ResultReg);
-}
-
-void ISel::emitDivRemOperation(MachineBasicBlock *BB,
- MachineBasicBlock::iterator IP,
- Value *Op0, Value *Op1, bool isDiv,
- unsigned ResultReg) {
- const Type *Ty = Op0->getType();
- unsigned Class = getClass(Ty);
- switch (Class) {
- case cFP32:
- if (isDiv) {
- // Floating point divide...
- emitBinaryFPOperation(BB, IP, Op0, Op1, 3, ResultReg);
- return;
- } else {
- // Floating point remainder via fmodf(float x, float y);
- unsigned Op0Reg = getReg(Op0, BB, IP);
- unsigned Op1Reg = getReg(Op1, BB, IP);
- MachineInstr *TheCall =
- BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(fmodfFn, true);
- std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(Op0Reg, Type::FloatTy));
- Args.push_back(ValueRecord(Op1Reg, Type::FloatTy));
- doCall(ValueRecord(ResultReg, Type::FloatTy), TheCall, Args, false);
- TM.CalledFunctions.insert(fmodfFn);
- }
- return;
- case cFP64:
- if (isDiv) {
- // Floating point divide...
- emitBinaryFPOperation(BB, IP, Op0, Op1, 3, ResultReg);
- return;
- } else {
- // Floating point remainder via fmod(double x, double y);
- unsigned Op0Reg = getReg(Op0, BB, IP);
- unsigned Op1Reg = getReg(Op1, BB, IP);
- MachineInstr *TheCall =
- BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(fmodFn, true);
- std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(Op0Reg, Type::DoubleTy));
- Args.push_back(ValueRecord(Op1Reg, Type::DoubleTy));
- doCall(ValueRecord(ResultReg, Type::DoubleTy), TheCall, Args, false);
- TM.CalledFunctions.insert(fmodFn);
- }
- return;
- case cLong: {
- static Function* const Funcs[] =
- { __moddi3Fn, __divdi3Fn, __umoddi3Fn, __udivdi3Fn };
- unsigned Op0Reg = getReg(Op0, BB, IP);
- unsigned Op1Reg = getReg(Op1, BB, IP);
- unsigned NameIdx = Ty->isUnsigned()*2 + isDiv;
- MachineInstr *TheCall =
- BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(Funcs[NameIdx], true);
-
- std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(Op0Reg, Type::LongTy));
- Args.push_back(ValueRecord(Op1Reg, Type::LongTy));
- doCall(ValueRecord(ResultReg, Type::LongTy), TheCall, Args, false);
- TM.CalledFunctions.insert(Funcs[NameIdx]);
- return;
- }
- case cByte: case cShort: case cInt:
- break; // Small integrals, handled below...
- default: assert(0 && "Unknown class!");
- }
-
- // Special case signed division by power of 2.
- if (isDiv)
- if (ConstantSInt *CI = dyn_cast<ConstantSInt>(Op1)) {
- assert(Class != cLong && "This doesn't handle 64-bit divides!");
- int V = CI->getValue();
-
- if (V == 1) { // X /s 1 => X
- unsigned Op0Reg = getReg(Op0, BB, IP);
- BuildMI(*BB, IP, PPC32::OR, 2, ResultReg).addReg(Op0Reg).addReg(Op0Reg);
- return;
- }
-
- if (V == -1) { // X /s -1 => -X
- unsigned Op0Reg = getReg(Op0, BB, IP);
- BuildMI(*BB, IP, PPC32::NEG, 1, ResultReg).addReg(Op0Reg);
- return;
- }
-
- unsigned log2V = ExactLog2(V);
- if (log2V != 0 && Ty->isSigned()) {
- unsigned Op0Reg = getReg(Op0, BB, IP);
- unsigned TmpReg = makeAnotherReg(Op0->getType());
-
- BuildMI(*BB, IP, PPC32::SRAWI, 2, TmpReg).addReg(Op0Reg).addImm(log2V);
- BuildMI(*BB, IP, PPC32::ADDZE, 1, ResultReg).addReg(TmpReg);
- return;
- }
- }
-
- unsigned Op0Reg = getReg(Op0, BB, IP);
- unsigned Op1Reg = getReg(Op1, BB, IP);
- unsigned Opcode = Ty->isSigned() ? PPC32::DIVW : PPC32::DIVWU;
-
- if (isDiv) {
- BuildMI(*BB, IP, Opcode, 2, ResultReg).addReg(Op0Reg).addReg(Op1Reg);
- } else { // Remainder
- unsigned TmpReg1 = makeAnotherReg(Op0->getType());
- unsigned TmpReg2 = makeAnotherReg(Op0->getType());
-
- BuildMI(*BB, IP, Opcode, 2, TmpReg1).addReg(Op0Reg).addReg(Op1Reg);
- BuildMI(*BB, IP, PPC32::MULLW, 2, TmpReg2).addReg(TmpReg1).addReg(Op1Reg);
- BuildMI(*BB, IP, PPC32::SUBF, 2, ResultReg).addReg(TmpReg2).addReg(Op0Reg);
- }
-}
-
-
-/// Shift instructions: 'shl', 'sar', 'shr' - Some special cases here
-/// for constant immediate shift values, and for constant immediate
-/// shift values equal to 1. Even the general case is sort of special,
-/// because the shift amount has to be in CL, not just any old register.
-///
-void ISel::visitShiftInst(ShiftInst &I) {
- MachineBasicBlock::iterator IP = BB->end();
- emitShiftOperation(BB, IP, I.getOperand(0), I.getOperand(1),
- I.getOpcode() == Instruction::Shl, I.getType(),
- getReg(I));
-}
-
-/// emitShiftOperation - Common code shared between visitShiftInst and
-/// constant expression support.
-///
-void ISel::emitShiftOperation(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Value *Op, Value *ShiftAmount, bool isLeftShift,
- const Type *ResultTy, unsigned DestReg) {
- unsigned SrcReg = getReg (Op, MBB, IP);
- bool isSigned = ResultTy->isSigned ();
- unsigned Class = getClass (ResultTy);
-
- // Longs, as usual, are handled specially...
- if (Class == cLong) {
- // If we have a constant shift, we can generate much more efficient code
- // than otherwise...
- //
- if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(ShiftAmount)) {
- unsigned Amount = CUI->getValue();
- if (Amount < 32) {
- if (isLeftShift) {
- // FIXME: RLWIMI is a use-and-def of DestReg+1, but that violates SSA
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg)
- .addImm(Amount).addImm(0).addImm(31-Amount);
- BuildMI(*MBB, IP, PPC32::RLWIMI, 5).addReg(DestReg).addReg(SrcReg+1)
- .addImm(Amount).addImm(32-Amount).addImm(31);
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg+1).addReg(SrcReg+1)
- .addImm(Amount).addImm(0).addImm(31-Amount);
- } else {
- // FIXME: RLWIMI is a use-and-def of DestReg, but that violates SSA
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg+1).addReg(SrcReg+1)
- .addImm(32-Amount).addImm(Amount).addImm(31);
- BuildMI(*MBB, IP, PPC32::RLWIMI, 5).addReg(DestReg+1).addReg(SrcReg)
- .addImm(32-Amount).addImm(0).addImm(Amount-1);
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg)
- .addImm(32-Amount).addImm(Amount).addImm(31);
- }
- } else { // Shifting more than 32 bits
- Amount -= 32;
- if (isLeftShift) {
- if (Amount != 0) {
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg+1)
- .addImm(Amount).addImm(0).addImm(31-Amount);
- } else {
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg+1)
- .addReg(SrcReg+1);
- }
- BuildMI(*MBB, IP, PPC32::LI, 1, DestReg+1).addSImm(0);
- } else {
- if (Amount != 0) {
- if (isSigned)
- BuildMI(*MBB, IP, PPC32::SRAWI, 2, DestReg+1).addReg(SrcReg)
- .addImm(Amount);
- else
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg+1).addReg(SrcReg)
- .addImm(32-Amount).addImm(Amount).addImm(31);
- } else {
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg)
- .addReg(SrcReg);
- }
- BuildMI(*MBB, IP,PPC32::LI, 1, DestReg).addSImm(0);
- }
- }
- } else {
- unsigned TmpReg1 = makeAnotherReg(Type::IntTy);
- unsigned TmpReg2 = makeAnotherReg(Type::IntTy);
- unsigned TmpReg3 = makeAnotherReg(Type::IntTy);
- unsigned TmpReg4 = makeAnotherReg(Type::IntTy);
- unsigned TmpReg5 = makeAnotherReg(Type::IntTy);
- unsigned TmpReg6 = makeAnotherReg(Type::IntTy);
- unsigned ShiftAmountReg = getReg (ShiftAmount, MBB, IP);
-
- if (isLeftShift) {
- BuildMI(*MBB, IP, PPC32::SUBFIC, 2, TmpReg1).addReg(ShiftAmountReg)
- .addSImm(32);
- BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg2).addReg(SrcReg)
- .addReg(ShiftAmountReg);
- BuildMI(*MBB, IP, PPC32::SRW, 2, TmpReg3).addReg(SrcReg+1)
- .addReg(TmpReg1);
- BuildMI(*MBB, IP, PPC32::OR, 2,TmpReg4).addReg(TmpReg2).addReg(TmpReg3);
- BuildMI(*MBB, IP, PPC32::ADDI, 2, TmpReg5).addReg(ShiftAmountReg)
- .addSImm(-32);
- BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg6).addReg(SrcReg+1)
- .addReg(TmpReg5);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(TmpReg4)
- .addReg(TmpReg6);
- BuildMI(*MBB, IP, PPC32::SLW, 2, DestReg+1).addReg(SrcReg+1)
- .addReg(ShiftAmountReg);
- } else {
- if (isSigned) {
- // FIXME: Unimplemented
- // Page C-3 of the PowerPC 32bit Programming Environments Manual
- std::cerr << "ERROR: Unimplemented: signed right shift of long\n";
- abort();
- } else {
- BuildMI(*MBB, IP, PPC32::SUBFIC, 2, TmpReg1).addReg(ShiftAmountReg)
- .addSImm(32);
- BuildMI(*MBB, IP, PPC32::SRW, 2, TmpReg2).addReg(SrcReg+1)
- .addReg(ShiftAmountReg);
- BuildMI(*MBB, IP, PPC32::SLW, 2, TmpReg3).addReg(SrcReg)
- .addReg(TmpReg1);
- BuildMI(*MBB, IP, PPC32::OR, 2, TmpReg4).addReg(TmpReg2)
- .addReg(TmpReg3);
- BuildMI(*MBB, IP, PPC32::ADDI, 2, TmpReg5).addReg(ShiftAmountReg)
- .addSImm(-32);
- BuildMI(*MBB, IP, PPC32::SRW, 2, TmpReg6).addReg(SrcReg)
- .addReg(TmpReg5);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(TmpReg4)
- .addReg(TmpReg6);
- BuildMI(*MBB, IP, PPC32::SRW, 2, DestReg).addReg(SrcReg)
- .addReg(ShiftAmountReg);
- }
- }
- }
- return;
- }
-
- if (ConstantUInt *CUI = dyn_cast<ConstantUInt>(ShiftAmount)) {
- // The shift amount is constant, guaranteed to be a ubyte. Get its value.
- assert(CUI->getType() == Type::UByteTy && "Shift amount not a ubyte?");
- unsigned Amount = CUI->getValue();
-
- if (isLeftShift) {
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg)
- .addImm(Amount).addImm(0).addImm(31-Amount);
- } else {
- if (isSigned) {
- BuildMI(*MBB, IP, PPC32::SRAWI,2,DestReg).addReg(SrcReg).addImm(Amount);
- } else {
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg)
- .addImm(32-Amount).addImm(Amount).addImm(31);
- }
- }
- } else { // The shift amount is non-constant.
- unsigned ShiftAmountReg = getReg (ShiftAmount, MBB, IP);
-
- if (isLeftShift) {
- BuildMI(*MBB, IP, PPC32::SLW, 2, DestReg).addReg(SrcReg)
- .addReg(ShiftAmountReg);
- } else {
- BuildMI(*MBB, IP, isSigned ? PPC32::SRAW : PPC32::SRW, 2, DestReg)
- .addReg(SrcReg).addReg(ShiftAmountReg);
- }
- }
-}
-
-
-/// visitLoadInst - Implement LLVM load instructions. Pretty straightforward
-/// mapping of LLVM classes to PPC load instructions, with the exception of
-/// signed byte loads, which need a sign extension following them.
-///
-void ISel::visitLoadInst(LoadInst &I) {
- // Immediate opcodes, for reg+imm addressing
- static const unsigned ImmOpcodes[] = {
- PPC32::LBZ, PPC32::LHZ, PPC32::LWZ,
- PPC32::LFS, PPC32::LFD, PPC32::LWZ
- };
- // Indexed opcodes, for reg+reg addressing
- static const unsigned IdxOpcodes[] = {
- PPC32::LBZX, PPC32::LHZX, PPC32::LWZX,
- PPC32::LFSX, PPC32::LFDX, PPC32::LWZX
- };
-
- unsigned Class = getClassB(I.getType());
- unsigned ImmOpcode = ImmOpcodes[Class];
- unsigned IdxOpcode = IdxOpcodes[Class];
- unsigned DestReg = getReg(I);
- Value *SourceAddr = I.getOperand(0);
-
- if (Class == cShort && I.getType()->isSigned()) ImmOpcode = PPC32::LHA;
- if (Class == cShort && I.getType()->isSigned()) IdxOpcode = PPC32::LHAX;
-
- if (AllocaInst *AI = dyn_castFixedAlloca(SourceAddr)) {
- unsigned FI = getFixedSizedAllocaFI(AI);
- if (Class == cLong) {
- addFrameReference(BuildMI(BB, ImmOpcode, 2, DestReg), FI);
- addFrameReference(BuildMI(BB, ImmOpcode, 2, DestReg+1), FI, 4);
- } else if (Class == cByte && I.getType()->isSigned()) {
- unsigned TmpReg = makeAnotherReg(I.getType());
- addFrameReference(BuildMI(BB, ImmOpcode, 2, TmpReg), FI);
- BuildMI(BB, PPC32::EXTSB, 1, DestReg).addReg(TmpReg);
- } else {
- addFrameReference(BuildMI(BB, ImmOpcode, 2, DestReg), FI);
- }
- return;
- }
-
- // If this load is the only use of the GEP instruction that is its address,
- // then we can fold the GEP directly into the load instruction.
- // emitGEPOperation with a second to last arg of 'true' will place the
- // base register for the GEP into baseReg, and the constant offset from that
- // into offset. If the offset fits in 16 bits, we can emit a reg+imm store
- // otherwise, we copy the offset into another reg, and use reg+reg addressing.
- if (GetElementPtrInst *GEPI = canFoldGEPIntoLoadOrStore(SourceAddr)) {
- unsigned baseReg = getReg(GEPI);
- ConstantSInt *offset;
-
- emitGEPOperation(BB, BB->end(), GEPI->getOperand(0), GEPI->op_begin()+1,
- GEPI->op_end(), baseReg, true, &offset);
-
- if (Class != cLong && canUseAsImmediateForOpcode(offset, 0)) {
- if (Class == cByte && I.getType()->isSigned()) {
- unsigned TmpReg = makeAnotherReg(I.getType());
- BuildMI(BB, ImmOpcode, 2, TmpReg).addSImm(offset->getValue())
- .addReg(baseReg);
- BuildMI(BB, PPC32::EXTSB, 1, DestReg).addReg(TmpReg);
- } else {
- BuildMI(BB, ImmOpcode, 2, DestReg).addSImm(offset->getValue())
- .addReg(baseReg);
- }
- return;
- }
-
- unsigned indexReg = getReg(offset);
-
- if (Class == cLong) {
- unsigned indexPlus4 = makeAnotherReg(Type::IntTy);
- BuildMI(BB, PPC32::ADDI, 2, indexPlus4).addReg(indexReg).addSImm(4);
- BuildMI(BB, IdxOpcode, 2, DestReg).addReg(indexReg).addReg(baseReg);
- BuildMI(BB, IdxOpcode, 2, DestReg+1).addReg(indexPlus4).addReg(baseReg);
- } else if (Class == cByte && I.getType()->isSigned()) {
- unsigned TmpReg = makeAnotherReg(I.getType());
- BuildMI(BB, IdxOpcode, 2, DestReg).addReg(indexReg).addReg(baseReg);
- BuildMI(BB, PPC32::EXTSB, 1, DestReg).addReg(TmpReg);
- } else {
- BuildMI(BB, IdxOpcode, 2, DestReg).addReg(indexReg).addReg(baseReg);
- }
- return;
- }
-
- // The fallback case, where the load was from a source that could not be
- // folded into the load instruction.
- unsigned SrcAddrReg = getReg(SourceAddr);
-
- if (Class == cLong) {
- BuildMI(BB, ImmOpcode, 2, DestReg).addSImm(0).addReg(SrcAddrReg);
- BuildMI(BB, ImmOpcode, 2, DestReg+1).addSImm(4).addReg(SrcAddrReg);
- } else if (Class == cByte && I.getType()->isSigned()) {
- unsigned TmpReg = makeAnotherReg(I.getType());
- BuildMI(BB, ImmOpcode, 2, TmpReg).addSImm(0).addReg(SrcAddrReg);
- BuildMI(BB, PPC32::EXTSB, 1, DestReg).addReg(TmpReg);
- } else {
- BuildMI(BB, ImmOpcode, 2, DestReg).addSImm(0).addReg(SrcAddrReg);
- }
-}
-
-/// visitStoreInst - Implement LLVM store instructions
-///
-void ISel::visitStoreInst(StoreInst &I) {
- // Immediate opcodes, for reg+imm addressing
- static const unsigned ImmOpcodes[] = {
- PPC32::STB, PPC32::STH, PPC32::STW,
- PPC32::STFS, PPC32::STFD, PPC32::STW
- };
- // Indexed opcodes, for reg+reg addressing
- static const unsigned IdxOpcodes[] = {
- PPC32::STBX, PPC32::STHX, PPC32::STWX,
- PPC32::STFSX, PPC32::STDX, PPC32::STWX
- };
-
- Value *SourceAddr = I.getOperand(1);
- const Type *ValTy = I.getOperand(0)->getType();
- unsigned Class = getClassB(ValTy);
- unsigned ImmOpcode = ImmOpcodes[Class];
- unsigned IdxOpcode = IdxOpcodes[Class];
- unsigned ValReg = getReg(I.getOperand(0));
-
- // If this store is the only use of the GEP instruction that is its address,
- // then we can fold the GEP directly into the store instruction.
- // emitGEPOperation with a second to last arg of 'true' will place the
- // base register for the GEP into baseReg, and the constant offset from that
- // into offset. If the offset fits in 16 bits, we can emit a reg+imm store
- // otherwise, we copy the offset into another reg, and use reg+reg addressing.
- if (GetElementPtrInst *GEPI = canFoldGEPIntoLoadOrStore(SourceAddr)) {
- unsigned baseReg = getReg(GEPI);
- ConstantSInt *offset;
-
- emitGEPOperation(BB, BB->end(), GEPI->getOperand(0), GEPI->op_begin()+1,
- GEPI->op_end(), baseReg, true, &offset);
-
- if (Class != cLong && canUseAsImmediateForOpcode(offset, 0)) {
- BuildMI(BB, ImmOpcode, 3).addReg(ValReg).addSImm(offset->getValue())
- .addReg(baseReg);
- return;
- }
-
- unsigned indexReg = getReg(offset);
-
- if (Class == cLong) {
- unsigned indexPlus4 = makeAnotherReg(Type::IntTy);
- BuildMI(BB, PPC32::ADDI, 2, indexPlus4).addReg(indexReg).addSImm(4);
- BuildMI(BB, IdxOpcode, 3).addReg(ValReg).addReg(indexReg).addReg(baseReg);
- BuildMI(BB, IdxOpcode, 3).addReg(ValReg+1).addReg(indexPlus4)
- .addReg(baseReg);
- return;
- }
- BuildMI(BB, IdxOpcode, 3).addReg(ValReg).addReg(indexReg).addReg(baseReg);
- return;
- }
-
- // If the store address wasn't the only use of a GEP, we fall back to the
- // standard path: store the ValReg at the value in AddressReg.
- unsigned AddressReg = getReg(I.getOperand(1));
- if (Class == cLong) {
- BuildMI(BB, ImmOpcode, 3).addReg(ValReg).addSImm(0).addReg(AddressReg);
- BuildMI(BB, ImmOpcode, 3).addReg(ValReg+1).addSImm(4).addReg(AddressReg);
- return;
- }
- BuildMI(BB, ImmOpcode, 3).addReg(ValReg).addSImm(0).addReg(AddressReg);
-}
-
-
-/// visitCastInst - Here we have various kinds of copying with or without sign
-/// extension going on.
-///
-void ISel::visitCastInst(CastInst &CI) {
- Value *Op = CI.getOperand(0);
-
- unsigned SrcClass = getClassB(Op->getType());
- unsigned DestClass = getClassB(CI.getType());
-
- // If this is a cast from a 32-bit integer to a Long type, and the only uses
- // of the case are GEP instructions, then the cast does not need to be
- // generated explicitly, it will be folded into the GEP.
- if (DestClass == cLong && SrcClass == cInt) {
- bool AllUsesAreGEPs = true;
- for (Value::use_iterator I = CI.use_begin(), E = CI.use_end(); I != E; ++I)
- if (!isa<GetElementPtrInst>(*I)) {
- AllUsesAreGEPs = false;
- break;
- }
-
- // No need to codegen this cast if all users are getelementptr instrs...
- if (AllUsesAreGEPs) return;
- }
-
- unsigned DestReg = getReg(CI);
- MachineBasicBlock::iterator MI = BB->end();
- emitCastOperation(BB, MI, Op, CI.getType(), DestReg);
-}
-
-/// emitCastOperation - Common code shared between visitCastInst and constant
-/// expression cast support.
-///
-void ISel::emitCastOperation(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Value *Src, const Type *DestTy,
- unsigned DestReg) {
- const Type *SrcTy = Src->getType();
- unsigned SrcClass = getClassB(SrcTy);
- unsigned DestClass = getClassB(DestTy);
- unsigned SrcReg = getReg(Src, MBB, IP);
-
- // Implement casts to bool by using compare on the operand followed by set if
- // not zero on the result.
- if (DestTy == Type::BoolTy) {
- switch (SrcClass) {
- case cByte:
- case cShort:
- case cInt: {
- unsigned TmpReg = makeAnotherReg(Type::IntTy);
- BuildMI(*MBB, IP, PPC32::ADDIC, 2, TmpReg).addReg(SrcReg).addSImm(-1);
- BuildMI(*MBB, IP, PPC32::SUBFE, 2, DestReg).addReg(TmpReg).addReg(SrcReg);
- break;
- }
- case cLong: {
- unsigned TmpReg = makeAnotherReg(Type::IntTy);
- unsigned SrcReg2 = makeAnotherReg(Type::IntTy);
- BuildMI(*MBB, IP, PPC32::OR, 2, SrcReg2).addReg(SrcReg).addReg(SrcReg+1);
- BuildMI(*MBB, IP, PPC32::ADDIC, 2, TmpReg).addReg(SrcReg2).addSImm(-1);
- BuildMI(*MBB, IP, PPC32::SUBFE, 2, DestReg).addReg(TmpReg)
- .addReg(SrcReg2);
- break;
- }
- case cFP32:
- case cFP64:
- // FSEL perhaps?
- std::cerr << "ERROR: Cast fp-to-bool not implemented!\n";
- abort();
- }
- return;
- }
-
- // Handle cast of Float -> Double
- if (SrcClass == cFP32 && DestClass == cFP64) {
- BuildMI(*MBB, IP, PPC32::FMR, 1, DestReg).addReg(SrcReg);
- return;
- }
-
- // Handle cast of Double -> Float
- if (SrcClass == cFP64 && DestClass == cFP32) {
- BuildMI(*MBB, IP, PPC32::FRSP, 1, DestReg).addReg(SrcReg);
- return;
- }
-
- // Handle casts from integer to floating point now...
- if (DestClass == cFP32 || DestClass == cFP64) {
-
- // Emit a library call for long to float conversion
- if (SrcClass == cLong) {
- std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(SrcReg, SrcTy));
- Function *floatFn = (DestClass == cFP32) ? __floatdisfFn : __floatdidfFn;
- MachineInstr *TheCall =
- BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(floatFn, true);
- doCall(ValueRecord(DestReg, DestTy), TheCall, Args, false);
- TM.CalledFunctions.insert(floatFn);
- return;
- }
-
- // Make sure we're dealing with a full 32 bits
- unsigned TmpReg = makeAnotherReg(Type::IntTy);
- promote32(TmpReg, ValueRecord(SrcReg, SrcTy));
-
- SrcReg = TmpReg;
-
- // Spill the integer to memory and reload it from there.
- // Also spill room for a special conversion constant
- int ConstantFrameIndex =
- F->getFrameInfo()->CreateStackObject(Type::DoubleTy, TM.getTargetData());
- int ValueFrameIdx =
- F->getFrameInfo()->CreateStackObject(Type::DoubleTy, TM.getTargetData());
-
- unsigned constantHi = makeAnotherReg(Type::IntTy);
- unsigned constantLo = makeAnotherReg(Type::IntTy);
- unsigned ConstF = makeAnotherReg(Type::DoubleTy);
- unsigned TempF = makeAnotherReg(Type::DoubleTy);
-
- if (!SrcTy->isSigned()) {
- BuildMI(*BB, IP, PPC32::LIS, 1, constantHi).addSImm(0x4330);
- BuildMI(*BB, IP, PPC32::LI, 1, constantLo).addSImm(0);
- addFrameReference(BuildMI(*BB, IP, PPC32::STW, 3).addReg(constantHi),
- ConstantFrameIndex);
- addFrameReference(BuildMI(*BB, IP, PPC32::STW, 3).addReg(constantLo),
- ConstantFrameIndex, 4);
- addFrameReference(BuildMI(*BB, IP, PPC32::STW, 3).addReg(constantHi),
- ValueFrameIdx);
- addFrameReference(BuildMI(*BB, IP, PPC32::STW, 3).addReg(SrcReg),
- ValueFrameIdx, 4);
- addFrameReference(BuildMI(*BB, IP, PPC32::LFD, 2, ConstF),
- ConstantFrameIndex);
- addFrameReference(BuildMI(*BB, IP, PPC32::LFD, 2, TempF), ValueFrameIdx);
- BuildMI(*BB, IP, PPC32::FSUB, 2, DestReg).addReg(TempF).addReg(ConstF);
- } else {
- unsigned TempLo = makeAnotherReg(Type::IntTy);
- BuildMI(*BB, IP, PPC32::LIS, 1, constantHi).addSImm(0x4330);
- BuildMI(*BB, IP, PPC32::LIS, 1, constantLo).addSImm(0x8000);
- addFrameReference(BuildMI(*BB, IP, PPC32::STW, 3).addReg(constantHi),
- ConstantFrameIndex);
- addFrameReference(BuildMI(*BB, IP, PPC32::STW, 3).addReg(constantLo),
- ConstantFrameIndex, 4);
- addFrameReference(BuildMI(*BB, IP, PPC32::STW, 3).addReg(constantHi),
- ValueFrameIdx);
- BuildMI(*BB, IP, PPC32::XORIS, 2, TempLo).addReg(SrcReg).addImm(0x8000);
- addFrameReference(BuildMI(*BB, IP, PPC32::STW, 3).addReg(TempLo),
- ValueFrameIdx, 4);
- addFrameReference(BuildMI(*BB, IP, PPC32::LFD, 2, ConstF),
- ConstantFrameIndex);
- addFrameReference(BuildMI(*BB, IP, PPC32::LFD, 2, TempF), ValueFrameIdx);
- BuildMI(*BB, IP, PPC32::FSUB, 2, DestReg).addReg(TempF).addReg(ConstF);
- }
- return;
- }
-
- // Handle casts from floating point to integer now...
- if (SrcClass == cFP32 || SrcClass == cFP64) {
- // emit library call
- if (DestClass == cLong) {
- std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(SrcReg, SrcTy));
- Function *floatFn = (DestClass == cFP32) ? __fixsfdiFn : __fixdfdiFn;
- MachineInstr *TheCall =
- BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(floatFn, true);
- doCall(ValueRecord(DestReg, DestTy), TheCall, Args, false);
- TM.CalledFunctions.insert(floatFn);
- return;
- }
-
- int ValueFrameIdx =
- F->getFrameInfo()->CreateStackObject(SrcTy, TM.getTargetData());
-
- if (DestTy->isSigned()) {
- unsigned TempReg = makeAnotherReg(Type::DoubleTy);
-
- // Convert to integer in the FP reg and store it to a stack slot
- BuildMI(*BB, IP, PPC32::FCTIWZ, 1, TempReg).addReg(SrcReg);
- addFrameReference(BuildMI(*BB, IP, PPC32::STFD, 3)
- .addReg(TempReg), ValueFrameIdx);
-
- // There is no load signed byte opcode, so we must emit a sign extend for
- // that particular size. Make sure to source the new integer from the
- // correct offset.
- if (DestClass == cByte) {
- unsigned TempReg2 = makeAnotherReg(DestTy);
- addFrameReference(BuildMI(*BB, IP, PPC32::LBZ, 2, TempReg2),
- ValueFrameIdx, 7);
- BuildMI(*MBB, IP, PPC32::EXTSB, DestReg).addReg(TempReg2);
- } else {
- int offset = (DestClass == cShort) ? 6 : 4;
- unsigned LoadOp = (DestClass == cShort) ? PPC32::LHA : PPC32::LWZ;
- addFrameReference(BuildMI(*BB, IP, LoadOp, 2, DestReg),
- ValueFrameIdx, offset);
- }
- } else {
- unsigned Zero = getReg(ConstantFP::get(Type::DoubleTy, 0.0f));
- double maxInt = (1LL << 32) - 1;
- unsigned MaxInt = getReg(ConstantFP::get(Type::DoubleTy, maxInt));
- double border = 1LL << 31;
- unsigned Border = getReg(ConstantFP::get(Type::DoubleTy, border));
- unsigned UseZero = makeAnotherReg(Type::DoubleTy);
- unsigned UseMaxInt = makeAnotherReg(Type::DoubleTy);
- unsigned UseChoice = makeAnotherReg(Type::DoubleTy);
- unsigned TmpReg = makeAnotherReg(Type::DoubleTy);
- unsigned TmpReg2 = makeAnotherReg(Type::DoubleTy);
- unsigned ConvReg = makeAnotherReg(Type::DoubleTy);
- unsigned IntTmp = makeAnotherReg(Type::IntTy);
- unsigned XorReg = makeAnotherReg(Type::IntTy);
- int FrameIdx =
- F->getFrameInfo()->CreateStackObject(SrcTy, TM.getTargetData());
- // Update machine-CFG edges
- MachineBasicBlock *XorMBB = new MachineBasicBlock(BB->getBasicBlock());
- MachineBasicBlock *PhiMBB = new MachineBasicBlock(BB->getBasicBlock());
- MachineBasicBlock *OldMBB = BB;
- ilist<MachineBasicBlock>::iterator It = BB; ++It;
- F->getBasicBlockList().insert(It, XorMBB);
- F->getBasicBlockList().insert(It, PhiMBB);
- BB->addSuccessor(XorMBB);
- BB->addSuccessor(PhiMBB);
-
- // Convert from floating point to unsigned 32-bit value
- // Use 0 if incoming value is < 0.0
- BuildMI(*BB, IP, PPC32::FSEL, 3, UseZero).addReg(SrcReg).addReg(SrcReg)
- .addReg(Zero);
- // Use 2**32 - 1 if incoming value is >= 2**32
- BuildMI(*BB, IP, PPC32::FSUB, 2, UseMaxInt).addReg(MaxInt).addReg(SrcReg);
- BuildMI(*BB, IP, PPC32::FSEL, 3, UseChoice).addReg(UseMaxInt)
- .addReg(UseZero).addReg(MaxInt);
- // Subtract 2**31
- BuildMI(*BB, IP, PPC32::FSUB, 2, TmpReg).addReg(UseChoice).addReg(Border);
- // Use difference if >= 2**31
- BuildMI(*BB, IP, PPC32::FCMPU, 2, PPC32::CR0).addReg(UseChoice)
- .addReg(Border);
- BuildMI(*BB, IP, PPC32::FSEL, 3, TmpReg2).addReg(TmpReg).addReg(TmpReg)
- .addReg(UseChoice);
- // Convert to integer
- BuildMI(*BB, IP, PPC32::FCTIWZ, 1, ConvReg).addReg(TmpReg2);
- addFrameReference(BuildMI(*BB, IP, PPC32::STFD, 3).addReg(ConvReg),
- FrameIdx);
- if (DestClass == cByte) {
- addFrameReference(BuildMI(*BB, IP, PPC32::LBZ, 2, DestReg),
- FrameIdx, 7);
- } else if (DestClass == cShort) {
- addFrameReference(BuildMI(*BB, IP, PPC32::LHZ, 2, DestReg),
- FrameIdx, 6);
- } if (DestClass == cInt) {
- addFrameReference(BuildMI(*BB, IP, PPC32::LWZ, 2, IntTmp),
- FrameIdx, 4);
- BuildMI(*BB, IP, PPC32::BLT, 2).addReg(PPC32::CR0).addMBB(PhiMBB);
- BuildMI(*BB, IP, PPC32::B, 1).addMBB(XorMBB);
-
- // XorMBB:
- // add 2**31 if input was >= 2**31
- BB = XorMBB;
- BuildMI(BB, PPC32::XORIS, 2, XorReg).addReg(IntTmp).addImm(0x8000);
- XorMBB->addSuccessor(PhiMBB);
-
- // PhiMBB:
- // DestReg = phi [ IntTmp, OldMBB ], [ XorReg, XorMBB ]
- BB = PhiMBB;
- BuildMI(BB, PPC32::PHI, 2, DestReg).addReg(IntTmp).addMBB(OldMBB)
- .addReg(XorReg).addMBB(XorMBB);
- }
- }
- return;
- }
-
- // Check our invariants
- assert((SrcClass <= cInt || SrcClass == cLong) &&
- "Unhandled source class for cast operation!");
- assert((DestClass <= cInt || DestClass == cLong) &&
- "Unhandled destination class for cast operation!");
-
- bool sourceUnsigned = SrcTy->isUnsigned() || SrcTy == Type::BoolTy;
- bool destUnsigned = DestTy->isUnsigned();
-
- // Unsigned -> Unsigned, clear if larger,
- if (sourceUnsigned && destUnsigned) {
- // handle long dest class now to keep switch clean
- if (DestClass == cLong) {
- if (SrcClass == cLong) {
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg+1)
- .addReg(SrcReg+1);
- } else {
- BuildMI(*MBB, IP, PPC32::LI, 1, DestReg).addSImm(0);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg)
- .addReg(SrcReg);
- }
- return;
- }
-
- // handle u{ byte, short, int } x u{ byte, short, int }
- unsigned clearBits = (SrcClass == cByte || DestClass == cByte) ? 24 : 16;
- switch (SrcClass) {
- case cByte:
- case cShort:
- if (SrcClass == DestClass)
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- else
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg)
- .addImm(0).addImm(clearBits).addImm(31);
- break;
- case cLong:
- ++SrcReg;
- // Fall through
- case cInt:
- if (DestClass == cInt)
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- else
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg)
- .addImm(0).addImm(clearBits).addImm(31);
- break;
- }
- return;
- }
-
- // Signed -> Signed
- if (!sourceUnsigned && !destUnsigned) {
- // handle long dest class now to keep switch clean
- if (DestClass == cLong) {
- if (SrcClass == cLong) {
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg+1)
- .addReg(SrcReg+1);
- } else {
- BuildMI(*MBB, IP, PPC32::SRAWI, 2, DestReg).addReg(SrcReg).addImm(31);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg)
- .addReg(SrcReg);
- }
- return;
- }
-
- // handle { byte, short, int } x { byte, short, int }
- switch (SrcClass) {
- case cByte:
- if (DestClass == cByte)
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- else
- BuildMI(*MBB, IP, PPC32::EXTSB, 1, DestReg).addReg(SrcReg);
- break;
- case cShort:
- if (DestClass == cByte)
- BuildMI(*MBB, IP, PPC32::EXTSB, 1, DestReg).addReg(SrcReg);
- else if (DestClass == cShort)
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- else
- BuildMI(*MBB, IP, PPC32::EXTSH, 1, DestReg).addReg(SrcReg);
- break;
- case cLong:
- ++SrcReg;
- // Fall through
- case cInt:
- if (DestClass == cByte)
- BuildMI(*MBB, IP, PPC32::EXTSB, 1, DestReg).addReg(SrcReg);
- else if (DestClass == cShort)
- BuildMI(*MBB, IP, PPC32::EXTSH, 1, DestReg).addReg(SrcReg);
- else
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- break;
- }
- return;
- }
-
- // Unsigned -> Signed
- if (sourceUnsigned && !destUnsigned) {
- // handle long dest class now to keep switch clean
- if (DestClass == cLong) {
- if (SrcClass == cLong) {
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg+1).
- addReg(SrcReg+1);
- } else {
- BuildMI(*MBB, IP, PPC32::LI, 1, DestReg).addSImm(0);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg)
- .addReg(SrcReg);
- }
- return;
- }
-
- // handle u{ byte, short, int } -> { byte, short, int }
- switch (SrcClass) {
- case cByte:
- if (DestClass == cByte)
- // uByte 255 -> signed byte == -1
- BuildMI(*MBB, IP, PPC32::EXTSB, 1, DestReg).addReg(SrcReg);
- else
- // uByte 255 -> signed short/int == 255
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg).addImm(0)
- .addImm(24).addImm(31);
- break;
- case cShort:
- if (DestClass == cByte)
- BuildMI(*MBB, IP, PPC32::EXTSB, 1, DestReg).addReg(SrcReg);
- else if (DestClass == cShort)
- BuildMI(*MBB, IP, PPC32::EXTSH, 1, DestReg).addReg(SrcReg);
- else
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg).addImm(0)
- .addImm(16).addImm(31);
- break;
- case cLong:
- ++SrcReg;
- // Fall through
- case cInt:
- if (DestClass == cByte)
- BuildMI(*MBB, IP, PPC32::EXTSB, 1, DestReg).addReg(SrcReg);
- else if (DestClass == cShort)
- BuildMI(*MBB, IP, PPC32::EXTSH, 1, DestReg).addReg(SrcReg);
- else
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- break;
- }
- return;
- }
-
- // Signed -> Unsigned
- if (!sourceUnsigned && destUnsigned) {
- // handle long dest class now to keep switch clean
- if (DestClass == cLong) {
- if (SrcClass == cLong) {
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg+1)
- .addReg(SrcReg+1);
- } else {
- BuildMI(*MBB, IP, PPC32::SRAWI, 2, DestReg).addReg(SrcReg).addImm(31);
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg+1).addReg(SrcReg)
- .addReg(SrcReg);
- }
- return;
- }
-
- // handle { byte, short, int } -> u{ byte, short, int }
- unsigned clearBits = (DestClass == cByte) ? 24 : 16;
- switch (SrcClass) {
- case cByte:
- case cShort:
- if (DestClass == cByte || DestClass == cShort)
- // sbyte -1 -> ubyte 0x000000FF
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg)
- .addImm(0).addImm(clearBits).addImm(31);
- else
- // sbyte -1 -> ubyte 0xFFFFFFFF
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- break;
- case cLong:
- ++SrcReg;
- // Fall through
- case cInt:
- if (DestClass == cInt)
- BuildMI(*MBB, IP, PPC32::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg);
- else
- BuildMI(*MBB, IP, PPC32::RLWINM, 4, DestReg).addReg(SrcReg)
- .addImm(0).addImm(clearBits).addImm(31);
- break;
- }
- return;
- }
-
- // Anything we haven't handled already, we can't (yet) handle at all.
- std::cerr << "Unhandled cast from " << SrcTy->getDescription()
- << "to " << DestTy->getDescription() << '\n';
- abort();
-}
-
-/// visitVANextInst - Implement the va_next instruction...
-///
-void ISel::visitVANextInst(VANextInst &I) {
- unsigned VAList = getReg(I.getOperand(0));
- unsigned DestReg = getReg(I);
-
- unsigned Size;
- switch (I.getArgType()->getTypeID()) {
- default:
- std::cerr << I;
- assert(0 && "Error: bad type for va_next instruction!");
- return;
- case Type::PointerTyID:
- case Type::UIntTyID:
- case Type::IntTyID:
- Size = 4;
- break;
- case Type::ULongTyID:
- case Type::LongTyID:
- case Type::DoubleTyID:
- Size = 8;
- break;
- }
-
- // Increment the VAList pointer...
- BuildMI(BB, PPC32::ADDI, 2, DestReg).addReg(VAList).addSImm(Size);
-}
-
-void ISel::visitVAArgInst(VAArgInst &I) {
- unsigned VAList = getReg(I.getOperand(0));
- unsigned DestReg = getReg(I);
-
- switch (I.getType()->getTypeID()) {
- default:
- std::cerr << I;
- assert(0 && "Error: bad type for va_next instruction!");
- return;
- case Type::PointerTyID:
- case Type::UIntTyID:
- case Type::IntTyID:
- BuildMI(BB, PPC32::LWZ, 2, DestReg).addSImm(0).addReg(VAList);
- break;
- case Type::ULongTyID:
- case Type::LongTyID:
- BuildMI(BB, PPC32::LWZ, 2, DestReg).addSImm(0).addReg(VAList);
- BuildMI(BB, PPC32::LWZ, 2, DestReg+1).addSImm(4).addReg(VAList);
- break;
- case Type::FloatTyID:
- BuildMI(BB, PPC32::LFS, 2, DestReg).addSImm(0).addReg(VAList);
- break;
- case Type::DoubleTyID:
- BuildMI(BB, PPC32::LFD, 2, DestReg).addSImm(0).addReg(VAList);
- break;
- }
-}
-
-/// visitGetElementPtrInst - instruction-select GEP instructions
-///
-void ISel::visitGetElementPtrInst(GetElementPtrInst &I) {
- if (canFoldGEPIntoLoadOrStore(&I))
- return;
-
- unsigned outputReg = getReg(I);
- emitGEPOperation(BB, BB->end(), I.getOperand(0), I.op_begin()+1, I.op_end(),
- outputReg, false, 0);
-}
-
-/// emitGEPOperation - Common code shared between visitGetElementPtrInst and
-/// constant expression GEP support.
-///
-void ISel::emitGEPOperation(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Value *Src, User::op_iterator IdxBegin,
- User::op_iterator IdxEnd, unsigned TargetReg,
- bool GEPIsFolded, ConstantSInt **RemainderPtr) {
- const TargetData &TD = TM.getTargetData();
- const Type *Ty = Src->getType();
- unsigned basePtrReg = getReg(Src, MBB, IP);
- int64_t constValue = 0;
-
- // Record the operations to emit the GEP in a vector so that we can emit them
- // after having analyzed the entire instruction.
- std::vector<CollapsedGepOp> ops;
-
- // GEPs have zero or more indices; we must perform a struct access
- // or array access for each one.
- for (GetElementPtrInst::op_iterator oi = IdxBegin, oe = IdxEnd; oi != oe;
- ++oi) {
- Value *idx = *oi;
- if (const StructType *StTy = dyn_cast<StructType>(Ty)) {
- // It's a struct access. idx is the index into the structure,
- // which names the field. Use the TargetData structure to
- // pick out what the layout of the structure is in memory.
- // Use the (constant) structure index's value to find the
- // right byte offset from the StructLayout class's list of
- // structure member offsets.
- unsigned fieldIndex = cast<ConstantUInt>(idx)->getValue();
- unsigned memberOffset =
- TD.getStructLayout(StTy)->MemberOffsets[fieldIndex];
-
- // StructType member offsets are always constant values. Add it to the
- // running total.
- constValue += memberOffset;
-
- // The next type is the member of the structure selected by the
- // index.
- Ty = StTy->getElementType (fieldIndex);
- } else if (const SequentialType *SqTy = dyn_cast<SequentialType> (Ty)) {
- // Many GEP instructions use a [cast (int/uint) to LongTy] as their
- // operand. Handle this case directly now...
- if (CastInst *CI = dyn_cast<CastInst>(idx))
- if (CI->getOperand(0)->getType() == Type::IntTy ||
- CI->getOperand(0)->getType() == Type::UIntTy)
- idx = CI->getOperand(0);
-
- // It's an array or pointer access: [ArraySize x ElementType].
- // We want to add basePtrReg to (idxReg * sizeof ElementType). First, we
- // must find the size of the pointed-to type (Not coincidentally, the next
- // type is the type of the elements in the array).
- Ty = SqTy->getElementType();
- unsigned elementSize = TD.getTypeSize(Ty);
-
- if (ConstantInt *C = dyn_cast<ConstantInt>(idx)) {
- if (ConstantSInt *CS = dyn_cast<ConstantSInt>(C))
- constValue += CS->getValue() * elementSize;
- else if (ConstantUInt *CU = dyn_cast<ConstantUInt>(C))
- constValue += CU->getValue() * elementSize;
- else
- assert(0 && "Invalid ConstantInt GEP index type!");
- } else {
- // Push current gep state to this point as an add
- ops.push_back(CollapsedGepOp(false, 0,
- ConstantSInt::get(Type::IntTy,constValue)));
-
- // Push multiply gep op and reset constant value
- ops.push_back(CollapsedGepOp(true, idx,
- ConstantSInt::get(Type::IntTy, elementSize)));
-
- constValue = 0;
- }
- }
- }
- // Emit instructions for all the collapsed ops
- for(std::vector<CollapsedGepOp>::iterator cgo_i = ops.begin(),
- cgo_e = ops.end(); cgo_i != cgo_e; ++cgo_i) {
- CollapsedGepOp& cgo = *cgo_i;
- unsigned nextBasePtrReg = makeAnotherReg (Type::IntTy);
-
- if (cgo.isMul) {
- // We know the elementSize is a constant, so we can emit a constant mul
- // and then add it to the current base reg
- unsigned TmpReg = makeAnotherReg(Type::IntTy);
- doMultiplyConst(MBB, IP, TmpReg, cgo.index, cgo.size);
- BuildMI(*MBB, IP, PPC32::ADD, 2, nextBasePtrReg).addReg(basePtrReg)
- .addReg(TmpReg);
- } else {
- // Try and generate an immediate addition if possible
- if (cgo.size->isNullValue()) {
- BuildMI(*MBB, IP, PPC32::OR, 2, nextBasePtrReg).addReg(basePtrReg)
- .addReg(basePtrReg);
- } else if (canUseAsImmediateForOpcode(cgo.size, 0)) {
- BuildMI(*MBB, IP, PPC32::ADDI, 2, nextBasePtrReg).addReg(basePtrReg)
- .addSImm(cgo.size->getValue());
- } else {
- unsigned Op1r = getReg(cgo.size, MBB, IP);
- BuildMI(*MBB, IP, PPC32::ADD, 2, nextBasePtrReg).addReg(basePtrReg)
- .addReg(Op1r);
- }
- }
-
- basePtrReg = nextBasePtrReg;
- }
- // Add the current base register plus any accumulated constant value
- ConstantSInt *remainder = ConstantSInt::get(Type::IntTy, constValue);
-
- // If we are emitting this during a fold, copy the current base register to
- // the target, and save the current constant offset so the folding load or
- // store can try and use it as an immediate.
- if (GEPIsFolded) {
- BuildMI (BB, PPC32::OR, 2, TargetReg).addReg(basePtrReg).addReg(basePtrReg);
- *RemainderPtr = remainder;
- return;
- }
-
- // After we have processed all the indices, the result is left in
- // basePtrReg. Move it to the register where we were expected to
- // put the answer.
- if (remainder->isNullValue()) {
- BuildMI (BB, PPC32::OR, 2, TargetReg).addReg(basePtrReg).addReg(basePtrReg);
- } else if (canUseAsImmediateForOpcode(remainder, 0)) {
- BuildMI(*MBB, IP, PPC32::ADDI, 2, TargetReg).addReg(basePtrReg)
- .addSImm(remainder->getValue());
- } else {
- unsigned Op1r = getReg(remainder, MBB, IP);
- BuildMI(*MBB, IP, PPC32::ADD, 2, TargetReg).addReg(basePtrReg).addReg(Op1r);
- }
-}
-
-/// visitAllocaInst - If this is a fixed size alloca, allocate space from the
-/// frame manager, otherwise do it the hard way.
-///
-void ISel::visitAllocaInst(AllocaInst &I) {
- // If this is a fixed size alloca in the entry block for the function, we
- // statically stack allocate the space, so we don't need to do anything here.
- //
- if (dyn_castFixedAlloca(&I)) return;
-
- // Find the data size of the alloca inst's getAllocatedType.
- const Type *Ty = I.getAllocatedType();
- unsigned TySize = TM.getTargetData().getTypeSize(Ty);
-
- // Create a register to hold the temporary result of multiplying the type size
- // constant by the variable amount.
- unsigned TotalSizeReg = makeAnotherReg(Type::UIntTy);
-
- // TotalSizeReg = mul <numelements>, <TypeSize>
- MachineBasicBlock::iterator MBBI = BB->end();
- ConstantUInt *CUI = ConstantUInt::get(Type::UIntTy, TySize);
- doMultiplyConst(BB, MBBI, TotalSizeReg, I.getArraySize(), CUI);
-
- // AddedSize = add <TotalSizeReg>, 15
- unsigned AddedSizeReg = makeAnotherReg(Type::UIntTy);
- BuildMI(BB, PPC32::ADDI, 2, AddedSizeReg).addReg(TotalSizeReg).addSImm(15);
-
- // AlignedSize = and <AddedSize>, ~15
- unsigned AlignedSize = makeAnotherReg(Type::UIntTy);
- BuildMI(BB, PPC32::RLWINM, 4, AlignedSize).addReg(AddedSizeReg).addImm(0)
- .addImm(0).addImm(27);
-
- // Subtract size from stack pointer, thereby allocating some space.
- BuildMI(BB, PPC32::SUB, 2, PPC32::R1).addReg(PPC32::R1).addReg(AlignedSize);
-
- // Put a pointer to the space into the result register, by copying
- // the stack pointer.
- BuildMI(BB, PPC32::OR, 2, getReg(I)).addReg(PPC32::R1).addReg(PPC32::R1);
-
- // Inform the Frame Information that we have just allocated a variable-sized
- // object.
- F->getFrameInfo()->CreateVariableSizedObject();
-}
-
-/// visitMallocInst - Malloc instructions are code generated into direct calls
-/// to the library malloc.
-///
-void ISel::visitMallocInst(MallocInst &I) {
- unsigned AllocSize = TM.getTargetData().getTypeSize(I.getAllocatedType());
- unsigned Arg;
-
- if (ConstantUInt *C = dyn_cast<ConstantUInt>(I.getOperand(0))) {
- Arg = getReg(ConstantUInt::get(Type::UIntTy, C->getValue() * AllocSize));
- } else {
- Arg = makeAnotherReg(Type::UIntTy);
- MachineBasicBlock::iterator MBBI = BB->end();
- ConstantUInt *CUI = ConstantUInt::get(Type::UIntTy, AllocSize);
- doMultiplyConst(BB, MBBI, Arg, I.getOperand(0), CUI);
- }
-
- std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(Arg, Type::UIntTy));
- MachineInstr *TheCall =
- BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(mallocFn, true);
- doCall(ValueRecord(getReg(I), I.getType()), TheCall, Args, false);
- TM.CalledFunctions.insert(mallocFn);
-}
-
-
-/// visitFreeInst - Free instructions are code gen'd to call the free libc
-/// function.
-///
-void ISel::visitFreeInst(FreeInst &I) {
- std::vector<ValueRecord> Args;
- Args.push_back(ValueRecord(I.getOperand(0)));
- MachineInstr *TheCall =
- BuildMI(PPC32::CALLpcrel, 1).addGlobalAddress(freeFn, true);
- doCall(ValueRecord(0, Type::VoidTy), TheCall, Args, false);
- TM.CalledFunctions.insert(freeFn);
-}
-
-/// createPPC32SimpleInstructionSelector - This pass converts an LLVM function
-/// into a machine code representation is a very simple peep-hole fashion. The
-/// generated code sucks but the implementation is nice and simple.
-///
-FunctionPass *llvm::createPPCSimpleInstructionSelector(TargetMachine &TM) {
- return new ISel(TM);
-}
diff --git a/llvm/lib/Target/SparcV8/DelaySlotFiller.cpp b/llvm/lib/Target/SparcV8/DelaySlotFiller.cpp
deleted file mode 100644
index 78d5baa1f9b3..000000000000
--- a/llvm/lib/Target/SparcV8/DelaySlotFiller.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-//===-- DelaySlotFiller.cpp - SparcV8 delay slot filler -------------------===//
-//
-// 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.
-//
-//===----------------------------------------------------------------------===//
-//
-// Simple local delay slot filler for SparcV8 machine code
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcV8.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "Support/Statistic.h"
-
-using namespace llvm;
-
-namespace {
- Statistic<> FilledSlots ("delayslotfiller", "Num. of delay slots filled");
-
- struct Filler : public MachineFunctionPass {
- /// Target machine description which we query for reg. names, data
- /// layout, etc.
- ///
- TargetMachine &TM;
-
- Filler (TargetMachine &tm) : TM (tm) { }
-
- virtual const char *getPassName () const {
- return "SparcV8 Delay Slot Filler";
- }
-
- bool runOnMachineBasicBlock (MachineBasicBlock &MBB);
- bool runOnMachineFunction (MachineFunction &F) {
- bool Changed = false;
- for (MachineFunction::iterator FI = F.begin (), FE = F.end ();
- FI != FE; ++FI)
- Changed |= runOnMachineBasicBlock (*FI);
- return Changed;
- }
-
- };
-} // end of anonymous namespace
-
-/// createSparcV8DelaySlotFillerPass - Returns a pass that fills in delay
-/// slots in SparcV8 MachineFunctions
-///
-FunctionPass *llvm::createSparcV8DelaySlotFillerPass (TargetMachine &tm) {
- return new Filler (tm);
-}
-
-static bool hasDelaySlot (unsigned Opcode) {
- switch (Opcode) {
- case V8::BA:
- case V8::BCC:
- case V8::BCS:
- case V8::BE:
- case V8::BG:
- case V8::BGE:
- case V8::BGU:
- case V8::BL:
- case V8::BLE:
- case V8::BLEU:
- case V8::BNE:
- case V8::CALL:
- case V8::JMPLrr:
- case V8::RETL:
- case V8::FBA:
- case V8::FBN:
- case V8::FBU:
- case V8::FBG:
- case V8::FBUG:
- case V8::FBL:
- case V8::FBUL:
- case V8::FBLG:
- case V8::FBNE:
- case V8::FBE:
- case V8::FBUE:
- case V8::FBGE:
- case V8::FBUGE:
- case V8::FBLE:
- case V8::FBULE:
- case V8::FBO:
- case V8::FCMPS:
- case V8::FCMPD:
- case V8::FCMPES:
- case V8::FCMPED:
- return true;
- default:
- return false;
- }
-}
-
-/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
-/// Currently, we fill delay slots with NOPs. We assume there is only one
-/// delay slot per delayed instruction.
-///
-bool Filler::runOnMachineBasicBlock (MachineBasicBlock &MBB) {
- bool Changed = false;
- for (MachineBasicBlock::iterator I = MBB.begin (); I != MBB.end (); ++I)
- if (hasDelaySlot (I->getOpcode ())) {
- MachineBasicBlock::iterator J = I;
- ++J;
- BuildMI (MBB, J, V8::NOP, 0);
- ++FilledSlots;
- Changed = true;
- }
- return Changed;
-}
diff --git a/llvm/lib/Target/SparcV8/InstSelectSimple.cpp b/llvm/lib/Target/SparcV8/InstSelectSimple.cpp
deleted file mode 100644
index ac33ef574b8f..000000000000
--- a/llvm/lib/Target/SparcV8/InstSelectSimple.cpp
+++ /dev/null
@@ -1,1151 +0,0 @@
-//===-- InstSelectSimple.cpp - A simple instruction selector for SparcV8 --===//
-//
-// 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 a simple peephole instruction selector for the V8 target
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcV8.h"
-#include "SparcV8InstrInfo.h"
-#include "Support/Debug.h"
-#include "llvm/Instructions.h"
-#include "llvm/Pass.h"
-#include "llvm/Constants.h"
-#include "llvm/CodeGen/IntrinsicLowering.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/SSARegMap.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/GetElementPtrTypeIterator.h"
-#include "llvm/Support/InstVisitor.h"
-#include "llvm/Support/CFG.h"
-#include <iostream>
-using namespace llvm;
-
-namespace {
- struct V8ISel : public FunctionPass, public InstVisitor<V8ISel> {
- TargetMachine &TM;
- MachineFunction *F; // The function we are compiling into
- MachineBasicBlock *BB; // The current MBB we are compiling
-
- std::map<Value*, unsigned> RegMap; // Mapping between Val's and SSA Regs
-
- // MBBMap - Mapping between LLVM BB -> Machine BB
- std::map<const BasicBlock*, MachineBasicBlock*> MBBMap;
-
- V8ISel(TargetMachine &tm) : TM(tm), F(0), BB(0) {}
-
- /// runOnFunction - Top level implementation of instruction selection for
- /// the entire function.
- ///
- bool runOnFunction(Function &Fn);
-
- virtual const char *getPassName() const {
- return "SparcV8 Simple Instruction Selection";
- }
-
- /// emitGEPOperation - Common code shared between visitGetElementPtrInst and
- /// constant expression GEP support.
- ///
- void emitGEPOperation(MachineBasicBlock *BB, MachineBasicBlock::iterator IP,
- Value *Src, User::op_iterator IdxBegin,
- User::op_iterator IdxEnd, unsigned TargetReg);
-
- /// emitCastOperation - Common code shared between visitCastInst and
- /// constant expression cast support.
- ///
- void emitCastOperation(MachineBasicBlock *BB,MachineBasicBlock::iterator IP,
- Value *Src, const Type *DestTy, unsigned TargetReg);
-
- /// visitBasicBlock - This method is called when we are visiting a new basic
- /// block. This simply creates a new MachineBasicBlock to emit code into
- /// and adds it to the current MachineFunction. Subsequent visit* for
- /// instructions will be invoked for all instructions in the basic block.
- ///
- void visitBasicBlock(BasicBlock &LLVM_BB) {
- BB = MBBMap[&LLVM_BB];
- }
-
- void visitBinaryOperator(Instruction &I);
- void visitShiftInst (ShiftInst &SI) { visitBinaryOperator (SI); }
- void visitSetCondInst(SetCondInst &I);
- void visitCallInst(CallInst &I);
- void visitReturnInst(ReturnInst &I);
- void visitBranchInst(BranchInst &I);
- void visitCastInst(CastInst &I);
- void visitLoadInst(LoadInst &I);
- void visitStoreInst(StoreInst &I);
- void visitPHINode(PHINode &I) {} // PHI nodes handled by second pass
- void visitGetElementPtrInst(GetElementPtrInst &I);
- void visitAllocaInst(AllocaInst &I);
-
- void visitInstruction(Instruction &I) {
- std::cerr << "Unhandled instruction: " << I;
- abort();
- }
-
- /// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
- /// function, lowering any calls to unknown intrinsic functions into the
- /// equivalent LLVM code.
- void LowerUnknownIntrinsicFunctionCalls(Function &F);
- void visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI);
-
- void LoadArgumentsToVirtualRegs(Function *F);
-
- /// SelectPHINodes - Insert machine code to generate phis. This is tricky
- /// because we have to generate our sources into the source basic blocks,
- /// not the current one.
- ///
- void SelectPHINodes();
-
- /// copyConstantToRegister - Output the instructions required to put the
- /// specified constant into the specified register.
- ///
- void copyConstantToRegister(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Constant *C, unsigned R);
-
- /// makeAnotherReg - This method returns the next register number we haven't
- /// yet used.
- ///
- /// Long values are handled somewhat specially. They are always allocated
- /// as pairs of 32 bit integer values. The register number returned is the
- /// lower 32 bits of the long value, and the regNum+1 is the upper 32 bits
- /// of the long value.
- ///
- unsigned makeAnotherReg(const Type *Ty) {
- assert(dynamic_cast<const SparcV8RegisterInfo*>(TM.getRegisterInfo()) &&
- "Current target doesn't have SparcV8 reg info??");
- const SparcV8RegisterInfo *MRI =
- static_cast<const SparcV8RegisterInfo*>(TM.getRegisterInfo());
- if (Ty == Type::LongTy || Ty == Type::ULongTy) {
- const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy);
- // Create the lower part
- F->getSSARegMap()->createVirtualRegister(RC);
- // Create the upper part.
- return F->getSSARegMap()->createVirtualRegister(RC)-1;
- }
-
- // Add the mapping of regnumber => reg class to MachineFunction
- const TargetRegisterClass *RC = MRI->getRegClassForType(Ty);
- return F->getSSARegMap()->createVirtualRegister(RC);
- }
-
- unsigned getReg(Value &V) { return getReg (&V); } // allow refs.
- unsigned getReg(Value *V) {
- // Just append to the end of the current bb.
- MachineBasicBlock::iterator It = BB->end();
- return getReg(V, BB, It);
- }
- unsigned getReg(Value *V, MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IPt) {
- unsigned &Reg = RegMap[V];
- if (Reg == 0) {
- Reg = makeAnotherReg(V->getType());
- RegMap[V] = Reg;
- }
- // If this operand is a constant, emit the code to copy the constant into
- // the register here...
- //
- if (Constant *C = dyn_cast<Constant>(V)) {
- copyConstantToRegister(MBB, IPt, C, Reg);
- RegMap.erase(V); // Assign a new name to this constant if ref'd again
- } else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
- // Move the address of the global into the register
- unsigned TmpReg = makeAnotherReg(V->getType());
- BuildMI (*MBB, IPt, V8::SETHIi, 1, TmpReg).addGlobalAddress (GV);
- BuildMI (*MBB, IPt, V8::ORri, 2, Reg).addReg (TmpReg)
- .addGlobalAddress (GV);
- RegMap.erase(V); // Assign a new name to this address if ref'd again
- }
-
- return Reg;
- }
-
- };
-}
-
-FunctionPass *llvm::createSparcV8SimpleInstructionSelector(TargetMachine &TM) {
- return new V8ISel(TM);
-}
-
-enum TypeClass {
- cByte, cShort, cInt, cLong, cFloat, cDouble
-};
-
-static TypeClass getClass (const Type *T) {
- switch (T->getTypeID()) {
- case Type::UByteTyID: case Type::SByteTyID: return cByte;
- case Type::UShortTyID: case Type::ShortTyID: return cShort;
- case Type::PointerTyID:
- case Type::UIntTyID: case Type::IntTyID: return cInt;
- case Type::ULongTyID: case Type::LongTyID: return cLong;
- case Type::FloatTyID: return cFloat;
- case Type::DoubleTyID: return cDouble;
- default:
- assert (0 && "Type of unknown class passed to getClass?");
- return cByte;
- }
-}
-static TypeClass getClassB(const Type *T) {
- if (T == Type::BoolTy) return cByte;
- return getClass(T);
-}
-
-
-
-/// copyConstantToRegister - Output the instructions required to put the
-/// specified constant into the specified register.
-///
-void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Constant *C, unsigned R) {
- if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
- switch (CE->getOpcode()) {
- case Instruction::GetElementPtr:
- emitGEPOperation(MBB, IP, CE->getOperand(0),
- CE->op_begin()+1, CE->op_end(), R);
- return;
- case Instruction::Cast:
- emitCastOperation(MBB, IP, CE->getOperand(0), CE->getType(), R);
- return;
- default:
- std::cerr << "Copying this constant expr not yet handled: " << *CE;
- abort();
- }
- }
-
- if (C->getType()->isIntegral ()) {
- uint64_t Val;
- unsigned Class = getClassB (C->getType ());
- if (Class == cLong) {
- unsigned TmpReg = makeAnotherReg (Type::IntTy);
- unsigned TmpReg2 = makeAnotherReg (Type::IntTy);
- // Copy the value into the register pair.
- // R = top(more-significant) half, R+1 = bottom(less-significant) half
- uint64_t Val = cast<ConstantInt>(C)->getRawValue();
- unsigned bottomHalf = Val & 0xffffffffU;
- unsigned topHalf = Val >> 32;
- unsigned HH = topHalf >> 10;
- unsigned HM = topHalf & 0x03ff;
- unsigned LM = bottomHalf >> 10;
- unsigned LO = bottomHalf & 0x03ff;
- BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addZImm(HH);
- BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg)
- .addSImm (HM);
- BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg2).addZImm(LM);
- BuildMI (*MBB, IP, V8::ORri, 2, R+1).addReg (TmpReg2)
- .addSImm (LO);
- return;
- }
-
- assert(Class <= cInt && "Type not handled yet!");
-
- if (C->getType() == Type::BoolTy) {
- Val = (C == ConstantBool::True);
- } else {
- ConstantInt *CI = cast<ConstantInt> (C);
- Val = CI->getRawValue ();
- }
- switch (Class) {
- case cByte: Val = (int8_t) Val; break;
- case cShort: Val = (int16_t) Val; break;
- case cInt: Val = (int32_t) Val; break;
- default:
- std::cerr << "Offending constant: " << *C << "\n";
- assert (0 && "Can't copy this kind of constant into register yet");
- return;
- }
- if (Val == 0) {
- BuildMI (*MBB, IP, V8::ORrr, 2, R).addReg (V8::G0).addReg(V8::G0);
- } else if (((int64_t)Val >= -4096) && ((int64_t)Val <= 4095)) {
- BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addSImm(Val);
- } else {
- unsigned TmpReg = makeAnotherReg (C->getType ());
- BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg)
- .addSImm (((uint32_t) Val) >> 10);
- BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg)
- .addSImm (((uint32_t) Val) & 0x03ff);
- return;
- }
- } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
- // We need to spill the constant to memory...
- MachineConstantPool *CP = F->getConstantPool();
- unsigned CPI = CP->getConstantPoolIndex(CFP);
- const Type *Ty = CFP->getType();
-
- assert(Ty == Type::FloatTy || Ty == Type::DoubleTy && "Unknown FP type!");
- unsigned LoadOpcode = Ty == Type::FloatTy ? V8::LDFri : V8::LDDFri;
- BuildMI (*MBB, IP, LoadOpcode, 2, R).addConstantPoolIndex (CPI).addSImm (0);
- } else if (isa<ConstantPointerNull>(C)) {
- // Copy zero (null pointer) to the register.
- BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addSImm (0);
- } else if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
- // Copy it with a SETHI/OR pair; the JIT + asmwriter should recognize
- // that SETHI %reg,global == SETHI %reg,%hi(global) and
- // OR %reg,global,%reg == OR %reg,%lo(global),%reg.
- unsigned TmpReg = makeAnotherReg (C->getType ());
- BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addGlobalAddress(GV);
- BuildMI (*MBB, IP, V8::ORri, 2, R).addReg(TmpReg).addGlobalAddress(GV);
- } else {
- std::cerr << "Offending constant: " << *C << "\n";
- assert (0 && "Can't copy this kind of constant into register yet");
- }
-}
-
-void V8ISel::LoadArgumentsToVirtualRegs (Function *LF) {
- unsigned ArgOffset;
- static const unsigned IncomingArgRegs[] = { V8::I0, V8::I1, V8::I2,
- V8::I3, V8::I4, V8::I5 };
- assert (LF->asize () < 7
- && "Can't handle loading excess call args off the stack yet");
-
- // Add IMPLICIT_DEFs of input regs.
- ArgOffset = 0;
- for (Function::aiterator I = LF->abegin(), E = LF->aend(); I != E; ++I) {
- unsigned Reg = getReg(*I);
- switch (getClassB(I->getType())) {
- case cByte:
- case cShort:
- case cInt:
- case cFloat:
- BuildMI(BB, V8::IMPLICIT_DEF, 0, IncomingArgRegs[ArgOffset]);
- break;
- default:
- // FIXME: handle cDouble, cLong
- assert (0 && "64-bit (double, long, etc.) function args not handled");
- return;
- }
- ++ArgOffset;
- }
-
- ArgOffset = 0;
- for (Function::aiterator I = LF->abegin(), E = LF->aend(); I != E; ++I) {
- unsigned Reg = getReg(*I);
- switch (getClassB(I->getType())) {
- case cByte:
- case cShort:
- case cInt:
- BuildMI(BB, V8::ORrr, 2, Reg).addReg (V8::G0)
- .addReg (IncomingArgRegs[ArgOffset]);
- break;
- case cFloat: {
- // Single-fp args are passed in integer registers; go through
- // memory to get them into FP registers. (Bleh!)
- unsigned FltAlign = TM.getTargetData().getFloatAlignment();
- int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign);
- BuildMI (BB, V8::ST, 3).addFrameIndex (FI).addSImm (0)
- .addReg (IncomingArgRegs[ArgOffset]);
- BuildMI (BB, V8::LDFri, 2, Reg).addFrameIndex (FI).addSImm (0);
- break;
- }
- default:
- // FIXME: handle cDouble, cLong
- assert (0 && "64-bit (double, long, etc.) function args not handled");
- return;
- }
- ++ArgOffset;
- }
-
-}
-
-void V8ISel::SelectPHINodes() {
- const TargetInstrInfo &TII = *TM.getInstrInfo();
- const Function &LF = *F->getFunction(); // The LLVM function...
- for (Function::const_iterator I = LF.begin(), E = LF.end(); I != E; ++I) {
- const BasicBlock *BB = I;
- MachineBasicBlock &MBB = *MBBMap[I];
-
- // Loop over all of the PHI nodes in the LLVM basic block...
- MachineBasicBlock::iterator PHIInsertPoint = MBB.begin();
- for (BasicBlock::const_iterator I = BB->begin();
- PHINode *PN = const_cast<PHINode*>(dyn_cast<PHINode>(I)); ++I) {
-
- // Create a new machine instr PHI node, and insert it.
- unsigned PHIReg = getReg(*PN);
- MachineInstr *PhiMI = BuildMI(MBB, PHIInsertPoint,
- V8::PHI, PN->getNumOperands(), PHIReg);
-
- MachineInstr *LongPhiMI = 0;
- if (PN->getType() == Type::LongTy || PN->getType() == Type::ULongTy)
- LongPhiMI = BuildMI(MBB, PHIInsertPoint,
- V8::PHI, PN->getNumOperands(), PHIReg+1);
-
- // PHIValues - Map of blocks to incoming virtual registers. We use this
- // so that we only initialize one incoming value for a particular block,
- // even if the block has multiple entries in the PHI node.
- //
- std::map<MachineBasicBlock*, unsigned> PHIValues;
-
- for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
- MachineBasicBlock *PredMBB = 0;
- for (MachineBasicBlock::pred_iterator PI = MBB.pred_begin (),
- PE = MBB.pred_end (); PI != PE; ++PI)
- if (PN->getIncomingBlock(i) == (*PI)->getBasicBlock()) {
- PredMBB = *PI;
- break;
- }
- assert (PredMBB && "Couldn't find incoming machine-cfg edge for phi");
-
- unsigned ValReg;
- std::map<MachineBasicBlock*, unsigned>::iterator EntryIt =
- PHIValues.lower_bound(PredMBB);
-
- if (EntryIt != PHIValues.end() && EntryIt->first == PredMBB) {
- // We already inserted an initialization of the register for this
- // predecessor. Recycle it.
- ValReg = EntryIt->second;
-
- } else {
- // Get the incoming value into a virtual register.
- //
- Value *Val = PN->getIncomingValue(i);
-
- // If this is a constant or GlobalValue, we may have to insert code
- // into the basic block to compute it into a virtual register.
- if ((isa<Constant>(Val) && !isa<ConstantExpr>(Val)) ||
- isa<GlobalValue>(Val)) {
- // Simple constants get emitted at the end of the basic block,
- // before any terminator instructions. We "know" that the code to
- // move a constant into a register will never clobber any flags.
- ValReg = getReg(Val, PredMBB, PredMBB->getFirstTerminator());
- } else {
- // Because we don't want to clobber any values which might be in
- // physical registers with the computation of this constant (which
- // might be arbitrarily complex if it is a constant expression),
- // just insert the computation at the top of the basic block.
- MachineBasicBlock::iterator PI = PredMBB->begin();
-
- // Skip over any PHI nodes though!
- while (PI != PredMBB->end() && PI->getOpcode() == V8::PHI)
- ++PI;
-
- ValReg = getReg(Val, PredMBB, PI);
- }
-
- // Remember that we inserted a value for this PHI for this predecessor
- PHIValues.insert(EntryIt, std::make_pair(PredMBB, ValReg));
- }
-
- PhiMI->addRegOperand(ValReg);
- PhiMI->addMachineBasicBlockOperand(PredMBB);
- if (LongPhiMI) {
- LongPhiMI->addRegOperand(ValReg+1);
- LongPhiMI->addMachineBasicBlockOperand(PredMBB);
- }
- }
-
- // Now that we emitted all of the incoming values for the PHI node, make
- // sure to reposition the InsertPoint after the PHI that we just added.
- // This is needed because we might have inserted a constant into this
- // block, right after the PHI's which is before the old insert point!
- PHIInsertPoint = LongPhiMI ? LongPhiMI : PhiMI;
- ++PHIInsertPoint;
- }
- }
-}
-
-bool V8ISel::runOnFunction(Function &Fn) {
- // First pass over the function, lower any unknown intrinsic functions
- // with the IntrinsicLowering class.
- LowerUnknownIntrinsicFunctionCalls(Fn);
-
- F = &MachineFunction::construct(&Fn, TM);
-
- // Create all of the machine basic blocks for the function...
- for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
- F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I));
-
- BB = &F->front();
-
- // Set up a frame object for the return address. This is used by the
- // llvm.returnaddress & llvm.frameaddress intrinisics.
- //ReturnAddressIndex = F->getFrameInfo()->CreateFixedObject(4, -4);
-
- // Copy incoming arguments off of the stack and out of fixed registers.
- LoadArgumentsToVirtualRegs(&Fn);
-
- // Instruction select everything except PHI nodes
- visit(Fn);
-
- // Select the PHI nodes
- SelectPHINodes();
-
- RegMap.clear();
- MBBMap.clear();
- F = 0;
- // We always build a machine code representation for the function
- return true;
-}
-
-void V8ISel::visitCastInst(CastInst &I) {
- Value *Op = I.getOperand(0);
- unsigned DestReg = getReg(I);
- MachineBasicBlock::iterator MI = BB->end();
- emitCastOperation(BB, MI, Op, I.getType(), DestReg);
-}
-
-/// emitCastOperation - Common code shared between visitCastInst and constant
-/// expression cast support.
-///
-void V8ISel::emitCastOperation(MachineBasicBlock *BB,
- MachineBasicBlock::iterator IP,
- Value *Src, const Type *DestTy,
- unsigned DestReg) {
- const Type *SrcTy = Src->getType();
- unsigned SrcClass = getClassB(SrcTy);
- unsigned DestClass = getClassB(DestTy);
- unsigned SrcReg = getReg(Src, BB, IP);
-
- const Type *oldTy = SrcTy;
- const Type *newTy = DestTy;
- unsigned oldTyClass = SrcClass;
- unsigned newTyClass = DestClass;
-
- if (oldTyClass < cLong && newTyClass < cLong) {
- if (oldTyClass >= newTyClass) {
- // Emit a reg->reg copy to do a equal-size or narrowing cast,
- // and do sign/zero extension (necessary if we change signedness).
- unsigned TmpReg1 = makeAnotherReg (newTy);
- unsigned TmpReg2 = makeAnotherReg (newTy);
- BuildMI (*BB, IP, V8::ORrr, 2, TmpReg1).addReg (V8::G0).addReg (SrcReg);
- unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
- BuildMI (*BB, IP, V8::SLLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
- if (newTy->isSigned ()) { // sign-extend with SRA
- BuildMI(*BB, IP, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
- } else { // zero-extend with SRL
- BuildMI(*BB, IP, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg2);
- }
- } else {
- unsigned TmpReg1 = makeAnotherReg (oldTy);
- unsigned TmpReg2 = makeAnotherReg (newTy);
- unsigned TmpReg3 = makeAnotherReg (newTy);
- // Widening integer cast. Make sure it's fully sign/zero-extended
- // wrt the input type, then make sure it's fully sign/zero-extended wrt
- // the output type. Kind of stupid, but simple...
- unsigned shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (oldTy));
- BuildMI (*BB, IP, V8::SLLri, 2, TmpReg1).addZImm (shiftWidth).addReg(SrcReg);
- if (oldTy->isSigned ()) { // sign-extend with SRA
- BuildMI(*BB, IP, V8::SRAri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
- } else { // zero-extend with SRL
- BuildMI(*BB, IP, V8::SRLri, 2, TmpReg2).addZImm (shiftWidth).addReg(TmpReg1);
- }
- shiftWidth = 32 - (8 * TM.getTargetData ().getTypeSize (newTy));
- BuildMI (*BB, IP, V8::SLLri, 2, TmpReg3).addZImm (shiftWidth).addReg(TmpReg2);
- if (newTy->isSigned ()) { // sign-extend with SRA
- BuildMI(*BB, IP, V8::SRAri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
- } else { // zero-extend with SRL
- BuildMI(*BB, IP, V8::SRLri, 2, DestReg).addZImm (shiftWidth).addReg(TmpReg3);
- }
- }
- } else {
- if (newTyClass == cFloat) {
- assert (oldTyClass != cLong && "cast long to float not implemented yet");
- switch (oldTyClass) {
- case cFloat:
- BuildMI (*BB, IP, V8::FMOVS, 1, DestReg).addReg (SrcReg);
- break;
- case cDouble:
- BuildMI (*BB, IP, V8::FDTOS, 1, DestReg).addReg (SrcReg);
- break;
- default: {
- unsigned FltAlign = TM.getTargetData().getFloatAlignment();
- // cast int to float. Store it to a stack slot and then load
- // it using ldf into a floating point register. then do fitos.
- unsigned TmpReg = makeAnotherReg (newTy);
- int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign);
- BuildMI (*BB, IP, V8::ST, 3).addFrameIndex (FI).addSImm (0)
- .addReg (SrcReg);
- BuildMI (*BB, IP, V8::LDFri, 2, TmpReg).addFrameIndex (FI).addSImm (0);
- BuildMI (*BB, IP, V8::FITOS, 1, DestReg).addReg(TmpReg);
- break;
- }
- }
- } else if (newTyClass == cDouble) {
- assert (oldTyClass != cLong && "cast long to double not implemented yet");
- switch (oldTyClass) {
- case cFloat:
- BuildMI (*BB, IP, V8::FSTOD, 1, DestReg).addReg (SrcReg);
- break;
- case cDouble: {
- // go through memory, for now
- unsigned DoubleAlignment = TM.getTargetData().getDoubleAlignment();
- int FI = F->getFrameInfo()->CreateStackObject(8, DoubleAlignment);
- BuildMI (*BB, IP, V8::STDFri, 3).addFrameIndex (FI).addSImm (0)
- .addReg (SrcReg);
- BuildMI (*BB, IP, V8::LDDFri, 2, DestReg).addFrameIndex (FI)
- .addSImm (0);
- break;
- }
- default: {
- unsigned DoubleAlignment = TM.getTargetData().getDoubleAlignment();
- unsigned TmpReg = makeAnotherReg (newTy);
- int FI = F->getFrameInfo()->CreateStackObject(8, DoubleAlignment);
- BuildMI (*BB, IP, V8::ST, 3).addFrameIndex (FI).addSImm (0)
- .addReg (SrcReg);
- BuildMI (*BB, IP, V8::LDDFri, 2, TmpReg).addFrameIndex (FI).addSImm (0);
- BuildMI (*BB, IP, V8::FITOD, 1, DestReg).addReg(TmpReg);
- break;
- }
- }
- } else if (newTyClass == cLong) {
- if (oldTyClass == cLong) {
- // Just copy it
- BuildMI (*BB, IP, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (SrcReg);
- BuildMI (*BB, IP, V8::ORrr, 2, DestReg+1).addReg (V8::G0)
- .addReg (SrcReg+1);
- } else {
- std::cerr << "Cast still unsupported: SrcTy = "
- << *SrcTy << ", DestTy = " << *DestTy << "\n";
- abort ();
- }
- } else {
- std::cerr << "Cast still unsupported: SrcTy = "
- << *SrcTy << ", DestTy = " << *DestTy << "\n";
- abort ();
- }
- }
-}
-
-void V8ISel::visitLoadInst(LoadInst &I) {
- unsigned DestReg = getReg (I);
- unsigned PtrReg = getReg (I.getOperand (0));
- switch (getClassB (I.getType ())) {
- case cByte:
- if (I.getType ()->isSigned ())
- BuildMI (BB, V8::LDSB, 2, DestReg).addReg (PtrReg).addSImm(0);
- else
- BuildMI (BB, V8::LDUB, 2, DestReg).addReg (PtrReg).addSImm(0);
- return;
- case cShort:
- if (I.getType ()->isSigned ())
- BuildMI (BB, V8::LDSH, 2, DestReg).addReg (PtrReg).addSImm(0);
- else
- BuildMI (BB, V8::LDUH, 2, DestReg).addReg (PtrReg).addSImm(0);
- return;
- case cInt:
- BuildMI (BB, V8::LD, 2, DestReg).addReg (PtrReg).addSImm(0);
- return;
- case cLong:
- BuildMI (BB, V8::LD, 2, DestReg).addReg (PtrReg).addSImm(0);
- BuildMI (BB, V8::LD, 2, DestReg+1).addReg (PtrReg).addSImm(4);
- return;
- case cFloat:
- BuildMI (BB, V8::LDFri, 2, DestReg).addReg (PtrReg).addSImm(0);
- return;
- case cDouble:
- BuildMI (BB, V8::LDDFri, 2, DestReg).addReg (PtrReg).addSImm(0);
- return;
- default:
- std::cerr << "Load instruction not handled: " << I;
- abort ();
- return;
- }
-}
-
-void V8ISel::visitStoreInst(StoreInst &I) {
- Value *SrcVal = I.getOperand (0);
- unsigned SrcReg = getReg (SrcVal);
- unsigned PtrReg = getReg (I.getOperand (1));
- switch (getClassB (SrcVal->getType ())) {
- case cByte:
- BuildMI (BB, V8::STB, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
- return;
- case cShort:
- BuildMI (BB, V8::STH, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
- return;
- case cInt:
- BuildMI (BB, V8::ST, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
- return;
- case cLong:
- BuildMI (BB, V8::ST, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
- BuildMI (BB, V8::ST, 3).addReg (PtrReg).addSImm (4).addReg (SrcReg+1);
- return;
- case cFloat:
- BuildMI (BB, V8::STFri, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
- return;
- case cDouble:
- BuildMI (BB, V8::STDFri, 3).addReg (PtrReg).addSImm (0).addReg (SrcReg);
- return;
- default:
- std::cerr << "Store instruction not handled: " << I;
- abort ();
- return;
- }
-}
-
-void V8ISel::visitCallInst(CallInst &I) {
- MachineInstr *TheCall;
- // Is it an intrinsic function call?
- if (Function *F = I.getCalledFunction()) {
- if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) {
- visitIntrinsicCall(ID, I); // Special intrinsics are not handled here
- return;
- }
- }
-
- // Deal with args
- assert (I.getNumOperands () < 8
- && "Can't handle pushing excess call args on the stack yet");
- static const unsigned OutgoingArgRegs[] = { V8::O0, V8::O1, V8::O2, V8::O3,
- V8::O4, V8::O5 };
- for (unsigned i = 1; i < 7; ++i)
- if (i < I.getNumOperands ()) {
- unsigned ArgReg = getReg (I.getOperand (i));
- if (getClassB (I.getOperand (i)->getType ()) < cLong) {
- // Schlep it over into the incoming arg register
- BuildMI (BB, V8::ORrr, 2, OutgoingArgRegs[i - 1]).addReg (V8::G0)
- .addReg (ArgReg);
- } else if (getClassB (I.getOperand (i)->getType ()) == cFloat) {
- // Single-fp args are passed in integer registers; go through
- // memory to get them out of FP registers. (Bleh!)
- unsigned FltAlign = TM.getTargetData().getFloatAlignment();
- int FI = F->getFrameInfo()->CreateStackObject(4, FltAlign);
- BuildMI (BB, V8::STFri, 3).addFrameIndex (FI).addSImm (0)
- .addReg (ArgReg);
- BuildMI (BB, V8::LD, 2, OutgoingArgRegs[i - 1]).addFrameIndex (FI)
- .addSImm (0);
- } else {
- assert (0 && "64-bit (double, long, etc.) 'call' opnds not handled");
- }
- }
-
- // Emit call instruction
- if (Function *F = I.getCalledFunction ()) {
- BuildMI (BB, V8::CALL, 1).addGlobalAddress (F, true);
- } else { // Emit an indirect call...
- unsigned Reg = getReg (I.getCalledValue ());
- BuildMI (BB, V8::JMPLrr, 3, V8::O7).addReg (Reg).addReg (V8::G0);
- }
-
- // Deal w/ return value: schlep it over into the destination register
- if (I.getType () == Type::VoidTy)
- return;
- unsigned DestReg = getReg (I);
- switch (getClass (I.getType ())) {
- case cByte:
- case cShort:
- case cInt:
- BuildMI (BB, V8::ORrr, 2, DestReg).addReg(V8::G0).addReg(V8::O0);
- break;
- case cFloat:
- BuildMI (BB, V8::FMOVS, 2, DestReg).addReg(V8::F0);
- break;
- default:
- std::cerr << "Return type of call instruction not handled: " << I;
- abort ();
- }
-}
-
-void V8ISel::visitReturnInst(ReturnInst &I) {
- if (I.getNumOperands () == 1) {
- unsigned RetValReg = getReg (I.getOperand (0));
- switch (getClass (I.getOperand (0)->getType ())) {
- case cByte:
- case cShort:
- case cInt:
- // Schlep it over into i0 (where it will become o0 after restore).
- BuildMI (BB, V8::ORrr, 2, V8::I0).addReg(V8::G0).addReg(RetValReg);
- break;
- case cFloat:
- BuildMI (BB, V8::FMOVS, 2, V8::F0).addReg(RetValReg);
- break;
- case cDouble: {
- unsigned DoubleAlignment = TM.getTargetData().getDoubleAlignment();
- int FI = F->getFrameInfo()->CreateStackObject(8, DoubleAlignment);
- BuildMI (BB, V8::STDFri, 3).addFrameIndex (FI).addSImm (0)
- .addReg (RetValReg);
- BuildMI (BB, V8::LDDFri, 2, V8::F0).addFrameIndex (FI).addSImm (0);
- break;
- }
- case cLong:
- BuildMI (BB, V8::ORrr, 2, V8::I0).addReg(V8::G0).addReg(RetValReg);
- BuildMI (BB, V8::ORrr, 2, V8::I1).addReg(V8::G0).addReg(RetValReg+1);
- break;
- default:
- std::cerr << "Return instruction of this type not handled: " << I;
- abort ();
- }
- }
-
- // Just emit a 'retl' instruction to return.
- BuildMI(BB, V8::RETL, 0);
- return;
-}
-
-static inline BasicBlock *getBlockAfter(BasicBlock *BB) {
- Function::iterator I = BB; ++I; // Get iterator to next block
- return I != BB->getParent()->end() ? &*I : 0;
-}
-
-/// visitBranchInst - Handles conditional and unconditional branches.
-///
-void V8ISel::visitBranchInst(BranchInst &I) {
- BasicBlock *takenSucc = I.getSuccessor (0);
- MachineBasicBlock *takenSuccMBB = MBBMap[takenSucc];
- BB->addSuccessor (takenSuccMBB);
- if (I.isConditional()) { // conditional branch
- BasicBlock *notTakenSucc = I.getSuccessor (1);
- MachineBasicBlock *notTakenSuccMBB = MBBMap[notTakenSucc];
- BB->addSuccessor (notTakenSuccMBB);
-
- // CondReg=(<condition>);
- // If (CondReg==0) goto notTakenSuccMBB;
- unsigned CondReg = getReg (I.getCondition ());
- BuildMI (BB, V8::CMPri, 2).addSImm (0).addReg (CondReg);
- BuildMI (BB, V8::BE, 1).addMBB (notTakenSuccMBB);
- }
- // goto takenSuccMBB;
- BuildMI (BB, V8::BA, 1).addMBB (takenSuccMBB);
-}
-
-/// emitGEPOperation - Common code shared between visitGetElementPtrInst and
-/// constant expression GEP support.
-///
-void V8ISel::emitGEPOperation (MachineBasicBlock *MBB,
- MachineBasicBlock::iterator IP,
- Value *Src, User::op_iterator IdxBegin,
- User::op_iterator IdxEnd, unsigned TargetReg) {
- const TargetData &TD = TM.getTargetData ();
- const Type *Ty = Src->getType ();
- unsigned basePtrReg = getReg (Src, MBB, IP);
-
- // GEPs have zero or more indices; we must perform a struct access
- // or array access for each one.
- for (GetElementPtrInst::op_iterator oi = IdxBegin, oe = IdxEnd; oi != oe;
- ++oi) {
- Value *idx = *oi;
- unsigned nextBasePtrReg = makeAnotherReg (Type::UIntTy);
- if (const StructType *StTy = dyn_cast<StructType> (Ty)) {
- // It's a struct access. idx is the index into the structure,
- // which names the field. Use the TargetData structure to
- // pick out what the layout of the structure is in memory.
- // Use the (constant) structure index's value to find the
- // right byte offset from the StructLayout class's list of
- // structure member offsets.
- unsigned fieldIndex = cast<ConstantUInt> (idx)->getValue ();
- unsigned memberOffset =
- TD.getStructLayout (StTy)->MemberOffsets[fieldIndex];
- // Emit an ADD to add memberOffset to the basePtr.
- BuildMI (*MBB, IP, V8::ADDri, 2,
- nextBasePtrReg).addReg (basePtrReg).addZImm (memberOffset);
- // The next type is the member of the structure selected by the
- // index.
- Ty = StTy->getElementType (fieldIndex);
- } else if (const SequentialType *SqTy = dyn_cast<SequentialType> (Ty)) {
- // It's an array or pointer access: [ArraySize x ElementType].
- // We want to add basePtrReg to (idxReg * sizeof ElementType). First, we
- // must find the size of the pointed-to type (Not coincidentally, the next
- // type is the type of the elements in the array).
- Ty = SqTy->getElementType ();
- unsigned elementSize = TD.getTypeSize (Ty);
- unsigned idxReg = getReg (idx, MBB, IP);
- unsigned OffsetReg = makeAnotherReg (Type::IntTy);
- unsigned elementSizeReg = makeAnotherReg (Type::UIntTy);
- copyConstantToRegister (MBB, IP,
- ConstantUInt::get(Type::UIntTy, elementSize), elementSizeReg);
- // Emit a SMUL to multiply the register holding the index by
- // elementSize, putting the result in OffsetReg.
- BuildMI (*MBB, IP, V8::SMULrr, 2,
- OffsetReg).addReg (elementSizeReg).addReg (idxReg);
- // Emit an ADD to add OffsetReg to the basePtr.
- BuildMI (*MBB, IP, V8::ADDrr, 2,
- nextBasePtrReg).addReg (basePtrReg).addReg (OffsetReg);
- }
- basePtrReg = nextBasePtrReg;
- }
- // After we have processed all the indices, the result is left in
- // basePtrReg. Move it to the register where we were expected to
- // put the answer.
- BuildMI (BB, V8::ORrr, 1, TargetReg).addReg (V8::G0).addReg (basePtrReg);
-}
-
-void V8ISel::visitGetElementPtrInst (GetElementPtrInst &I) {
- unsigned outputReg = getReg (I);
- emitGEPOperation (BB, BB->end (), I.getOperand (0),
- I.op_begin ()+1, I.op_end (), outputReg);
-}
-
-
-void V8ISel::visitBinaryOperator (Instruction &I) {
- unsigned DestReg = getReg (I);
- unsigned Op0Reg = getReg (I.getOperand (0));
- unsigned Op1Reg = getReg (I.getOperand (1));
-
- unsigned Class = getClassB (I.getType());
- unsigned OpCase = ~0;
-
- if (Class > cLong) {
- switch (I.getOpcode ()) {
- case Instruction::Add: OpCase = 0; break;
- case Instruction::Sub: OpCase = 1; break;
- case Instruction::Mul: OpCase = 2; break;
- case Instruction::Div: OpCase = 3; break;
- default: visitInstruction (I); return;
- }
- static unsigned Opcodes[] = { V8::FADDS, V8::FADDD,
- V8::FSUBS, V8::FSUBD,
- V8::FMULS, V8::FMULD,
- V8::FDIVS, V8::FDIVD };
- BuildMI (BB, Opcodes[2*OpCase + (Class - cFloat)], 2, DestReg)
- .addReg (Op0Reg).addReg (Op1Reg);
- return;
- }
-
- unsigned ResultReg = DestReg;
- if (Class != cInt)
- ResultReg = makeAnotherReg (I.getType ());
-
- // FIXME: support long, ulong, fp.
- switch (I.getOpcode ()) {
- case Instruction::Add: OpCase = 0; break;
- case Instruction::Sub: OpCase = 1; break;
- case Instruction::Mul: OpCase = 2; break;
- case Instruction::And: OpCase = 3; break;
- case Instruction::Or: OpCase = 4; break;
- case Instruction::Xor: OpCase = 5; break;
- case Instruction::Shl: OpCase = 6; break;
- case Instruction::Shr: OpCase = 7+I.getType()->isSigned(); break;
-
- case Instruction::Div:
- case Instruction::Rem: {
- unsigned Dest = ResultReg;
- if (I.getOpcode() == Instruction::Rem)
- Dest = makeAnotherReg(I.getType());
-
- // FIXME: this is probably only right for 32 bit operands.
- if (I.getType ()->isSigned()) {
- unsigned Tmp = makeAnotherReg (I.getType ());
- // Sign extend into the Y register
- BuildMI (BB, V8::SRAri, 2, Tmp).addReg (Op0Reg).addZImm (31);
- BuildMI (BB, V8::WRrr, 2, V8::Y).addReg (Tmp).addReg (V8::G0);
- BuildMI (BB, V8::SDIVrr, 2, Dest).addReg (Op0Reg).addReg (Op1Reg);
- } else {
- // Zero extend into the Y register, ie, just set it to zero
- BuildMI (BB, V8::WRrr, 2, V8::Y).addReg (V8::G0).addReg (V8::G0);
- BuildMI (BB, V8::UDIVrr, 2, Dest).addReg (Op0Reg).addReg (Op1Reg);
- }
-
- if (I.getOpcode() == Instruction::Rem) {
- unsigned Tmp = makeAnotherReg (I.getType ());
- BuildMI (BB, V8::SMULrr, 2, Tmp).addReg(Dest).addReg(Op1Reg);
- BuildMI (BB, V8::SUBrr, 2, ResultReg).addReg(Op0Reg).addReg(Tmp);
- }
- break;
- }
- default:
- visitInstruction (I);
- return;
- }
-
- static const unsigned Opcodes[] = {
- V8::ADDrr, V8::SUBrr, V8::SMULrr, V8::ANDrr, V8::ORrr, V8::XORrr,
- V8::SLLrr, V8::SRLrr, V8::SRArr
- };
- if (OpCase != ~0U) {
- BuildMI (BB, Opcodes[OpCase], 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
- }
-
- switch (getClassB (I.getType ())) {
- case cByte:
- if (I.getType ()->isSigned ()) { // add byte
- BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff);
- } else { // add ubyte
- unsigned TmpReg = makeAnotherReg (I.getType ());
- BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24);
- BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (24);
- }
- break;
- case cShort:
- if (I.getType ()->isSigned ()) { // add short
- unsigned TmpReg = makeAnotherReg (I.getType ());
- BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (16);
- BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (16);
- } else { // add ushort
- unsigned TmpReg = makeAnotherReg (I.getType ());
- BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (16);
- BuildMI (BB, V8::SRLri, 2, DestReg).addReg (TmpReg).addZImm (16);
- }
- break;
- case cInt:
- // Nothing to do here.
- break;
- case cLong:
- // Only support and, or, xor.
- if (OpCase < 3 || OpCase > 5) {
- visitInstruction (I);
- return;
- }
- // Do the other half of the value:
- BuildMI (BB, Opcodes[OpCase], 2, ResultReg+1).addReg (Op0Reg+1)
- .addReg (Op1Reg+1);
- break;
- default:
- visitInstruction (I);
- }
-}
-
-void V8ISel::visitSetCondInst(SetCondInst &I) {
- unsigned Op0Reg = getReg (I.getOperand (0));
- unsigned Op1Reg = getReg (I.getOperand (1));
- unsigned DestReg = getReg (I);
- const Type *Ty = I.getOperand (0)->getType ();
-
- // Compare the two values.
- assert (getClass (Ty) != cLong && "can't setcc on longs yet");
- if (getClass (Ty) < cLong) {
- BuildMI(BB, V8::SUBCCrr, 2, V8::G0).addReg(Op0Reg).addReg(Op1Reg);
- } else if (getClass (Ty) == cFloat) {
- BuildMI(BB, V8::FCMPS, 2).addReg(Op0Reg).addReg(Op1Reg);
- } else if (getClass (Ty) == cDouble) {
- BuildMI(BB, V8::FCMPD, 2).addReg(Op0Reg).addReg(Op1Reg);
- }
-
- unsigned BranchIdx;
- switch (I.getOpcode()) {
- default: assert(0 && "Unknown setcc instruction!");
- case Instruction::SetEQ: BranchIdx = 0; break;
- case Instruction::SetNE: BranchIdx = 1; break;
- case Instruction::SetLT: BranchIdx = 2; break;
- case Instruction::SetGT: BranchIdx = 3; break;
- case Instruction::SetLE: BranchIdx = 4; break;
- case Instruction::SetGE: BranchIdx = 5; break;
- }
- unsigned Column = 0;
- if (Ty->isSigned()) ++Column;
- if (Ty->isFloatingPoint()) ++Column;
- static unsigned OpcodeTab[3*6] = {
- // LLVM SparcV8
- // unsigned signed fp
- V8::BE, V8::BE, V8::FBE, // seteq = be be fbe
- V8::BNE, V8::BNE, V8::FBNE, // setne = bne bne fbne
- V8::BCS, V8::BL, V8::FBL, // setlt = bcs bl fbl
- V8::BGU, V8::BG, V8::FBG, // setgt = bgu bg fbg
- V8::BLEU, V8::BLE, V8::FBLE, // setle = bleu ble fble
- V8::BCC, V8::BGE, V8::FBGE // setge = bcc bge fbge
- };
- unsigned Opcode = OpcodeTab[3*BranchIdx + Column];
-
- MachineBasicBlock *thisMBB = BB;
- const BasicBlock *LLVM_BB = BB->getBasicBlock ();
- // thisMBB:
- // ...
- // subcc %reg0, %reg1, %g0
- // bCC copy1MBB
- // ba copy0MBB
-
- // FIXME: we wouldn't need copy0MBB (we could fold it into thisMBB)
- // if we could insert other, non-terminator instructions after the
- // bCC. But MBB->getFirstTerminator() can't understand this.
- MachineBasicBlock *copy1MBB = new MachineBasicBlock (LLVM_BB);
- F->getBasicBlockList ().push_back (copy1MBB);
- BuildMI (BB, Opcode, 1).addMBB (copy1MBB);
- MachineBasicBlock *copy0MBB = new MachineBasicBlock (LLVM_BB);
- F->getBasicBlockList ().push_back (copy0MBB);
- BuildMI (BB, V8::BA, 1).addMBB (copy0MBB);
- // Update machine-CFG edges
- BB->addSuccessor (copy1MBB);
- BB->addSuccessor (copy0MBB);
-
- // copy0MBB:
- // %FalseValue = or %G0, 0
- // ba sinkMBB
- BB = copy0MBB;
- unsigned FalseValue = makeAnotherReg (I.getType ());
- BuildMI (BB, V8::ORri, 2, FalseValue).addReg (V8::G0).addZImm (0);
- MachineBasicBlock *sinkMBB = new MachineBasicBlock (LLVM_BB);
- F->getBasicBlockList ().push_back (sinkMBB);
- BuildMI (BB, V8::BA, 1).addMBB (sinkMBB);
- // Update machine-CFG edges
- BB->addSuccessor (sinkMBB);
-
- DEBUG (std::cerr << "thisMBB is at " << (void*)thisMBB << "\n");
- DEBUG (std::cerr << "copy1MBB is at " << (void*)copy1MBB << "\n");
- DEBUG (std::cerr << "copy0MBB is at " << (void*)copy0MBB << "\n");
- DEBUG (std::cerr << "sinkMBB is at " << (void*)sinkMBB << "\n");
-
- // copy1MBB:
- // %TrueValue = or %G0, 1
- // ba sinkMBB
- BB = copy1MBB;
- unsigned TrueValue = makeAnotherReg (I.getType ());
- BuildMI (BB, V8::ORri, 2, TrueValue).addReg (V8::G0).addZImm (1);
- BuildMI (BB, V8::BA, 1).addMBB (sinkMBB);
- // Update machine-CFG edges
- BB->addSuccessor (sinkMBB);
-
- // sinkMBB:
- // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, copy1MBB ]
- // ...
- BB = sinkMBB;
- BuildMI (BB, V8::PHI, 4, DestReg).addReg (FalseValue)
- .addMBB (copy0MBB).addReg (TrueValue).addMBB (copy1MBB);
-}
-
-void V8ISel::visitAllocaInst(AllocaInst &I) {
- // Find the data size of the alloca inst's getAllocatedType.
- const Type *Ty = I.getAllocatedType();
- unsigned TySize = TM.getTargetData().getTypeSize(Ty);
-
- unsigned ArraySizeReg = getReg (I.getArraySize ());
- unsigned TySizeReg = getReg (ConstantUInt::get (Type::UIntTy, TySize));
- unsigned TmpReg1 = makeAnotherReg (Type::UIntTy);
- unsigned TmpReg2 = makeAnotherReg (Type::UIntTy);
- unsigned StackAdjReg = makeAnotherReg (Type::UIntTy);
-
- // StackAdjReg = (ArraySize * TySize) rounded up to nearest doubleword boundary
- BuildMI (BB, V8::UMULrr, 2, TmpReg1).addReg (ArraySizeReg).addReg (TySizeReg);
-
- // Round up TmpReg1 to nearest doubleword boundary:
- BuildMI (BB, V8::ADDri, 2, TmpReg2).addReg (TmpReg1).addSImm (7);
- BuildMI (BB, V8::ANDri, 2, StackAdjReg).addReg (TmpReg2).addSImm (-8);
-
- // Subtract size from stack pointer, thereby allocating some space.
- BuildMI (BB, V8::SUBrr, 2, V8::SP).addReg (V8::SP).addReg (StackAdjReg);
-
- // Put a pointer to the space into the result register, by copying
- // the stack pointer.
- BuildMI (BB, V8::ADDri, 2, getReg(I)).addReg (V8::SP).addSImm (96);
-
- // Inform the Frame Information that we have just allocated a variable-sized
- // object.
- F->getFrameInfo()->CreateVariableSizedObject();
-}
-
-/// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
-/// function, lowering any calls to unknown intrinsic functions into the
-/// equivalent LLVM code.
-void V8ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
- 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()) {
- case Intrinsic::not_intrinsic: break;
- default:
- // All other intrinsic calls we must lower.
- Instruction *Before = CI->getPrev();
- TM.getIntrinsicLowering().LowerIntrinsicCall(CI);
- if (Before) { // Move iterator to instruction after call
- I = Before; ++I;
- } else {
- I = BB->begin();
- }
- }
-}
-
-
-void V8ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
- unsigned TmpReg1, TmpReg2;
- switch (ID) {
- default: assert(0 && "Intrinsic not supported!");
- }
-}
diff --git a/llvm/lib/Target/SparcV8/Makefile b/llvm/lib/Target/SparcV8/Makefile
deleted file mode 100644
index 78da738aa7b0..000000000000
--- a/llvm/lib/Target/SparcV8/Makefile
+++ /dev/null
@@ -1,46 +0,0 @@
-##===- lib/Target/SparcV8/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 = sparcv8
-include $(LEVEL)/Makefile.common
-
-TDFILES := $(wildcard $(SourceDir)/*.td) $(SourceDir)/../Target.td
-TDFILE := $(SourceDir)/SparcV8.td
-
-# Make sure that tblgen is run, first thing.
-$(SourceDepend): SparcV8GenRegisterInfo.h.inc SparcV8GenRegisterNames.inc \
- SparcV8GenRegisterInfo.inc SparcV8GenInstrNames.inc \
- SparcV8GenInstrInfo.inc SparcV8GenInstrSelector.inc
-
-SparcV8GenRegisterNames.inc:: $(TDFILES) $(TBLGEN)
- @echo "Building SparcV8.td register names with tblgen"
- $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-register-enums -o $@
-
-SparcV8GenRegisterInfo.h.inc:: $(TDFILES) $(TBLGEN)
- @echo "Building SparcV8.td register information header with tblgen"
- $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-register-desc-header -o $@
-
-SparcV8GenRegisterInfo.inc:: $(TDFILES) $(TBLGEN)
- @echo "Building SparcV8.td register information implementation with tblgen"
- $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-register-desc -o $@
-
-SparcV8GenInstrNames.inc:: $(TDFILES) $(TBLGEN)
- @echo "Building SparcV8.td instruction names with tblgen"
- $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-instr-enums -o $@
-
-SparcV8GenInstrInfo.inc:: $(TDFILES) $(TBLGEN)
- @echo "Building SparcV8.td instruction information with tblgen"
- $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-instr-desc -o $@
-
-SparcV8GenInstrSelector.inc:: $(TDFILES) $(TBLGEN)
- @echo "Building SparcV8.td instruction selector with tblgen"
- $(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-instr-selector -o $@
-
-clean::
- $(VERB) rm -f *.inc
diff --git a/llvm/lib/Target/SparcV8/README.txt b/llvm/lib/Target/SparcV8/README.txt
deleted file mode 100644
index 691ad3f80469..000000000000
--- a/llvm/lib/Target/SparcV8/README.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-
-SparcV8 backend skeleton
-------------------------
-
-This directory houses a 32-bit SPARC V8 backend employing a expander-based
-instruction selector. It is not yet functionally complete. Watch
-this space for more news coming soon!
-
-To-do
------
-
-* support 64-bit (double FP, long, ulong) arguments to functions
-* support functions with more than 6 args
-* support setcc on longs
-* support basic binary operations on longs
-* support casting <=32-bit integers, bools to long
-* support casting 64-bit integers to FP types
-
-$Date$
-
diff --git a/llvm/lib/Target/SparcV8/SparcV8.h b/llvm/lib/Target/SparcV8/SparcV8.h
deleted file mode 100644
index 44ee15aeae84..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//===-- SparcV8.h - Top-level interface for SparcV8 representation -*- 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 entry points for global functions defined in the LLVM
-// SparcV8 back-end.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TARGET_SPARCV8_H
-#define TARGET_SPARCV8_H
-
-#include <iosfwd>
-
-namespace llvm {
-
- class FunctionPass;
- class TargetMachine;
-
- FunctionPass *createSparcV8SimpleInstructionSelector(TargetMachine &TM);
- FunctionPass *createSparcV8CodePrinterPass(std::ostream &OS,
- TargetMachine &TM);
- FunctionPass *createSparcV8DelaySlotFillerPass(TargetMachine &TM);
-
-} // end namespace llvm;
-
-// Defines symbolic names for SparcV8 registers. This defines a mapping from
-// register name to register number.
-//
-#include "SparcV8GenRegisterNames.inc"
-
-// Defines symbolic names for the SparcV8 instructions.
-//
-#include "SparcV8GenInstrNames.inc"
-
-#endif
diff --git a/llvm/lib/Target/SparcV8/SparcV8.td b/llvm/lib/Target/SparcV8/SparcV8.td
deleted file mode 100644
index b8dff53a5758..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8.td
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- SparcV8.td - Describe the SparcV8 Target Machine ---------*- 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.
-//
-//===----------------------------------------------------------------------===//
-//
-//
-//===----------------------------------------------------------------------===//
-
-// Get the target-independent interfaces which we are implementing...
-//
-include "../Target.td"
-
-//===----------------------------------------------------------------------===//
-// Register File Description
-//===----------------------------------------------------------------------===//
-
-include "SparcV8RegisterInfo.td"
-include "SparcV8InstrInfo.td"
-
-def SparcV8InstrInfo : InstrInfo {
- let PHIInst = PHI;
-}
-
-def SparcV8 : Target {
- // Pointers are 32-bits in size.
- let PointerType = i32;
-
- // These regs are nonvolatile across calls:
- let CalleeSavedRegisters = [];
-
- // Pull in Instruction Info:
- let InstructionSet = SparcV8InstrInfo;
-}
diff --git a/llvm/lib/Target/SparcV8/SparcV8AsmPrinter.cpp b/llvm/lib/Target/SparcV8/SparcV8AsmPrinter.cpp
deleted file mode 100644
index 6c3bd7645dbf..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8AsmPrinter.cpp
+++ /dev/null
@@ -1,632 +0,0 @@
-//===-- SparcV8AsmPrinter.cpp - SparcV8 LLVM assembly writer --------------===//
-//
-// 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 printer that converts from our internal representation
-// of machine-dependent LLVM code to GAS-format Sparc V8 assembly language.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcV8.h"
-#include "SparcV8InstrInfo.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/Assembly/Writer.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/Mangler.h"
-#include "Support/Statistic.h"
-#include "Support/StringExtras.h"
-#include "Support/CommandLine.h"
-#include <cctype>
-using namespace llvm;
-
-namespace {
- Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
-
- struct V8Printer : public MachineFunctionPass {
- /// Output stream on which we're printing assembly code.
- ///
- std::ostream &O;
-
- /// Target machine description which we query for reg. names, data
- /// layout, etc.
- ///
- TargetMachine &TM;
-
- /// Name-mangler for global names.
- ///
- Mangler *Mang;
-
- V8Printer(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { }
-
- /// We name each basic block in a Function with a unique number, so
- /// that we can consistently refer to them later. This is cleared
- /// at the beginning of each call to runOnMachineFunction().
- ///
- typedef std::map<const Value *, unsigned> ValueMapTy;
- ValueMapTy NumberForBB;
-
- /// Cache of mangled name for current function. This is
- /// recalculated at the beginning of each call to
- /// runOnMachineFunction().
- ///
- std::string CurrentFnName;
-
- virtual const char *getPassName() const {
- return "SparcV8 Assembly Printer";
- }
-
- void emitConstantValueOnly(const Constant *CV);
- void emitGlobalConstant(const Constant *CV);
- void printConstantPool(MachineConstantPool *MCP);
- void printOperand(const MachineInstr *MI, int opNum);
- void printBaseOffsetPair (const MachineInstr *MI, int i, bool brackets=true);
- void printMachineInstruction(const MachineInstr *MI);
- bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
- };
-} // end of anonymous namespace
-
-/// createSparcV8CodePrinterPass - Returns a pass that prints the SparcV8
-/// assembly code for a MachineFunction to the given output stream,
-/// using the given target machine description. This should work
-/// regardless of whether the function is in SSA form.
-///
-FunctionPass *llvm::createSparcV8CodePrinterPass (std::ostream &o,
- TargetMachine &tm) {
- return new V8Printer(o, tm);
-}
-
-/// toOctal - Convert the low order bits of X into an octal digit.
-///
-static inline char toOctal(int X) {
- return (X&7)+'0';
-}
-
-/// getAsCString - Return the specified array as a C compatible
-/// string, only if the predicate isStringCompatible is true.
-///
-static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
- assert(CVA->isString() && "Array is not string compatible!");
-
- O << "\"";
- for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
- unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
-
- if (C == '"') {
- O << "\\\"";
- } else if (C == '\\') {
- O << "\\\\";
- } else if (isprint(C)) {
- O << C;
- } else {
- switch(C) {
- case '\b': O << "\\b"; break;
- case '\f': O << "\\f"; break;
- case '\n': O << "\\n"; break;
- case '\r': O << "\\r"; break;
- case '\t': O << "\\t"; break;
- default:
- O << '\\';
- O << toOctal(C >> 6);
- O << toOctal(C >> 3);
- O << toOctal(C >> 0);
- break;
- }
- }
- }
- O << "\"";
-}
-
-// Print out the specified constant, without a storage class. Only the
-// constants valid in constant expressions can occur here.
-void V8Printer::emitConstantValueOnly(const Constant *CV) {
- if (CV->isNullValue())
- O << "0";
- else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
- assert(CB == ConstantBool::True);
- O << "1";
- } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
- if (((CI->getValue() << 32) >> 32) == CI->getValue())
- O << CI->getValue();
- else
- O << (unsigned long long)CI->getValue();
- else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
- O << CI->getValue();
- else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV))
- // This is a constant address for a global variable or function. Use the
- // name of the variable or function as the address value.
- O << Mang->getValueName(GV);
- else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
- const TargetData &TD = TM.getTargetData();
- switch(CE->getOpcode()) {
- case Instruction::GetElementPtr: {
- // generate a symbolic expression for the byte address
- const Constant *ptrVal = CE->getOperand(0);
- std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
- if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
- O << "(";
- emitConstantValueOnly(ptrVal);
- O << ") + " << Offset;
- } else {
- emitConstantValueOnly(ptrVal);
- }
- break;
- }
- case Instruction::Cast: {
- // Support only non-converting or widening casts for now, that is, ones
- // that do not involve a change in value. This assertion is really gross,
- // and may not even be a complete check.
- Constant *Op = CE->getOperand(0);
- const Type *OpTy = Op->getType(), *Ty = CE->getType();
-
- // Pointers on ILP32 machines can be losslessly converted back and
- // forth into 32-bit or wider integers, regardless of signedness.
- assert(((isa<PointerType>(OpTy)
- && (Ty == Type::LongTy || Ty == Type::ULongTy
- || Ty == Type::IntTy || Ty == Type::UIntTy))
- || (isa<PointerType>(Ty)
- && (OpTy == Type::LongTy || OpTy == Type::ULongTy
- || OpTy == Type::IntTy || OpTy == Type::UIntTy))
- || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
- && OpTy->isLosslesslyConvertibleTo(Ty))))
- && "FIXME: Don't yet support this kind of constant cast expr");
- O << "(";
- emitConstantValueOnly(Op);
- O << ")";
- break;
- }
- case Instruction::Add:
- O << "(";
- emitConstantValueOnly(CE->getOperand(0));
- O << ") + (";
- emitConstantValueOnly(CE->getOperand(1));
- O << ")";
- break;
- default:
- assert(0 && "Unsupported operator!");
- }
- } else {
- assert(0 && "Unknown constant value!");
- }
-}
-
-// Print a constant value or values, with the appropriate storage class as a
-// prefix.
-void V8Printer::emitGlobalConstant(const Constant *CV) {
- const TargetData &TD = TM.getTargetData();
-
- if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
- if (CVA->isString()) {
- O << "\t.ascii\t";
- printAsCString(O, CVA);
- O << "\n";
- } else { // Not a string. Print the values in successive locations
- for (unsigned i = 0, e = CVA->getNumOperands(); i != e; i++)
- emitGlobalConstant(CVA->getOperand(i));
- }
- return;
- } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
- // Print the fields in successive locations. Pad to align if needed!
- const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
- unsigned sizeSoFar = 0;
- for (unsigned i = 0, e = CVS->getNumOperands(); i != e; i++) {
- const Constant* field = CVS->getOperand(i);
-
- // Check if padding is needed and insert one or more 0s.
- unsigned fieldSize = TD.getTypeSize(field->getType());
- unsigned padSize = ((i == e-1? cvsLayout->StructSize
- : cvsLayout->MemberOffsets[i+1])
- - cvsLayout->MemberOffsets[i]) - fieldSize;
- sizeSoFar += fieldSize + padSize;
-
- // Now print the actual field value
- emitGlobalConstant(field);
-
- // Insert the field padding unless it's zero bytes...
- if (padSize)
- O << "\t.skip\t " << padSize << "\n";
- }
- assert(sizeSoFar == cvsLayout->StructSize &&
- "Layout of constant struct may be incorrect!");
- return;
- } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
- // FP Constants are printed as integer constants to avoid losing
- // precision...
- double Val = CFP->getValue();
- switch (CFP->getType()->getTypeID()) {
- default: assert(0 && "Unknown floating point type!");
- case Type::FloatTyID: {
- union FU { // Abide by C TBAA rules
- float FVal;
- unsigned UVal;
- } U;
- U.FVal = Val;
- O << ".long\t" << U.UVal << "\t! float " << Val << "\n";
- return;
- }
- case Type::DoubleTyID: {
- union DU { // Abide by C TBAA rules
- double FVal;
- uint64_t UVal;
- } U;
- U.FVal = Val;
- O << ".quad\t" << U.UVal << "\t! double " << Val << "\n";
- return;
- }
- }
- }
-
- const Type *type = CV->getType();
- O << "\t";
- switch (type->getTypeID()) {
- case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
- O << ".byte";
- break;
- case Type::UShortTyID: case Type::ShortTyID:
- O << ".word";
- break;
- case Type::FloatTyID: case Type::PointerTyID:
- case Type::UIntTyID: case Type::IntTyID:
- O << ".long";
- break;
- case Type::DoubleTyID:
- case Type::ULongTyID: case Type::LongTyID:
- O << ".quad";
- break;
- default:
- assert (0 && "Can't handle printing this type of thing");
- break;
- }
- O << "\t";
- emitConstantValueOnly(CV);
- O << "\n";
-}
-
-/// printConstantPool - Print to the current output stream assembly
-/// representations of the constants in the constant pool MCP. This is
-/// used to print out constants which have been "spilled to memory" by
-/// the code generator.
-///
-void V8Printer::printConstantPool(MachineConstantPool *MCP) {
- const std::vector<Constant*> &CP = MCP->getConstants();
- const TargetData &TD = TM.getTargetData();
-
- if (CP.empty()) return;
-
- for (unsigned i = 0, e = CP.size(); i != e; ++i) {
- O << "\t.section .rodata\n";
- O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
- << "\n";
- O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t!"
- << *CP[i] << "\n";
- emitGlobalConstant(CP[i]);
- }
-}
-
-/// runOnMachineFunction - This uses the printMachineInstruction()
-/// method to print assembly for each instruction.
-///
-bool V8Printer::runOnMachineFunction(MachineFunction &MF) {
- // BBNumber is used here so that a given Printer will never give two
- // BBs the same name. (If you have a better way, please let me know!)
- static unsigned BBNumber = 0;
-
- O << "\n\n";
- // What's my mangled name?
- CurrentFnName = Mang->getValueName(MF.getFunction());
-
- // Print out constants referenced by the function
- printConstantPool(MF.getConstantPool());
-
- // Print out labels for the function.
- O << "\t.text\n";
- O << "\t.align 16\n";
- O << "\t.globl\t" << CurrentFnName << "\n";
- O << "\t.type\t" << CurrentFnName << ", #function\n";
- O << CurrentFnName << ":\n";
-
- // Number each basic block so that we can consistently refer to them
- // in PC-relative references.
- NumberForBB.clear();
- for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
- I != E; ++I) {
- NumberForBB[I->getBasicBlock()] = BBNumber++;
- }
-
- // Print out code for the function.
- for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
- I != E; ++I) {
- // Print a label for the basic block.
- O << ".LBB" << Mang->getValueName(MF.getFunction ())
- << "_" << I->getNumber () << ":\t! "
- << I->getBasicBlock ()->getName () << "\n";
- for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II) {
- // Print the assembly for the instruction.
- O << "\t";
- printMachineInstruction(II);
- }
- }
-
- // We didn't modify anything.
- return false;
-}
-
-void V8Printer::printOperand(const MachineInstr *MI, int opNum) {
- const MachineOperand &MO = MI->getOperand (opNum);
- const MRegisterInfo &RI = *TM.getRegisterInfo();
- bool CloseParen = false;
- if (MI->getOpcode() == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) {
- O << "%hi(";
- CloseParen = true;
- } else if (MI->getOpcode() ==V8::ORri &&!MO.isRegister() &&!MO.isImmediate())
- {
- O << "%lo(";
- CloseParen = true;
- }
- switch (MO.getType()) {
- case MachineOperand::MO_VirtualRegister:
- if (Value *V = MO.getVRegValueOrNull()) {
- O << "<" << V->getName() << ">";
- break;
- }
- // FALLTHROUGH
- case MachineOperand::MO_MachineRegister:
- if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
- O << "%" << LowercaseString (RI.get(MO.getReg()).Name);
- else
- O << "%reg" << MO.getReg();
- break;
-
- case MachineOperand::MO_SignExtendedImmed:
- case MachineOperand::MO_UnextendedImmed:
- O << (int)MO.getImmedValue();
- break;
- case MachineOperand::MO_MachineBasicBlock: {
- MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
- O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
- << "_" << MBBOp->getNumber () << "\t! "
- << MBBOp->getBasicBlock ()->getName ();
- return;
- }
- case MachineOperand::MO_PCRelativeDisp:
- std::cerr << "Shouldn't use addPCDisp() when building SparcV8 MachineInstrs";
- abort ();
- return;
- case MachineOperand::MO_GlobalAddress:
- O << Mang->getValueName(MO.getGlobal());
- break;
- case MachineOperand::MO_ExternalSymbol:
- O << MO.getSymbolName();
- break;
- case MachineOperand::MO_ConstantPoolIndex:
- O << ".CPI" << CurrentFnName << "_" << MO.getConstantPoolIndex();
- break;
- default:
- O << "<unknown operand type>"; abort (); break;
- }
- if (CloseParen) O << ")";
-}
-
-static bool isLoadInstruction (const MachineInstr *MI) {
- switch (MI->getOpcode ()) {
- case V8::LDSB:
- case V8::LDSH:
- case V8::LDUB:
- case V8::LDUH:
- case V8::LD:
- case V8::LDD:
- case V8::LDFrr:
- case V8::LDFri:
- case V8::LDDFrr:
- case V8::LDDFri:
- return true;
- default:
- return false;
- }
-}
-
-static bool isStoreInstruction (const MachineInstr *MI) {
- switch (MI->getOpcode ()) {
- case V8::STB:
- case V8::STH:
- case V8::ST:
- case V8::STD:
- case V8::STFrr:
- case V8::STFri:
- case V8::STDFrr:
- case V8::STDFri:
- return true;
- default:
- return false;
- }
-}
-
-static bool isPseudoInstruction (const MachineInstr *MI) {
- switch (MI->getOpcode ()) {
- case V8::PHI:
- case V8::ADJCALLSTACKUP:
- case V8::ADJCALLSTACKDOWN:
- case V8::IMPLICIT_USE:
- case V8::IMPLICIT_DEF:
- return true;
- default:
- return false;
- }
-}
-
-/// printBaseOffsetPair - Print two consecutive operands of MI, starting at #i,
-/// which form a base + offset pair (which may have brackets around it, if
-/// brackets is true, or may be in the form base - constant, if offset is a
-/// negative constant).
-///
-void V8Printer::printBaseOffsetPair (const MachineInstr *MI, int i,
- bool brackets) {
- if (brackets) O << "[";
- printOperand (MI, i);
- if (MI->getOperand (i + 1).isImmediate()) {
- int Val = (int) MI->getOperand (i + 1).getImmedValue ();
- if (Val != 0) {
- O << ((Val >= 0) ? " + " : " - ");
- O << ((Val >= 0) ? Val : -Val);
- }
- } else {
- O << " + ";
- printOperand (MI, i + 1);
- }
- if (brackets) O << "]";
-}
-
-/// printMachineInstruction -- Print out a single SparcV8 LLVM instruction
-/// MI in GAS syntax to the current output stream.
-///
-void V8Printer::printMachineInstruction(const MachineInstr *MI) {
- unsigned Opcode = MI->getOpcode();
- const TargetInstrInfo &TII = *TM.getInstrInfo();
- const TargetInstrDescriptor &Desc = TII.get(Opcode);
-
- // If it's a pseudo-instruction, comment it out.
- if (isPseudoInstruction (MI))
- O << "! ";
-
- O << Desc.Name << " ";
-
- // Printing memory instructions is a special case.
- // for loads: %dest = op %base, offset --> op [%base + offset], %dest
- // for stores: op %base, offset, %src --> op %src, [%base + offset]
- if (isLoadInstruction (MI)) {
- printBaseOffsetPair (MI, 1);
- O << ", ";
- printOperand (MI, 0);
- O << "\n";
- return;
- } else if (isStoreInstruction (MI)) {
- printOperand (MI, 2);
- O << ", ";
- printBaseOffsetPair (MI, 0);
- O << "\n";
- return;
- } else if (Opcode == V8::JMPLrr) {
- printBaseOffsetPair (MI, 1, false);
- O << ", ";
- printOperand (MI, 0);
- O << "\n";
- return;
- }
-
- // print non-immediate, non-register-def operands
- // then print immediate operands
- // then print register-def operands.
- std::vector<int> print_order;
- for (unsigned i = 0; i < MI->getNumOperands (); ++i)
- if (!(MI->getOperand (i).isImmediate ()
- || (MI->getOperand (i).isRegister ()
- && MI->getOperand (i).isDef ())))
- print_order.push_back (i);
- for (unsigned i = 0; i < MI->getNumOperands (); ++i)
- if (MI->getOperand (i).isImmediate ())
- print_order.push_back (i);
- for (unsigned i = 0; i < MI->getNumOperands (); ++i)
- if (MI->getOperand (i).isRegister () && MI->getOperand (i).isDef ())
- print_order.push_back (i);
- for (unsigned i = 0, e = print_order.size (); i != e; ++i) {
- printOperand (MI, print_order[i]);
- if (i != (print_order.size () - 1))
- O << ", ";
- }
- O << "\n";
-}
-
-bool V8Printer::doInitialization(Module &M) {
- Mang = new Mangler(M);
- return false; // success
-}
-
-// SwitchSection - Switch to the specified section of the executable if we are
-// not already in it!
-//
-static void SwitchSection(std::ostream &OS, std::string &CurSection,
- const char *NewSection) {
- if (CurSection != NewSection) {
- CurSection = NewSection;
- if (!CurSection.empty())
- OS << "\t.section " << NewSection << "\n";
- }
-}
-
-bool V8Printer::doFinalization(Module &M) {
- const TargetData &TD = TM.getTargetData();
- std::string CurSection;
-
- // Print out module-level global variables here.
- for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
- if (I->hasInitializer()) { // External global require no code
- O << "\n\n";
- std::string name = Mang->getValueName(I);
- Constant *C = I->getInitializer();
- unsigned Size = TD.getTypeSize(C->getType());
- unsigned Align = TD.getTypeAlignment(C->getType());
-
- if (C->isNullValue() &&
- (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
- I->hasWeakLinkage() /* FIXME: Verify correct */)) {
- SwitchSection(O, CurSection, ".data");
- if (I->hasInternalLinkage())
- O << "\t.local " << name << "\n";
-
- O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
- << "," << (unsigned)TD.getTypeAlignment(C->getType());
- O << "\t\t! ";
- WriteAsOperand(O, I, true, true, &M);
- O << "\n";
- } else {
- switch (I->getLinkage()) {
- case GlobalValue::LinkOnceLinkage:
- case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
- // Nonnull linkonce -> weak
- O << "\t.weak " << name << "\n";
- SwitchSection(O, CurSection, "");
- O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
- break;
-
- case GlobalValue::AppendingLinkage:
- // FIXME: appending linkage variables should go into a section of
- // their name or something. For now, just emit them as external.
- case GlobalValue::ExternalLinkage:
- // If external or appending, declare as a global symbol
- O << "\t.globl " << name << "\n";
- // FALL THROUGH
- case GlobalValue::InternalLinkage:
- if (C->isNullValue())
- SwitchSection(O, CurSection, ".bss");
- else
- SwitchSection(O, CurSection, ".data");
- break;
- }
-
- O << "\t.align " << Align << "\n";
- O << "\t.type " << name << ",#object\n";
- O << "\t.size " << name << "," << Size << "\n";
- O << name << ":\t\t\t\t! ";
- WriteAsOperand(O, I, true, true, &M);
- O << " = ";
- WriteAsOperand(O, C, false, false, &M);
- O << "\n";
- emitGlobalConstant(C);
- }
- }
-
- delete Mang;
- return false; // success
-}
diff --git a/llvm/lib/Target/SparcV8/SparcV8CodeEmitter.cpp b/llvm/lib/Target/SparcV8/SparcV8CodeEmitter.cpp
deleted file mode 100644
index e1c1c0690017..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8CodeEmitter.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-//===-- SparcV8CodeEmitter.cpp - JIT Code Emitter for SparcV8 -----*- 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.
-//
-//===----------------------------------------------------------------------===//
-//
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcV8TargetMachine.h"
-
-namespace llvm {
-
-/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
-/// machine code emitted. This uses a MachineCodeEmitter object to handle
-/// actually outputting the machine code and resolving things like the address
-/// of functions. This method should returns true if machine code emission is
-/// not supported.
-///
-bool SparcV8TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
- MachineCodeEmitter &MCE) {
- return true;
- // It should go something like this:
- // PM.add(new Emitter(MCE)); // Machine code emitter pass for SparcV8
- // Delete machine code for this function after emitting it:
- // PM.add(createMachineCodeDeleter());
-}
-
-void *SparcV8JITInfo::getJITStubForFunction(Function *F,
- MachineCodeEmitter &MCE) {
- assert (0 && "SparcV8JITInfo::getJITStubForFunction not implemented");
- return 0;
-}
-
-void SparcV8JITInfo::replaceMachineCodeForFunction (void *Old, void *New) {
- assert (0 && "SparcV8JITInfo::replaceMachineCodeForFunction not implemented");
-}
-
-} // end llvm namespace
-
diff --git a/llvm/lib/Target/SparcV8/SparcV8InstrInfo.cpp b/llvm/lib/Target/SparcV8/SparcV8InstrInfo.cpp
deleted file mode 100644
index 64e225faf218..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8InstrInfo.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- SparcV8InstrInfo.cpp - SparcV8 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 contains the SparcV8 implementation of the TargetInstrInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcV8InstrInfo.h"
-#include "SparcV8.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "SparcV8GenInstrInfo.inc"
-using namespace llvm;
-
-SparcV8InstrInfo::SparcV8InstrInfo()
- : TargetInstrInfo(SparcV8Insts, sizeof(SparcV8Insts)/sizeof(SparcV8Insts[0])){
-}
-
-/// Return true if the instruction is a register to register move and
-/// leave the source and dest operands in the passed parameters.
-///
-bool SparcV8InstrInfo::isMoveInstr(const MachineInstr &MI,
- unsigned &SrcReg, unsigned &DstReg) const {
- if (MI.getOpcode() == V8::ORrr) {
- if (MI.getOperand(1).getReg() == V8::G0) { // X = or G0, Y -> X = Y
- DstReg = MI.getOperand(0).getReg();
- SrcReg = MI.getOperand(2).getReg();
- }
- return true;
- } else if (MI.getOpcode() == V8::FMOVS) {
- SrcReg = MI.getOperand(1).getReg();
- DstReg = MI.getOperand(0).getReg();
- return true;
- }
- return false;
-}
diff --git a/llvm/lib/Target/SparcV8/SparcV8InstrInfo.h b/llvm/lib/Target/SparcV8/SparcV8InstrInfo.h
deleted file mode 100644
index 9c7838dfdd7e..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8InstrInfo.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- SparcV8InstrInfo.h - SparcV8 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 contains the SparcV8 implementation of the TargetInstrInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARCV8INSTRUCTIONINFO_H
-#define SPARCV8INSTRUCTIONINFO_H
-
-#include "llvm/Target/TargetInstrInfo.h"
-#include "SparcV8RegisterInfo.h"
-
-namespace llvm {
-
-/// V8II - This namespace holds all of the target specific flags that
-/// instruction info tracks.
-///
-namespace V8II {
- enum {
- Pseudo = (1<<0),
- Load = (1<<1),
- Store = (1<<2),
- DelaySlot = (1<<3)
- };
-};
-
-class SparcV8InstrInfo : public TargetInstrInfo {
- const SparcV8RegisterInfo RI;
-public:
- SparcV8InstrInfo();
-
- /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
- /// such, whenever a client has an instance of instruction info, it should
- /// always be able to get register info as well (through this method).
- ///
- virtual const MRegisterInfo &getRegisterInfo() const { return RI; }
-
- /// Return true if the instruction is a register to register move and
- /// leave the source and dest operands in the passed parameters.
- ///
- virtual bool isMoveInstr(const MachineInstr &MI,
- unsigned &SrcReg, unsigned &DstReg) const;
-};
-
-}
-
-#endif
diff --git a/llvm/lib/Target/SparcV8/SparcV8InstrInfo.td b/llvm/lib/Target/SparcV8/SparcV8InstrInfo.td
deleted file mode 100644
index 07491eb1c10e..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8InstrInfo.td
+++ /dev/null
@@ -1,242 +0,0 @@
-//===- SparcV8Instrs.td - Target Description for SparcV8 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.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file describes the SparcV8 instructions in TableGen format.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Instruction format superclass
-//===----------------------------------------------------------------------===//
-
-class InstV8 : Instruction { // SparcV8 instruction baseline
- field bits<32> Inst;
-
- let Namespace = "V8";
-
- bits<2> op;
- let Inst{31-30} = op; // Top two bits are the 'op' field
-
- // Bit attributes specific to SparcV8 instructions
- bit isPasi = 0; // Does this instruction affect an alternate addr space?
- bit isPrivileged = 0; // Is this a privileged instruction?
-}
-
-include "SparcV8InstrInfo_F2.td"
-include "SparcV8InstrInfo_F3.td"
-
-//===----------------------------------------------------------------------===//
-// Instructions
-//===----------------------------------------------------------------------===//
-
-// Pseudo instructions.
-class PseudoInstV8<string nm> : InstV8 {
- let Name = nm;
-}
-def PHI : PseudoInstV8<"PHI">;
-def ADJCALLSTACKDOWN : PseudoInstV8<"ADJCALLSTACKDOWN">;
-def ADJCALLSTACKUP : PseudoInstV8<"ADJCALLSTACKUP">;
-def IMPLICIT_USE : PseudoInstV8<"IMPLICIT_USE">;
-def IMPLICIT_DEF : PseudoInstV8<"IMPLICIT_DEF">;
-
-// Section A.3 - Synthetic Instructions, p. 85
-// special cases of JMPL:
-let isReturn = 1, isTerminator = 1, simm13 = 8 in
- def RET : F3_2<2, 0b111000, "ret">;
-let isReturn = 1, isTerminator = 1, simm13 = 8 in
- def RETL: F3_2<2, 0b111000, "retl">;
-// CMP is a special case of SUBCC where destination is ignored, by setting it to
-// %g0 (hardwired zero).
-// FIXME: should keep track of the fact that it defs the integer condition codes
-let rd = 0 in
- def CMPri: F3_2<2, 0b010100, "cmp">;
-
-// Section B.1 - Load Integer Instructions, p. 90
-def LDSB: F3_2<3, 0b001001, "ldsb">;
-def LDSH: F3_2<3, 0b001010, "ldsh">;
-def LDUB: F3_2<3, 0b000001, "ldub">;
-def LDUH: F3_2<3, 0b000010, "lduh">;
-def LD : F3_2<3, 0b000000, "ld">;
-def LDD : F3_2<3, 0b000011, "ldd">;
-
-// Section B.2 - Load Floating-point Instructions, p. 92
-def LDFrr : F3_1<3, 0b100000, "ld">;
-def LDFri : F3_2<3, 0b100000, "ld">;
-def LDDFrr : F3_1<3, 0b100011, "ldd">;
-def LDDFri : F3_2<3, 0b100011, "ldd">;
-def LDFSRrr: F3_1<3, 0b100001, "ld">;
-def LDFSRri: F3_2<3, 0b100001, "ld">;
-
-// Section B.4 - Store Integer Instructions, p. 95
-def STB : F3_2<3, 0b000101, "stb">;
-def STH : F3_2<3, 0b000110, "sth">;
-def ST : F3_2<3, 0b000100, "st">;
-def STD : F3_2<3, 0b000111, "std">;
-
-// Section B.5 - Store Floating-point Instructions, p. 97
-def STFrr : F3_1<3, 0b100100, "st">;
-def STFri : F3_2<3, 0b100100, "st">;
-def STDFrr : F3_1<3, 0b100111, "std">;
-def STDFri : F3_2<3, 0b100111, "std">;
-def STFSRrr : F3_1<3, 0b100101, "st">;
-def STFSRri : F3_2<3, 0b100101, "st">;
-def STDFQrr : F3_1<3, 0b100110, "std">;
-def STDFQri : F3_2<3, 0b100110, "std">;
-
-// Section B.9 - SETHI Instruction, p. 104
-def SETHIi: F2_1<0b100, "sethi">;
-
-// Section B.10 - NOP Instruction, p. 105
-// (It's a special case of SETHI)
-let rd = 0, imm = 0 in
- def NOP : F2_1<0b100, "nop">;
-
-// Section B.11 - Logical Instructions, p. 106
-def ANDrr : F3_1<2, 0b000001, "and">;
-def ANDri : F3_2<2, 0b000001, "and">;
-def ORrr : F3_1<2, 0b000010, "or">;
-def ORri : F3_2<2, 0b000010, "or">;
-def XORrr : F3_1<2, 0b000011, "xor">;
-def XORri : F3_2<2, 0b000011, "xor">;
-
-// Section B.12 - Shift Instructions, p. 107
-def SLLrr : F3_1<2, 0b100101, "sll">;
-def SLLri : F3_2<2, 0b100101, "sll">;
-def SRLrr : F3_1<2, 0b100110, "srl">;
-def SRLri : F3_2<2, 0b100110, "srl">;
-def SRArr : F3_1<2, 0b100111, "sra">;
-def SRAri : F3_2<2, 0b100111, "sra">;
-
-// Section B.13 - Add Instructions, p. 108
-def ADDrr : F3_1<2, 0b000000, "add">;
-def ADDri : F3_2<2, 0b000000, "add">;
-
-// Section B.15 - Subtract Instructions, p. 110
-def SUBrr : F3_1<2, 0b000100, "sub">;
-def SUBCCrr : F3_1<2, 0b010100, "subcc">;
-def SUBCCri : F3_2<2, 0b010100, "subcc">;
-
-// Section B.18 - Multiply Instructions, p. 113
-def UMULrr : F3_1<2, 0b001010, "umul">;
-def SMULrr : F3_1<2, 0b001011, "smul">;
-
-// Section B.19 - Divide Instructions, p. 115
-def UDIVrr : F3_1<2, 0b001110, "udiv">;
-def UDIVri : F3_2<2, 0b001110, "udiv">;
-def SDIVrr : F3_1<2, 0b001111, "sdiv">;
-def SDIVri : F3_2<2, 0b001111, "sdiv">;
-def UDIVCCrr : F3_1<2, 0b011110, "udivcc">;
-def UDIVCCri : F3_2<2, 0b011110, "udivcc">;
-def SDIVCCrr : F3_1<2, 0b011111, "sdivcc">;
-def SDIVCCri : F3_2<2, 0b011111, "sdivcc">;
-
-// Section B.20 - SAVE and RESTORE, p. 117
-def SAVErr : F3_1<2, 0b111100, "save">; // save r, r, r
-def SAVEri : F3_2<2, 0b111100, "save">; // save r, i, r
-def RESTORErr : F3_1<2, 0b111101, "restore">; // restore r, r, r
-def RESTOREri : F3_2<2, 0b111101, "restore">; // restore r, i, r
-
-// Section B.21 - Branch on Integer Condition Codes Instructions, p. 119
-
-// conditional branch class:
-class BranchV8<bits<4> cc, string nm> : F2_2<cc, 0b010, nm> {
- let isBranch = 1;
- let isTerminator = 1;
-}
-
-let isBarrier = 1 in
- def BA : BranchV8<0b1000, "ba">;
-def BN : BranchV8<0b0000, "bn">;
-def BNE : BranchV8<0b1001, "bne">;
-def BE : BranchV8<0b0001, "be">;
-def BG : BranchV8<0b1010, "bg">;
-def BLE : BranchV8<0b0010, "ble">;
-def BGE : BranchV8<0b1011, "bge">;
-def BL : BranchV8<0b0011, "bl">;
-def BGU : BranchV8<0b1100, "bgu">;
-def BLEU : BranchV8<0b0100, "bleu">;
-def BCC : BranchV8<0b1101, "bcc">;
-def BCS : BranchV8<0b0101, "bcs">;
-
-// Section B.22 - Branch on Floating-point Condition Codes Instructions, p. 121
-
-// floating-point conditional branch class:
-class FPBranchV8<bits<4> cc, string nm> : F2_2<cc, 0b110, nm> {
- let isBranch = 1;
- let isTerminator = 1;
-}
-
-def FBA : FPBranchV8<0b1000, "fba">;
-def FBN : FPBranchV8<0b0000, "fbn">;
-def FBU : FPBranchV8<0b0111, "fbu">;
-def FBG : FPBranchV8<0b0110, "fbg">;
-def FBUG : FPBranchV8<0b0101, "fbug">;
-def FBL : FPBranchV8<0b0100, "fbl">;
-def FBUL : FPBranchV8<0b0011, "fbul">;
-def FBLG : FPBranchV8<0b0010, "fblg">;
-def FBNE : FPBranchV8<0b0001, "fbne">;
-def FBE : FPBranchV8<0b1001, "fbe">;
-def FBUE : FPBranchV8<0b1010, "fbue">;
-def FBGE : FPBranchV8<0b1011, "fbge">;
-def FBUGE: FPBranchV8<0b1100, "fbuge">;
-def FBLE : FPBranchV8<0b1101, "fble">;
-def FBULE: FPBranchV8<0b1110, "fbule">;
-def FBO : FPBranchV8<0b1111, "fbo">;
-
-// Section B.24 - Call and Link Instruction, p. 125
-// This is the only Format 1 instruction
-def CALL : InstV8 {
- bits<30> disp;
- let op = 1;
- let Inst{29-0} = disp;
- let Name = "call";
- let isCall = 1;
-}
-
-// Section B.25 - Jump and Link, p. 126
-let isCall = 1 in
- def JMPLrr : F3_1<2, 0b111000, "jmpl">; // jmpl [rs1+rs2], rd
-
-// Section B.29 - Write State Register Instructions
-def WRrr : F3_1<2, 0b110000, "wr">; // wr rs1, rs2, rd
-def WRri : F3_2<2, 0b110000, "wr">; // wr rs1, imm, rd
-
-// Convert Integer to Floating-point Instructions, p. 141
-def FITOS : F3_3<2, 0b110100, 0b011000100, "fitos">;
-def FITOD : F3_3<2, 0b110100, 0b011001000, "fitos">;
-
-// Convert between Floating-point Formats Instructions, p. 143
-def FSTOD : F3_3<2, 0b110100, 0b011001001, "fstod">;
-def FDTOS : F3_3<2, 0b110100, 0b011000110, "fdtos">;
-
-// Floating-point Move Instructions, p. 144
-def FMOVS : F3_3<2, 0b110100, 0b000000001, "fmovs">;
-def FNEGS : F3_3<2, 0b110100, 0b000000101, "fnegs">;
-def FABSS : F3_3<2, 0b110100, 0b000001001, "fabss">;
-
-// Floating-point Add and Subtract Instructions, p. 146
-def FADDS : F3_3<2, 0b110100, 0b001000001, "fadds">;
-def FADDD : F3_3<2, 0b110100, 0b001000010, "faddd">;
-def FSUBS : F3_3<2, 0b110100, 0b001000101, "fsubs">;
-def FSUBD : F3_3<2, 0b110100, 0b001000110, "fsubd">;
-
-// Floating-point Multiply and Divide Instructions, p. 147
-def FMULS : F3_3<2, 0b110100, 0b001001001, "fmuls">;
-def FMULD : F3_3<2, 0b110100, 0b001001010, "fmuld">;
-def FSMULD : F3_3<2, 0b110100, 0b001101001, "fsmuld">;
-def FDIVS : F3_3<2, 0b110100, 0b001001101, "fdivs">;
-def FDIVD : F3_3<2, 0b110100, 0b001001110, "fdivd">;
-
-// Floating-point Compare Instructions, p. 148
-// Note: the 2nd template arg is different for these guys
-def FCMPS : F3_3<2, 0b110101, 0b001010001, "fcmps">;
-def FCMPD : F3_3<2, 0b110101, 0b001010010, "fcmpd">;
-def FCMPES : F3_3<2, 0b110101, 0b001010101, "fcmpes">;
-def FCMPED : F3_3<2, 0b110101, 0b001010110, "fcmped">;
-
diff --git a/llvm/lib/Target/SparcV8/SparcV8InstrInfo_F2.td b/llvm/lib/Target/SparcV8/SparcV8InstrInfo_F2.td
deleted file mode 100644
index 7b550bd7ddf7..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8InstrInfo_F2.td
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- SparcV8Instrs_F2.td - Format 2 instructions: SparcV8 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 instruction classes in the SparcV8
-//
-//===----------------------------------------------------------------------===//
-
-class F2 : InstV8 { // Format 2 instructions
- bits<3> op2;
- bits<22> imm22;
- let op = 0; // op = 0
- let Inst{24-22} = op2;
- let Inst{21-0} = imm22;
-}
-
-// Specific F2 classes: SparcV8 manual, page 44
-//
-class F2_1<bits<3> op2Val, string name> : F2 {
- bits<5> rd;
- bits<22> imm;
-
- let op2 = op2Val;
- let Name = name;
-
- let Inst{29-25} = rd;
-}
-
-class F2_2<bits<4> condVal, bits<3> op2Val, string name> : F2 {
- bits<4> cond;
- bit annul = 0; // currently unused
-
- let cond = condVal;
- let op2 = op2Val;
- let Name = name;
-
- let Inst{29} = annul;
- let Inst{28-25} = cond;
-}
diff --git a/llvm/lib/Target/SparcV8/SparcV8InstrInfo_F3.td b/llvm/lib/Target/SparcV8/SparcV8InstrInfo_F3.td
deleted file mode 100644
index 4906b9de04d3..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8InstrInfo_F3.td
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- SparcV8Instrs_F3.td - Format 3 Instructions: SparcV8 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 instruction classes in the SparcV8
-//
-//===----------------------------------------------------------------------===//
-
-class F3 : InstV8 {
- bits<5> rd;
- bits<6> op3;
- bits<5> rs1;
- let op{1} = 1; // Op = 2 or 3
- let Inst{29-25} = rd;
- let Inst{24-19} = op3;
- let Inst{18-14} = rs1;
-}
-
-// Specific F3 classes: SparcV8 manual, page 44
-//
-class F3_1<bits<2> opVal, bits<6> op3val, string name> : F3 {
- bits<8> asi;
- bits<5> rs2;
-
- let op = opVal;
- let op3 = op3val;
- let Name = name;
-
- let Inst{13} = 0; // i field = 0
- let Inst{12-5} = asi; // address space identifier
- let Inst{4-0} = rs2;
-}
-
-class F3_2<bits<2> opVal, bits<6> op3val, string name> : F3 {
- bits<13> simm13;
-
- let op = opVal;
- let op3 = op3val;
- let Name = name;
-
- let Inst{13} = 1; // i field = 1
- let Inst{12-0} = simm13;
-}
-
-// floating-point
-class F3_3<bits<2> opVal, bits<6> op3val, bits<9> opfval, string name> : F3 {
- bits<8> asi;
- bits<5> rs2;
-
- let op = opVal;
- let op3 = op3val;
- let Name = name;
-
- let Inst{13-5} = opfval; // fp opcode
- let Inst{4-0} = rs2;
-}
diff --git a/llvm/lib/Target/SparcV8/SparcV8JITInfo.h b/llvm/lib/Target/SparcV8/SparcV8JITInfo.h
deleted file mode 100644
index db866a0af775..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8JITInfo.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===- SparcV8JITInfo.h - SparcV8 impl. 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 SparcV8 implementation of the TargetJITInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARCV8JITINFO_H
-#define SPARCV8JITINFO_H
-
-#include "llvm/Target/TargetJITInfo.h"
-
-namespace llvm {
- class TargetMachine;
- class IntrinsicLowering;
-
- class SparcV8JITInfo : public TargetJITInfo {
- TargetMachine &TM;
- public:
- SparcV8JITInfo(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/SparcV8/SparcV8RegisterInfo.cpp b/llvm/lib/Target/SparcV8/SparcV8RegisterInfo.cpp
deleted file mode 100644
index 918b39419e0e..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8RegisterInfo.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-//===- SparcV8RegisterInfo.cpp - SparcV8 Register 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 contains the SparcV8 implementation of the MRegisterInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcV8.h"
-#include "SparcV8RegisterInfo.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/Type.h"
-#include "Support/STLExtras.h"
-#include <iostream>
-using namespace llvm;
-
-SparcV8RegisterInfo::SparcV8RegisterInfo()
- : SparcV8GenRegisterInfo(V8::ADJCALLSTACKDOWN,
- V8::ADJCALLSTACKUP) {}
-
-int SparcV8RegisterInfo::storeRegToStackSlot(
- MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned SrcReg, int FrameIdx,
- const TargetRegisterClass *RC) const
-{
- // On the order of operands here: think "[FrameIdx + 0] = SrcReg".
- if (RC == SparcV8::IntRegsRegisterClass)
- BuildMI (MBB, I, V8::ST, 3).addFrameIndex (FrameIdx).addSImm (0)
- .addReg (SrcReg);
- else if (RC == SparcV8::FPRegsRegisterClass)
- BuildMI (MBB, I, V8::STFri, 3).addFrameIndex (FrameIdx).addSImm (0)
- .addReg (SrcReg);
- else if (RC == SparcV8::DFPRegsRegisterClass)
- BuildMI (MBB, I, V8::STDFri, 3).addFrameIndex (FrameIdx).addSImm (0)
- .addReg (SrcReg);
- else
- assert (0 && "Can't store this register to stack slot");
- return 1;
-}
-
-int SparcV8RegisterInfo::loadRegFromStackSlot(
- MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned DestReg, int FrameIdx,
- const TargetRegisterClass *RC) const
-{
- if (RC == SparcV8::IntRegsRegisterClass)
- BuildMI (MBB, I, V8::LD, 2, DestReg).addFrameIndex (FrameIdx).addSImm (0);
- else if (RC == SparcV8::FPRegsRegisterClass)
- BuildMI (MBB, I, V8::LDFri, 2, DestReg).addFrameIndex (FrameIdx)
- .addSImm (0);
- else if (RC == SparcV8::DFPRegsRegisterClass)
- BuildMI (MBB, I, V8::LDDFri, 2, DestReg).addFrameIndex (FrameIdx)
- .addSImm (0);
- else
- assert (0 && "Can't load this register from stack slot");
- return 1;
-}
-
-int SparcV8RegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned DestReg, unsigned SrcReg,
- const TargetRegisterClass *RC) const {
- if (RC == SparcV8::IntRegsRegisterClass)
- BuildMI (MBB, I, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (SrcReg);
- else if (RC == SparcV8::FPRegsRegisterClass)
- BuildMI (MBB, I, V8::FMOVS, 1, DestReg).addReg (SrcReg);
- else
- assert (0 && "Can't copy this register");
- return 1;
-}
-
-void SparcV8RegisterInfo::
-eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I) const {
- std::cerr
- << "Sorry, I don't know how to eliminate call frame pseudo instrs yet, in\n"
- << __FUNCTION__ << " at " << __FILE__ << ":" << __LINE__ << "\n";
- abort();
-}
-
-void
-SparcV8RegisterInfo::eliminateFrameIndex(MachineFunction &MF,
- MachineBasicBlock::iterator II) const {
- unsigned i = 0;
- MachineInstr &MI = *II;
- while (!MI.getOperand(i).isFrameIndex()) {
- ++i;
- assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
- }
-
- int FrameIndex = MI.getOperand(i).getFrameIndex();
-
- // Replace frame index with a frame pointer reference
- MI.SetMachineOperandReg (i, V8::FP);
-
- // Addressable stack objects are accessed using neg. offsets from %fp
- int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
- MI.getOperand(i+1).getImmedValue();
- // note: Offset < 0
- MI.SetMachineOperandConst (i+1, MachineOperand::MO_SignExtendedImmed, Offset);
-}
-
-void SparcV8RegisterInfo::
-processFunctionBeforeFrameFinalized(MachineFunction &MF) const {}
-
-void SparcV8RegisterInfo::emitPrologue(MachineFunction &MF) const {
- MachineBasicBlock &MBB = MF.front();
- MachineFrameInfo *MFI = MF.getFrameInfo();
-
- // Get the number of bytes to allocate from the FrameInfo
- int NumBytes = (int) MFI->getStackSize();
-
- // Emit the correct save instruction based on the number of bytes in the frame.
- // Minimum stack frame size according to V8 ABI is:
- // 16 words for register window spill
- // 1 word for address of returned aggregate-value
- // + 6 words for passing parameters on the stack
- // ----------
- // 23 words * 4 bytes per word = 92 bytes
- NumBytes += 92;
- // Round up to next doubleword boundary -- a double-word boundary
- // is required by the ABI.
- NumBytes = (NumBytes + 7) & ~7;
- BuildMI(MBB, MBB.begin(), V8::SAVEri, 2,
- V8::SP).addImm(-NumBytes).addReg(V8::SP);
-}
-
-void SparcV8RegisterInfo::emitEpilogue(MachineFunction &MF,
- MachineBasicBlock &MBB) const {
- MachineBasicBlock::iterator MBBI = prior(MBB.end());
- assert(MBBI->getOpcode() == V8::RETL &&
- "Can only put epilog before 'retl' instruction!");
- BuildMI(MBB, MBBI, V8::RESTORErr, 2, V8::G0).addReg(V8::G0).addReg(V8::G0);
-}
-
-#include "SparcV8GenRegisterInfo.inc"
-
-const TargetRegisterClass*
-SparcV8RegisterInfo::getRegClassForType(const Type* Ty) const {
- switch (Ty->getTypeID()) {
- case Type::FloatTyID: return &FPRegsInstance;
- case Type::DoubleTyID: return &DFPRegsInstance;
- case Type::LongTyID:
- case Type::ULongTyID: assert(0 && "Long values do not fit in registers!");
- default: assert(0 && "Invalid type to getClass!");
- case Type::BoolTyID:
- case Type::SByteTyID:
- case Type::UByteTyID:
- case Type::ShortTyID:
- case Type::UShortTyID:
- case Type::IntTyID:
- case Type::UIntTyID:
- case Type::PointerTyID: return &IntRegsInstance;
- }
-}
-
diff --git a/llvm/lib/Target/SparcV8/SparcV8RegisterInfo.h b/llvm/lib/Target/SparcV8/SparcV8RegisterInfo.h
deleted file mode 100644
index 85ea576872e5..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8RegisterInfo.h
+++ /dev/null
@@ -1,58 +0,0 @@
-//===- SparcV8RegisterInfo.h - SparcV8 Register Information Impl -*- 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 SparcV8 implementation of the MRegisterInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARCV8REGISTERINFO_H
-#define SPARCV8REGISTERINFO_H
-
-#include "llvm/Target/MRegisterInfo.h"
-#include "SparcV8GenRegisterInfo.h.inc"
-
-namespace llvm {
-
-class Type;
-
-struct SparcV8RegisterInfo : public SparcV8GenRegisterInfo {
- SparcV8RegisterInfo();
- const TargetRegisterClass* getRegClassForType(const Type* Ty) const;
-
- /// Code Generation virtual methods...
- int storeRegToStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- unsigned SrcReg, int FrameIndex,
- const TargetRegisterClass *RC) const;
-
- int loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- unsigned DestReg, int FrameIndex,
- const TargetRegisterClass *RC) const;
-
- int copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
- unsigned DestReg, unsigned SrcReg,
- const TargetRegisterClass *RC) const;
-
- void eliminateCallFramePseudoInstr(MachineFunction &MF,
- MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I) const;
-
- void eliminateFrameIndex(MachineFunction &MF,
- MachineBasicBlock::iterator II) const;
-
- void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
-
- void emitPrologue(MachineFunction &MF) const;
- void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/llvm/lib/Target/SparcV8/SparcV8RegisterInfo.td b/llvm/lib/Target/SparcV8/SparcV8RegisterInfo.td
deleted file mode 100644
index ccbdb2054acc..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8RegisterInfo.td
+++ /dev/null
@@ -1,111 +0,0 @@
-//===- SparcV8Reg.td - Describe the SparcV8 Register File -------*- 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.
-//
-//===----------------------------------------------------------------------===//
-//
-// Declarations that describe the SparcV8 register file
-//
-//===----------------------------------------------------------------------===//
-
-// Registers are identified with 5-bit ID numbers.
-// Ri - 32-bit integer registers
-class Ri<bits<5> num> : Register {
- field bits<5> Num = num;
-}
-// Rf - 32-bit floating-point registers
-class Rf<bits<5> num> : Register {
- field bits<5> Num = num;
-}
-// Rd - Slots in the FP register file for 64-bit floating-point values.
-class Rd<bits<5> num, string realName> : Register {
- field bits<5> Num = num;
- let Name = realName;
-}
-// Rs - Special "ancillary state registers" registers, like the Y, ASR, PSR,
-// WIM, TBR, etc registers
-class Rs<bits<5> num> : Register {
- field bits<5> Num = num;
-}
-
-let Namespace = "V8" 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>;
-
- // Standard register aliases.
- def SP : Ri<14>; def FP : Ri<30>;
-
- // Floating-point registers:
- def F0 : Rf< 0>; def F1 : Rf< 1>; def F2 : Rf< 2>; def F3 : Rf< 3>;
- def F4 : Rf< 4>; def F5 : Rf< 5>; def F6 : Rf< 6>; def F7 : Rf< 7>;
- def F8 : Rf< 8>; def F9 : Rf< 9>; def F10 : Rf<10>; def F11 : Rf<11>;
- def F12 : Rf<12>; def F13 : Rf<13>; def F14 : Rf<14>; def F15 : Rf<15>;
- def F16 : Rf<16>; def F17 : Rf<17>; def F18 : Rf<18>; def F19 : Rf<19>;
- def F20 : Rf<20>; def F21 : Rf<21>; def F22 : Rf<22>; def F23 : Rf<23>;
- def F24 : Rf<24>; def F25 : Rf<25>; def F26 : Rf<26>; def F27 : Rf<27>;
- def F28 : Rf<28>; def F29 : Rf<29>; def F30 : Rf<30>; def F31 : Rf<31>;
-
- // Aliases of the F* registers used to hold 64-bit fp values (doubles).
- def D0 : Rd< 0, "F0">; def D1 : Rd< 2, "F2">; def D2 : Rd< 4, "F4">;
- def D3 : Rd< 6, "F6">; def D4 : Rd< 8, "F8">; def D5 : Rd<10, "F10">;
- def D6 : Rd<12, "F12">; def D7 : Rd<14, "F14">; def D8 : Rd<16, "F16">;
- def D9 : Rd<18, "F18">; def D10 : Rd<20, "F20">; def D11 : Rd<22, "F22">;
- def D12 : Rd<24, "F24">; def D13 : Rd<26, "F26">; def D14 : Rd<28, "F28">;
- def D15 : Rd<30, "F30">;
-
- // The Y register.
- def Y : Rs<0>;
-}
-
-// Register classes.
-//
-// FIXME: the register order should be defined in terms of the preferred
-// allocation order...
-//
-def IntRegs : RegisterClass<i32, 8, [L0, L1, L2, L3, L4, L5, L6, L7,
- I0, I1, I2, I3, I4, I5,
- G1, G2, G3, G4, G5, G6, G7,
- O0, O1, O2, O3, O4, O5, O7,
- // Non-allocatable regs
- O6, I6, I7, G0]> {
- let Methods = [{
- iterator allocation_order_end(MachineFunction &MF) const {
- return end()-4; // Don't allocate special registers
- }
- }];
-}
-
-def FPRegs : RegisterClass<f32, 4, [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]>;
-
-def DFPRegs : RegisterClass<f64, 8, [D0, D1, D2, D3, D4, D5, D6, D7,
- D8, D9, D10, D11, D12, D13, D14, D15]>;
-
-// Tell the register file generator that the double-fp pseudo-registers
-// alias the registers used for single-fp values.
-def : RegisterAliases<D0, [F0, F1]>;
-def : RegisterAliases<D1, [F2, F3]>;
-def : RegisterAliases<D2, [F4, F5]>;
-def : RegisterAliases<D3, [F6, F7]>;
-def : RegisterAliases<D4, [F8, F9]>;
-def : RegisterAliases<D5, [F10, F11]>;
-def : RegisterAliases<D6, [F12, F13]>;
-def : RegisterAliases<D7, [F14, F15]>;
-def : RegisterAliases<D8, [F16, F17]>;
-def : RegisterAliases<D9, [F18, F19]>;
-def : RegisterAliases<D10, [F20, F21]>;
-def : RegisterAliases<D11, [F22, F23]>;
-def : RegisterAliases<D12, [F24, F25]>;
-def : RegisterAliases<D13, [F26, F27]>;
-def : RegisterAliases<D14, [F28, F29]>;
-def : RegisterAliases<D15, [F30, F31]>;
diff --git a/llvm/lib/Target/SparcV8/SparcV8TargetMachine.cpp b/llvm/lib/Target/SparcV8/SparcV8TargetMachine.cpp
deleted file mode 100644
index 63da5af51e6b..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8TargetMachine.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-//===-- SparcV8TargetMachine.cpp - Define TargetMachine for SparcV8 -------===//
-//
-// 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 "SparcV8TargetMachine.h"
-#include "SparcV8.h"
-#include "llvm/Module.h"
-#include "llvm/PassManager.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetMachineRegistry.h"
-#include "llvm/Transforms/Scalar.h"
-#include <iostream>
-using namespace llvm;
-
-namespace {
- // Register the target.
- RegisterTarget<SparcV8TargetMachine> X("sparcv8"," SPARC V8 (experimental)");
-}
-
-/// SparcV8TargetMachine ctor - Create an ILP32 architecture model
-///
-SparcV8TargetMachine::SparcV8TargetMachine(const Module &M,
- IntrinsicLowering *IL)
- : TargetMachine("SparcV8", IL, true, 4, 4, 4, 4, 4),
- FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 0), JITInfo(*this) {
-}
-
-/// addPassesToEmitAssembly - Add passes to the specified pass manager
-/// to implement a static compiler for this target.
-///
-bool SparcV8TargetMachine::addPassesToEmitAssembly(PassManager &PM,
- std::ostream &Out) {
- // FIXME: Implement efficient support for garbage collection intrinsics.
- PM.add(createLowerGCPass());
-
- // Replace malloc and free instructions with library calls.
- PM.add(createLowerAllocationsPass());
-
- // FIXME: implement the select instruction in the instruction selector.
- PM.add(createLowerSelectPass());
-
- // FIXME: implement the switch instruction in the instruction selector.
- PM.add(createLowerSwitchPass());
-
- // FIXME: implement the invoke/unwind instructions!
- PM.add(createLowerInvokePass());
-
- PM.add(createLowerConstantExpressionsPass());
-
- // Make sure that no unreachable blocks are instruction selected.
- PM.add(createUnreachableBlockEliminationPass());
-
- PM.add(createSparcV8SimpleInstructionSelector(*this));
-
- // Print machine instructions as they were initially generated.
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
-
- PM.add(createRegisterAllocator());
- PM.add(createPrologEpilogCodeInserter());
-
- // Print machine instructions after register allocation and prolog/epilog
- // insertion.
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
-
- PM.add(createSparcV8DelaySlotFillerPass(*this));
-
- // Print machine instructions after filling delay slots.
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
-
- // Output assembly language.
- PM.add(createSparcV8CodePrinterPass(Out, *this));
-
- // Delete the MachineInstrs we generated, since they're no longer needed.
- PM.add(createMachineCodeDeleter());
- return false;
-}
-
-/// addPassesToJITCompile - Add passes to the specified pass manager to
-/// implement a fast dynamic compiler for this target.
-///
-void SparcV8JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
- // FIXME: Implement efficient support for garbage collection intrinsics.
- PM.add(createLowerGCPass());
-
- // Replace malloc and free instructions with library calls.
- PM.add(createLowerAllocationsPass());
-
- // FIXME: implement the select instruction in the instruction selector.
- PM.add(createLowerSelectPass());
-
- // FIXME: implement the switch instruction in the instruction selector.
- PM.add(createLowerSwitchPass());
-
- // FIXME: implement the invoke/unwind instructions!
- PM.add(createLowerInvokePass());
-
- PM.add(createLowerConstantExpressionsPass());
-
- // Make sure that no unreachable blocks are instruction selected.
- PM.add(createUnreachableBlockEliminationPass());
-
- PM.add(createSparcV8SimpleInstructionSelector(TM));
-
- // Print machine instructions as they were initially generated.
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
-
- PM.add(createRegisterAllocator());
- PM.add(createPrologEpilogCodeInserter());
-
- // Print machine instructions after register allocation and prolog/epilog
- // insertion.
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
-
- PM.add(createSparcV8DelaySlotFillerPass(TM));
-
- // Print machine instructions after filling delay slots.
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
-}
diff --git a/llvm/lib/Target/SparcV8/SparcV8TargetMachine.h b/llvm/lib/Target/SparcV8/SparcV8TargetMachine.h
deleted file mode 100644
index cbb8e043dd16..000000000000
--- a/llvm/lib/Target/SparcV8/SparcV8TargetMachine.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//===-- SparcV8TargetMachine.h - Define TargetMachine for SparcV8 -*- 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 SparcV8 specific subclass of TargetMachine.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARCV8TARGETMACHINE_H
-#define SPARCV8TARGETMACHINE_H
-
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetFrameInfo.h"
-#include "llvm/PassManager.h"
-#include "SparcV8InstrInfo.h"
-#include "SparcV8JITInfo.h"
-
-namespace llvm {
-
-class IntrinsicLowering;
-
-class SparcV8TargetMachine : public TargetMachine {
- SparcV8InstrInfo InstrInfo;
- TargetFrameInfo FrameInfo;
- SparcV8JITInfo JITInfo;
-public:
- SparcV8TargetMachine(const Module &M, IntrinsicLowering *IL);
-
- virtual const SparcV8InstrInfo *getInstrInfo() const { return &InstrInfo; }
- virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
- virtual const MRegisterInfo *getRegisterInfo() const {
- return &InstrInfo.getRegisterInfo();
- }
- virtual TargetJITInfo *getJITInfo() {
- return &JITInfo;
- }
-
- /// addPassesToEmitMachineCode - Add passes to the specified pass manager to
- /// get machine code emitted. This uses a MachineCodeEmitter object to handle
- /// actually outputting the machine code and resolving things like the address
- /// of functions. This method should returns true if machine code emission is
- /// not supported.
- ///
- virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM,
- MachineCodeEmitter &MCE);
-
- virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
-};
-
-} // end namespace llvm
-
-#endif