summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-10-15 16:26:17 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-10-15 16:26:17 +0000
commit1adacceba9c9ee0f16e54388e56c9a249b296f75 (patch)
treefbc3e1401bc9623b861166be5940c750f5ca52da /lib
parent5effb5c6a161c1bdbdd9585dfdc97a6105e3df66 (diff)
downloadFreeBSD-src-1adacceba9c9ee0f16e54388e56c9a249b296f75.zip
FreeBSD-src-1adacceba9c9ee0f16e54388e56c9a249b296f75.tar.gz
Delete all stale files.
Diffstat (limited to 'lib')
-rw-r--r--lib/Analysis/LoopVR.cpp291
-rw-r--r--lib/CodeGen/LazyLiveness.cpp167
-rw-r--r--lib/CodeGen/PBQP.cpp1395
-rw-r--r--lib/CodeGen/PBQP.h284
-rw-r--r--lib/CodeGen/RegAllocBigBlock.cpp892
-rw-r--r--lib/CodeGen/RegAllocSimple.cpp257
-rw-r--r--lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp671
-rw-r--r--lib/Debugger/CMakeLists.txt10
-rw-r--r--lib/Debugger/Debugger.cpp231
-rw-r--r--lib/Debugger/Makefile16
-rw-r--r--lib/Debugger/ProgramInfo.cpp375
-rw-r--r--lib/Debugger/README.txt7
-rw-r--r--lib/Debugger/RuntimeInfo.cpp69
-rw-r--r--lib/Debugger/SourceFile.cpp82
-rw-r--r--lib/Debugger/SourceLanguage-CFamily.cpp28
-rw-r--r--lib/Debugger/SourceLanguage-CPlusPlus.cpp27
-rw-r--r--lib/Debugger/SourceLanguage-Unknown.cpp138
-rw-r--r--lib/Debugger/SourceLanguage.cpp54
-rw-r--r--lib/Support/Annotation.cpp130
-rw-r--r--lib/Support/Streams.cpp30
-rw-r--r--lib/System/LICENSE.TXT6
-rw-r--r--lib/Target/ARM/ARMTargetAsmInfo.cpp254
-rw-r--r--lib/Target/ARM/ARMTargetAsmInfo.h63
-rw-r--r--lib/Target/Alpha/AlphaTargetAsmInfo.cpp31
-rw-r--r--lib/Target/Alpha/AlphaTargetAsmInfo.h32
-rw-r--r--lib/Target/CellSPU/SPUTargetAsmInfo.cpp73
-rw-r--r--lib/Target/CellSPU/SPUTargetAsmInfo.h51
-rw-r--r--lib/Target/DarwinTargetAsmInfo.cpp216
-rw-r--r--lib/Target/ELFTargetAsmInfo.cpp227
-rw-r--r--lib/Target/IA64/AsmPrinter/CMakeLists.txt9
-rw-r--r--lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp389
-rw-r--r--lib/Target/IA64/AsmPrinter/Makefile17
-rw-r--r--lib/Target/IA64/CMakeLists.txt22
-rw-r--r--lib/Target/IA64/IA64.h57
-rw-r--r--lib/Target/IA64/IA64.td39
-rw-r--r--lib/Target/IA64/IA64Bundling.cpp118
-rw-r--r--lib/Target/IA64/IA64ISelDAGToDAG.cpp575
-rw-r--r--lib/Target/IA64/IA64ISelLowering.cpp632
-rw-r--r--lib/Target/IA64/IA64ISelLowering.h78
-rw-r--r--lib/Target/IA64/IA64InstrBuilder.h40
-rw-r--r--lib/Target/IA64/IA64InstrFormats.td80
-rw-r--r--lib/Target/IA64/IA64InstrInfo.cpp193
-rw-r--r--lib/Target/IA64/IA64InstrInfo.h70
-rw-r--r--lib/Target/IA64/IA64InstrInfo.td751
-rw-r--r--lib/Target/IA64/IA64MachineFunctionInfo.h34
-rw-r--r--lib/Target/IA64/IA64RegisterInfo.cpp319
-rw-r--r--lib/Target/IA64/IA64RegisterInfo.h63
-rw-r--r--lib/Target/IA64/IA64RegisterInfo.td509
-rw-r--r--lib/Target/IA64/IA64Subtarget.cpp18
-rw-r--r--lib/Target/IA64/IA64Subtarget.h28
-rw-r--r--lib/Target/IA64/IA64TargetAsmInfo.cpp44
-rw-r--r--lib/Target/IA64/IA64TargetAsmInfo.h33
-rw-r--r--lib/Target/IA64/IA64TargetMachine.cpp97
-rw-r--r--lib/Target/IA64/IA64TargetMachine.h75
-rw-r--r--lib/Target/IA64/Makefile20
-rw-r--r--lib/Target/IA64/README48
-rw-r--r--lib/Target/MSP430/MSP430AsmPrinter.cpp262
-rw-r--r--lib/Target/MSP430/MSP430TargetAsmInfo.cpp22
-rw-r--r--lib/Target/MSP430/MSP430TargetAsmInfo.h31
-rw-r--r--lib/Target/Mips/MipsTargetAsmInfo.cpp98
-rw-r--r--lib/Target/Mips/MipsTargetAsmInfo.h51
-rw-r--r--lib/Target/PIC16/PIC16AsmPrinter.cpp442
-rw-r--r--lib/Target/PIC16/PIC16AsmPrinter.h70
-rw-r--r--lib/Target/PIC16/PIC16TargetAsmInfo.cpp264
-rw-r--r--lib/Target/PIC16/PIC16TargetAsmInfo.h83
-rw-r--r--lib/Target/PowerPC/PPCTargetAsmInfo.cpp121
-rw-r--r--lib/Target/PowerPC/PPCTargetAsmInfo.h62
-rw-r--r--lib/Target/Sparc/SparcTargetAsmInfo.cpp50
-rw-r--r--lib/Target/Sparc/SparcTargetAsmInfo.h33
-rw-r--r--lib/Target/TargetAsmInfo.cpp456
-rw-r--r--lib/Target/TargetMachineRegistry.cpp78
-rw-r--r--lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp1108
-rw-r--r--lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h226
-rw-r--r--lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp633
-rw-r--r--lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h162
-rw-r--r--lib/Target/X86/X86TargetAsmInfo.cpp429
-rw-r--r--lib/Target/X86/X86TargetAsmInfo.h75
-rw-r--r--lib/Target/XCore/XCoreAsmPrinter.cpp438
-rw-r--r--lib/Target/XCore/XCoreTargetAsmInfo.cpp202
-rw-r--r--lib/Target/XCore/XCoreTargetAsmInfo.h45
-rw-r--r--lib/Transforms/Scalar/GVNPRE.cpp1892
-rw-r--r--lib/Transforms/Scalar/PredicateSimplifier.cpp2721
-rw-r--r--lib/Transforms/Utils/CloneTrace.cpp119
-rw-r--r--lib/Transforms/Utils/InlineCost.cpp315
84 files changed, 0 insertions, 20953 deletions
diff --git a/lib/Analysis/LoopVR.cpp b/lib/Analysis/LoopVR.cpp
deleted file mode 100644
index ae715ac..0000000
--- a/lib/Analysis/LoopVR.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-//===- LoopVR.cpp - Value Range analysis driven by loop information -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// FIXME: What does this do?
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "loopvr"
-#include "llvm/Analysis/LoopVR.h"
-#include "llvm/Constants.h"
-#include "llvm/Instructions.h"
-#include "llvm/Analysis/ScalarEvolutionExpressions.h"
-#include "llvm/Assembly/Writer.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-char LoopVR::ID = 0;
-static RegisterPass<LoopVR> X("loopvr", "Loop Value Ranges", false, true);
-
-/// getRange - determine the range for a particular SCEV within a given Loop
-ConstantRange LoopVR::getRange(const SCEV* S, Loop *L, ScalarEvolution &SE) {
- const SCEV* T = SE.getBackedgeTakenCount(L);
- if (isa<SCEVCouldNotCompute>(T))
- return ConstantRange(cast<IntegerType>(S->getType())->getBitWidth(), true);
-
- T = SE.getTruncateOrZeroExtend(T, S->getType());
- return getRange(S, T, SE);
-}
-
-/// getRange - determine the range for a particular SCEV with a given trip count
-ConstantRange LoopVR::getRange(const SCEV* S, const SCEV* T, ScalarEvolution &SE){
-
- if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S))
- return ConstantRange(C->getValue()->getValue());
-
- ConstantRange FullSet(cast<IntegerType>(S->getType())->getBitWidth(), true);
-
- // {x,+,y,+,...z}. We detect overflow by checking the size of the set after
- // summing the upper and lower.
- if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
- ConstantRange X = getRange(Add->getOperand(0), T, SE);
- if (X.isFullSet()) return FullSet;
- for (unsigned i = 1, e = Add->getNumOperands(); i != e; ++i) {
- ConstantRange Y = getRange(Add->getOperand(i), T, SE);
- if (Y.isFullSet()) return FullSet;
-
- APInt Spread_X = X.getSetSize(), Spread_Y = Y.getSetSize();
- APInt NewLower = X.getLower() + Y.getLower();
- APInt NewUpper = X.getUpper() + Y.getUpper() - 1;
- if (NewLower == NewUpper)
- return FullSet;
-
- X = ConstantRange(NewLower, NewUpper);
- if (X.getSetSize().ult(Spread_X) || X.getSetSize().ult(Spread_Y))
- return FullSet; // we've wrapped, therefore, full set.
- }
- return X;
- }
-
- // {x,*,y,*,...,z}. In order to detect overflow, we use k*bitwidth where
- // k is the number of terms being multiplied.
- if (const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(S)) {
- ConstantRange X = getRange(Mul->getOperand(0), T, SE);
- if (X.isFullSet()) return FullSet;
-
- const IntegerType *Ty = IntegerType::get(X.getBitWidth());
- const IntegerType *ExTy = IntegerType::get(X.getBitWidth() *
- Mul->getNumOperands());
- ConstantRange XExt = X.zeroExtend(ExTy->getBitWidth());
-
- for (unsigned i = 1, e = Mul->getNumOperands(); i != e; ++i) {
- ConstantRange Y = getRange(Mul->getOperand(i), T, SE);
- if (Y.isFullSet()) return FullSet;
-
- ConstantRange YExt = Y.zeroExtend(ExTy->getBitWidth());
- XExt = ConstantRange(XExt.getLower() * YExt.getLower(),
- ((XExt.getUpper()-1) * (YExt.getUpper()-1)) + 1);
- }
- return XExt.truncate(Ty->getBitWidth());
- }
-
- // X smax Y smax ... Z is: range(smax(X_smin, Y_smin, ..., Z_smin),
- // smax(X_smax, Y_smax, ..., Z_smax))
- // It doesn't matter if one of the SCEVs has FullSet because we're taking
- // a maximum of the minimums across all of them.
- if (const SCEVSMaxExpr *SMax = dyn_cast<SCEVSMaxExpr>(S)) {
- ConstantRange X = getRange(SMax->getOperand(0), T, SE);
- if (X.isFullSet()) return FullSet;
-
- APInt smin = X.getSignedMin(), smax = X.getSignedMax();
- for (unsigned i = 1, e = SMax->getNumOperands(); i != e; ++i) {
- ConstantRange Y = getRange(SMax->getOperand(i), T, SE);
- smin = APIntOps::smax(smin, Y.getSignedMin());
- smax = APIntOps::smax(smax, Y.getSignedMax());
- }
- if (smax + 1 == smin) return FullSet;
- return ConstantRange(smin, smax + 1);
- }
-
- // X umax Y umax ... Z is: range(umax(X_umin, Y_umin, ..., Z_umin),
- // umax(X_umax, Y_umax, ..., Z_umax))
- // It doesn't matter if one of the SCEVs has FullSet because we're taking
- // a maximum of the minimums across all of them.
- if (const SCEVUMaxExpr *UMax = dyn_cast<SCEVUMaxExpr>(S)) {
- ConstantRange X = getRange(UMax->getOperand(0), T, SE);
- if (X.isFullSet()) return FullSet;
-
- APInt umin = X.getUnsignedMin(), umax = X.getUnsignedMax();
- for (unsigned i = 1, e = UMax->getNumOperands(); i != e; ++i) {
- ConstantRange Y = getRange(UMax->getOperand(i), T, SE);
- umin = APIntOps::umax(umin, Y.getUnsignedMin());
- umax = APIntOps::umax(umax, Y.getUnsignedMax());
- }
- if (umax + 1 == umin) return FullSet;
- return ConstantRange(umin, umax + 1);
- }
-
- // L udiv R. Luckily, there's only ever 2 sides to a udiv.
- if (const SCEVUDivExpr *UDiv = dyn_cast<SCEVUDivExpr>(S)) {
- ConstantRange L = getRange(UDiv->getLHS(), T, SE);
- ConstantRange R = getRange(UDiv->getRHS(), T, SE);
- if (L.isFullSet() && R.isFullSet()) return FullSet;
-
- if (R.getUnsignedMax() == 0) {
- // RHS must be single-element zero. Return an empty set.
- return ConstantRange(R.getBitWidth(), false);
- }
-
- APInt Lower = L.getUnsignedMin().udiv(R.getUnsignedMax());
-
- APInt Upper;
-
- if (R.getUnsignedMin() == 0) {
- // Just because it contains zero, doesn't mean it will also contain one.
- // Use maximalIntersectWith to get the right behaviour.
- ConstantRange NotZero(APInt(L.getBitWidth(), 1),
- APInt::getNullValue(L.getBitWidth()));
- R = R.maximalIntersectWith(NotZero);
- }
-
- // But, the maximal intersection might still include zero. If it does, then
- // we know it also included one.
- if (R.contains(APInt::getNullValue(L.getBitWidth())))
- Upper = L.getUnsignedMax();
- else
- Upper = L.getUnsignedMax().udiv(R.getUnsignedMin());
-
- return ConstantRange(Lower, Upper);
- }
-
- // ConstantRange already implements the cast operators.
-
- if (const SCEVZeroExtendExpr *ZExt = dyn_cast<SCEVZeroExtendExpr>(S)) {
- T = SE.getTruncateOrZeroExtend(T, ZExt->getOperand()->getType());
- ConstantRange X = getRange(ZExt->getOperand(), T, SE);
- return X.zeroExtend(cast<IntegerType>(ZExt->getType())->getBitWidth());
- }
-
- if (const SCEVSignExtendExpr *SExt = dyn_cast<SCEVSignExtendExpr>(S)) {
- T = SE.getTruncateOrZeroExtend(T, SExt->getOperand()->getType());
- ConstantRange X = getRange(SExt->getOperand(), T, SE);
- return X.signExtend(cast<IntegerType>(SExt->getType())->getBitWidth());
- }
-
- if (const SCEVTruncateExpr *Trunc = dyn_cast<SCEVTruncateExpr>(S)) {
- T = SE.getTruncateOrZeroExtend(T, Trunc->getOperand()->getType());
- ConstantRange X = getRange(Trunc->getOperand(), T, SE);
- if (X.isFullSet()) return FullSet;
- return X.truncate(cast<IntegerType>(Trunc->getType())->getBitWidth());
- }
-
- if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
- const SCEVConstant *Trip = dyn_cast<SCEVConstant>(T);
- if (!Trip) return FullSet;
-
- if (AddRec->isAffine()) {
- const SCEV* StartHandle = AddRec->getStart();
- const SCEV* StepHandle = AddRec->getOperand(1);
-
- const SCEVConstant *Step = dyn_cast<SCEVConstant>(StepHandle);
- if (!Step) return FullSet;
-
- uint32_t ExWidth = 2 * Trip->getValue()->getBitWidth();
- APInt TripExt = Trip->getValue()->getValue(); TripExt.zext(ExWidth);
- APInt StepExt = Step->getValue()->getValue(); StepExt.zext(ExWidth);
- if ((TripExt * StepExt).ugt(APInt::getLowBitsSet(ExWidth, ExWidth >> 1)))
- return FullSet;
-
- const SCEV* EndHandle = SE.getAddExpr(StartHandle,
- SE.getMulExpr(T, StepHandle));
- const SCEVConstant *Start = dyn_cast<SCEVConstant>(StartHandle);
- const SCEVConstant *End = dyn_cast<SCEVConstant>(EndHandle);
- if (!Start || !End) return FullSet;
-
- const APInt &StartInt = Start->getValue()->getValue();
- const APInt &EndInt = End->getValue()->getValue();
- const APInt &StepInt = Step->getValue()->getValue();
-
- if (StepInt.isNegative()) {
- if (EndInt == StartInt + 1) return FullSet;
- return ConstantRange(EndInt, StartInt + 1);
- } else {
- if (StartInt == EndInt + 1) return FullSet;
- return ConstantRange(StartInt, EndInt + 1);
- }
- }
- }
-
- // TODO: non-affine addrec, udiv, SCEVUnknown (narrowed from elsewhere)?
-
- return FullSet;
-}
-
-bool LoopVR::runOnFunction(Function &F) { Map.clear(); return false; }
-
-void LoopVR::print(std::ostream &os, const Module *) const {
- raw_os_ostream OS(os);
- for (std::map<Value *, ConstantRange *>::const_iterator I = Map.begin(),
- E = Map.end(); I != E; ++I) {
- OS << *I->first << ": " << *I->second << '\n';
- }
-}
-
-void LoopVR::releaseMemory() {
- for (std::map<Value *, ConstantRange *>::iterator I = Map.begin(),
- E = Map.end(); I != E; ++I) {
- delete I->second;
- }
-
- Map.clear();
-}
-
-ConstantRange LoopVR::compute(Value *V) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
- return ConstantRange(CI->getValue());
-
- Instruction *I = dyn_cast<Instruction>(V);
- if (!I)
- return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);
-
- LoopInfo &LI = getAnalysis<LoopInfo>();
-
- Loop *L = LI.getLoopFor(I->getParent());
- if (!L || L->isLoopInvariant(I))
- return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);
-
- ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
-
- const SCEV* S = SE.getSCEV(I);
- if (isa<SCEVUnknown>(S) || isa<SCEVCouldNotCompute>(S))
- return ConstantRange(cast<IntegerType>(V->getType())->getBitWidth(), false);
-
- return ConstantRange(getRange(S, L, SE));
-}
-
-ConstantRange LoopVR::get(Value *V) {
- std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
- if (I == Map.end()) {
- ConstantRange *CR = new ConstantRange(compute(V));
- Map[V] = CR;
- return *CR;
- }
-
- return *I->second;
-}
-
-void LoopVR::remove(Value *V) {
- std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
- if (I != Map.end()) {
- delete I->second;
- Map.erase(I);
- }
-}
-
-void LoopVR::narrow(Value *V, const ConstantRange &CR) {
- if (CR.isFullSet()) return;
-
- std::map<Value *, ConstantRange *>::iterator I = Map.find(V);
- if (I == Map.end())
- Map[V] = new ConstantRange(CR);
- else
- Map[V] = new ConstantRange(Map[V]->maximalIntersectWith(CR));
-}
diff --git a/lib/CodeGen/LazyLiveness.cpp b/lib/CodeGen/LazyLiveness.cpp
deleted file mode 100644
index a951c99..0000000
--- a/lib/CodeGen/LazyLiveness.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-//===- LazyLiveness.cpp - Lazy, CFG-invariant liveness information --------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass implements a lazy liveness analysis as per "Fast Liveness Checking
-// for SSA-form Programs," by Boissinot, et al.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "lazyliveness"
-#include "llvm/CodeGen/LazyLiveness.h"
-#include "llvm/CodeGen/MachineDominators.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/ADT/DepthFirstIterator.h"
-#include "llvm/ADT/PostOrderIterator.h"
-using namespace llvm;
-
-char LazyLiveness::ID = 0;
-static RegisterPass<LazyLiveness> X("lazy-liveness", "Lazy Liveness Analysis");
-
-void LazyLiveness::computeBackedgeChain(MachineFunction& mf,
- MachineBasicBlock* MBB) {
- SparseBitVector<128> tmp = rv[MBB];
- tmp.set(preorder[MBB]);
- tmp &= backedge_source;
- calculated.set(preorder[MBB]);
-
- for (SparseBitVector<128>::iterator I = tmp.begin(); I != tmp.end(); ++I) {
- assert(rev_preorder.size() > *I && "Unknown block!");
-
- MachineBasicBlock* SrcMBB = rev_preorder[*I];
-
- for (MachineBasicBlock::succ_iterator SI = SrcMBB->succ_begin(),
- SE = SrcMBB->succ_end(); SI != SE; ++SI) {
- MachineBasicBlock* TgtMBB = *SI;
-
- if (backedges.count(std::make_pair(SrcMBB, TgtMBB)) &&
- !rv[MBB].test(preorder[TgtMBB])) {
- if (!calculated.test(preorder[TgtMBB]))
- computeBackedgeChain(mf, TgtMBB);
-
- tv[MBB].set(preorder[TgtMBB]);
- SparseBitVector<128> right = tv[TgtMBB];
- tv[MBB] |= right;
- }
- }
-
- tv[MBB].reset(preorder[MBB]);
- }
-}
-
-bool LazyLiveness::runOnMachineFunction(MachineFunction &mf) {
- rv.clear();
- tv.clear();
- backedges.clear();
- backedge_source.clear();
- backedge_target.clear();
- calculated.clear();
- preorder.clear();
- rev_preorder.clear();
-
- rv.resize(mf.size());
- tv.resize(mf.size());
- preorder.resize(mf.size());
- rev_preorder.reserve(mf.size());
-
- MRI = &mf.getRegInfo();
- MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>();
-
- // Step 0: Compute preorder numbering for all MBBs.
- unsigned num = 0;
- for (df_iterator<MachineDomTreeNode*> DI = df_begin(MDT.getRootNode()),
- DE = df_end(MDT.getRootNode()); DI != DE; ++DI) {
- preorder[(*DI)->getBlock()] = num++;
- rev_preorder.push_back((*DI)->getBlock());
- }
-
- // Step 1: Compute the transitive closure of the CFG, ignoring backedges.
- for (po_iterator<MachineBasicBlock*> POI = po_begin(&*mf.begin()),
- POE = po_end(&*mf.begin()); POI != POE; ++POI) {
- MachineBasicBlock* MBB = *POI;
- SparseBitVector<128>& entry = rv[MBB];
- entry.set(preorder[MBB]);
-
- for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(),
- SE = MBB->succ_end(); SI != SE; ++SI) {
- DenseMap<MachineBasicBlock*, SparseBitVector<128> >::iterator SII =
- rv.find(*SI);
-
- // Because we're iterating in postorder, any successor that does not yet
- // have an rv entry must be on a backedge.
- if (SII != rv.end()) {
- entry |= SII->second;
- } else {
- backedges.insert(std::make_pair(MBB, *SI));
- backedge_source.set(preorder[MBB]);
- backedge_target.set(preorder[*SI]);
- }
- }
- }
-
- for (SparseBitVector<128>::iterator I = backedge_source.begin();
- I != backedge_source.end(); ++I)
- computeBackedgeChain(mf, rev_preorder[*I]);
-
- for (po_iterator<MachineBasicBlock*> POI = po_begin(&*mf.begin()),
- POE = po_end(&*mf.begin()); POI != POE; ++POI)
- if (!backedge_target.test(preorder[*POI]))
- for (MachineBasicBlock::succ_iterator SI = (*POI)->succ_begin(),
- SE = (*POI)->succ_end(); SI != SE; ++SI)
- if (!backedges.count(std::make_pair(*POI, *SI)) && tv.count(*SI)) {
- SparseBitVector<128> right = tv[*SI];
- tv[*POI] |= right;
- }
-
- for (po_iterator<MachineBasicBlock*> POI = po_begin(&*mf.begin()),
- POE = po_end(&*mf.begin()); POI != POE; ++POI)
- tv[*POI].set(preorder[*POI]);
-
- return false;
-}
-
-bool LazyLiveness::vregLiveIntoMBB(unsigned vreg, MachineBasicBlock* MBB) {
- MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>();
-
- MachineBasicBlock* DefMBB = MRI->def_begin(vreg)->getParent();
- unsigned def = preorder[DefMBB];
- unsigned max_dom = 0;
- for (df_iterator<MachineDomTreeNode*> DI = df_begin(MDT[DefMBB]),
- DE = df_end(MDT[DefMBB]); DI != DE; ++DI) {
- if (preorder[DI->getBlock()] > max_dom) {
- max_dom = preorder[(*DI)->getBlock()];
- }
- }
-
- if (preorder[MBB] <= def || max_dom < preorder[MBB])
- return false;
-
- SparseBitVector<128>::iterator I = tv[MBB].begin();
- while (I != tv[MBB].end() && *I <= def) ++I;
- while (I != tv[MBB].end() && *I < max_dom) {
- for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(vreg),
- UE = MachineRegisterInfo::use_end(); UI != UE; ++UI) {
- MachineBasicBlock* UseMBB = UI->getParent();
- if (rv[rev_preorder[*I]].test(preorder[UseMBB]))
- return true;
-
- unsigned t_dom = 0;
- for (df_iterator<MachineDomTreeNode*> DI =
- df_begin(MDT[rev_preorder[*I]]), DE = df_end(MDT[rev_preorder[*I]]);
- DI != DE; ++DI)
- if (preorder[DI->getBlock()] > t_dom) {
- max_dom = preorder[(*DI)->getBlock()];
- }
- I = tv[MBB].begin();
- while (I != tv[MBB].end() && *I < t_dom) ++I;
- }
- }
-
- return false;
-}
diff --git a/lib/CodeGen/PBQP.cpp b/lib/CodeGen/PBQP.cpp
deleted file mode 100644
index 562300f..0000000
--- a/lib/CodeGen/PBQP.cpp
+++ /dev/null
@@ -1,1395 +0,0 @@
-//===---------------- PBQP.cpp --------- PBQP Solver ------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Developed by: Bernhard Scholz
-// The University of Sydney
-// http://www.it.usyd.edu.au/~scholz
-//===----------------------------------------------------------------------===//
-
-#include "PBQP.h"
-#include "llvm/Config/alloca.h"
-#include <limits>
-#include <cassert>
-#include <cstring>
-
-namespace llvm {
-
-/**************************************************************************
- * Data Structures
- **************************************************************************/
-
-/* edge of PBQP graph */
-typedef struct adjnode {
- struct adjnode *prev, /* doubly chained list */
- *succ,
- *reverse; /* reverse edge */
- int adj; /* adj. node */
- PBQPMatrix *costs; /* cost matrix of edge */
-
- bool tc_valid; /* flag whether following fields are valid */
- int *tc_safe_regs; /* safe registers */
- int tc_impact; /* impact */
-} adjnode;
-
-/* bucket node */
-typedef struct bucketnode {
- struct bucketnode *prev; /* doubly chained list */
- struct bucketnode *succ;
- int u; /* node */
-} bucketnode;
-
-/* data structure of partitioned boolean quadratic problem */
-struct pbqp {
- int num_nodes; /* number of nodes */
- int max_deg; /* maximal degree of a node */
- bool solved; /* flag that indicates whether PBQP has been solved yet */
- bool optimal; /* flag that indicates whether PBQP is optimal */
- PBQPNum min;
- bool changed; /* flag whether graph has changed in simplification */
-
- /* node fields */
- PBQPVector **node_costs; /* cost vectors of nodes */
- int *node_deg; /* node degree of nodes */
- int *solution; /* solution for node */
- adjnode **adj_list; /* adj. list */
- bucketnode **bucket_ptr; /* bucket pointer of a node */
-
- /* node stack */
- int *stack; /* stack of nodes */
- int stack_ptr; /* stack pointer */
-
- /* bucket fields */
- bucketnode **bucket_list; /* bucket list */
-
- int num_r0; /* counters for number statistics */
- int num_ri;
- int num_rii;
- int num_rn;
- int num_rn_special;
-};
-
-bool isInf(PBQPNum n) { return n == std::numeric_limits<PBQPNum>::infinity(); }
-
-/*****************************************************************************
- * allocation/de-allocation of pbqp problem
- ****************************************************************************/
-
-/* allocate new partitioned boolean quadratic program problem */
-pbqp *alloc_pbqp(int num_nodes)
-{
- pbqp *this_;
- int u;
-
- assert(num_nodes > 0);
-
- /* allocate memory for pbqp data structure */
- this_ = (pbqp *)malloc(sizeof(pbqp));
-
- /* Initialize pbqp fields */
- this_->num_nodes = num_nodes;
- this_->solved = false;
- this_->optimal = true;
- this_->min = 0.0;
- this_->max_deg = 0;
- this_->changed = false;
- this_->num_r0 = 0;
- this_->num_ri = 0;
- this_->num_rii = 0;
- this_->num_rn = 0;
- this_->num_rn_special = 0;
-
- /* initialize/allocate stack fields of pbqp */
- this_->stack = (int *) malloc(sizeof(int)*num_nodes);
- this_->stack_ptr = 0;
-
- /* initialize/allocate node fields of pbqp */
- this_->adj_list = (adjnode **) malloc(sizeof(adjnode *)*num_nodes);
- this_->node_deg = (int *) malloc(sizeof(int)*num_nodes);
- this_->solution = (int *) malloc(sizeof(int)*num_nodes);
- this_->bucket_ptr = (bucketnode **) malloc(sizeof(bucketnode **)*num_nodes);
- this_->node_costs = (PBQPVector**) malloc(sizeof(PBQPVector*) * num_nodes);
- for(u=0;u<num_nodes;u++) {
- this_->solution[u]=-1;
- this_->adj_list[u]=NULL;
- this_->node_deg[u]=0;
- this_->bucket_ptr[u]=NULL;
- this_->node_costs[u]=NULL;
- }
-
- /* initialize bucket list */
- this_->bucket_list = NULL;
-
- return this_;
-}
-
-/* free pbqp problem */
-void free_pbqp(pbqp *this_)
-{
- int u;
- int deg;
- adjnode *adj_ptr,*adj_next;
- bucketnode *bucket,*bucket_next;
-
- assert(this_ != NULL);
-
- /* free node cost fields */
- for(u=0;u < this_->num_nodes;u++) {
- delete this_->node_costs[u];
- }
- free(this_->node_costs);
-
- /* free bucket list */
- for(deg=0;deg<=this_->max_deg;deg++) {
- for(bucket=this_->bucket_list[deg];bucket!=NULL;bucket=bucket_next) {
- this_->bucket_ptr[bucket->u] = NULL;
- bucket_next = bucket-> succ;
- free(bucket);
- }
- }
- free(this_->bucket_list);
-
- /* free adj. list */
- assert(this_->adj_list != NULL);
- for(u=0;u < this_->num_nodes; u++) {
- for(adj_ptr = this_->adj_list[u]; adj_ptr != NULL; adj_ptr = adj_next) {
- adj_next = adj_ptr -> succ;
- if (u < adj_ptr->adj) {
- assert(adj_ptr != NULL);
- delete adj_ptr->costs;
- }
- if (adj_ptr -> tc_safe_regs != NULL) {
- free(adj_ptr -> tc_safe_regs);
- }
- free(adj_ptr);
- }
- }
- free(this_->adj_list);
-
- /* free other node fields */
- free(this_->node_deg);
- free(this_->solution);
- free(this_->bucket_ptr);
-
- /* free stack */
- free(this_->stack);
-
- /* free pbqp data structure itself */
- free(this_);
-}
-
-
-/****************************************************************************
- * adj. node routines
- ****************************************************************************/
-
-/* find data structure of adj. node of a given node */
-static
-adjnode *find_adjnode(pbqp *this_,int u,int v)
-{
- adjnode *adj_ptr;
-
- assert (this_ != NULL);
- assert (u >= 0 && u < this_->num_nodes);
- assert (v >= 0 && v < this_->num_nodes);
- assert(this_->adj_list != NULL);
-
- for(adj_ptr = this_ -> adj_list[u];adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
- if (adj_ptr->adj == v) {
- return adj_ptr;
- }
- }
- return NULL;
-}
-
-/* allocate a new data structure for adj. node */
-static
-adjnode *alloc_adjnode(pbqp *this_,int u, PBQPMatrix *costs)
-{
- adjnode *p;
-
- assert(this_ != NULL);
- assert(costs != NULL);
- assert(u >= 0 && u < this_->num_nodes);
-
- p = (adjnode *)malloc(sizeof(adjnode));
- assert(p != NULL);
-
- p->adj = u;
- p->costs = costs;
-
- p->tc_valid= false;
- p->tc_safe_regs = NULL;
- p->tc_impact = 0;
-
- return p;
-}
-
-/* insert adjacence node to adj. list */
-static
-void insert_adjnode(pbqp *this_, int u, adjnode *adj_ptr)
-{
-
- assert(this_ != NULL);
- assert(adj_ptr != NULL);
- assert(u >= 0 && u < this_->num_nodes);
-
- /* if adjacency list of node is not empty -> update
- first node of the list */
- if (this_ -> adj_list[u] != NULL) {
- assert(this_->adj_list[u]->prev == NULL);
- this_->adj_list[u] -> prev = adj_ptr;
- }
-
- /* update doubly chained list pointers of pointers */
- adj_ptr -> succ = this_->adj_list[u];
- adj_ptr -> prev = NULL;
-
- /* update adjacency list pointer of node u */
- this_->adj_list[u] = adj_ptr;
-}
-
-/* remove entry in an adj. list */
-static
-void remove_adjnode(pbqp *this_, int u, adjnode *adj_ptr)
-{
- assert(this_!= NULL);
- assert(u >= 0 && u <= this_->num_nodes);
- assert(this_->adj_list != NULL);
- assert(adj_ptr != NULL);
-
- if (adj_ptr -> prev == NULL) {
- this_->adj_list[u] = adj_ptr -> succ;
- } else {
- adj_ptr -> prev -> succ = adj_ptr -> succ;
- }
-
- if (adj_ptr -> succ != NULL) {
- adj_ptr -> succ -> prev = adj_ptr -> prev;
- }
-
- if(adj_ptr->reverse != NULL) {
- adjnode *rev = adj_ptr->reverse;
- rev->reverse = NULL;
- }
-
- if (adj_ptr -> tc_safe_regs != NULL) {
- free(adj_ptr -> tc_safe_regs);
- }
-
- free(adj_ptr);
-}
-
-/*****************************************************************************
- * node functions
- ****************************************************************************/
-
-/* get degree of a node */
-static
-int get_deg(pbqp *this_,int u)
-{
- adjnode *adj_ptr;
- int deg = 0;
-
- assert(this_ != NULL);
- assert(u >= 0 && u < this_->num_nodes);
- assert(this_->adj_list != NULL);
-
- for(adj_ptr = this_ -> adj_list[u];adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
- deg ++;
- }
- return deg;
-}
-
-/* reinsert node */
-static
-void reinsert_node(pbqp *this_,int u)
-{
- adjnode *adj_u,
- *adj_v;
-
- assert(this_!= NULL);
- assert(u >= 0 && u <= this_->num_nodes);
- assert(this_->adj_list != NULL);
-
- for(adj_u = this_ -> adj_list[u]; adj_u != NULL; adj_u = adj_u -> succ) {
- int v = adj_u -> adj;
- adj_v = alloc_adjnode(this_,u,adj_u->costs);
- insert_adjnode(this_,v,adj_v);
- }
-}
-
-/* remove node */
-static
-void remove_node(pbqp *this_,int u)
-{
- adjnode *adj_ptr;
-
- assert(this_!= NULL);
- assert(u >= 0 && u <= this_->num_nodes);
- assert(this_->adj_list != NULL);
-
- for(adj_ptr = this_ -> adj_list[u]; adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
- remove_adjnode(this_,adj_ptr->adj,adj_ptr -> reverse);
- }
-}
-
-/*****************************************************************************
- * edge functions
- ****************************************************************************/
-
-/* insert edge to graph */
-/* (does not check whether edge exists in graph */
-static
-void insert_edge(pbqp *this_, int u, int v, PBQPMatrix *costs)
-{
- adjnode *adj_u,
- *adj_v;
-
- /* create adjanceny entry for u */
- adj_u = alloc_adjnode(this_,v,costs);
- insert_adjnode(this_,u,adj_u);
-
-
- /* create adjanceny entry for v */
- adj_v = alloc_adjnode(this_,u,costs);
- insert_adjnode(this_,v,adj_v);
-
- /* create link for reverse edge */
- adj_u -> reverse = adj_v;
- adj_v -> reverse = adj_u;
-}
-
-/* delete edge */
-static
-void delete_edge(pbqp *this_,int u,int v)
-{
- adjnode *adj_ptr;
- adjnode *rev;
-
- assert(this_ != NULL);
- assert( u >= 0 && u < this_->num_nodes);
- assert( v >= 0 && v < this_->num_nodes);
-
- adj_ptr=find_adjnode(this_,u,v);
- assert(adj_ptr != NULL);
- assert(adj_ptr->reverse != NULL);
-
- delete adj_ptr -> costs;
-
- rev = adj_ptr->reverse;
- remove_adjnode(this_,u,adj_ptr);
- remove_adjnode(this_,v,rev);
-}
-
-/*****************************************************************************
- * cost functions
- ****************************************************************************/
-
-/* Note: Since cost(u,v) = transpose(cost(v,u)), it would be necessary to store
- two matrices for both edges (u,v) and (v,u). However, we only store the
- matrix for the case u < v. For the other case we transpose the stored matrix
- if required.
-*/
-
-/* add costs to cost vector of a node */
-void add_pbqp_nodecosts(pbqp *this_,int u, PBQPVector *costs)
-{
- assert(this_ != NULL);
- assert(costs != NULL);
- assert(u >= 0 && u <= this_->num_nodes);
-
- if (!this_->node_costs[u]) {
- this_->node_costs[u] = new PBQPVector(*costs);
- } else {
- *this_->node_costs[u] += *costs;
- }
-}
-
-/* get cost matrix ptr */
-static
-PBQPMatrix *get_costmatrix_ptr(pbqp *this_, int u, int v)
-{
- adjnode *adj_ptr;
- PBQPMatrix *m = NULL;
-
- assert (this_ != NULL);
- assert (u >= 0 && u < this_->num_nodes);
- assert (v >= 0 && v < this_->num_nodes);
-
- adj_ptr = find_adjnode(this_,u,v);
-
- if (adj_ptr != NULL) {
- m = adj_ptr -> costs;
- }
-
- return m;
-}
-
-/* get cost matrix ptr */
-/* Note: only the pointer is returned for
- cost(u,v), if u < v.
-*/
-static
-PBQPMatrix *pbqp_get_costmatrix(pbqp *this_, int u, int v)
-{
- adjnode *adj_ptr = find_adjnode(this_,u,v);
-
- if (adj_ptr != NULL) {
- if ( u < v) {
- return new PBQPMatrix(*adj_ptr->costs);
- } else {
- return new PBQPMatrix(adj_ptr->costs->transpose());
- }
- } else {
- return NULL;
- }
-}
-
-/* add costs to cost matrix of an edge */
-void add_pbqp_edgecosts(pbqp *this_,int u,int v, PBQPMatrix *costs)
-{
- PBQPMatrix *adj_costs;
-
- assert(this_!= NULL);
- assert(costs != NULL);
- assert(u >= 0 && u <= this_->num_nodes);
- assert(v >= 0 && v <= this_->num_nodes);
-
- /* does the edge u-v exists ? */
- if (u == v) {
- PBQPVector *diag = new PBQPVector(costs->diagonalize());
- add_pbqp_nodecosts(this_,v,diag);
- delete diag;
- } else if ((adj_costs = get_costmatrix_ptr(this_,u,v))!=NULL) {
- if ( u < v) {
- *adj_costs += *costs;
- } else {
- *adj_costs += costs->transpose();
- }
- } else {
- adj_costs = new PBQPMatrix((u < v) ? *costs : costs->transpose());
- insert_edge(this_,u,v,adj_costs);
- }
-}
-
-/* remove bucket from bucket list */
-static
-void pbqp_remove_bucket(pbqp *this_, bucketnode *bucket)
-{
- int u = bucket->u;
-
- assert(this_ != NULL);
- assert(u >= 0 && u < this_->num_nodes);
- assert(this_->bucket_list != NULL);
- assert(this_->bucket_ptr[u] != NULL);
-
- /* update predecessor node in bucket list
- (if no preceeding bucket exists, then
- the bucket_list pointer needs to be
- updated.)
- */
- if (bucket->prev != NULL) {
- bucket->prev-> succ = bucket->succ;
- } else {
- this_->bucket_list[this_->node_deg[u]] = bucket -> succ;
- }
-
- /* update successor node in bucket list */
- if (bucket->succ != NULL) {
- bucket->succ-> prev = bucket->prev;
- }
-}
-
-/**********************************************************************************
- * pop functions
- **********************************************************************************/
-
-/* pop node of given degree */
-static
-int pop_node(pbqp *this_,int deg)
-{
- bucketnode *bucket;
- int u;
-
- assert(this_ != NULL);
- assert(deg >= 0 && deg <= this_->max_deg);
- assert(this_->bucket_list != NULL);
-
- /* get first bucket of bucket list */
- bucket = this_->bucket_list[deg];
- assert(bucket != NULL);
-
- /* remove bucket */
- pbqp_remove_bucket(this_,bucket);
- u = bucket->u;
- free(bucket);
- return u;
-}
-
-/**********************************************************************************
- * reorder functions
- **********************************************************************************/
-
-/* add bucket to bucketlist */
-static
-void add_to_bucketlist(pbqp *this_,bucketnode *bucket, int deg)
-{
- bucketnode *old_head;
-
- assert(bucket != NULL);
- assert(this_ != NULL);
- assert(deg >= 0 && deg <= this_->max_deg);
- assert(this_->bucket_list != NULL);
-
- /* store node degree (for re-ordering purposes)*/
- this_->node_deg[bucket->u] = deg;
-
- /* put bucket to front of doubly chained list */
- old_head = this_->bucket_list[deg];
- bucket -> prev = NULL;
- bucket -> succ = old_head;
- this_ -> bucket_list[deg] = bucket;
- if (bucket -> succ != NULL ) {
- assert ( old_head -> prev == NULL);
- old_head -> prev = bucket;
- }
-}
-
-
-/* reorder node in bucket list according to
- current node degree */
-static
-void reorder_node(pbqp *this_, int u)
-{
- int deg;
-
- assert(this_ != NULL);
- assert(u>= 0 && u < this_->num_nodes);
- assert(this_->bucket_list != NULL);
- assert(this_->bucket_ptr[u] != NULL);
-
- /* get current node degree */
- deg = get_deg(this_,u);
-
- /* remove bucket from old bucket list only
- if degree of node has changed. */
- if (deg != this_->node_deg[u]) {
- pbqp_remove_bucket(this_,this_->bucket_ptr[u]);
- add_to_bucketlist(this_,this_->bucket_ptr[u],deg);
- }
-}
-
-/* reorder adj. nodes of a node */
-static
-void reorder_adjnodes(pbqp *this_,int u)
-{
- adjnode *adj_ptr;
-
- assert(this_!= NULL);
- assert(u >= 0 && u <= this_->num_nodes);
- assert(this_->adj_list != NULL);
-
- for(adj_ptr = this_ -> adj_list[u]; adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
- reorder_node(this_,adj_ptr->adj);
- }
-}
-
-/**********************************************************************************
- * creation functions
- **********************************************************************************/
-
-/* create new bucket entry */
-/* consistency of the bucket list is not checked! */
-static
-void create_bucket(pbqp *this_,int u,int deg)
-{
- bucketnode *bucket;
-
- assert(this_ != NULL);
- assert(u >= 0 && u < this_->num_nodes);
- assert(this_->bucket_list != NULL);
-
- bucket = (bucketnode *)malloc(sizeof(bucketnode));
- assert(bucket != NULL);
-
- bucket -> u = u;
- this_->bucket_ptr[u] = bucket;
-
- add_to_bucketlist(this_,bucket,deg);
-}
-
-/* create bucket list */
-static
-void create_bucketlist(pbqp *this_)
-{
- int u;
- int max_deg;
- int deg;
-
- assert(this_ != NULL);
- assert(this_->bucket_list == NULL);
-
- /* determine max. degree of the nodes */
- max_deg = 2; /* at least of degree two! */
- for(u=0;u<this_->num_nodes;u++) {
- deg = this_->node_deg[u] = get_deg(this_,u);
- if (deg > max_deg) {
- max_deg = deg;
- }
- }
- this_->max_deg = max_deg;
-
- /* allocate bucket list */
- this_ -> bucket_list = (bucketnode **)malloc(sizeof(bucketnode *)*(max_deg + 1));
- memset(this_->bucket_list,0,sizeof(bucketnode *)*(max_deg + 1));
- assert(this_->bucket_list != NULL);
-
- /* insert nodes to the list */
- for(u=0;u<this_->num_nodes;u++) {
- create_bucket(this_,u,this_->node_deg[u]);
- }
-}
-
-/*****************************************************************************
- * PBQP simplification for trivial nodes
- ****************************************************************************/
-
-/* remove trivial node with cost vector length of one */
-static
-void disconnect_trivialnode(pbqp *this_,int u)
-{
- int v;
- adjnode *adj_ptr,
- *next;
- PBQPMatrix *c_uv;
- PBQPVector *c_v;
-
- assert(this_ != NULL);
- assert(this_->node_costs != NULL);
- assert(u >= 0 && u < this_ -> num_nodes);
- assert(this_->node_costs[u]->getLength() == 1);
-
- /* add edge costs to node costs of adj. nodes */
- for(adj_ptr = this_->adj_list[u]; adj_ptr != NULL; adj_ptr = next){
- next = adj_ptr -> succ;
- v = adj_ptr -> adj;
- assert(v >= 0 && v < this_ -> num_nodes);
-
- /* convert matrix to cost vector offset for adj. node */
- c_uv = pbqp_get_costmatrix(this_,u,v);
- c_v = new PBQPVector(c_uv->getRowAsVector(0));
- *this_->node_costs[v] += *c_v;
-
- /* delete edge & free vec/mat */
- delete c_v;
- delete c_uv;
- delete_edge(this_,u,v);
- }
-}
-
-/* find all trivial nodes and disconnect them */
-static
-void eliminate_trivial_nodes(pbqp *this_)
-{
- int u;
-
- assert(this_ != NULL);
- assert(this_ -> node_costs != NULL);
-
- for(u=0;u < this_ -> num_nodes; u++) {
- if (this_->node_costs[u]->getLength() == 1) {
- disconnect_trivialnode(this_,u);
- }
- }
-}
-
-/*****************************************************************************
- * Normal form for PBQP
- ****************************************************************************/
-
-/* simplify a cost matrix. If the matrix
- is independent, then simplify_matrix
- returns true - otherwise false. In
- vectors u and v the offset values of
- the decomposition are stored.
-*/
-
-static
-bool normalize_matrix(PBQPMatrix *m, PBQPVector *u, PBQPVector *v)
-{
- assert( m != NULL);
- assert( u != NULL);
- assert( v != NULL);
- assert( u->getLength() > 0);
- assert( v->getLength() > 0);
-
- assert(m->getRows() == u->getLength());
- assert(m->getCols() == v->getLength());
-
- /* determine u vector */
- for(unsigned r = 0; r < m->getRows(); ++r) {
- PBQPNum min = m->getRowMin(r);
- (*u)[r] += min;
- if (!isInf(min)) {
- m->subFromRow(r, min);
- } else {
- m->setRow(r, 0);
- }
- }
-
- /* determine v vector */
- for(unsigned c = 0; c < m->getCols(); ++c) {
- PBQPNum min = m->getColMin(c);
- (*v)[c] += min;
- if (!isInf(min)) {
- m->subFromCol(c, min);
- } else {
- m->setCol(c, 0);
- }
- }
-
- /* determine whether matrix is
- independent or not.
- */
- return m->isZero();
-}
-
-/* simplify single edge */
-static
-void simplify_edge(pbqp *this_,int u,int v)
-{
- PBQPMatrix *costs;
- bool is_zero;
-
- assert (this_ != NULL);
- assert (u >= 0 && u <this_->num_nodes);
- assert (v >= 0 && v <this_->num_nodes);
- assert (u != v);
-
- /* swap u and v if u > v in order to avoid un-necessary
- tranpositions of the cost matrix */
-
- if (u > v) {
- int swap = u;
- u = v;
- v = swap;
- }
-
- /* get cost matrix and simplify it */
- costs = get_costmatrix_ptr(this_,u,v);
- is_zero=normalize_matrix(costs,this_->node_costs[u],this_->node_costs[v]);
-
- /* delete edge */
- if(is_zero){
- delete_edge(this_,u,v);
- this_->changed = true;
- }
-}
-
-/* normalize cost matrices and remove
- edges in PBQP if they ary independent,
- i.e. can be decomposed into two
- cost vectors.
-*/
-static
-void eliminate_independent_edges(pbqp *this_)
-{
- int u,v;
- adjnode *adj_ptr,*next;
-
- assert(this_ != NULL);
- assert(this_ -> adj_list != NULL);
-
- this_->changed = false;
- for(u=0;u < this_->num_nodes;u++) {
- for (adj_ptr = this_ -> adj_list[u]; adj_ptr != NULL; adj_ptr = next) {
- next = adj_ptr -> succ;
- v = adj_ptr -> adj;
- assert(v >= 0 && v < this_->num_nodes);
- if (u < v) {
- simplify_edge(this_,u,v);
- }
- }
- }
-}
-
-
-/*****************************************************************************
- * PBQP reduction rules
- ****************************************************************************/
-
-/* RI reduction
- This reduction rule is applied for nodes
- of degree one. */
-
-static
-void apply_RI(pbqp *this_,int x)
-{
- int y;
- unsigned xlen,
- ylen;
- PBQPMatrix *c_yx;
- PBQPVector *c_x, *delta;
-
- assert(this_ != NULL);
- assert(x >= 0 && x < this_->num_nodes);
- assert(this_ -> adj_list[x] != NULL);
- assert(this_ -> adj_list[x] -> succ == NULL);
-
- /* get adjacence matrix */
- y = this_ -> adj_list[x] -> adj;
- assert(y >= 0 && y < this_->num_nodes);
-
- /* determine length of cost vectors for node x and y */
- xlen = this_ -> node_costs[x]->getLength();
- ylen = this_ -> node_costs[y]->getLength();
-
- /* get cost vector c_x and matrix c_yx */
- c_x = this_ -> node_costs[x];
- c_yx = pbqp_get_costmatrix(this_,y,x);
- assert (c_yx != NULL);
-
-
- /* allocate delta vector */
- delta = new PBQPVector(ylen);
-
- /* compute delta vector */
- for(unsigned i = 0; i < ylen; ++i) {
- PBQPNum min = (*c_yx)[i][0] + (*c_x)[0];
- for(unsigned j = 1; j < xlen; ++j) {
- PBQPNum c = (*c_yx)[i][j] + (*c_x)[j];
- if ( c < min )
- min = c;
- }
- (*delta)[i] = min;
- }
-
- /* add delta vector */
- *this_ -> node_costs[y] += *delta;
-
- /* delete node x */
- remove_node(this_,x);
-
- /* reorder adj. nodes of node x */
- reorder_adjnodes(this_,x);
-
- /* push node x on stack */
- assert(this_ -> stack_ptr < this_ -> num_nodes);
- this_->stack[this_ -> stack_ptr++] = x;
-
- /* free vec/mat */
- delete c_yx;
- delete delta;
-
- /* increment counter for number statistic */
- this_->num_ri++;
-}
-
-/* RII reduction
- This reduction rule is applied for nodes
- of degree two. */
-
-static
-void apply_RII(pbqp *this_,int x)
-{
- int y,z;
- unsigned xlen,ylen,zlen;
- adjnode *adj_yz;
-
- PBQPMatrix *c_yx, *c_zx;
- PBQPVector *cx;
- PBQPMatrix *delta;
-
- assert(this_ != NULL);
- assert(x >= 0 && x < this_->num_nodes);
- assert(this_ -> adj_list[x] != NULL);
- assert(this_ -> adj_list[x] -> succ != NULL);
- assert(this_ -> adj_list[x] -> succ -> succ == NULL);
-
- /* get adjacence matrix */
- y = this_ -> adj_list[x] -> adj;
- z = this_ -> adj_list[x] -> succ -> adj;
- assert(y >= 0 && y < this_->num_nodes);
- assert(z >= 0 && z < this_->num_nodes);
-
- /* determine length of cost vectors for node x and y */
- xlen = this_ -> node_costs[x]->getLength();
- ylen = this_ -> node_costs[y]->getLength();
- zlen = this_ -> node_costs[z]->getLength();
-
- /* get cost vector c_x and matrix c_yx */
- cx = this_ -> node_costs[x];
- c_yx = pbqp_get_costmatrix(this_,y,x);
- c_zx = pbqp_get_costmatrix(this_,z,x);
- assert(c_yx != NULL);
- assert(c_zx != NULL);
-
- /* Colour Heuristic */
- if ( (adj_yz = find_adjnode(this_,y,z)) != NULL) {
- adj_yz->tc_valid = false;
- adj_yz->reverse->tc_valid = false;
- }
-
- /* allocate delta matrix */
- delta = new PBQPMatrix(ylen, zlen);
-
- /* compute delta matrix */
- for(unsigned i=0;i<ylen;i++) {
- for(unsigned j=0;j<zlen;j++) {
- PBQPNum min = (*c_yx)[i][0] + (*c_zx)[j][0] + (*cx)[0];
- for(unsigned k=1;k<xlen;k++) {
- PBQPNum c = (*c_yx)[i][k] + (*c_zx)[j][k] + (*cx)[k];
- if ( c < min ) {
- min = c;
- }
- }
- (*delta)[i][j] = min;
- }
- }
-
- /* add delta matrix */
- add_pbqp_edgecosts(this_,y,z,delta);
-
- /* delete node x */
- remove_node(this_,x);
-
- /* simplify cost matrix c_yz */
- simplify_edge(this_,y,z);
-
- /* reorder adj. nodes */
- reorder_adjnodes(this_,x);
-
- /* push node x on stack */
- assert(this_ -> stack_ptr < this_ -> num_nodes);
- this_->stack[this_ -> stack_ptr++] = x;
-
- /* free vec/mat */
- delete c_yx;
- delete c_zx;
- delete delta;
-
- /* increment counter for number statistic */
- this_->num_rii++;
-
-}
-
-/* RN reduction */
-static
-void apply_RN(pbqp *this_,int x)
-{
- unsigned xlen;
-
- assert(this_ != NULL);
- assert(x >= 0 && x < this_->num_nodes);
- assert(this_ -> node_costs[x] != NULL);
-
- xlen = this_ -> node_costs[x] -> getLength();
-
- /* after application of RN rule no optimality
- can be guaranteed! */
- this_ -> optimal = false;
-
- /* push node x on stack */
- assert(this_ -> stack_ptr < this_ -> num_nodes);
- this_->stack[this_ -> stack_ptr++] = x;
-
- /* delete node x */
- remove_node(this_,x);
-
- /* reorder adj. nodes of node x */
- reorder_adjnodes(this_,x);
-
- /* increment counter for number statistic */
- this_->num_rn++;
-}
-
-
-static
-void compute_tc_info(pbqp *this_, adjnode *p)
-{
- adjnode *r;
- PBQPMatrix *m;
- int x,y;
- PBQPVector *c_x, *c_y;
- int *row_inf_counts;
-
- assert(p->reverse != NULL);
-
- /* set flags */
- r = p->reverse;
- p->tc_valid = true;
- r->tc_valid = true;
-
- /* get edge */
- x = r->adj;
- y = p->adj;
-
- /* get cost vectors */
- c_x = this_ -> node_costs[x];
- c_y = this_ -> node_costs[y];
-
- /* get cost matrix */
- m = pbqp_get_costmatrix(this_, x, y);
-
-
- /* allocate allowed set for edge (x,y) and (y,x) */
- if (p->tc_safe_regs == NULL) {
- p->tc_safe_regs = (int *) malloc(sizeof(int) * c_x->getLength());
- }
-
- if (r->tc_safe_regs == NULL ) {
- r->tc_safe_regs = (int *) malloc(sizeof(int) * c_y->getLength());
- }
-
- p->tc_impact = r->tc_impact = 0;
-
- row_inf_counts = (int *) alloca(sizeof(int) * c_x->getLength());
-
- /* init arrays */
- p->tc_safe_regs[0] = 0;
- row_inf_counts[0] = 0;
- for(unsigned i = 1; i < c_x->getLength(); ++i){
- p->tc_safe_regs[i] = 1;
- row_inf_counts[i] = 0;
- }
-
- r->tc_safe_regs[0] = 0;
- for(unsigned j = 1; j < c_y->getLength(); ++j){
- r->tc_safe_regs[j] = 1;
- }
-
- for(unsigned j = 0; j < c_y->getLength(); ++j) {
- int col_inf_counts = 0;
- for (unsigned i = 0; i < c_x->getLength(); ++i) {
- if (isInf((*m)[i][j])) {
- ++col_inf_counts;
- ++row_inf_counts[i];
-
- p->tc_safe_regs[i] = 0;
- r->tc_safe_regs[j] = 0;
- }
- }
- if (col_inf_counts > p->tc_impact) {
- p->tc_impact = col_inf_counts;
- }
- }
-
- for(unsigned i = 0; i < c_x->getLength(); ++i){
- if (row_inf_counts[i] > r->tc_impact)
- {
- r->tc_impact = row_inf_counts[i];
- }
- }
-
- delete m;
-}
-
-/*
- * Checks whether node x can be locally coloured.
- */
-static
-int is_colorable(pbqp *this_,int x)
-{
- adjnode *adj_ptr;
- PBQPVector *c_x;
- int result = 1;
- int *allowed;
- int num_allowed = 0;
- unsigned total_impact = 0;
-
- assert(this_ != NULL);
- assert(x >= 0 && x < this_->num_nodes);
- assert(this_ -> node_costs[x] != NULL);
-
- c_x = this_ -> node_costs[x];
-
- /* allocate allowed set */
- allowed = (int *)malloc(sizeof(int) * c_x->getLength());
- for(unsigned i = 0; i < c_x->getLength(); ++i){
- if (!isInf((*c_x)[i]) && i > 0) {
- allowed[i] = 1;
- ++num_allowed;
- } else {
- allowed[i] = 0;
- }
- }
-
- /* determine local minimum */
- for(adj_ptr=this_->adj_list[x] ;adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
- if (!adj_ptr -> tc_valid) {
- compute_tc_info(this_, adj_ptr);
- }
-
- total_impact += adj_ptr->tc_impact;
-
- if (num_allowed > 0) {
- for (unsigned i = 1; i < c_x->getLength(); ++i){
- if (allowed[i]){
- if (!adj_ptr->tc_safe_regs[i]){
- allowed[i] = 0;
- --num_allowed;
- if (num_allowed == 0)
- break;
- }
- }
- }
- }
-
- if ( total_impact >= c_x->getLength() - 1 && num_allowed == 0 ) {
- result = 0;
- break;
- }
- }
- free(allowed);
-
- return result;
-}
-
-/* use briggs heuristic
- note: this_ is not a general heuristic. it only is useful for
- interference graphs.
- */
-int pop_colorablenode(pbqp *this_)
-{
- int deg;
- bucketnode *min_bucket=NULL;
- PBQPNum min = std::numeric_limits<PBQPNum>::infinity();
-
- /* select node where the number of colors is less than the node degree */
- for(deg=this_->max_deg;deg > 2;deg--) {
- bucketnode *bucket;
- for(bucket=this_->bucket_list[deg];bucket!= NULL;bucket = bucket -> succ) {
- int u = bucket->u;
- if (is_colorable(this_,u)) {
- pbqp_remove_bucket(this_,bucket);
- this_->num_rn_special++;
- free(bucket);
- return u;
- }
- }
- }
-
- /* select node with minimal ratio between average node costs and degree of node */
- for(deg=this_->max_deg;deg >2; deg--) {
- bucketnode *bucket;
- for(bucket=this_->bucket_list[deg];bucket!= NULL;bucket = bucket -> succ) {
- PBQPNum h;
- int u;
-
- u = bucket->u;
- assert(u>=0 && u < this_->num_nodes);
- h = (*this_->node_costs[u])[0] / (PBQPNum) deg;
- if (h < min) {
- min_bucket = bucket;
- min = h;
- }
- }
- }
-
- /* return node and free bucket */
- if (min_bucket != NULL) {
- int u;
-
- pbqp_remove_bucket(this_,min_bucket);
- u = min_bucket->u;
- free(min_bucket);
- return u;
- } else {
- return -1;
- }
-}
-
-
-/*****************************************************************************
- * PBQP graph parsing
- ****************************************************************************/
-
-/* reduce pbqp problem (first phase) */
-static
-void reduce_pbqp(pbqp *this_)
-{
- int u;
-
- assert(this_ != NULL);
- assert(this_->bucket_list != NULL);
-
- for(;;){
-
- if (this_->bucket_list[1] != NULL) {
- u = pop_node(this_,1);
- apply_RI(this_,u);
- } else if (this_->bucket_list[2] != NULL) {
- u = pop_node(this_,2);
- apply_RII(this_,u);
- } else if ((u = pop_colorablenode(this_)) != -1) {
- apply_RN(this_,u);
- } else {
- break;
- }
- }
-}
-
-/*****************************************************************************
- * PBQP back propagation
- ****************************************************************************/
-
-/* determine solution of a reduced node. Either
- RI or RII was applied for this_ node. */
-static
-void determine_solution(pbqp *this_,int x)
-{
- PBQPVector *v = new PBQPVector(*this_ -> node_costs[x]);
- adjnode *adj_ptr;
-
- assert(this_ != NULL);
- assert(x >= 0 && x < this_->num_nodes);
- assert(this_ -> adj_list != NULL);
- assert(this_ -> solution != NULL);
-
- for(adj_ptr=this_->adj_list[x] ;adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
- int y = adj_ptr -> adj;
- int y_sol = this_ -> solution[y];
-
- PBQPMatrix *c_yx = pbqp_get_costmatrix(this_,y,x);
- assert(y_sol >= 0 && y_sol < (int)this_->node_costs[y]->getLength());
- (*v) += c_yx->getRowAsVector(y_sol);
- delete c_yx;
- }
- this_ -> solution[x] = v->minIndex();
-
- delete v;
-}
-
-/* back popagation phase of PBQP */
-static
-void back_propagate(pbqp *this_)
-{
- int i;
-
- assert(this_ != NULL);
- assert(this_->stack != NULL);
- assert(this_->stack_ptr < this_->num_nodes);
-
- for(i=this_ -> stack_ptr-1;i>=0;i--) {
- int x = this_ -> stack[i];
- assert( x >= 0 && x < this_ -> num_nodes);
- reinsert_node(this_,x);
- determine_solution(this_,x);
- }
-}
-
-/* solve trivial nodes of degree zero */
-static
-void determine_trivialsolution(pbqp *this_)
-{
- int u;
- PBQPNum delta;
-
- assert( this_ != NULL);
- assert( this_ -> bucket_list != NULL);
-
- /* determine trivial solution */
- while (this_->bucket_list[0] != NULL) {
- u = pop_node(this_,0);
-
- assert( u >= 0 && u < this_ -> num_nodes);
-
- this_->solution[u] = this_->node_costs[u]->minIndex();
- delta = (*this_->node_costs[u])[this_->solution[u]];
- this_->min = this_->min + delta;
-
- /* increment counter for number statistic */
- this_->num_r0++;
- }
-}
-
-/*****************************************************************************
- * debug facilities
- ****************************************************************************/
-static
-void check_pbqp(pbqp *this_)
-{
- int u,v;
- PBQPMatrix *costs;
- adjnode *adj_ptr;
-
- assert( this_ != NULL);
-
- for(u=0;u< this_->num_nodes; u++) {
- assert (this_ -> node_costs[u] != NULL);
- for(adj_ptr = this_ -> adj_list[u];adj_ptr != NULL; adj_ptr = adj_ptr -> succ) {
- v = adj_ptr -> adj;
- assert( v>= 0 && v < this_->num_nodes);
- if (u < v ) {
- costs = adj_ptr -> costs;
- assert( costs->getRows() == this_->node_costs[u]->getLength() &&
- costs->getCols() == this_->node_costs[v]->getLength());
- }
- }
- }
-}
-
-/*****************************************************************************
- * PBQP solve routines
- ****************************************************************************/
-
-/* solve PBQP problem */
-void solve_pbqp(pbqp *this_)
-{
- assert(this_ != NULL);
- assert(!this_->solved);
-
- /* check vector & matrix dimensions */
- check_pbqp(this_);
-
- /* simplify PBQP problem */
-
- /* eliminate trivial nodes, i.e.
- nodes with cost vectors of length one. */
- eliminate_trivial_nodes(this_);
-
- /* eliminate edges with independent
- cost matrices and normalize matrices */
- eliminate_independent_edges(this_);
-
- /* create bucket list for graph parsing */
- create_bucketlist(this_);
-
- /* reduce phase */
- reduce_pbqp(this_);
-
- /* solve trivial nodes */
- determine_trivialsolution(this_);
-
- /* back propagation phase */
- back_propagate(this_);
-
- this_->solved = true;
-}
-
-/* get solution of a node */
-int get_pbqp_solution(pbqp *this_,int x)
-{
- assert(this_ != NULL);
- assert(this_->solution != NULL);
- assert(this_ -> solved);
-
- return this_->solution[x];
-}
-
-/* is solution optimal? */
-bool is_pbqp_optimal(pbqp *this_)
-{
- assert(this_ -> solved);
- return this_->optimal;
-}
-
-}
-
-/* end of pbqp.c */
diff --git a/lib/CodeGen/PBQP.h b/lib/CodeGen/PBQP.h
deleted file mode 100644
index 5fd2c06..0000000
--- a/lib/CodeGen/PBQP.h
+++ /dev/null
@@ -1,284 +0,0 @@
-//===---------------- PBQP.cpp --------- PBQP Solver ------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Developed by: Bernhard Scholz
-// The University of Sydney
-// http://www.it.usyd.edu.au/~scholz
-//===----------------------------------------------------------------------===//
-
-// TODO:
-//
-// * Default to null costs on vector initialisation?
-// * C++-ify the rest of the solver.
-
-#ifndef LLVM_CODEGEN_PBQPSOLVER_H
-#define LLVM_CODEGEN_PBQPSOLVER_H
-
-#include <cassert>
-#include <algorithm>
-#include <functional>
-
-namespace llvm {
-
-//! \brief Floating point type to use in PBQP solver.
-typedef double PBQPNum;
-
-//! \brief PBQP Vector class.
-class PBQPVector {
-public:
-
- //! \brief Construct a PBQP vector of the given size.
- explicit PBQPVector(unsigned length) :
- length(length), data(new PBQPNum[length]) {
- std::fill(data, data + length, 0);
- }
-
- //! \brief Copy construct a PBQP vector.
- PBQPVector(const PBQPVector &v) :
- length(v.length), data(new PBQPNum[length]) {
- std::copy(v.data, v.data + length, data);
- }
-
- ~PBQPVector() { delete[] data; }
-
- //! \brief Assignment operator.
- PBQPVector& operator=(const PBQPVector &v) {
- delete[] data;
- length = v.length;
- data = new PBQPNum[length];
- std::copy(v.data, v.data + length, data);
- return *this;
- }
-
- //! \brief Return the length of the vector
- unsigned getLength() const throw () {
- return length;
- }
-
- //! \brief Element access.
- PBQPNum& operator[](unsigned index) {
- assert(index < length && "PBQPVector element access out of bounds.");
- return data[index];
- }
-
- //! \brief Const element access.
- const PBQPNum& operator[](unsigned index) const {
- assert(index < length && "PBQPVector element access out of bounds.");
- return data[index];
- }
-
- //! \brief Add another vector to this one.
- PBQPVector& operator+=(const PBQPVector &v) {
- assert(length == v.length && "PBQPVector length mismatch.");
- std::transform(data, data + length, v.data, data, std::plus<PBQPNum>());
- return *this;
- }
-
- //! \brief Subtract another vector from this one.
- PBQPVector& operator-=(const PBQPVector &v) {
- assert(length == v.length && "PBQPVector length mismatch.");
- std::transform(data, data + length, v.data, data, std::minus<PBQPNum>());
- return *this;
- }
-
- //! \brief Returns the index of the minimum value in this vector
- unsigned minIndex() const {
- return std::min_element(data, data + length) - data;
- }
-
-private:
- unsigned length;
- PBQPNum *data;
-};
-
-
-//! \brief PBQP Matrix class
-class PBQPMatrix {
-public:
-
- //! \brief Construct a PBQP Matrix with the given dimensions.
- PBQPMatrix(unsigned rows, unsigned cols) :
- rows(rows), cols(cols), data(new PBQPNum[rows * cols]) {
- std::fill(data, data + (rows * cols), 0);
- }
-
- //! \brief Copy construct a PBQP matrix.
- PBQPMatrix(const PBQPMatrix &m) :
- rows(m.rows), cols(m.cols), data(new PBQPNum[rows * cols]) {
- std::copy(m.data, m.data + (rows * cols), data);
- }
-
- ~PBQPMatrix() { delete[] data; }
-
- //! \brief Assignment operator.
- PBQPMatrix& operator=(const PBQPMatrix &m) {
- delete[] data;
- rows = m.rows; cols = m.cols;
- data = new PBQPNum[rows * cols];
- std::copy(m.data, m.data + (rows * cols), data);
- return *this;
- }
-
- //! \brief Return the number of rows in this matrix.
- unsigned getRows() const throw () { return rows; }
-
- //! \brief Return the number of cols in this matrix.
- unsigned getCols() const throw () { return cols; }
-
- //! \brief Matrix element access.
- PBQPNum* operator[](unsigned r) {
- assert(r < rows && "Row out of bounds.");
- return data + (r * cols);
- }
-
- //! \brief Matrix element access.
- const PBQPNum* operator[](unsigned r) const {
- assert(r < rows && "Row out of bounds.");
- return data + (r * cols);
- }
-
- //! \brief Returns the given row as a vector.
- PBQPVector getRowAsVector(unsigned r) const {
- PBQPVector v(cols);
- for (unsigned c = 0; c < cols; ++c)
- v[c] = (*this)[r][c];
- return v;
- }
-
- //! \brief Reset the matrix to the given value.
- PBQPMatrix& reset(PBQPNum val = 0) {
- std::fill(data, data + (rows * cols), val);
- return *this;
- }
-
- //! \brief Set a single row of this matrix to the given value.
- PBQPMatrix& setRow(unsigned r, PBQPNum val) {
- assert(r < rows && "Row out of bounds.");
- std::fill(data + (r * cols), data + ((r + 1) * cols), val);
- return *this;
- }
-
- //! \brief Set a single column of this matrix to the given value.
- PBQPMatrix& setCol(unsigned c, PBQPNum val) {
- assert(c < cols && "Column out of bounds.");
- for (unsigned r = 0; r < rows; ++r)
- (*this)[r][c] = val;
- return *this;
- }
-
- //! \brief Matrix transpose.
- PBQPMatrix transpose() const {
- PBQPMatrix m(cols, rows);
- for (unsigned r = 0; r < rows; ++r)
- for (unsigned c = 0; c < cols; ++c)
- m[c][r] = (*this)[r][c];
- return m;
- }
-
- //! \brief Returns the diagonal of the matrix as a vector.
- //!
- //! Matrix must be square.
- PBQPVector diagonalize() const {
- assert(rows == cols && "Attempt to diagonalize non-square matrix.");
-
- PBQPVector v(rows);
- for (unsigned r = 0; r < rows; ++r)
- v[r] = (*this)[r][r];
- return v;
- }
-
- //! \brief Add the given matrix to this one.
- PBQPMatrix& operator+=(const PBQPMatrix &m) {
- assert(rows == m.rows && cols == m.cols &&
- "Matrix dimensions mismatch.");
- std::transform(data, data + (rows * cols), m.data, data,
- std::plus<PBQPNum>());
- return *this;
- }
-
- //! \brief Returns the minimum of the given row
- PBQPNum getRowMin(unsigned r) const {
- assert(r < rows && "Row out of bounds");
- return *std::min_element(data + (r * cols), data + ((r + 1) * cols));
- }
-
- //! \brief Returns the minimum of the given column
- PBQPNum getColMin(unsigned c) const {
- PBQPNum minElem = (*this)[0][c];
- for (unsigned r = 1; r < rows; ++r)
- if ((*this)[r][c] < minElem) minElem = (*this)[r][c];
- return minElem;
- }
-
- //! \brief Subtracts the given scalar from the elements of the given row.
- PBQPMatrix& subFromRow(unsigned r, PBQPNum val) {
- assert(r < rows && "Row out of bounds");
- std::transform(data + (r * cols), data + ((r + 1) * cols),
- data + (r * cols),
- std::bind2nd(std::minus<PBQPNum>(), val));
- return *this;
- }
-
- //! \brief Subtracts the given scalar from the elements of the given column.
- PBQPMatrix& subFromCol(unsigned c, PBQPNum val) {
- for (unsigned r = 0; r < rows; ++r)
- (*this)[r][c] -= val;
- return *this;
- }
-
- //! \brief Returns true if this is a zero matrix.
- bool isZero() const {
- return find_if(data, data + (rows * cols),
- std::bind2nd(std::not_equal_to<PBQPNum>(), 0)) ==
- data + (rows * cols);
- }
-
-private:
- unsigned rows, cols;
- PBQPNum *data;
-};
-
-#define EPS (1E-8)
-
-#ifndef PBQP_TYPE
-#define PBQP_TYPE
-struct pbqp;
-typedef struct pbqp pbqp;
-#endif
-
-/*****************
- * PBQP routines *
- *****************/
-
-/* allocate pbqp problem */
-pbqp *alloc_pbqp(int num);
-
-/* add node costs */
-void add_pbqp_nodecosts(pbqp *this_,int u, PBQPVector *costs);
-
-/* add edge mat */
-void add_pbqp_edgecosts(pbqp *this_,int u,int v,PBQPMatrix *costs);
-
-/* solve PBQP problem */
-void solve_pbqp(pbqp *this_);
-
-/* get solution of a node */
-int get_pbqp_solution(pbqp *this_,int u);
-
-/* alloc PBQP */
-pbqp *alloc_pbqp(int num);
-
-/* free PBQP */
-void free_pbqp(pbqp *this_);
-
-/* is optimal */
-bool is_pbqp_optimal(pbqp *this_);
-
-}
-#endif
diff --git a/lib/CodeGen/RegAllocBigBlock.cpp b/lib/CodeGen/RegAllocBigBlock.cpp
deleted file mode 100644
index 91e4099..0000000
--- a/lib/CodeGen/RegAllocBigBlock.cpp
+++ /dev/null
@@ -1,892 +0,0 @@
-//===- RegAllocBigBlock.cpp - A register allocator for large basic blocks -===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the RABigBlock class
-//
-//===----------------------------------------------------------------------===//
-
-// This register allocator is derived from RegAllocLocal.cpp. Like it, this
-// allocator works on one basic block at a time, oblivious to others.
-// However, the algorithm used here is suited for long blocks of
-// instructions - registers are spilled by greedily choosing those holding
-// values that will not be needed for the longest amount of time. This works
-// particularly well for blocks with 10 or more times as many instructions
-// as machine registers, but can be used for general code.
-//
-//===----------------------------------------------------------------------===//
-//
-// TODO: - automagically invoke linearscan for (groups of) small BBs?
-// - break ties when picking regs? (probably not worth it in a
-// JIT context)
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "regalloc"
-#include "llvm/BasicBlock.h"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/LiveVariables.h"
-#include "llvm/CodeGen/RegAllocRegistry.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/ADT/IndexedMap.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Statistic.h"
-#include <algorithm>
-using namespace llvm;
-
-STATISTIC(NumStores, "Number of stores added");
-STATISTIC(NumLoads , "Number of loads added");
-STATISTIC(NumFolded, "Number of loads/stores folded into instructions");
-
-static RegisterRegAlloc
- bigBlockRegAlloc("bigblock", "Big-block register allocator",
- createBigBlockRegisterAllocator);
-
-namespace {
-/// VRegKeyInfo - Defines magic values required to use VirtRegs as DenseMap
-/// keys.
- struct VRegKeyInfo {
- static inline unsigned getEmptyKey() { return -1U; }
- static inline unsigned getTombstoneKey() { return -2U; }
- static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; }
- static unsigned getHashValue(const unsigned &Key) { return Key; }
- };
-
-
-/// This register allocator is derived from RegAllocLocal.cpp. Like it, this
-/// allocator works on one basic block at a time, oblivious to others.
-/// However, the algorithm used here is suited for long blocks of
-/// instructions - registers are spilled by greedily choosing those holding
-/// values that will not be needed for the longest amount of time. This works
-/// particularly well for blocks with 10 or more times as many instructions
-/// as machine registers, but can be used for general code.
-///
-/// TODO: - automagically invoke linearscan for (groups of) small BBs?
-/// - break ties when picking regs? (probably not worth it in a
-/// JIT context)
-///
- class VISIBILITY_HIDDEN RABigBlock : public MachineFunctionPass {
- public:
- static char ID;
- RABigBlock() : MachineFunctionPass(&ID) {}
- private:
- /// TM - For getting at TargetMachine info
- ///
- const TargetMachine *TM;
-
- /// MF - Our generic MachineFunction pointer
- ///
- MachineFunction *MF;
-
- /// RegInfo - For dealing with machine register info (aliases, folds
- /// etc)
- const TargetRegisterInfo *RegInfo;
-
- typedef SmallVector<unsigned, 2> VRegTimes;
-
- /// VRegReadTable - maps VRegs in a BB to the set of times they are read
- ///
- DenseMap<unsigned, VRegTimes*, VRegKeyInfo> VRegReadTable;
-
- /// VRegReadIdx - keeps track of the "current time" in terms of
- /// positions in VRegReadTable
- DenseMap<unsigned, unsigned , VRegKeyInfo> VRegReadIdx;
-
- /// StackSlotForVirtReg - Maps virtual regs to the frame index where these
- /// values are spilled.
- IndexedMap<unsigned, VirtReg2IndexFunctor> StackSlotForVirtReg;
-
- /// Virt2PhysRegMap - This map contains entries for each virtual register
- /// that is currently available in a physical register.
- IndexedMap<unsigned, VirtReg2IndexFunctor> Virt2PhysRegMap;
-
- /// PhysRegsUsed - This array is effectively a map, containing entries for
- /// each physical register that currently has a value (ie, it is in
- /// Virt2PhysRegMap). The value mapped to is the virtual register
- /// corresponding to the physical register (the inverse of the
- /// Virt2PhysRegMap), or 0. The value is set to 0 if this register is pinned
- /// because it is used by a future instruction, and to -2 if it is not
- /// allocatable. If the entry for a physical register is -1, then the
- /// physical register is "not in the map".
- ///
- std::vector<int> PhysRegsUsed;
-
- /// VirtRegModified - This bitset contains information about which virtual
- /// registers need to be spilled back to memory when their registers are
- /// scavenged. If a virtual register has simply been rematerialized, there
- /// is no reason to spill it to memory when we need the register back.
- ///
- std::vector<int> VirtRegModified;
-
- /// MBBLastInsnTime - the number of the the last instruction in MBB
- ///
- int MBBLastInsnTime;
-
- /// MBBCurTime - the number of the the instruction being currently processed
- ///
- int MBBCurTime;
-
- unsigned &getVirt2PhysRegMapSlot(unsigned VirtReg) {
- return Virt2PhysRegMap[VirtReg];
- }
-
- unsigned &getVirt2StackSlot(unsigned VirtReg) {
- return StackSlotForVirtReg[VirtReg];
- }
-
- /// markVirtRegModified - Lets us flip bits in the VirtRegModified bitset
- ///
- void markVirtRegModified(unsigned Reg, bool Val = true) {
- assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Illegal VirtReg!");
- Reg -= TargetRegisterInfo::FirstVirtualRegister;
- if (VirtRegModified.size() <= Reg)
- VirtRegModified.resize(Reg+1);
- VirtRegModified[Reg] = Val;
- }
-
- /// isVirtRegModified - Lets us query the VirtRegModified bitset
- ///
- bool isVirtRegModified(unsigned Reg) const {
- assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Illegal VirtReg!");
- assert(Reg - TargetRegisterInfo::FirstVirtualRegister < VirtRegModified.size()
- && "Illegal virtual register!");
- return VirtRegModified[Reg - TargetRegisterInfo::FirstVirtualRegister];
- }
-
- public:
- /// getPassName - returns the BigBlock allocator's name
- ///
- virtual const char *getPassName() const {
- return "BigBlock Register Allocator";
- }
-
- /// getAnalaysisUsage - declares the required analyses
- ///
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PHIEliminationID);
- AU.addRequiredID(TwoAddressInstructionPassID);
- MachineFunctionPass::getAnalysisUsage(AU);
- }
-
- private:
- /// runOnMachineFunction - Register allocate the whole function
- ///
- bool runOnMachineFunction(MachineFunction &Fn);
-
- /// AllocateBasicBlock - Register allocate the specified basic block.
- ///
- void AllocateBasicBlock(MachineBasicBlock &MBB);
-
- /// FillVRegReadTable - Fill out the table of vreg read times given a BB
- ///
- void FillVRegReadTable(MachineBasicBlock &MBB);
-
- /// areRegsEqual - This method returns true if the specified registers are
- /// related to each other. To do this, it checks to see if they are equal
- /// or if the first register is in the alias set of the second register.
- ///
- bool areRegsEqual(unsigned R1, unsigned R2) const {
- if (R1 == R2) return true;
- for (const unsigned *AliasSet = RegInfo->getAliasSet(R2);
- *AliasSet; ++AliasSet) {
- if (*AliasSet == R1) return true;
- }
- return false;
- }
-
- /// getStackSpaceFor - This returns the frame index of the specified virtual
- /// register on the stack, allocating space if necessary.
- int getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC);
-
- /// removePhysReg - This method marks the specified physical register as no
- /// longer being in use.
- ///
- void removePhysReg(unsigned PhysReg);
-
- /// spillVirtReg - This method spills the value specified by PhysReg into
- /// the virtual register slot specified by VirtReg. It then updates the RA
- /// data structures to indicate the fact that PhysReg is now available.
- ///
- void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
- unsigned VirtReg, unsigned PhysReg);
-
- /// spillPhysReg - This method spills the specified physical register into
- /// the virtual register slot associated with it. If OnlyVirtRegs is set to
- /// true, then the request is ignored if the physical register does not
- /// contain a virtual register.
- ///
- void spillPhysReg(MachineBasicBlock &MBB, MachineInstr *I,
- unsigned PhysReg, bool OnlyVirtRegs = false);
-
- /// assignVirtToPhysReg - This method updates local state so that we know
- /// that PhysReg is the proper container for VirtReg now. The physical
- /// register must not be used for anything else when this is called.
- ///
- void assignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg);
-
- /// isPhysRegAvailable - Return true if the specified physical register is
- /// free and available for use. This also includes checking to see if
- /// aliased registers are all free...
- ///
- bool isPhysRegAvailable(unsigned PhysReg) const;
-
- /// getFreeReg - Look to see if there is a free register available in the
- /// specified register class. If not, return 0.
- ///
- unsigned getFreeReg(const TargetRegisterClass *RC);
-
- /// chooseReg - Pick a physical register to hold the specified
- /// virtual register by choosing the one which will be read furthest
- /// in the future.
- ///
- unsigned chooseReg(MachineBasicBlock &MBB, MachineInstr *MI,
- unsigned VirtReg);
-
- /// reloadVirtReg - This method transforms the specified specified virtual
- /// register use to refer to a physical register. This method may do this
- /// in one of several ways: if the register is available in a physical
- /// register already, it uses that physical register. If the value is not
- /// in a physical register, and if there are physical registers available,
- /// it loads it into a register. If register pressure is high, and it is
- /// possible, it tries to fold the load of the virtual register into the
- /// instruction itself. It avoids doing this if register pressure is low to
- /// improve the chance that subsequent instructions can use the reloaded
- /// value. This method returns the modified instruction.
- ///
- MachineInstr *reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
- unsigned OpNum);
-
- };
- char RABigBlock::ID = 0;
-}
-
-/// getStackSpaceFor - This allocates space for the specified virtual register
-/// to be held on the stack.
-int RABigBlock::getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC) {
- // Find the location Reg would belong...
- int FrameIdx = getVirt2StackSlot(VirtReg);
-
- if (FrameIdx)
- return FrameIdx - 1; // Already has space allocated?
-
- // Allocate a new stack object for this spill location...
- FrameIdx = MF->getFrameInfo()->CreateStackObject(RC->getSize(),
- RC->getAlignment());
-
- // Assign the slot...
- getVirt2StackSlot(VirtReg) = FrameIdx + 1;
- return FrameIdx;
-}
-
-
-/// removePhysReg - This method marks the specified physical register as no
-/// longer being in use.
-///
-void RABigBlock::removePhysReg(unsigned PhysReg) {
- PhysRegsUsed[PhysReg] = -1; // PhyReg no longer used
-}
-
-
-/// spillVirtReg - This method spills the value specified by PhysReg into the
-/// virtual register slot specified by VirtReg. It then updates the RA data
-/// structures to indicate the fact that PhysReg is now available.
-///
-void RABigBlock::spillVirtReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned VirtReg, unsigned PhysReg) {
- assert(VirtReg && "Spilling a physical register is illegal!"
- " Must not have appropriate kill for the register or use exists beyond"
- " the intended one.");
- DOUT << " Spilling register " << RegInfo->getName(PhysReg)
- << " containing %reg" << VirtReg;
-
- const TargetInstrInfo* TII = MBB.getParent()->getTarget().getInstrInfo();
-
- if (!isVirtRegModified(VirtReg))
- DOUT << " which has not been modified, so no store necessary!";
-
- // Otherwise, there is a virtual register corresponding to this physical
- // register. We only need to spill it into its stack slot if it has been
- // modified.
- if (isVirtRegModified(VirtReg)) {
- const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg);
- int FrameIndex = getStackSpaceFor(VirtReg, RC);
- DOUT << " to stack slot #" << FrameIndex;
- TII->storeRegToStackSlot(MBB, I, PhysReg, true, FrameIndex, RC);
- ++NumStores; // Update statistics
- }
-
- getVirt2PhysRegMapSlot(VirtReg) = 0; // VirtReg no longer available
-
- DOUT << "\n";
- removePhysReg(PhysReg);
-}
-
-
-/// spillPhysReg - This method spills the specified physical register into the
-/// virtual register slot associated with it. If OnlyVirtRegs is set to true,
-/// then the request is ignored if the physical register does not contain a
-/// virtual register.
-///
-void RABigBlock::spillPhysReg(MachineBasicBlock &MBB, MachineInstr *I,
- unsigned PhysReg, bool OnlyVirtRegs) {
- if (PhysRegsUsed[PhysReg] != -1) { // Only spill it if it's used!
- assert(PhysRegsUsed[PhysReg] != -2 && "Non allocable reg used!");
- if (PhysRegsUsed[PhysReg] || !OnlyVirtRegs)
- spillVirtReg(MBB, I, PhysRegsUsed[PhysReg], PhysReg);
- } else {
- // If the selected register aliases any other registers, we must make
- // sure that one of the aliases isn't alive.
- for (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg);
- *AliasSet; ++AliasSet)
- if (PhysRegsUsed[*AliasSet] != -1 && // Spill aliased register.
- PhysRegsUsed[*AliasSet] != -2) // If allocatable.
- if (PhysRegsUsed[*AliasSet])
- spillVirtReg(MBB, I, PhysRegsUsed[*AliasSet], *AliasSet);
- }
-}
-
-
-/// assignVirtToPhysReg - This method updates local state so that we know
-/// that PhysReg is the proper container for VirtReg now. The physical
-/// register must not be used for anything else when this is called.
-///
-void RABigBlock::assignVirtToPhysReg(unsigned VirtReg, unsigned PhysReg) {
- assert(PhysRegsUsed[PhysReg] == -1 && "Phys reg already assigned!");
- // Update information to note the fact that this register was just used, and
- // it holds VirtReg.
- PhysRegsUsed[PhysReg] = VirtReg;
- getVirt2PhysRegMapSlot(VirtReg) = PhysReg;
-}
-
-
-/// isPhysRegAvailable - Return true if the specified physical register is free
-/// and available for use. This also includes checking to see if aliased
-/// registers are all free...
-///
-bool RABigBlock::isPhysRegAvailable(unsigned PhysReg) const {
- if (PhysRegsUsed[PhysReg] != -1) return false;
-
- // If the selected register aliases any other allocated registers, it is
- // not free!
- for (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg);
- *AliasSet; ++AliasSet)
- if (PhysRegsUsed[*AliasSet] >= 0) // Aliased register in use?
- return false; // Can't use this reg then.
- return true;
-}
-
-
-/// getFreeReg - Look to see if there is a free register available in the
-/// specified register class. If not, return 0.
-///
-unsigned RABigBlock::getFreeReg(const TargetRegisterClass *RC) {
- // Get iterators defining the range of registers that are valid to allocate in
- // this class, which also specifies the preferred allocation order.
- TargetRegisterClass::iterator RI = RC->allocation_order_begin(*MF);
- TargetRegisterClass::iterator RE = RC->allocation_order_end(*MF);
-
- for (; RI != RE; ++RI)
- if (isPhysRegAvailable(*RI)) { // Is reg unused?
- assert(*RI != 0 && "Cannot use register!");
- return *RI; // Found an unused register!
- }
- return 0;
-}
-
-
-/// chooseReg - Pick a physical register to hold the specified
-/// virtual register by choosing the one whose value will be read
-/// furthest in the future.
-///
-unsigned RABigBlock::chooseReg(MachineBasicBlock &MBB, MachineInstr *I,
- unsigned VirtReg) {
- const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg);
- // First check to see if we have a free register of the requested type...
- unsigned PhysReg = getFreeReg(RC);
-
- // If we didn't find an unused register, find the one which will be
- // read at the most distant point in time.
- if (PhysReg == 0) {
- unsigned delay=0, longest_delay=0;
- VRegTimes* ReadTimes;
-
- unsigned curTime = MBBCurTime;
-
- // for all physical regs in the RC,
- for(TargetRegisterClass::iterator pReg = RC->begin();
- pReg != RC->end(); ++pReg) {
- // how long until they're read?
- if(PhysRegsUsed[*pReg]>0) { // ignore non-allocatable regs
- ReadTimes = VRegReadTable[PhysRegsUsed[*pReg]];
- if(ReadTimes && !ReadTimes->empty()) {
- unsigned& pt = VRegReadIdx[PhysRegsUsed[*pReg]];
- while(pt < ReadTimes->size() && (*ReadTimes)[pt] < curTime) {
- ++pt;
- }
-
- if(pt < ReadTimes->size())
- delay = (*ReadTimes)[pt] - curTime;
- else
- delay = MBBLastInsnTime + 1 - curTime;
- } else {
- // This register is only defined, but never
- // read in this MBB. Therefore the next read
- // happens after the end of this MBB
- delay = MBBLastInsnTime + 1 - curTime;
- }
-
-
- if(delay > longest_delay) {
- longest_delay = delay;
- PhysReg = *pReg;
- }
- }
- }
-
- if(PhysReg == 0) { // ok, now we're desperate. We couldn't choose
- // a register to spill by looking through the
- // read timetable, so now we just spill the
- // first allocatable register we find.
-
- // for all physical regs in the RC,
- for(TargetRegisterClass::iterator pReg = RC->begin();
- pReg != RC->end(); ++pReg) {
- // if we find a register we can spill
- if(PhysRegsUsed[*pReg]>=-1)
- PhysReg = *pReg; // choose it to be spilled
- }
- }
-
- assert(PhysReg && "couldn't choose a register to spill :( ");
- // TODO: assert that RC->contains(PhysReg) / handle aliased registers?
-
- // since we needed to look in the table we need to spill this register.
- spillPhysReg(MBB, I, PhysReg);
- }
-
- // assign the vreg to our chosen physical register
- assignVirtToPhysReg(VirtReg, PhysReg);
- return PhysReg; // and return it
-}
-
-
-/// reloadVirtReg - This method transforms an instruction with a virtual
-/// register use to one that references a physical register. It does this as
-/// follows:
-///
-/// 1) If the register is already in a physical register, it uses it.
-/// 2) Otherwise, if there is a free physical register, it uses that.
-/// 3) Otherwise, it calls chooseReg() to get the physical register
-/// holding the most distantly needed value, generating a spill in
-/// the process.
-///
-/// This method returns the modified instruction.
-MachineInstr *RABigBlock::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI,
- unsigned OpNum) {
- unsigned VirtReg = MI->getOperand(OpNum).getReg();
- const TargetInstrInfo* TII = MBB.getParent()->getTarget().getInstrInfo();
-
- // If the virtual register is already available in a physical register,
- // just update the instruction and return.
- if (unsigned PR = getVirt2PhysRegMapSlot(VirtReg)) {
- MI->getOperand(OpNum).setReg(PR);
- return MI;
- }
-
- // Otherwise, if we have free physical registers available to hold the
- // value, use them.
- const TargetRegisterClass *RC = MF->getRegInfo().getRegClass(VirtReg);
- unsigned PhysReg = getFreeReg(RC);
- int FrameIndex = getStackSpaceFor(VirtReg, RC);
-
- if (PhysReg) { // we have a free register, so use it.
- assignVirtToPhysReg(VirtReg, PhysReg);
- } else { // no free registers available.
- // try to fold the spill into the instruction
- SmallVector<unsigned, 1> Ops;
- Ops.push_back(OpNum);
- if(MachineInstr* FMI = TII->foldMemoryOperand(*MF, MI, Ops, FrameIndex)) {
- ++NumFolded;
- FMI->copyKillDeadInfo(MI);
- return MBB.insert(MBB.erase(MI), FMI);
- }
-
- // determine which of the physical registers we'll kill off, since we
- // couldn't fold.
- PhysReg = chooseReg(MBB, MI, VirtReg);
- }
-
- // this virtual register is now unmodified (since we just reloaded it)
- markVirtRegModified(VirtReg, false);
-
- DOUT << " Reloading %reg" << VirtReg << " into "
- << RegInfo->getName(PhysReg) << "\n";
-
- // Add move instruction(s)
- TII->loadRegFromStackSlot(MBB, MI, PhysReg, FrameIndex, RC);
- ++NumLoads; // Update statistics
-
- MF->getRegInfo().setPhysRegUsed(PhysReg);
- MI->getOperand(OpNum).setReg(PhysReg); // Assign the input register
- return MI;
-}
-
-/// Fill out the vreg read timetable. Since ReadTime increases
-/// monotonically, the individual readtime sets will be sorted
-/// in ascending order.
-void RABigBlock::FillVRegReadTable(MachineBasicBlock &MBB) {
- // loop over each instruction
- MachineBasicBlock::iterator MII;
- unsigned ReadTime;
-
- for(ReadTime=0, MII = MBB.begin(); MII != MBB.end(); ++ReadTime, ++MII) {
- MachineInstr *MI = MII;
-
- for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
- MachineOperand& MO = MI->getOperand(i);
- // look for vreg reads..
- if (MO.isReg() && !MO.isDef() && MO.getReg() &&
- TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
- // ..and add them to the read table.
- VRegTimes* &Times = VRegReadTable[MO.getReg()];
- if(!VRegReadTable[MO.getReg()]) {
- Times = new VRegTimes;
- VRegReadIdx[MO.getReg()] = 0;
- }
- Times->push_back(ReadTime);
- }
- }
-
- }
-
- MBBLastInsnTime = ReadTime;
-
- for(DenseMap<unsigned, VRegTimes*, VRegKeyInfo>::iterator Reads = VRegReadTable.begin();
- Reads != VRegReadTable.end(); ++Reads) {
- if(Reads->second) {
- DOUT << "Reads[" << Reads->first << "]=" << Reads->second->size() << "\n";
- }
- }
-}
-
-/// isReadModWriteImplicitKill - True if this is an implicit kill for a
-/// read/mod/write register, i.e. update partial register.
-static bool isReadModWriteImplicitKill(MachineInstr *MI, unsigned Reg) {
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand& MO = MI->getOperand(i);
- if (MO.isReg() && MO.getReg() == Reg && MO.isImplicit() &&
- MO.isDef() && !MO.isDead())
- return true;
- }
- return false;
-}
-
-/// isReadModWriteImplicitDef - True if this is an implicit def for a
-/// read/mod/write register, i.e. update partial register.
-static bool isReadModWriteImplicitDef(MachineInstr *MI, unsigned Reg) {
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand& MO = MI->getOperand(i);
- if (MO.isReg() && MO.getReg() == Reg && MO.isImplicit() &&
- !MO.isDef() && MO.isKill())
- return true;
- }
- return false;
-}
-
-
-void RABigBlock::AllocateBasicBlock(MachineBasicBlock &MBB) {
- // loop over each instruction
- MachineBasicBlock::iterator MII = MBB.begin();
- const TargetInstrInfo &TII = *TM->getInstrInfo();
-
- DEBUG(const BasicBlock *LBB = MBB.getBasicBlock();
- if (LBB) DOUT << "\nStarting RegAlloc of BB: " << LBB->getName());
-
- // If this is the first basic block in the machine function, add live-in
- // registers as active.
- if (&MBB == &*MF->begin()) {
- for (MachineRegisterInfo::livein_iterator
- I = MF->getRegInfo().livein_begin(),
- E = MF->getRegInfo().livein_end(); I != E; ++I) {
- unsigned Reg = I->first;
- MF->getRegInfo().setPhysRegUsed(Reg);
- PhysRegsUsed[Reg] = 0; // It is free and reserved now
- for (const unsigned *AliasSet = RegInfo->getSubRegisters(Reg);
- *AliasSet; ++AliasSet) {
- if (PhysRegsUsed[*AliasSet] != -2) {
- PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now
- MF->getRegInfo().setPhysRegUsed(*AliasSet);
- }
- }
- }
- }
-
- // Otherwise, sequentially allocate each instruction in the MBB.
- MBBCurTime = -1;
- while (MII != MBB.end()) {
- MachineInstr *MI = MII++;
- MBBCurTime++;
- const TargetInstrDesc &TID = MI->getDesc();
- DEBUG(DOUT << "\nTime=" << MBBCurTime << " Starting RegAlloc of: " << *MI;
- DOUT << " Regs have values: ";
- for (unsigned i = 0; i != RegInfo->getNumRegs(); ++i)
- if (PhysRegsUsed[i] != -1 && PhysRegsUsed[i] != -2)
- DOUT << "[" << RegInfo->getName(i)
- << ",%reg" << PhysRegsUsed[i] << "] ";
- DOUT << "\n");
-
- SmallVector<unsigned, 8> Kills;
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand& MO = MI->getOperand(i);
- if (MO.isReg() && MO.isKill()) {
- if (!MO.isImplicit())
- Kills.push_back(MO.getReg());
- else if (!isReadModWriteImplicitKill(MI, MO.getReg()))
- // These are extra physical register kills when a sub-register
- // is defined (def of a sub-register is a read/mod/write of the
- // larger registers). Ignore.
- Kills.push_back(MO.getReg());
- }
- }
-
- // Get the used operands into registers. This has the potential to spill
- // incoming values if we are out of registers. Note that we completely
- // ignore physical register uses here. We assume that if an explicit
- // physical register is referenced by the instruction, that it is guaranteed
- // to be live-in, or the input is badly hosed.
- //
- for (unsigned i = 0; i != MI->getNumOperands(); ++i) {
- MachineOperand& MO = MI->getOperand(i);
- // here we are looking for only used operands (never def&use)
- if (MO.isReg() && !MO.isDef() && MO.getReg() && !MO.isImplicit() &&
- TargetRegisterInfo::isVirtualRegister(MO.getReg()))
- MI = reloadVirtReg(MBB, MI, i);
- }
-
- // If this instruction is the last user of this register, kill the
- // value, freeing the register being used, so it doesn't need to be
- // spilled to memory.
- //
- for (unsigned i = 0, e = Kills.size(); i != e; ++i) {
- unsigned VirtReg = Kills[i];
- unsigned PhysReg = VirtReg;
- if (TargetRegisterInfo::isVirtualRegister(VirtReg)) {
- // If the virtual register was never materialized into a register, it
- // might not be in the map, but it won't hurt to zero it out anyway.
- unsigned &PhysRegSlot = getVirt2PhysRegMapSlot(VirtReg);
- PhysReg = PhysRegSlot;
- PhysRegSlot = 0;
- } else if (PhysRegsUsed[PhysReg] == -2) {
- // Unallocatable register dead, ignore.
- continue;
- } else {
- assert((!PhysRegsUsed[PhysReg] || PhysRegsUsed[PhysReg] == -1) &&
- "Silently clearing a virtual register?");
- }
-
- if (PhysReg) {
- DOUT << " Last use of " << RegInfo->getName(PhysReg)
- << "[%reg" << VirtReg <<"], removing it from live set\n";
- removePhysReg(PhysReg);
- for (const unsigned *AliasSet = RegInfo->getSubRegisters(PhysReg);
- *AliasSet; ++AliasSet) {
- if (PhysRegsUsed[*AliasSet] != -2) {
- DOUT << " Last use of "
- << RegInfo->getName(*AliasSet)
- << "[%reg" << VirtReg <<"], removing it from live set\n";
- removePhysReg(*AliasSet);
- }
- }
- }
- }
-
- // Loop over all of the operands of the instruction, spilling registers that
- // are defined, and marking explicit destinations in the PhysRegsUsed map.
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand& MO = MI->getOperand(i);
- if (MO.isReg() && MO.isDef() && !MO.isImplicit() && MO.getReg() &&
- TargetRegisterInfo::isPhysicalRegister(MO.getReg())) {
- unsigned Reg = MO.getReg();
- if (PhysRegsUsed[Reg] == -2) continue; // Something like ESP.
- // These are extra physical register defs when a sub-register
- // is defined (def of a sub-register is a read/mod/write of the
- // larger registers). Ignore.
- if (isReadModWriteImplicitDef(MI, MO.getReg())) continue;
-
- MF->getRegInfo().setPhysRegUsed(Reg);
- spillPhysReg(MBB, MI, Reg, true); // Spill any existing value in reg
- PhysRegsUsed[Reg] = 0; // It is free and reserved now
- for (const unsigned *AliasSet = RegInfo->getSubRegisters(Reg);
- *AliasSet; ++AliasSet) {
- if (PhysRegsUsed[*AliasSet] != -2) {
- PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now
- MF->getRegInfo().setPhysRegUsed(*AliasSet);
- }
- }
- }
- }
-
- // Loop over the implicit defs, spilling them as well.
- if (TID.getImplicitDefs()) {
- for (const unsigned *ImplicitDefs = TID.getImplicitDefs();
- *ImplicitDefs; ++ImplicitDefs) {
- unsigned Reg = *ImplicitDefs;
- if (PhysRegsUsed[Reg] != -2) {
- spillPhysReg(MBB, MI, Reg, true);
- PhysRegsUsed[Reg] = 0; // It is free and reserved now
- }
- MF->getRegInfo().setPhysRegUsed(Reg);
- for (const unsigned *AliasSet = RegInfo->getSubRegisters(Reg);
- *AliasSet; ++AliasSet) {
- if (PhysRegsUsed[*AliasSet] != -2) {
- PhysRegsUsed[*AliasSet] = 0; // It is free and reserved now
- MF->getRegInfo().setPhysRegUsed(*AliasSet);
- }
- }
- }
- }
-
- SmallVector<unsigned, 8> DeadDefs;
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand& MO = MI->getOperand(i);
- if (MO.isReg() && MO.isDead())
- DeadDefs.push_back(MO.getReg());
- }
-
- // Okay, we have allocated all of the source operands and spilled any values
- // that would be destroyed by defs of this instruction. Loop over the
- // explicit defs and assign them to a register, spilling incoming values if
- // we need to scavenge a register.
- //
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand& MO = MI->getOperand(i);
- if (MO.isReg() && MO.isDef() && MO.getReg() &&
- TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
- unsigned DestVirtReg = MO.getReg();
- unsigned DestPhysReg;
-
- // If DestVirtReg already has a value, use it.
- if (!(DestPhysReg = getVirt2PhysRegMapSlot(DestVirtReg)))
- DestPhysReg = chooseReg(MBB, MI, DestVirtReg);
- MF->getRegInfo().setPhysRegUsed(DestPhysReg);
- markVirtRegModified(DestVirtReg);
- MI->getOperand(i).setReg(DestPhysReg); // Assign the output register
- }
- }
-
- // If this instruction defines any registers that are immediately dead,
- // kill them now.
- //
- for (unsigned i = 0, e = DeadDefs.size(); i != e; ++i) {
- unsigned VirtReg = DeadDefs[i];
- unsigned PhysReg = VirtReg;
- if (TargetRegisterInfo::isVirtualRegister(VirtReg)) {
- unsigned &PhysRegSlot = getVirt2PhysRegMapSlot(VirtReg);
- PhysReg = PhysRegSlot;
- assert(PhysReg != 0);
- PhysRegSlot = 0;
- } else if (PhysRegsUsed[PhysReg] == -2) {
- // Unallocatable register dead, ignore.
- continue;
- }
-
- if (PhysReg) {
- DOUT << " Register " << RegInfo->getName(PhysReg)
- << " [%reg" << VirtReg
- << "] is never used, removing it from live set\n";
- removePhysReg(PhysReg);
- for (const unsigned *AliasSet = RegInfo->getAliasSet(PhysReg);
- *AliasSet; ++AliasSet) {
- if (PhysRegsUsed[*AliasSet] != -2) {
- DOUT << " Register " << RegInfo->getName(*AliasSet)
- << " [%reg" << *AliasSet
- << "] is never used, removing it from live set\n";
- removePhysReg(*AliasSet);
- }
- }
- }
- }
-
- // Finally, if this is a noop copy instruction, zap it.
- unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
- if (TII.isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
- SrcReg == DstReg)
- MBB.erase(MI);
- }
-
- MachineBasicBlock::iterator MI = MBB.getFirstTerminator();
-
- // Spill all physical registers holding virtual registers now.
- for (unsigned i = 0, e = RegInfo->getNumRegs(); i != e; ++i)
- if (PhysRegsUsed[i] != -1 && PhysRegsUsed[i] != -2) {
- if (unsigned VirtReg = PhysRegsUsed[i])
- spillVirtReg(MBB, MI, VirtReg, i);
- else
- removePhysReg(i);
- }
-}
-
-/// runOnMachineFunction - Register allocate the whole function
-///
-bool RABigBlock::runOnMachineFunction(MachineFunction &Fn) {
- DOUT << "Machine Function " << "\n";
- MF = &Fn;
- TM = &Fn.getTarget();
- RegInfo = TM->getRegisterInfo();
-
- PhysRegsUsed.assign(RegInfo->getNumRegs(), -1);
-
- // At various places we want to efficiently check to see whether a register
- // is allocatable. To handle this, we mark all unallocatable registers as
- // being pinned down, permanently.
- {
- BitVector Allocable = RegInfo->getAllocatableSet(Fn);
- for (unsigned i = 0, e = Allocable.size(); i != e; ++i)
- if (!Allocable[i])
- PhysRegsUsed[i] = -2; // Mark the reg unallocable.
- }
-
- // initialize the virtual->physical register map to have a 'null'
- // mapping for all virtual registers
- Virt2PhysRegMap.grow(MF->getRegInfo().getLastVirtReg());
- StackSlotForVirtReg.grow(MF->getRegInfo().getLastVirtReg());
- VirtRegModified.resize(MF->getRegInfo().getLastVirtReg() -
- TargetRegisterInfo::FirstVirtualRegister + 1, 0);
-
- // Loop over all of the basic blocks, eliminating virtual register references
- for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
- MBB != MBBe; ++MBB) {
- // fill out the read timetable
- FillVRegReadTable(*MBB);
- // use it to allocate the BB
- AllocateBasicBlock(*MBB);
- // clear it
- VRegReadTable.clear();
- }
-
- StackSlotForVirtReg.clear();
- PhysRegsUsed.clear();
- VirtRegModified.clear();
- Virt2PhysRegMap.clear();
- return true;
-}
-
-FunctionPass *llvm::createBigBlockRegisterAllocator() {
- return new RABigBlock();
-}
-
diff --git a/lib/CodeGen/RegAllocSimple.cpp b/lib/CodeGen/RegAllocSimple.cpp
deleted file mode 100644
index 447e54c..0000000
--- a/lib/CodeGen/RegAllocSimple.cpp
+++ /dev/null
@@ -1,257 +0,0 @@
-//===-- RegAllocSimple.cpp - A simple generic register allocator ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a simple register allocator. *Very* simple: It immediate
-// spills every value right after it is computed, and it reloads all used
-// operands from the spill area to temporary registers before each instruction.
-// It does not keep values in registers across instructions.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "regalloc"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/RegAllocRegistry.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/STLExtras.h"
-#include <map>
-using namespace llvm;
-
-STATISTIC(NumStores, "Number of stores added");
-STATISTIC(NumLoads , "Number of loads added");
-
-namespace {
- static RegisterRegAlloc
- simpleRegAlloc("simple", "simple register allocator",
- createSimpleRegisterAllocator);
-
- class VISIBILITY_HIDDEN RegAllocSimple : public MachineFunctionPass {
- public:
- static char ID;
- RegAllocSimple() : MachineFunctionPass(&ID) {}
- private:
- MachineFunction *MF;
- const TargetMachine *TM;
- const TargetRegisterInfo *TRI;
- const TargetInstrInfo *TII;
-
- // StackSlotForVirtReg - Maps SSA Regs => frame index on the stack where
- // these values are spilled
- std::map<unsigned, int> StackSlotForVirtReg;
-
- // RegsUsed - Keep track of what registers are currently in use. This is a
- // bitset.
- std::vector<bool> RegsUsed;
-
- // RegClassIdx - Maps RegClass => which index we can take a register
- // from. Since this is a simple register allocator, when we need a register
- // of a certain class, we just take the next available one.
- std::map<const TargetRegisterClass*, unsigned> RegClassIdx;
-
- public:
- virtual const char *getPassName() const {
- return "Simple Register Allocator";
- }
-
- /// runOnMachineFunction - Register allocate the whole function
- bool runOnMachineFunction(MachineFunction &Fn);
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(PHIEliminationID); // Eliminate PHI nodes
- MachineFunctionPass::getAnalysisUsage(AU);
- }
- private:
- /// AllocateBasicBlock - Register allocate the specified basic block.
- void AllocateBasicBlock(MachineBasicBlock &MBB);
-
- /// getStackSpaceFor - This returns the offset of the specified virtual
- /// register on the stack, allocating space if necessary.
- int getStackSpaceFor(unsigned VirtReg, const TargetRegisterClass *RC);
-
- /// Given a virtual register, return a compatible physical register that is
- /// currently unused.
- ///
- /// Side effect: marks that register as being used until manually cleared
- ///
- unsigned getFreeReg(unsigned virtualReg);
-
- /// Moves value from memory into that register
- unsigned reloadVirtReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I, unsigned VirtReg);
-
- /// Saves reg value on the stack (maps virtual register to stack value)
- void spillVirtReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
- unsigned VirtReg, unsigned PhysReg);
- };
- char RegAllocSimple::ID = 0;
-}
-
-/// getStackSpaceFor - This allocates space for the specified virtual
-/// register to be held on the stack.
-int RegAllocSimple::getStackSpaceFor(unsigned VirtReg,
- const TargetRegisterClass *RC) {
- // Find the location VirtReg would belong...
- std::map<unsigned, int>::iterator I = StackSlotForVirtReg.find(VirtReg);
-
- if (I != StackSlotForVirtReg.end())
- return I->second; // Already has space allocated?
-
- // Allocate a new stack object for this spill location...
- int FrameIdx = MF->getFrameInfo()->CreateStackObject(RC->getSize(),
- RC->getAlignment());
-
- // Assign the slot...
- StackSlotForVirtReg.insert(I, std::make_pair(VirtReg, FrameIdx));
-
- return FrameIdx;
-}
-
-unsigned RegAllocSimple::getFreeReg(unsigned virtualReg) {
- const TargetRegisterClass* RC = MF->getRegInfo().getRegClass(virtualReg);
- TargetRegisterClass::iterator RI = RC->allocation_order_begin(*MF);
-#ifndef NDEBUG
- TargetRegisterClass::iterator RE = RC->allocation_order_end(*MF);
-#endif
-
- while (1) {
- unsigned regIdx = RegClassIdx[RC]++;
- assert(RI+regIdx != RE && "Not enough registers!");
- unsigned PhysReg = *(RI+regIdx);
-
- if (!RegsUsed[PhysReg]) {
- MF->getRegInfo().setPhysRegUsed(PhysReg);
- return PhysReg;
- }
- }
-}
-
-unsigned RegAllocSimple::reloadVirtReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned VirtReg) {
- const TargetRegisterClass* RC = MF->getRegInfo().getRegClass(VirtReg);
- int FrameIdx = getStackSpaceFor(VirtReg, RC);
- unsigned PhysReg = getFreeReg(VirtReg);
-
- // Add move instruction(s)
- ++NumLoads;
- TII->loadRegFromStackSlot(MBB, I, PhysReg, FrameIdx, RC);
- return PhysReg;
-}
-
-void RegAllocSimple::spillVirtReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I,
- unsigned VirtReg, unsigned PhysReg) {
- const TargetRegisterClass* RC = MF->getRegInfo().getRegClass(VirtReg);
-
- int FrameIdx = getStackSpaceFor(VirtReg, RC);
-
- // Add move instruction(s)
- ++NumStores;
- TII->storeRegToStackSlot(MBB, I, PhysReg, true, FrameIdx, RC);
-}
-
-
-void RegAllocSimple::AllocateBasicBlock(MachineBasicBlock &MBB) {
- // loop over each instruction
- for (MachineBasicBlock::iterator MI = MBB.begin(); MI != MBB.end(); ++MI) {
- // Made to combat the incorrect allocation of r2 = add r1, r1
- std::map<unsigned, unsigned> Virt2PhysRegMap;
-
- RegsUsed.resize(TRI->getNumRegs());
-
- // This is a preliminary pass that will invalidate any registers that are
- // used by the instruction (including implicit uses).
- const TargetInstrDesc &Desc = MI->getDesc();
- const unsigned *Regs;
- if (Desc.ImplicitUses) {
- for (Regs = Desc.ImplicitUses; *Regs; ++Regs)
- RegsUsed[*Regs] = true;
- }
-
- if (Desc.ImplicitDefs) {
- for (Regs = Desc.ImplicitDefs; *Regs; ++Regs) {
- RegsUsed[*Regs] = true;
- MF->getRegInfo().setPhysRegUsed(*Regs);
- }
- }
-
- // Loop over uses, move from memory into registers.
- for (int i = MI->getNumOperands() - 1; i >= 0; --i) {
- MachineOperand &MO = MI->getOperand(i);
-
- if (MO.isReg() && MO.getReg() &&
- TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
- unsigned virtualReg = (unsigned) MO.getReg();
- DOUT << "op: " << MO << "\n";
- DOUT << "\t inst[" << i << "]: ";
- DEBUG(MI->print(*cerr.stream(), TM));
-
- // make sure the same virtual register maps to the same physical
- // register in any given instruction
- unsigned physReg = Virt2PhysRegMap[virtualReg];
- if (physReg == 0) {
- if (MO.isDef()) {
- unsigned TiedOp;
- if (!MI->isRegTiedToUseOperand(i, &TiedOp)) {
- physReg = getFreeReg(virtualReg);
- } else {
- // must be same register number as the source operand that is
- // tied to. This maps a = b + c into b = b + c, and saves b into
- // a's spot.
- assert(MI->getOperand(TiedOp).isReg() &&
- MI->getOperand(TiedOp).getReg() &&
- MI->getOperand(TiedOp).isUse() &&
- "Two address instruction invalid!");
-
- physReg = MI->getOperand(TiedOp).getReg();
- }
- spillVirtReg(MBB, next(MI), virtualReg, physReg);
- } else {
- physReg = reloadVirtReg(MBB, MI, virtualReg);
- Virt2PhysRegMap[virtualReg] = physReg;
- }
- }
- MO.setReg(physReg);
- DOUT << "virt: " << virtualReg << ", phys: " << MO.getReg() << "\n";
- }
- }
- RegClassIdx.clear();
- RegsUsed.clear();
- }
-}
-
-
-/// runOnMachineFunction - Register allocate the whole function
-///
-bool RegAllocSimple::runOnMachineFunction(MachineFunction &Fn) {
- DOUT << "Machine Function\n";
- MF = &Fn;
- TM = &MF->getTarget();
- TRI = TM->getRegisterInfo();
- TII = TM->getInstrInfo();
-
- // Loop over all of the basic blocks, eliminating virtual register references
- for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
- MBB != MBBe; ++MBB)
- AllocateBasicBlock(*MBB);
-
- StackSlotForVirtReg.clear();
- return true;
-}
-
-FunctionPass *llvm::createSimpleRegisterAllocator() {
- return new RegAllocSimple();
-}
diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
deleted file mode 100644
index 7926339..0000000
--- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp
+++ /dev/null
@@ -1,671 +0,0 @@
-//===---- ScheduleDAGEmit.cpp - Emit routines for the ScheduleDAG class ---===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This implements the Emit routines for the ScheduleDAG class, which creates
-// MachineInstrs according to the computed schedule.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "pre-RA-sched"
-#include "ScheduleDAGSDNodes.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetLowering.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/MathExtras.h"
-using namespace llvm;
-
-/// EmitCopyFromReg - Generate machine code for an CopyFromReg node or an
-/// implicit physical register output.
-void ScheduleDAGSDNodes::
-EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned,
- unsigned SrcReg, DenseMap<SDValue, unsigned> &VRBaseMap) {
- unsigned VRBase = 0;
- if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
- // Just use the input register directly!
- SDValue Op(Node, ResNo);
- if (IsClone)
- VRBaseMap.erase(Op);
- bool isNew = VRBaseMap.insert(std::make_pair(Op, SrcReg)).second;
- isNew = isNew; // Silence compiler warning.
- assert(isNew && "Node emitted out of order - early");
- return;
- }
-
- // If the node is only used by a CopyToReg and the dest reg is a vreg, use
- // the CopyToReg'd destination register instead of creating a new vreg.
- bool MatchReg = true;
- const TargetRegisterClass *UseRC = NULL;
- if (!IsClone && !IsCloned)
- for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
- UI != E; ++UI) {
- SDNode *User = *UI;
- bool Match = true;
- if (User->getOpcode() == ISD::CopyToReg &&
- User->getOperand(2).getNode() == Node &&
- User->getOperand(2).getResNo() == ResNo) {
- unsigned DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
- if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
- VRBase = DestReg;
- Match = false;
- } else if (DestReg != SrcReg)
- Match = false;
- } else {
- for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
- SDValue Op = User->getOperand(i);
- if (Op.getNode() != Node || Op.getResNo() != ResNo)
- continue;
- MVT VT = Node->getValueType(Op.getResNo());
- if (VT == MVT::Other || VT == MVT::Flag)
- continue;
- Match = false;
- if (User->isMachineOpcode()) {
- const TargetInstrDesc &II = TII->get(User->getMachineOpcode());
- const TargetRegisterClass *RC =
- getInstrOperandRegClass(TRI, II, i+II.getNumDefs());
- if (!UseRC)
- UseRC = RC;
- else if (RC) {
- if (UseRC->hasSuperClass(RC))
- UseRC = RC;
- else
- assert((UseRC == RC || RC->hasSuperClass(UseRC)) &&
- "Multiple uses expecting different register classes!");
- }
- }
- }
- }
- MatchReg &= Match;
- if (VRBase)
- break;
- }
-
- MVT VT = Node->getValueType(ResNo);
- const TargetRegisterClass *SrcRC = 0, *DstRC = 0;
- SrcRC = TRI->getPhysicalRegisterRegClass(SrcReg, VT);
-
- // Figure out the register class to create for the destreg.
- if (VRBase) {
- DstRC = MRI.getRegClass(VRBase);
- } else if (UseRC) {
- assert(UseRC->hasType(VT) && "Incompatible phys register def and uses!");
- DstRC = UseRC;
- } else {
- DstRC = TLI->getRegClassFor(VT);
- }
-
- // If all uses are reading from the src physical register and copying the
- // register is either impossible or very expensive, then don't create a copy.
- if (MatchReg && SrcRC->getCopyCost() < 0) {
- VRBase = SrcReg;
- } else {
- // Create the reg, emit the copy.
- VRBase = MRI.createVirtualRegister(DstRC);
- bool Emitted = TII->copyRegToReg(*BB, InsertPos, VRBase, SrcReg,
- DstRC, SrcRC);
-
- assert(Emitted && "Unable to issue a copy instruction!\n");
- (void) Emitted;
- }
-
- SDValue Op(Node, ResNo);
- if (IsClone)
- VRBaseMap.erase(Op);
- bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second;
- isNew = isNew; // Silence compiler warning.
- assert(isNew && "Node emitted out of order - early");
-}
-
-/// getDstOfCopyToRegUse - If the only use of the specified result number of
-/// node is a CopyToReg, return its destination register. Return 0 otherwise.
-unsigned ScheduleDAGSDNodes::getDstOfOnlyCopyToRegUse(SDNode *Node,
- unsigned ResNo) const {
- if (!Node->hasOneUse())
- return 0;
-
- SDNode *User = *Node->use_begin();
- if (User->getOpcode() == ISD::CopyToReg &&
- User->getOperand(2).getNode() == Node &&
- User->getOperand(2).getResNo() == ResNo) {
- unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
- if (TargetRegisterInfo::isVirtualRegister(Reg))
- return Reg;
- }
- return 0;
-}
-
-void ScheduleDAGSDNodes::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
- const TargetInstrDesc &II,
- bool IsClone, bool IsCloned,
- DenseMap<SDValue, unsigned> &VRBaseMap) {
- assert(Node->getMachineOpcode() != TargetInstrInfo::IMPLICIT_DEF &&
- "IMPLICIT_DEF should have been handled as a special case elsewhere!");
-
- for (unsigned i = 0; i < II.getNumDefs(); ++i) {
- // If the specific node value is only used by a CopyToReg and the dest reg
- // is a vreg in the same register class, use the CopyToReg'd destination
- // register instead of creating a new vreg.
- unsigned VRBase = 0;
- const TargetRegisterClass *RC = getInstrOperandRegClass(TRI, II, i);
-
- if (!IsClone && !IsCloned)
- for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
- UI != E; ++UI) {
- SDNode *User = *UI;
- if (User->getOpcode() == ISD::CopyToReg &&
- User->getOperand(2).getNode() == Node &&
- User->getOperand(2).getResNo() == i) {
- unsigned Reg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
- if (TargetRegisterInfo::isVirtualRegister(Reg)) {
- const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
- if (RegRC == RC) {
- VRBase = Reg;
- MI->addOperand(MachineOperand::CreateReg(Reg, true));
- break;
- }
- }
- }
- }
-
- // Create the result registers for this node and add the result regs to
- // the machine instruction.
- if (VRBase == 0) {
- assert(RC && "Isn't a register operand!");
- VRBase = MRI.createVirtualRegister(RC);
- MI->addOperand(MachineOperand::CreateReg(VRBase, true));
- }
-
- SDValue Op(Node, i);
- if (IsClone)
- VRBaseMap.erase(Op);
- bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second;
- isNew = isNew; // Silence compiler warning.
- assert(isNew && "Node emitted out of order - early");
- }
-}
-
-/// getVR - Return the virtual register corresponding to the specified result
-/// of the specified node.
-unsigned ScheduleDAGSDNodes::getVR(SDValue Op,
- DenseMap<SDValue, unsigned> &VRBaseMap) {
- if (Op.isMachineOpcode() &&
- Op.getMachineOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
- // Add an IMPLICIT_DEF instruction before every use.
- unsigned VReg = getDstOfOnlyCopyToRegUse(Op.getNode(), Op.getResNo());
- // IMPLICIT_DEF can produce any type of result so its TargetInstrDesc
- // does not include operand register class info.
- if (!VReg) {
- const TargetRegisterClass *RC = TLI->getRegClassFor(Op.getValueType());
- VReg = MRI.createVirtualRegister(RC);
- }
- BuildMI(BB, Op.getDebugLoc(), TII->get(TargetInstrInfo::IMPLICIT_DEF),VReg);
- return VReg;
- }
-
- DenseMap<SDValue, unsigned>::iterator I = VRBaseMap.find(Op);
- assert(I != VRBaseMap.end() && "Node emitted out of order - late");
- return I->second;
-}
-
-
-/// AddRegisterOperand - Add the specified register as an operand to the
-/// specified machine instr. Insert register copies if the register is
-/// not in the required register class.
-void
-ScheduleDAGSDNodes::AddRegisterOperand(MachineInstr *MI, SDValue Op,
- unsigned IIOpNum,
- const TargetInstrDesc *II,
- DenseMap<SDValue, unsigned> &VRBaseMap) {
- assert(Op.getValueType() != MVT::Other &&
- Op.getValueType() != MVT::Flag &&
- "Chain and flag operands should occur at end of operand list!");
- // Get/emit the operand.
- unsigned VReg = getVR(Op, VRBaseMap);
- assert(TargetRegisterInfo::isVirtualRegister(VReg) && "Not a vreg?");
-
- const TargetInstrDesc &TID = MI->getDesc();
- bool isOptDef = IIOpNum < TID.getNumOperands() &&
- TID.OpInfo[IIOpNum].isOptionalDef();
-
- // If the instruction requires a register in a different class, create
- // a new virtual register and copy the value into it.
- if (II) {
- const TargetRegisterClass *SrcRC =
- MRI.getRegClass(VReg);
- const TargetRegisterClass *DstRC =
- getInstrOperandRegClass(TRI, *II, IIOpNum);
- assert((DstRC || (TID.isVariadic() && IIOpNum >= TID.getNumOperands())) &&
- "Don't have operand info for this instruction!");
- if (DstRC && SrcRC != DstRC && !SrcRC->hasSuperClass(DstRC)) {
- unsigned NewVReg = MRI.createVirtualRegister(DstRC);
- bool Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
- DstRC, SrcRC);
- assert(Emitted && "Unable to issue a copy instruction!\n");
- (void) Emitted;
- VReg = NewVReg;
- }
- }
-
- MI->addOperand(MachineOperand::CreateReg(VReg, isOptDef));
-}
-
-/// AddOperand - Add the specified operand to the specified machine instr. II
-/// specifies the instruction information for the node, and IIOpNum is the
-/// operand number (in the II) that we are adding. IIOpNum and II are used for
-/// assertions only.
-void ScheduleDAGSDNodes::AddOperand(MachineInstr *MI, SDValue Op,
- unsigned IIOpNum,
- const TargetInstrDesc *II,
- DenseMap<SDValue, unsigned> &VRBaseMap) {
- if (Op.isMachineOpcode()) {
- AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap);
- } else if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
- MI->addOperand(MachineOperand::CreateImm(C->getZExtValue()));
- } else if (ConstantFPSDNode *F = dyn_cast<ConstantFPSDNode>(Op)) {
- const ConstantFP *CFP = F->getConstantFPValue();
- MI->addOperand(MachineOperand::CreateFPImm(CFP));
- } else if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op)) {
- MI->addOperand(MachineOperand::CreateReg(R->getReg(), false));
- } else if (GlobalAddressSDNode *TGA = dyn_cast<GlobalAddressSDNode>(Op)) {
- MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(), TGA->getOffset(),
- TGA->getTargetFlags()));
- } else if (BasicBlockSDNode *BBNode = dyn_cast<BasicBlockSDNode>(Op)) {
- MI->addOperand(MachineOperand::CreateMBB(BBNode->getBasicBlock()));
- } else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op)) {
- MI->addOperand(MachineOperand::CreateFI(FI->getIndex()));
- } else if (JumpTableSDNode *JT = dyn_cast<JumpTableSDNode>(Op)) {
- MI->addOperand(MachineOperand::CreateJTI(JT->getIndex(),
- JT->getTargetFlags()));
- } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op)) {
- int Offset = CP->getOffset();
- unsigned Align = CP->getAlignment();
- const Type *Type = CP->getType();
- // MachineConstantPool wants an explicit alignment.
- if (Align == 0) {
- Align = TM.getTargetData()->getPrefTypeAlignment(Type);
- if (Align == 0) {
- // Alignment of vector types. FIXME!
- Align = TM.getTargetData()->getTypeAllocSize(Type);
- }
- }
-
- unsigned Idx;
- if (CP->isMachineConstantPoolEntry())
- Idx = ConstPool->getConstantPoolIndex(CP->getMachineCPVal(), Align);
- else
- Idx = ConstPool->getConstantPoolIndex(CP->getConstVal(), Align);
- MI->addOperand(MachineOperand::CreateCPI(Idx, Offset,
- CP->getTargetFlags()));
- } else if (ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) {
- MI->addOperand(MachineOperand::CreateES(ES->getSymbol(), 0,
- ES->getTargetFlags()));
- } else {
- assert(Op.getValueType() != MVT::Other &&
- Op.getValueType() != MVT::Flag &&
- "Chain and flag operands should occur at end of operand list!");
- AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap);
- }
-}
-
-/// getSuperRegisterRegClass - Returns the register class of a superreg A whose
-/// "SubIdx"'th sub-register class is the specified register class and whose
-/// type matches the specified type.
-static const TargetRegisterClass*
-getSuperRegisterRegClass(const TargetRegisterClass *TRC,
- unsigned SubIdx, MVT VT) {
- // Pick the register class of the superegister for this type
- for (TargetRegisterInfo::regclass_iterator I = TRC->superregclasses_begin(),
- E = TRC->superregclasses_end(); I != E; ++I)
- if ((*I)->hasType(VT) && (*I)->getSubRegisterRegClass(SubIdx) == TRC)
- return *I;
- assert(false && "Couldn't find the register class");
- return 0;
-}
-
-/// EmitSubregNode - Generate machine code for subreg nodes.
-///
-void ScheduleDAGSDNodes::EmitSubregNode(SDNode *Node,
- DenseMap<SDValue, unsigned> &VRBaseMap){
- unsigned VRBase = 0;
- unsigned Opc = Node->getMachineOpcode();
-
- // If the node is only used by a CopyToReg and the dest reg is a vreg, use
- // the CopyToReg'd destination register instead of creating a new vreg.
- for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
- UI != E; ++UI) {
- SDNode *User = *UI;
- if (User->getOpcode() == ISD::CopyToReg &&
- User->getOperand(2).getNode() == Node) {
- unsigned DestReg = cast<RegisterSDNode>(User->getOperand(1))->getReg();
- if (TargetRegisterInfo::isVirtualRegister(DestReg)) {
- VRBase = DestReg;
- break;
- }
- }
- }
-
- if (Opc == TargetInstrInfo::EXTRACT_SUBREG) {
- unsigned SubIdx = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
-
- // Create the extract_subreg machine instruction.
- MachineInstr *MI = BuildMI(MF, Node->getDebugLoc(),
- TII->get(TargetInstrInfo::EXTRACT_SUBREG));
-
- // Figure out the register class to create for the destreg.
- unsigned VReg = getVR(Node->getOperand(0), VRBaseMap);
- const TargetRegisterClass *TRC = MRI.getRegClass(VReg);
- const TargetRegisterClass *SRC = TRC->getSubRegisterRegClass(SubIdx);
- assert(SRC && "Invalid subregister index in EXTRACT_SUBREG");
-
- // Figure out the register class to create for the destreg.
- // Note that if we're going to directly use an existing register,
- // it must be precisely the required class, and not a subclass
- // thereof.
- if (VRBase == 0 || SRC != MRI.getRegClass(VRBase)) {
- // Create the reg
- assert(SRC && "Couldn't find source register class");
- VRBase = MRI.createVirtualRegister(SRC);
- }
-
- // Add def, source, and subreg index
- MI->addOperand(MachineOperand::CreateReg(VRBase, true));
- AddOperand(MI, Node->getOperand(0), 0, 0, VRBaseMap);
- MI->addOperand(MachineOperand::CreateImm(SubIdx));
- BB->insert(InsertPos, MI);
- } else if (Opc == TargetInstrInfo::INSERT_SUBREG ||
- Opc == TargetInstrInfo::SUBREG_TO_REG) {
- SDValue N0 = Node->getOperand(0);
- SDValue N1 = Node->getOperand(1);
- SDValue N2 = Node->getOperand(2);
- unsigned SubReg = getVR(N1, VRBaseMap);
- unsigned SubIdx = cast<ConstantSDNode>(N2)->getZExtValue();
- const TargetRegisterClass *TRC = MRI.getRegClass(SubReg);
- const TargetRegisterClass *SRC =
- getSuperRegisterRegClass(TRC, SubIdx,
- Node->getValueType(0));
-
- // Figure out the register class to create for the destreg.
- // Note that if we're going to directly use an existing register,
- // it must be precisely the required class, and not a subclass
- // thereof.
- if (VRBase == 0 || SRC != MRI.getRegClass(VRBase)) {
- // Create the reg
- assert(SRC && "Couldn't find source register class");
- VRBase = MRI.createVirtualRegister(SRC);
- }
-
- // Create the insert_subreg or subreg_to_reg machine instruction.
- MachineInstr *MI = BuildMI(MF, Node->getDebugLoc(), TII->get(Opc));
- MI->addOperand(MachineOperand::CreateReg(VRBase, true));
-
- // If creating a subreg_to_reg, then the first input operand
- // is an implicit value immediate, otherwise it's a register
- if (Opc == TargetInstrInfo::SUBREG_TO_REG) {
- const ConstantSDNode *SD = cast<ConstantSDNode>(N0);
- MI->addOperand(MachineOperand::CreateImm(SD->getZExtValue()));
- } else
- AddOperand(MI, N0, 0, 0, VRBaseMap);
- // Add the subregster being inserted
- AddOperand(MI, N1, 0, 0, VRBaseMap);
- MI->addOperand(MachineOperand::CreateImm(SubIdx));
- BB->insert(InsertPos, MI);
- } else
- assert(0 && "Node is not insert_subreg, extract_subreg, or subreg_to_reg");
-
- SDValue Op(Node, 0);
- bool isNew = VRBaseMap.insert(std::make_pair(Op, VRBase)).second;
- isNew = isNew; // Silence compiler warning.
- assert(isNew && "Node emitted out of order - early");
-}
-
-/// EmitCopyToRegClassNode - Generate machine code for COPY_TO_REGCLASS nodes.
-/// COPY_TO_REGCLASS is just a normal copy, except that the destination
-/// register is constrained to be in a particular register class.
-///
-void
-ScheduleDAGSDNodes::EmitCopyToRegClassNode(SDNode *Node,
- DenseMap<SDValue, unsigned> &VRBaseMap) {
- unsigned VReg = getVR(Node->getOperand(0), VRBaseMap);
- const TargetRegisterClass *SrcRC = MRI.getRegClass(VReg);
-
- unsigned DstRCIdx = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
- const TargetRegisterClass *DstRC = TRI->getRegClass(DstRCIdx);
-
- // Create the new VReg in the destination class and emit a copy.
- unsigned NewVReg = MRI.createVirtualRegister(DstRC);
- bool Emitted = TII->copyRegToReg(*BB, InsertPos, NewVReg, VReg,
- DstRC, SrcRC);
- assert(Emitted &&
- "Unable to issue a copy instruction for a COPY_TO_REGCLASS node!\n");
- (void) Emitted;
-
- SDValue Op(Node, 0);
- bool isNew = VRBaseMap.insert(std::make_pair(Op, NewVReg)).second;
- isNew = isNew; // Silence compiler warning.
- assert(isNew && "Node emitted out of order - early");
-}
-
-/// EmitNode - Generate machine code for an node and needed dependencies.
-///
-void ScheduleDAGSDNodes::EmitNode(SDNode *Node, bool IsClone, bool IsCloned,
- DenseMap<SDValue, unsigned> &VRBaseMap) {
- // If machine instruction
- if (Node->isMachineOpcode()) {
- unsigned Opc = Node->getMachineOpcode();
-
- // Handle subreg insert/extract specially
- if (Opc == TargetInstrInfo::EXTRACT_SUBREG ||
- Opc == TargetInstrInfo::INSERT_SUBREG ||
- Opc == TargetInstrInfo::SUBREG_TO_REG) {
- EmitSubregNode(Node, VRBaseMap);
- return;
- }
-
- // Handle COPY_TO_REGCLASS specially.
- if (Opc == TargetInstrInfo::COPY_TO_REGCLASS) {
- EmitCopyToRegClassNode(Node, VRBaseMap);
- return;
- }
-
- if (Opc == TargetInstrInfo::IMPLICIT_DEF)
- // We want a unique VR for each IMPLICIT_DEF use.
- return;
-
- const TargetInstrDesc &II = TII->get(Opc);
- unsigned NumResults = CountResults(Node);
- unsigned NodeOperands = CountOperands(Node);
- unsigned MemOperandsEnd = ComputeMemOperandsEnd(Node);
- bool HasPhysRegOuts = (NumResults > II.getNumDefs()) &&
- II.getImplicitDefs() != 0;
-#ifndef NDEBUG
- unsigned NumMIOperands = NodeOperands + NumResults;
- assert((II.getNumOperands() == NumMIOperands ||
- HasPhysRegOuts || II.isVariadic()) &&
- "#operands for dag node doesn't match .td file!");
-#endif
-
- // Create the new machine instruction.
- MachineInstr *MI = BuildMI(MF, Node->getDebugLoc(), II);
-
- // Add result register values for things that are defined by this
- // instruction.
- if (NumResults)
- CreateVirtualRegisters(Node, MI, II, IsClone, IsCloned, VRBaseMap);
-
- // Emit all of the actual operands of this instruction, adding them to the
- // instruction as appropriate.
- for (unsigned i = 0; i != NodeOperands; ++i)
- AddOperand(MI, Node->getOperand(i), i+II.getNumDefs(), &II, VRBaseMap);
-
- // Emit all of the memory operands of this instruction
- for (unsigned i = NodeOperands; i != MemOperandsEnd; ++i)
- AddMemOperand(MI, cast<MemOperandSDNode>(Node->getOperand(i))->MO);
-
- if (II.usesCustomDAGSchedInsertionHook()) {
- // Insert this instruction into the basic block using a target
- // specific inserter which may returns a new basic block.
- BB = TLI->EmitInstrWithCustomInserter(MI, BB);
- InsertPos = BB->end();
- } else {
- BB->insert(InsertPos, MI);
- }
-
- // Additional results must be an physical register def.
- if (HasPhysRegOuts) {
- for (unsigned i = II.getNumDefs(); i < NumResults; ++i) {
- unsigned Reg = II.getImplicitDefs()[i - II.getNumDefs()];
- if (Node->hasAnyUseOfValue(i))
- EmitCopyFromReg(Node, i, IsClone, IsCloned, Reg, VRBaseMap);
- }
- }
- return;
- }
-
- switch (Node->getOpcode()) {
- default:
-#ifndef NDEBUG
- Node->dump(DAG);
-#endif
- assert(0 && "This target-independent node should have been selected!");
- break;
- case ISD::EntryToken:
- assert(0 && "EntryToken should have been excluded from the schedule!");
- break;
- case ISD::TokenFactor: // fall thru
- break;
- case ISD::CopyToReg: {
- unsigned SrcReg;
- SDValue SrcVal = Node->getOperand(2);
- if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(SrcVal))
- SrcReg = R->getReg();
- else
- SrcReg = getVR(SrcVal, VRBaseMap);
-
- unsigned DestReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
- if (SrcReg == DestReg) // Coalesced away the copy? Ignore.
- break;
-
- const TargetRegisterClass *SrcTRC = 0, *DstTRC = 0;
- // Get the register classes of the src/dst.
- if (TargetRegisterInfo::isVirtualRegister(SrcReg))
- SrcTRC = MRI.getRegClass(SrcReg);
- else
- SrcTRC = TRI->getPhysicalRegisterRegClass(SrcReg,SrcVal.getValueType());
-
- if (TargetRegisterInfo::isVirtualRegister(DestReg))
- DstTRC = MRI.getRegClass(DestReg);
- else
- DstTRC = TRI->getPhysicalRegisterRegClass(DestReg,
- Node->getOperand(1).getValueType());
-
- bool Emitted = TII->copyRegToReg(*BB, InsertPos, DestReg, SrcReg,
- DstTRC, SrcTRC);
- assert(Emitted && "Unable to issue a copy instruction!\n");
- (void) Emitted;
- break;
- }
- case ISD::CopyFromReg: {
- unsigned SrcReg = cast<RegisterSDNode>(Node->getOperand(1))->getReg();
- EmitCopyFromReg(Node, 0, IsClone, IsCloned, SrcReg, VRBaseMap);
- break;
- }
- case ISD::INLINEASM: {
- unsigned NumOps = Node->getNumOperands();
- if (Node->getOperand(NumOps-1).getValueType() == MVT::Flag)
- --NumOps; // Ignore the flag operand.
-
- // Create the inline asm machine instruction.
- MachineInstr *MI = BuildMI(MF, Node->getDebugLoc(),
- TII->get(TargetInstrInfo::INLINEASM));
-
- // Add the asm string as an external symbol operand.
- const char *AsmStr =
- cast<ExternalSymbolSDNode>(Node->getOperand(1))->getSymbol();
- MI->addOperand(MachineOperand::CreateES(AsmStr));
-
- // Add all of the operand registers to the instruction.
- for (unsigned i = 2; i != NumOps;) {
- unsigned Flags =
- cast<ConstantSDNode>(Node->getOperand(i))->getZExtValue();
- unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
-
- MI->addOperand(MachineOperand::CreateImm(Flags));
- ++i; // Skip the ID value.
-
- switch (Flags & 7) {
- default: assert(0 && "Bad flags!");
- case 2: // Def of register.
- for (; NumVals; --NumVals, ++i) {
- unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
- MI->addOperand(MachineOperand::CreateReg(Reg, true));
- }
- break;
- case 6: // Def of earlyclobber register.
- for (; NumVals; --NumVals, ++i) {
- unsigned Reg = cast<RegisterSDNode>(Node->getOperand(i))->getReg();
- MI->addOperand(MachineOperand::CreateReg(Reg, true, false, false,
- false, false, true));
- }
- break;
- case 1: // Use of register.
- case 3: // Immediate.
- case 4: // Addressing mode.
- // The addressing mode has been selected, just add all of the
- // operands to the machine instruction.
- for (; NumVals; --NumVals, ++i)
- AddOperand(MI, Node->getOperand(i), 0, 0, VRBaseMap);
- break;
- }
- }
- BB->insert(InsertPos, MI);
- break;
- }
- }
-}
-
-/// EmitSchedule - Emit the machine code in scheduled order.
-MachineBasicBlock *ScheduleDAGSDNodes::EmitSchedule() {
- DenseMap<SDValue, unsigned> VRBaseMap;
- DenseMap<SUnit*, unsigned> CopyVRBaseMap;
- for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
- SUnit *SU = Sequence[i];
- if (!SU) {
- // Null SUnit* is a noop.
- EmitNoop();
- continue;
- }
-
- // For pre-regalloc scheduling, create instructions corresponding to the
- // SDNode and any flagged SDNodes and append them to the block.
- if (!SU->getNode()) {
- // Emit a copy.
- EmitPhysRegCopy(SU, CopyVRBaseMap);
- continue;
- }
-
- SmallVector<SDNode *, 4> FlaggedNodes;
- for (SDNode *N = SU->getNode()->getFlaggedNode(); N;
- N = N->getFlaggedNode())
- FlaggedNodes.push_back(N);
- while (!FlaggedNodes.empty()) {
- EmitNode(FlaggedNodes.back(), SU->OrigNode != SU, SU->isCloned,VRBaseMap);
- FlaggedNodes.pop_back();
- }
- EmitNode(SU->getNode(), SU->OrigNode != SU, SU->isCloned, VRBaseMap);
- }
-
- return BB;
-}
diff --git a/lib/Debugger/CMakeLists.txt b/lib/Debugger/CMakeLists.txt
deleted file mode 100644
index d2508cf..0000000
--- a/lib/Debugger/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-add_llvm_library(LLVMDebugger
- Debugger.cpp
- ProgramInfo.cpp
- RuntimeInfo.cpp
- SourceFile.cpp
- SourceLanguage-CFamily.cpp
- SourceLanguage-CPlusPlus.cpp
- SourceLanguage-Unknown.cpp
- SourceLanguage.cpp
- )
diff --git a/lib/Debugger/Debugger.cpp b/lib/Debugger/Debugger.cpp
deleted file mode 100644
index 77fd2ac..0000000
--- a/lib/Debugger/Debugger.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-//===-- Debugger.cpp - LLVM debugger library implementation ---------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the main implementation of the LLVM debugger library.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Debugger/Debugger.h"
-#include "llvm/Module.h"
-#include "llvm/ModuleProvider.h"
-#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/Debugger/InferiorProcess.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/ADT/StringExtras.h"
-#include <cstdlib>
-#include <memory>
-using namespace llvm;
-
-/// Debugger constructor - Initialize the debugger to its initial, empty, state.
-///
-Debugger::Debugger() : Environment(0), Program(0), Process(0) {
-}
-
-Debugger::~Debugger() {
- // Killing the program could throw an exception. We don't want to progagate
- // the exception out of our destructor though.
- try {
- killProgram();
- } catch (const char *) {
- } catch (const std::string &) {
- }
-
- unloadProgram();
-}
-
-/// getProgramPath - Get the path of the currently loaded program, or an
-/// empty string if none is loaded.
-std::string Debugger::getProgramPath() const {
- return Program ? Program->getModuleIdentifier() : "";
-}
-
-static Module *
-getMaterializedModuleProvider(const std::string &Filename,
- LLVMContext& C) {
- std::auto_ptr<MemoryBuffer> Buffer;
- Buffer.reset(MemoryBuffer::getFileOrSTDIN(Filename.c_str()));
- if (Buffer.get())
- return ParseBitcodeFile(Buffer.get(), C);
- return 0;
-}
-
-/// loadProgram - If a program is currently loaded, unload it. Then search
-/// the PATH for the specified program, loading it when found. If the
-/// specified program cannot be found, an exception is thrown to indicate the
-/// error.
-void Debugger::loadProgram(const std::string &Filename, LLVMContext& C) {
- if ((Program = getMaterializedModuleProvider(Filename, C)) ||
- (Program = getMaterializedModuleProvider(Filename+".bc", C)))
- return; // Successfully loaded the program.
-
- // Search the program path for the file...
- if (const char *PathS = getenv("PATH")) {
- std::string Path = PathS;
-
- std::string Directory = getToken(Path, ":");
- while (!Directory.empty()) {
- if ((Program = getMaterializedModuleProvider(Directory +"/"+ Filename, C))
- || (Program = getMaterializedModuleProvider(Directory +"/"+ Filename
- + ".bc", C)))
- return; // Successfully loaded the program.
-
- Directory = getToken(Path, ":");
- }
- }
-
- throw "Could not find program '" + Filename + "'!";
-}
-
-/// unloadProgram - If a program is running, kill it, then unload all traces
-/// of the current program. If no program is loaded, this method silently
-/// succeeds.
-void Debugger::unloadProgram() {
- if (!isProgramLoaded()) return;
- killProgram();
- delete Program;
- Program = 0;
-}
-
-
-/// createProgram - Create an instance of the currently loaded program,
-/// killing off any existing one. This creates the program and stops it at
-/// the first possible moment. If there is no program loaded or if there is a
-/// problem starting the program, this method throws an exception.
-void Debugger::createProgram() {
- if (!isProgramLoaded())
- throw "Cannot start program: none is loaded.";
-
- // Kill any existing program.
- killProgram();
-
- // Add argv[0] to the arguments vector..
- std::vector<std::string> Args(ProgramArguments);
- Args.insert(Args.begin(), getProgramPath());
-
- // Start the new program... this could throw if the program cannot be started.
- Process = InferiorProcess::create(Program, Args, Environment);
-}
-
-InferiorProcess *
-InferiorProcess::create(Module *M, const std::vector<std::string> &Arguments,
- const char * const *envp) {
- throw"No supported binding to inferior processes (debugger not implemented).";
-}
-
-/// killProgram - If the program is currently executing, kill off the
-/// process and free up any state related to the currently running program. If
-/// there is no program currently running, this just silently succeeds.
-void Debugger::killProgram() {
- // The destructor takes care of the dirty work.
- try {
- delete Process;
- } catch (...) {
- Process = 0;
- throw;
- }
- Process = 0;
-}
-
-/// stepProgram - Implement the 'step' command, continuing execution until
-/// the next possible stop point.
-void Debugger::stepProgram() {
- assert(isProgramRunning() && "Cannot step if the program isn't running!");
- try {
- Process->stepProgram();
- } catch (InferiorProcessDead &IPD) {
- killProgram();
- throw NonErrorException("The program stopped with exit code " +
- itostr(IPD.getExitCode()));
- } catch (...) {
- killProgram();
- throw;
- }
-}
-
-/// nextProgram - Implement the 'next' command, continuing execution until
-/// the next possible stop point that is in the current function.
-void Debugger::nextProgram() {
- assert(isProgramRunning() && "Cannot next if the program isn't running!");
- try {
- // This should step the process. If the process enters a function, then it
- // should 'finish' it. However, figuring this out is tricky. In
- // particular, the program can do any of:
- // 0. Not change current frame.
- // 1. Entering or exiting a region within the current function
- // (which changes the frame ID, but which we shouldn't 'finish')
- // 2. Exiting the current function (which changes the frame ID)
- // 3. Entering a function (which should be 'finish'ed)
- // For this reason, we have to be very careful about when we decide to do
- // the 'finish'.
-
- // Get the current frame, but don't trust it. It could change...
- void *CurrentFrame = Process->getPreviousFrame(0);
-
- // Don't trust the current frame: get the caller frame.
- void *ParentFrame = Process->getPreviousFrame(CurrentFrame);
-
- // Ok, we have some information, run the program one step.
- Process->stepProgram();
-
- // Where is the new frame? The most common case, by far is that it has not
- // been modified (Case #0), in which case we don't need to do anything more.
- void *NewFrame = Process->getPreviousFrame(0);
- if (NewFrame != CurrentFrame) {
- // Ok, the frame changed. If we are case #1, then the parent frame will
- // be identical.
- void *NewParentFrame = Process->getPreviousFrame(NewFrame);
- if (ParentFrame != NewParentFrame) {
- // Ok, now we know we aren't case #0 or #1. Check to see if we entered
- // a new function. If so, the parent frame will be "CurrentFrame".
- if (CurrentFrame == NewParentFrame)
- Process->finishProgram(NewFrame);
- }
- }
-
- } catch (InferiorProcessDead &IPD) {
- killProgram();
- throw NonErrorException("The program stopped with exit code " +
- itostr(IPD.getExitCode()));
- } catch (...) {
- killProgram();
- throw;
- }
-}
-
-/// finishProgram - Implement the 'finish' command, continuing execution
-/// until the specified frame ID returns.
-void Debugger::finishProgram(void *Frame) {
- assert(isProgramRunning() && "Cannot cont if the program isn't running!");
- try {
- Process->finishProgram(Frame);
- } catch (InferiorProcessDead &IPD) {
- killProgram();
- throw NonErrorException("The program stopped with exit code " +
- itostr(IPD.getExitCode()));
- } catch (...) {
- killProgram();
- throw;
- }
-}
-
-/// contProgram - Implement the 'cont' command, continuing execution until
-/// the next breakpoint is encountered.
-void Debugger::contProgram() {
- assert(isProgramRunning() && "Cannot cont if the program isn't running!");
- try {
- Process->contProgram();
- } catch (InferiorProcessDead &IPD) {
- killProgram();
- throw NonErrorException("The program stopped with exit code " +
- itostr(IPD.getExitCode()));
- } catch (...) {
- killProgram();
- throw;
- }
-}
diff --git a/lib/Debugger/Makefile b/lib/Debugger/Makefile
deleted file mode 100644
index 8290e30..0000000
--- a/lib/Debugger/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-##===- lib/Debugger/Makefile -------------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../..
-LIBRARYNAME = LLVMDebugger
-EXTRA_DIST = README.txt
-REQUIRES_EH := 1
-BUILD_ARCHIVE = 1
-
-include $(LEVEL)/Makefile.common
diff --git a/lib/Debugger/ProgramInfo.cpp b/lib/Debugger/ProgramInfo.cpp
deleted file mode 100644
index e58b3d5..0000000
--- a/lib/Debugger/ProgramInfo.cpp
+++ /dev/null
@@ -1,375 +0,0 @@
-//===-- ProgramInfo.cpp - Compute and cache info about a program ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the ProgramInfo and related classes, by sorting through
-// the loaded Module.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Debugger/ProgramInfo.h"
-#include "llvm/Constants.h"
-#include "llvm/Analysis/ValueTracking.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/IntrinsicInst.h"
-#include "llvm/Instructions.h"
-#include "llvm/Module.h"
-#include "llvm/Debugger/SourceFile.h"
-#include "llvm/Debugger/SourceLanguage.h"
-#include "llvm/Support/SlowOperationInformer.h"
-#include "llvm/Support/Streams.h"
-#include "llvm/ADT/STLExtras.h"
-using namespace llvm;
-
-/// getGlobalVariablesUsing - Return all of the global variables which have the
-/// specified value in their initializer somewhere.
-static void getGlobalVariablesUsing(Value *V,
- std::vector<GlobalVariable*> &Found) {
- for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) {
- if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I))
- Found.push_back(GV);
- else if (Constant *C = dyn_cast<Constant>(*I))
- getGlobalVariablesUsing(C, Found);
- }
-}
-
-/// getNextStopPoint - Follow the def-use chains of the specified LLVM value,
-/// traversing the use chains until we get to a stoppoint. When we do, return
-/// the source location of the stoppoint. If we don't find a stoppoint, return
-/// null.
-static const GlobalVariable *getNextStopPoint(const Value *V, unsigned &LineNo,
- unsigned &ColNo) {
- // The use-def chains can fork. As such, we pick the lowest numbered one we
- // find.
- const GlobalVariable *LastDesc = 0;
- unsigned LastLineNo = ~0;
- unsigned LastColNo = ~0;
-
- for (Value::use_const_iterator UI = V->use_begin(), E = V->use_end();
- UI != E; ++UI) {
- bool ShouldRecurse = true;
- if (cast<Instruction>(*UI)->getOpcode() == Instruction::PHI) {
- // Infinite loops == bad, ignore PHI nodes.
- ShouldRecurse = false;
- } else if (const CallInst *CI = dyn_cast<CallInst>(*UI)) {
-
- // If we found a stop point, check to see if it is earlier than what we
- // already have. If so, remember it.
- if (CI->getCalledFunction())
- if (const DbgStopPointInst *SPI = dyn_cast<DbgStopPointInst>(CI)) {
- unsigned CurLineNo = SPI->getLine();
- unsigned CurColNo = SPI->getColumn();
- const GlobalVariable *CurDesc = 0;
- const Value *Op = SPI->getContext();
-
- if ((CurDesc = dyn_cast<GlobalVariable>(Op)) &&
- (LineNo < LastLineNo ||
- (LineNo == LastLineNo && ColNo < LastColNo))) {
- LastDesc = CurDesc;
- LastLineNo = CurLineNo;
- LastColNo = CurColNo;
- }
- ShouldRecurse = false;
- }
- }
-
- // If this is not a phi node or a stopping point, recursively scan the users
- // of this instruction to skip over region.begin's and the like.
- if (ShouldRecurse) {
- unsigned CurLineNo, CurColNo;
- if (const GlobalVariable *GV = getNextStopPoint(*UI, CurLineNo,CurColNo)){
- if (LineNo < LastLineNo || (LineNo == LastLineNo && ColNo < LastColNo)){
- LastDesc = GV;
- LastLineNo = CurLineNo;
- LastColNo = CurColNo;
- }
- }
- }
- }
-
- if (LastDesc) {
- LineNo = LastLineNo != ~0U ? LastLineNo : 0;
- ColNo = LastColNo != ~0U ? LastColNo : 0;
- }
- return LastDesc;
-}
-
-
-//===----------------------------------------------------------------------===//
-// SourceFileInfo implementation
-//
-
-SourceFileInfo::SourceFileInfo(const GlobalVariable *Desc,
- const SourceLanguage &Lang)
- : Language(&Lang), Descriptor(Desc) {
- Version = 0;
- SourceText = 0;
-
- if (Desc && Desc->hasInitializer())
- if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer()))
- if (CS->getNumOperands() > 4) {
- if (ConstantInt *CUI = dyn_cast<ConstantInt>(CS->getOperand(1)))
- Version = CUI->getZExtValue();
-
- if (!GetConstantStringInfo(CS->getOperand(3), BaseName))
- BaseName = "";
- if (!GetConstantStringInfo(CS->getOperand(4), Directory))
- Directory = "";
- }
-}
-
-SourceFileInfo::~SourceFileInfo() {
- delete SourceText;
-}
-
-SourceFile &SourceFileInfo::getSourceText() const {
- // FIXME: this should take into account the source search directories!
- if (SourceText == 0) { // Read the file in if we haven't already.
- sys::Path tmpPath;
- if (!Directory.empty())
- tmpPath.set(Directory);
- tmpPath.appendComponent(BaseName);
- if (tmpPath.canRead())
- SourceText = new SourceFile(tmpPath.toString(), Descriptor);
- else
- SourceText = new SourceFile(BaseName, Descriptor);
- }
- return *SourceText;
-}
-
-
-//===----------------------------------------------------------------------===//
-// SourceFunctionInfo implementation
-//
-SourceFunctionInfo::SourceFunctionInfo(ProgramInfo &PI,
- const GlobalVariable *Desc)
- : Descriptor(Desc) {
- LineNo = ColNo = 0;
- if (Desc && Desc->hasInitializer())
- if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer()))
- if (CS->getNumOperands() > 2) {
- // Entry #1 is the file descriptor.
- if (const GlobalVariable *GV =
- dyn_cast<GlobalVariable>(CS->getOperand(1)))
- SourceFile = &PI.getSourceFile(GV);
-
- // Entry #2 is the function name.
- if (!GetConstantStringInfo(CS->getOperand(2), Name))
- Name = "";
- }
-}
-
-/// getSourceLocation - This method returns the location of the first stopping
-/// point in the function.
-void SourceFunctionInfo::getSourceLocation(unsigned &RetLineNo,
- unsigned &RetColNo) const {
- // If we haven't computed this yet...
- if (!LineNo) {
- // Look at all of the users of the function descriptor, looking for calls to
- // %llvm.dbg.func.start.
- for (Value::use_const_iterator UI = Descriptor->use_begin(),
- E = Descriptor->use_end(); UI != E; ++UI)
- if (const CallInst *CI = dyn_cast<CallInst>(*UI))
- if (const Function *F = CI->getCalledFunction())
- if (F->getIntrinsicID() == Intrinsic::dbg_func_start) {
- // We found the start of the function. Check to see if there are
- // any stop points on the use-list of the function start.
- const GlobalVariable *SD = getNextStopPoint(CI, LineNo, ColNo);
- if (SD) { // We found the first stop point!
- // This is just a sanity check.
- if (getSourceFile().getDescriptor() != SD)
- cout << "WARNING: first line of function is not in the"
- << " file that the function descriptor claims it is in.\n";
- break;
- }
- }
- }
- RetLineNo = LineNo; RetColNo = ColNo;
-}
-
-//===----------------------------------------------------------------------===//
-// ProgramInfo implementation
-//
-
-ProgramInfo::ProgramInfo(Module *m) : M(m), ProgramTimeStamp(0,0) {
- assert(M && "Cannot create program information with a null module!");
- sys::PathWithStatus ModPath(M->getModuleIdentifier());
- const sys::FileStatus *Stat = ModPath.getFileStatus();
- if (Stat)
- ProgramTimeStamp = Stat->getTimestamp();
-
- SourceFilesIsComplete = false;
- SourceFunctionsIsComplete = false;
-}
-
-ProgramInfo::~ProgramInfo() {
- // Delete cached information about source program objects...
- for (std::map<const GlobalVariable*, SourceFileInfo*>::iterator
- I = SourceFiles.begin(), E = SourceFiles.end(); I != E; ++I)
- delete I->second;
- for (std::map<const GlobalVariable*, SourceFunctionInfo*>::iterator
- I = SourceFunctions.begin(), E = SourceFunctions.end(); I != E; ++I)
- delete I->second;
-
- // Delete the source language caches.
- for (unsigned i = 0, e = LanguageCaches.size(); i != e; ++i)
- delete LanguageCaches[i].second;
-}
-
-
-//===----------------------------------------------------------------------===//
-// SourceFileInfo tracking...
-//
-
-/// getSourceFile - Return source file information for the specified source file
-/// descriptor object, adding it to the collection as needed. This method
-/// always succeeds (is unambiguous), and is always efficient.
-///
-const SourceFileInfo &
-ProgramInfo::getSourceFile(const GlobalVariable *Desc) {
- SourceFileInfo *&Result = SourceFiles[Desc];
- if (Result) return *Result;
-
- // Figure out what language this source file comes from...
- unsigned LangID = 0; // Zero is unknown language
- if (Desc && Desc->hasInitializer())
- if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer()))
- if (CS->getNumOperands() > 2)
- if (ConstantInt *CUI = dyn_cast<ConstantInt>(CS->getOperand(2)))
- LangID = CUI->getZExtValue();
-
- const SourceLanguage &Lang = SourceLanguage::get(LangID);
- SourceFileInfo *New = Lang.createSourceFileInfo(Desc, *this);
-
- // FIXME: this should check to see if there is already a Filename/WorkingDir
- // pair that matches this one. If so, we shouldn't create the duplicate!
- //
- SourceFileIndex.insert(std::make_pair(New->getBaseName(), New));
- return *(Result = New);
-}
-
-
-/// getSourceFiles - Index all of the source files in the program and return
-/// a mapping of it. This information is lazily computed the first time
-/// that it is requested. Since this information can take a long time to
-/// compute, the user is given a chance to cancel it. If this occurs, an
-/// exception is thrown.
-const std::map<const GlobalVariable*, SourceFileInfo*> &
-ProgramInfo::getSourceFiles(bool RequiresCompleteMap) {
- // If we have a fully populated map, or if the client doesn't need one, just
- // return what we have.
- if (SourceFilesIsComplete || !RequiresCompleteMap)
- return SourceFiles;
-
- // Ok, all of the source file descriptors (compile_unit in dwarf terms),
- // should be on the use list of the llvm.dbg.translation_units global.
- //
- GlobalVariable *Units =
- M->getGlobalVariable("llvm.dbg.translation_units", StructType::get());
- if (Units == 0)
- throw "Program contains no debugging information!";
-
- std::vector<GlobalVariable*> TranslationUnits;
- getGlobalVariablesUsing(Units, TranslationUnits);
-
- SlowOperationInformer SOI("building source files index");
-
- // Loop over all of the translation units found, building the SourceFiles
- // mapping.
- for (unsigned i = 0, e = TranslationUnits.size(); i != e; ++i) {
- getSourceFile(TranslationUnits[i]);
- if (SOI.progress(i+1, e))
- throw "While building source files index, operation cancelled.";
- }
-
- // Ok, if we got this far, then we indexed the whole program.
- SourceFilesIsComplete = true;
- return SourceFiles;
-}
-
-/// getSourceFile - Look up the file with the specified name. If there is
-/// more than one match for the specified filename, prompt the user to pick
-/// one. If there is no source file that matches the specified name, throw
-/// an exception indicating that we can't find the file. Otherwise, return
-/// the file information for that file.
-const SourceFileInfo &ProgramInfo::getSourceFile(const std::string &Filename) {
- std::multimap<std::string, SourceFileInfo*>::const_iterator Start, End;
- getSourceFiles();
- tie(Start, End) = SourceFileIndex.equal_range(Filename);
-
- if (Start == End) throw "Could not find source file '" + Filename + "'!";
- const SourceFileInfo &SFI = *Start->second;
- ++Start;
- if (Start == End) return SFI;
-
- throw "FIXME: Multiple source files with the same name not implemented!";
-}
-
-
-//===----------------------------------------------------------------------===//
-// SourceFunctionInfo tracking...
-//
-
-
-/// getFunction - Return function information for the specified function
-/// descriptor object, adding it to the collection as needed. This method
-/// always succeeds (is unambiguous), and is always efficient.
-///
-const SourceFunctionInfo &
-ProgramInfo::getFunction(const GlobalVariable *Desc) {
- SourceFunctionInfo *&Result = SourceFunctions[Desc];
- if (Result) return *Result;
-
- // Figure out what language this function comes from...
- const GlobalVariable *SourceFileDesc = 0;
- if (Desc && Desc->hasInitializer())
- if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Desc->getInitializer()))
- if (CS->getNumOperands() > 0)
- if (const GlobalVariable *GV =
- dyn_cast<GlobalVariable>(CS->getOperand(1)))
- SourceFileDesc = GV;
-
- const SourceLanguage &Lang = getSourceFile(SourceFileDesc).getLanguage();
- return *(Result = Lang.createSourceFunctionInfo(Desc, *this));
-}
-
-
-// getSourceFunctions - Index all of the functions in the program and return
-// them. This information is lazily computed the first time that it is
-// requested. Since this information can take a long time to compute, the user
-// is given a chance to cancel it. If this occurs, an exception is thrown.
-const std::map<const GlobalVariable*, SourceFunctionInfo*> &
-ProgramInfo::getSourceFunctions(bool RequiresCompleteMap) {
- if (SourceFunctionsIsComplete || !RequiresCompleteMap)
- return SourceFunctions;
-
- // Ok, all of the source function descriptors (subprogram in dwarf terms),
- // should be on the use list of the llvm.dbg.translation_units global.
- //
- GlobalVariable *Units =
- M->getGlobalVariable("llvm.dbg.globals", StructType::get());
- if (Units == 0)
- throw "Program contains no debugging information!";
-
- std::vector<GlobalVariable*> Functions;
- getGlobalVariablesUsing(Units, Functions);
-
- SlowOperationInformer SOI("building functions index");
-
- // Loop over all of the functions found, building the SourceFunctions mapping.
- for (unsigned i = 0, e = Functions.size(); i != e; ++i) {
- getFunction(Functions[i]);
- if (SOI.progress(i+1, e))
- throw "While functions index, operation cancelled.";
- }
-
- // Ok, if we got this far, then we indexed the whole program.
- SourceFunctionsIsComplete = true;
- return SourceFunctions;
-}
diff --git a/lib/Debugger/README.txt b/lib/Debugger/README.txt
deleted file mode 100644
index 89935c5..0000000
--- a/lib/Debugger/README.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-//===-- llvm/lib/Debugger/ - LLVM Debugger interfaces ---------------------===//
-
-This directory contains the implementation of the LLVM debugger backend. This
-directory builds into a library which can be used by various debugger
-front-ends to debug LLVM programs. The current command line LLVM debugger,
-llvm-db is currently the only client of this library, but others could be
-built, to provide a GUI front-end for example.
diff --git a/lib/Debugger/RuntimeInfo.cpp b/lib/Debugger/RuntimeInfo.cpp
deleted file mode 100644
index 2f0ff72..0000000
--- a/lib/Debugger/RuntimeInfo.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-//===-- RuntimeInfo.cpp - Compute and cache info about running program ----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the RuntimeInfo and related classes, by querying and
-// cachine information from the running inferior process.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Debugger/InferiorProcess.h"
-#include "llvm/Debugger/ProgramInfo.h"
-#include "llvm/Debugger/RuntimeInfo.h"
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// StackFrame class implementation
-
-StackFrame::StackFrame(RuntimeInfo &ri, void *ParentFrameID)
- : RI(ri), SourceInfo(0) {
- FrameID = RI.getInferiorProcess().getPreviousFrame(ParentFrameID);
- if (FrameID == 0) throw "Stack frame does not exist!";
-
- // Compute lazily as needed.
- FunctionDesc = 0;
-}
-
-const GlobalVariable *StackFrame::getFunctionDesc() {
- if (FunctionDesc == 0)
- FunctionDesc = RI.getInferiorProcess().getSubprogramDesc(FrameID);
- return FunctionDesc;
-}
-
-/// getSourceLocation - Return the source location that this stack frame is
-/// sitting at.
-void StackFrame::getSourceLocation(unsigned &lineNo, unsigned &colNo,
- const SourceFileInfo *&sourceInfo) {
- if (SourceInfo == 0) {
- const GlobalVariable *SourceDesc = 0;
- RI.getInferiorProcess().getFrameLocation(FrameID, LineNo,ColNo, SourceDesc);
- SourceInfo = &RI.getProgramInfo().getSourceFile(SourceDesc);
- }
-
- lineNo = LineNo;
- colNo = ColNo;
- sourceInfo = SourceInfo;
-}
-
-//===----------------------------------------------------------------------===//
-// RuntimeInfo class implementation
-
-/// materializeFrame - Create and process all frames up to and including the
-/// specified frame number. This throws an exception if the specified frame
-/// ID is nonexistant.
-void RuntimeInfo::materializeFrame(unsigned ID) {
- assert(ID >= CallStack.size() && "no need to materialize this frame!");
- void *CurFrame = 0;
- if (!CallStack.empty())
- CurFrame = CallStack.back().getFrameID();
-
- while (CallStack.size() <= ID) {
- CallStack.push_back(StackFrame(*this, CurFrame));
- CurFrame = CallStack.back().getFrameID();
- }
-}
diff --git a/lib/Debugger/SourceFile.cpp b/lib/Debugger/SourceFile.cpp
deleted file mode 100644
index 03c60f8..0000000
--- a/lib/Debugger/SourceFile.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-//===-- SourceFile.cpp - SourceFile implementation for the debugger -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the SourceFile class for the LLVM debugger.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Debugger/SourceFile.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <cassert>
-using namespace llvm;
-
-static const char EmptyFile = 0;
-
-SourceFile::SourceFile(const std::string &fn, const GlobalVariable *Desc)
- : Filename(fn), Descriptor(Desc) {
- File.reset(MemoryBuffer::getFileOrSTDIN(fn));
-
- // On error, return an empty buffer.
- if (File == 0)
- File.reset(MemoryBuffer::getMemBuffer(&EmptyFile, &EmptyFile));
-}
-
-SourceFile::~SourceFile() {
-}
-
-
-/// calculateLineOffsets - Compute the LineOffset vector for the current file.
-///
-void SourceFile::calculateLineOffsets() const {
- assert(LineOffset.empty() && "Line offsets already computed!");
- const char *BufPtr = File->getBufferStart();
- const char *FileStart = BufPtr;
- const char *FileEnd = File->getBufferEnd();
- do {
- LineOffset.push_back(BufPtr-FileStart);
-
- // Scan until we get to a newline.
- while (BufPtr != FileEnd && *BufPtr != '\n' && *BufPtr != '\r')
- ++BufPtr;
-
- if (BufPtr != FileEnd) {
- ++BufPtr; // Skip over the \n or \r
- if (BufPtr[-1] == '\r' && BufPtr != FileEnd && BufPtr[0] == '\n')
- ++BufPtr; // Skip over dos/windows style \r\n's
- }
- } while (BufPtr != FileEnd);
-}
-
-
-/// getSourceLine - Given a line number, return the start and end of the line
-/// in the file. If the line number is invalid, or if the file could not be
-/// loaded, null pointers are returned for the start and end of the file. Note
-/// that line numbers start with 0, not 1.
-void SourceFile::getSourceLine(unsigned LineNo, const char *&LineStart,
- const char *&LineEnd) const {
- LineStart = LineEnd = 0;
- if (LineOffset.empty()) calculateLineOffsets();
-
- // Asking for an out-of-range line number?
- if (LineNo >= LineOffset.size()) return;
-
- // Otherwise, they are asking for a valid line, which we can fulfill.
- LineStart = File->getBufferStart()+LineOffset[LineNo];
-
- if (LineNo+1 < LineOffset.size())
- LineEnd = File->getBufferStart()+LineOffset[LineNo+1];
- else
- LineEnd = File->getBufferEnd();
-
- // If the line ended with a newline, strip it off.
- while (LineEnd != LineStart && (LineEnd[-1] == '\n' || LineEnd[-1] == '\r'))
- --LineEnd;
-
- assert(LineEnd >= LineStart && "We somehow got our pointers swizzled!");
-}
diff --git a/lib/Debugger/SourceLanguage-CFamily.cpp b/lib/Debugger/SourceLanguage-CFamily.cpp
deleted file mode 100644
index f329db4..0000000
--- a/lib/Debugger/SourceLanguage-CFamily.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===-- SourceLanguage-CFamily.cpp - C family SourceLanguage impl ---------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the SourceLanguage class for the C family of languages
-// (K&R C, C89, C99, etc).
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Debugger/SourceLanguage.h"
-using namespace llvm;
-
-#if 0
-namespace {
- struct CSL : public SourceLanguage {
- } TheCSourceLanguageInstance;
-}
-#endif
-
-const SourceLanguage &SourceLanguage::getCFamilyInstance() {
- return get(0); // We don't have an implementation for C yet fall back on
- // generic
-}
diff --git a/lib/Debugger/SourceLanguage-CPlusPlus.cpp b/lib/Debugger/SourceLanguage-CPlusPlus.cpp
deleted file mode 100644
index ce94ff4..0000000
--- a/lib/Debugger/SourceLanguage-CPlusPlus.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-//===-- SourceLanguage-CPlusPlus.cpp - C++ SourceLanguage impl ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the SourceLanguage class for the C++ language.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Debugger/SourceLanguage.h"
-using namespace llvm;
-
-#if 0
-namespace {
- struct CPPSL : public SourceLanguage {
- } TheCPlusPlusLanguageInstance;
-}
-#endif
-
-const SourceLanguage &SourceLanguage::getCPlusPlusInstance() {
- return get(0); // We don't have an implementation for C yet fall back on
- // generic
-}
diff --git a/lib/Debugger/SourceLanguage-Unknown.cpp b/lib/Debugger/SourceLanguage-Unknown.cpp
deleted file mode 100644
index b806fc7..0000000
--- a/lib/Debugger/SourceLanguage-Unknown.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-//===-- SourceLanguage-Unknown.cpp - Implement itf for unknown languages --===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// If the LLVM debugger does not have a module for a particular language, it
-// falls back on using this one to perform the source-language interface. This
-// interface is not wonderful, but it gets the job done.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Debugger/SourceLanguage.h"
-#include "llvm/Debugger/ProgramInfo.h"
-#include "llvm/Support/Streams.h"
-#include <cassert>
-#include <ostream>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Implement the SourceLanguage cache for the Unknown language.
-//
-
-namespace {
- /// SLUCache - This cache allows for efficient lookup of source functions by
- /// name.
- ///
- struct SLUCache : public SourceLanguageCache {
- ProgramInfo &PI;
- std::multimap<std::string, SourceFunctionInfo*> FunctionMap;
- public:
- SLUCache(ProgramInfo &pi);
-
- typedef std::multimap<std::string, SourceFunctionInfo*>::const_iterator
- fm_iterator;
-
- std::pair<fm_iterator, fm_iterator>
- getFunction(const std::string &Name) const {
- return FunctionMap.equal_range(Name);
- }
-
- SourceFunctionInfo *addSourceFunction(SourceFunctionInfo *SF) {
- FunctionMap.insert(std::make_pair(SF->getSymbolicName(), SF));
- return SF;
- }
- };
-}
-
-SLUCache::SLUCache(ProgramInfo &pi) : PI(pi) {
-}
-
-
-//===----------------------------------------------------------------------===//
-// Implement SourceLanguageUnknown class, which is used to handle unrecognized
-// languages.
-//
-
-namespace {
- static struct SLU : public SourceLanguage {
- //===------------------------------------------------------------------===//
- // Implement the miscellaneous methods...
- //
- virtual const char *getSourceLanguageName() const {
- return "unknown";
- }
-
- /// lookupFunction - Given a textual function name, return the
- /// SourceFunctionInfo descriptor for that function, or null if it cannot be
- /// found. If the program is currently running, the RuntimeInfo object
- /// provides information about the current evaluation context, otherwise it
- /// will be null.
- ///
- virtual SourceFunctionInfo *lookupFunction(const std::string &FunctionName,
- ProgramInfo &PI,
- RuntimeInfo *RI = 0) const;
-
- //===------------------------------------------------------------------===//
- // We do use a cache for information...
- //
- typedef SLUCache CacheType;
- SLUCache *createSourceLanguageCache(ProgramInfo &PI) const {
- return new SLUCache(PI);
- }
-
- /// createSourceFunctionInfo - Create the new object and inform the cache of
- /// the new function.
- virtual SourceFunctionInfo *
- createSourceFunctionInfo(const GlobalVariable *Desc, ProgramInfo &PI) const;
-
- } TheUnknownSourceLanguageInstance;
-}
-
-const SourceLanguage &SourceLanguage::getUnknownLanguageInstance() {
- return TheUnknownSourceLanguageInstance;
-}
-
-
-SourceFunctionInfo *
-SLU::createSourceFunctionInfo(const GlobalVariable *Desc,
- ProgramInfo &PI) const {
- SourceFunctionInfo *Result = new SourceFunctionInfo(PI, Desc);
- return PI.getLanguageCache(this).addSourceFunction(Result);
-}
-
-
-/// lookupFunction - Given a textual function name, return the
-/// SourceFunctionInfo descriptor for that function, or null if it cannot be
-/// found. If the program is currently running, the RuntimeInfo object
-/// provides information about the current evaluation context, otherwise it will
-/// be null.
-///
-SourceFunctionInfo *SLU::lookupFunction(const std::string &FunctionName,
- ProgramInfo &PI, RuntimeInfo *RI) const{
- SLUCache &Cache = PI.getLanguageCache(this);
- std::pair<SLUCache::fm_iterator, SLUCache::fm_iterator> IP
- = Cache.getFunction(FunctionName);
-
- if (IP.first == IP.second) {
- if (PI.allSourceFunctionsRead())
- return 0; // Nothing found
-
- // Otherwise, we might be able to find the function if we read all of them
- // in. Do so now.
- PI.getSourceFunctions();
- assert(PI.allSourceFunctionsRead() && "Didn't read in all functions?");
- return lookupFunction(FunctionName, PI, RI);
- }
-
- SourceFunctionInfo *Found = IP.first->second;
- ++IP.first;
- if (IP.first != IP.second)
- cout << "Whoa, found multiple functions with the same name. I should"
- << " ask the user which one to use: FIXME!\n";
- return Found;
-}
diff --git a/lib/Debugger/SourceLanguage.cpp b/lib/Debugger/SourceLanguage.cpp
deleted file mode 100644
index 4fcc38b..0000000
--- a/lib/Debugger/SourceLanguage.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===-- SourceLanguage.cpp - Implement the SourceLanguage class -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the SourceLanguage class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Debugger/SourceLanguage.h"
-#include "llvm/Debugger/ProgramInfo.h"
-using namespace llvm;
-
-const SourceLanguage &SourceLanguage::get(unsigned ID) {
- switch (ID) {
- case 1: // DW_LANG_C89
- case 2: // DW_LANG_C
- case 12: // DW_LANG_C99
- return getCFamilyInstance();
-
- case 4: // DW_LANG_C_plus_plus
- return getCPlusPlusInstance();
-
- case 3: // DW_LANG_Ada83
- case 5: // DW_LANG_Cobol74
- case 6: // DW_LANG_Cobol85
- case 7: // DW_LANG_Fortran77
- case 8: // DW_LANG_Fortran90
- case 9: // DW_LANG_Pascal83
- case 10: // DW_LANG_Modula2
- case 11: // DW_LANG_Java
- case 13: // DW_LANG_Ada95
- case 14: // DW_LANG_Fortran95
- default:
- return getUnknownLanguageInstance();
- }
-}
-
-
-SourceFileInfo *
-SourceLanguage::createSourceFileInfo(const GlobalVariable *Desc,
- ProgramInfo &PI) const {
- return new SourceFileInfo(Desc, *this);
-}
-
-SourceFunctionInfo *
-SourceLanguage::createSourceFunctionInfo(const GlobalVariable *Desc,
- ProgramInfo &PI) const {
- return new SourceFunctionInfo(PI, Desc);
-}
diff --git a/lib/Support/Annotation.cpp b/lib/Support/Annotation.cpp
deleted file mode 100644
index 4b5b97e..0000000
--- a/lib/Support/Annotation.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-//===-- Annotation.cpp - Implement the Annotation Classes -----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the AnnotationManager class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Annotation.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/System/RWMutex.h"
-#include <map>
-#include <cstring>
-using namespace llvm;
-
-Annotation::~Annotation() {} // Designed to be subclassed
-
-Annotable::~Annotable() { // Virtual because it's designed to be subclassed...
- Annotation *A = AnnotationList;
- while (A) {
- Annotation *Next = A->getNext();
- delete A;
- A = Next;
- }
-}
-
-namespace {
- class StrCmp {
- public:
- bool operator()(const char *a, const char *b) const {
- return strcmp(a, b) < 0;
- }
- };
-}
-
-typedef std::map<const char*, unsigned, StrCmp> IDMapType;
-static volatile sys::cas_flag IDCounter = 0; // Unique ID counter
-
-// Static member to ensure initialiation on demand.
-static ManagedStatic<IDMapType> IDMap;
-static ManagedStatic<sys::SmartRWMutex<true> > AnnotationsLock;
-
-// On demand annotation creation support...
-typedef Annotation *(*AnnFactory)(AnnotationID, const Annotable *, void *);
-typedef std::map<unsigned, std::pair<AnnFactory,void*> > FactMapType;
-
-static ManagedStatic<FactMapType> TheFactMap;
-static FactMapType &getFactMap() {
- return *TheFactMap;
-}
-
-static void eraseFromFactMap(unsigned ID) {
- sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
- TheFactMap->erase(ID);
-}
-
-AnnotationID AnnotationManager::getID(const char *Name) { // Name -> ID
- AnnotationsLock->reader_acquire();
- IDMapType::iterator I = IDMap->find(Name);
- IDMapType::iterator E = IDMap->end();
- AnnotationsLock->reader_release();
-
- if (I == E) {
- sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
- I = IDMap->find(Name);
- if (I == IDMap->end()) {
- unsigned newCount = sys::AtomicIncrement(&IDCounter);
- (*IDMap)[Name] = newCount-1; // Add a new element
- return AnnotationID(newCount-1);
- } else
- return AnnotationID(I->second);
- }
- return AnnotationID(I->second);
-}
-
-// getID - Name -> ID + registration of a factory function for demand driven
-// annotation support.
-AnnotationID AnnotationManager::getID(const char *Name, Factory Fact,
- void *Data) {
- AnnotationID Result(getID(Name));
- registerAnnotationFactory(Result, Fact, Data);
- return Result;
-}
-
-// getName - This function is especially slow, but that's okay because it should
-// only be used for debugging.
-//
-const char *AnnotationManager::getName(AnnotationID ID) { // ID -> Name
- sys::SmartScopedReader<true> Reader(&*AnnotationsLock);
- IDMapType &TheMap = *IDMap;
- for (IDMapType::iterator I = TheMap.begin(); ; ++I) {
- assert(I != TheMap.end() && "Annotation ID is unknown!");
- if (I->second == ID.ID) return I->first;
- }
-}
-
-// registerAnnotationFactory - This method is used to register a callback
-// function used to create an annotation on demand if it is needed by the
-// Annotable::findOrCreateAnnotation method.
-//
-void AnnotationManager::registerAnnotationFactory(AnnotationID ID, AnnFactory F,
- void *ExtraData) {
- if (F) {
- sys::SmartScopedWriter<true> Writer(&*AnnotationsLock);
- getFactMap()[ID.ID] = std::make_pair(F, ExtraData);
- } else {
- eraseFromFactMap(ID.ID);
- }
-}
-
-// createAnnotation - Create an annotation of the specified ID for the
-// specified object, using a register annotation creation function.
-//
-Annotation *AnnotationManager::createAnnotation(AnnotationID ID,
- const Annotable *Obj) {
- AnnotationsLock->reader_acquire();
- FactMapType::iterator I = getFactMap().find(ID.ID);
- if (I == getFactMap().end()) {
- AnnotationsLock->reader_release();
- return 0;
- }
-
- AnnotationsLock->reader_release();
- return I->second.first(ID, Obj, I->second.second);
-}
diff --git a/lib/Support/Streams.cpp b/lib/Support/Streams.cpp
deleted file mode 100644
index cf6cfeb..0000000
--- a/lib/Support/Streams.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//===-- Streams.cpp - Wrappers for iostreams ------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements a wrapper for the std::cout and std::cerr I/O streams.
-// It prevents the need to include <iostream> to each file just to get I/O.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Support/Streams.h"
-#include <iostream>
-using namespace llvm;
-
-OStream llvm::cout(std::cout);
-OStream llvm::cerr(std::cerr);
-IStream llvm::cin(std::cin);
-
-namespace llvm {
-
-/// FlushStream - Function called by BaseStream to flush an ostream.
-void FlushStream(std::ostream &S) {
- S << std::flush;
-}
-
-} // end anonymous namespace
diff --git a/lib/System/LICENSE.TXT b/lib/System/LICENSE.TXT
deleted file mode 100644
index f569da2..0000000
--- a/lib/System/LICENSE.TXT
+++ /dev/null
@@ -1,6 +0,0 @@
-LLVM System Interface Library
--------------------------------------------------------------------------------
-The LLVM System Interface Library is licensed under the Illinois Open Source
-License and has the following additional copyright:
-
-Copyright (C) 2004 eXtensible Systems, Inc.
diff --git a/lib/Target/ARM/ARMTargetAsmInfo.cpp b/lib/Target/ARM/ARMTargetAsmInfo.cpp
deleted file mode 100644
index bf2c14e..0000000
--- a/lib/Target/ARM/ARMTargetAsmInfo.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-//===-- ARMTargetAsmInfo.cpp - ARM asm properties ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the ARMTargetAsmInfo properties.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ARMTargetAsmInfo.h"
-#include "ARMTargetMachine.h"
-#include <cstring>
-#include <cctype>
-using namespace llvm;
-
-const char *const llvm::arm_asm_table[] = {
- "{r0}", "r0",
- "{r1}", "r1",
- "{r2}", "r2",
- "{r3}", "r3",
- "{r4}", "r4",
- "{r5}", "r5",
- "{r6}", "r6",
- "{r7}", "r7",
- "{r8}", "r8",
- "{r9}", "r9",
- "{r10}", "r10",
- "{r11}", "r11",
- "{r12}", "r12",
- "{r13}", "r13",
- "{r14}", "r14",
- "{lr}", "lr",
- "{sp}", "sp",
- "{ip}", "ip",
- "{fp}", "fp",
- "{sl}", "sl",
- "{memory}", "memory",
- "{cc}", "cc",
- 0,0
-};
-
-ARMDarwinTargetAsmInfo::ARMDarwinTargetAsmInfo(const ARMBaseTargetMachine &TM):
- ARMTargetAsmInfo<DarwinTargetAsmInfo>(TM) {
- Subtarget = &TM.getSubtarget<ARMSubtarget>();
-
- ZeroDirective = "\t.space\t";
- ZeroFillDirective = "\t.zerofill\t"; // Uses .zerofill
- SetDirective = "\t.set\t";
- ProtectedDirective = NULL;
- HasDotTypeDotSizeDirective = false;
- SupportsDebugInformation = true;
-}
-
-ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMBaseTargetMachine &TM):
- ARMTargetAsmInfo<ELFTargetAsmInfo>(TM) {
- Subtarget = &TM.getSubtarget<ARMSubtarget>();
-
- NeedsSet = false;
- HasLEB128 = true;
- AbsoluteDebugSectionOffsets = true;
- CStringSection = ".rodata.str";
- PrivateGlobalPrefix = ".L";
- WeakRefDirective = "\t.weak\t";
- SetDirective = "\t.set\t";
- DwarfRequiresFrameSection = false;
- DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"\",%progbits";
- DwarfInfoSection = "\t.section\t.debug_info,\"\",%progbits";
- DwarfLineSection = "\t.section\t.debug_line,\"\",%progbits";
- DwarfFrameSection = "\t.section\t.debug_frame,\"\",%progbits";
- DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"\",%progbits";
- DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"\",%progbits";
- DwarfStrSection = "\t.section\t.debug_str,\"\",%progbits";
- DwarfLocSection = "\t.section\t.debug_loc,\"\",%progbits";
- DwarfARangesSection = "\t.section\t.debug_aranges,\"\",%progbits";
- DwarfRangesSection = "\t.section\t.debug_ranges,\"\",%progbits";
- DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"\",%progbits";
-
- if (Subtarget->isAAPCS_ABI()) {
- StaticCtorsSection = "\t.section .init_array,\"aw\",%init_array";
- StaticDtorsSection = "\t.section .fini_array,\"aw\",%fini_array";
- } else {
- StaticCtorsSection = "\t.section .ctors,\"aw\",%progbits";
- StaticDtorsSection = "\t.section .dtors,\"aw\",%progbits";
- }
- SupportsDebugInformation = true;
-}
-
-/// Count the number of comma-separated arguments.
-/// Do not try to detect errors.
-template <class BaseTAI>
-unsigned ARMTargetAsmInfo<BaseTAI>::countArguments(const char* p) const {
- unsigned count = 0;
- while (*p && isspace(*p) && *p != '\n')
- p++;
- count++;
- while (*p && *p!='\n' &&
- strncmp(p, BaseTAI::CommentString,
- strlen(BaseTAI::CommentString))!=0) {
- if (*p==',')
- count++;
- p++;
- }
- return count;
-}
-
-/// Count the length of a string enclosed in quote characters.
-/// Do not try to detect errors.
-template <class BaseTAI>
-unsigned ARMTargetAsmInfo<BaseTAI>::countString(const char* p) const {
- unsigned count = 0;
- while (*p && isspace(*p) && *p!='\n')
- p++;
- if (!*p || *p != '\"')
- return count;
- while (*++p && *p != '\"')
- count++;
- return count;
-}
-
-/// ARM-specific version of TargetAsmInfo::getInlineAsmLength.
-template <class BaseTAI>
-unsigned ARMTargetAsmInfo<BaseTAI>::getInlineAsmLength(const char *s) const {
- // Make a lowercase-folded version of s for counting purposes.
- char *q, *s_copy = (char *)malloc(strlen(s) + 1);
- strcpy(s_copy, s);
- for (q=s_copy; *q; q++)
- *q = tolower(*q);
- const char *Str = s_copy;
-
- // Count the number of bytes in the asm.
- bool atInsnStart = true;
- bool inTextSection = true;
- unsigned Length = 0;
- for (; *Str; ++Str) {
- if (atInsnStart) {
- // Skip whitespace
- while (*Str && isspace(*Str) && *Str != '\n')
- Str++;
- // Skip label
- for (const char* p = Str; *p && !isspace(*p); p++)
- if (*p == ':') {
- Str = p+1;
- while (*Str && isspace(*Str) && *Str != '\n')
- Str++;
- break;
- }
-
- if (*Str == 0) break;
-
- // Ignore everything from comment char(s) to EOL
- if (strncmp(Str, BaseTAI::CommentString,
- strlen(BaseTAI::CommentString)) == 0)
- atInsnStart = false;
- // FIXME do something like the following for non-Darwin
- else if (*Str == '.' && Subtarget->isTargetDarwin()) {
- // Directive.
- atInsnStart = false;
-
- // Some change the section, but don't generate code.
- if (strncmp(Str, ".literal4", strlen(".literal4"))==0 ||
- strncmp(Str, ".literal8", strlen(".literal8"))==0 ||
- strncmp(Str, ".const", strlen(".const"))==0 ||
- strncmp(Str, ".constructor", strlen(".constructor"))==0 ||
- strncmp(Str, ".cstring", strlen(".cstring"))==0 ||
- strncmp(Str, ".data", strlen(".data"))==0 ||
- strncmp(Str, ".destructor", strlen(".destructor"))==0 ||
- strncmp(Str, ".fvmlib_init0", strlen(".fvmlib_init0"))==0 ||
- strncmp(Str, ".fvmlib_init1", strlen(".fvmlib_init1"))==0 ||
- strncmp(Str, ".mod_init_func", strlen(".mod_init_func"))==0 ||
- strncmp(Str, ".mod_term_func", strlen(".mod_term_func"))==0 ||
- strncmp(Str, ".picsymbol_stub", strlen(".picsymbol_stub"))==0 ||
- strncmp(Str, ".symbol_stub", strlen(".symbol_stub"))==0 ||
- strncmp(Str, ".static_data", strlen(".static_data"))==0 ||
- strncmp(Str, ".section", strlen(".section"))==0 ||
- strncmp(Str, ".lazy_symbol_pointer", strlen(".lazy_symbol_pointer"))==0 ||
- strncmp(Str, ".non_lazy_symbol_pointer", strlen(".non_lazy_symbol_pointer"))==0 ||
- strncmp(Str, ".dyld", strlen(".dyld"))==0 ||
- strncmp(Str, ".const_data", strlen(".const_data"))==0 ||
- strncmp(Str, ".objc", strlen(".objc"))==0 || //// many directives
- strncmp(Str, ".static_const", strlen(".static_const"))==0)
- inTextSection=false;
- else if (strncmp(Str, ".text", strlen(".text"))==0)
- inTextSection = true;
- // Some can't really be handled without implementing significant pieces
- // of an assembler. Others require dynamic adjustment of block sizes in
- // AdjustBBOffsetsAfter; it's a big compile-time speed hit to check every
- // instruction in there, and none of these are currently used in the kernel.
- else if (strncmp(Str, ".macro", strlen(".macro"))==0 ||
- strncmp(Str, ".if", strlen(".if"))==0 ||
- strncmp(Str, ".align", strlen(".align"))==0 ||
- strncmp(Str, ".fill", strlen(".fill"))==0 ||
- strncmp(Str, ".space", strlen(".space"))==0 ||
- strncmp(Str, ".zerofill", strlen(".zerofill"))==0 ||
- strncmp(Str, ".p2align", strlen(".p2align"))==0 ||
- strncmp(Str, ".p2alignw", strlen(".p2alignw"))==0 ||
- strncmp(Str, ".p2alignl", strlen(".p2alignl"))==0 ||
- strncmp(Str, ".align32", strlen(".p2align32"))==0 ||
- strncmp(Str, ".include", strlen(".include"))==0)
- cerr << "Directive " << Str << " in asm may lead to invalid offsets for" <<
- " constant pools (the assembler will tell you if this happens).\n";
- // Some generate code, but this is only interesting in the text section.
- else if (inTextSection) {
- if (strncmp(Str, ".long", strlen(".long"))==0)
- Length += 4*countArguments(Str+strlen(".long"));
- else if (strncmp(Str, ".short", strlen(".short"))==0)
- Length += 2*countArguments(Str+strlen(".short"));
- else if (strncmp(Str, ".byte", strlen(".byte"))==0)
- Length += 1*countArguments(Str+strlen(".byte"));
- else if (strncmp(Str, ".single", strlen(".single"))==0)
- Length += 4*countArguments(Str+strlen(".single"));
- else if (strncmp(Str, ".double", strlen(".double"))==0)
- Length += 8*countArguments(Str+strlen(".double"));
- else if (strncmp(Str, ".quad", strlen(".quad"))==0)
- Length += 16*countArguments(Str+strlen(".quad"));
- else if (strncmp(Str, ".ascii", strlen(".ascii"))==0)
- Length += countString(Str+strlen(".ascii"));
- else if (strncmp(Str, ".asciz", strlen(".asciz"))==0)
- Length += countString(Str+strlen(".asciz"))+1;
- }
- } else if (inTextSection) {
- // An instruction
- atInsnStart = false;
- if (Subtarget->isThumb()) {
- // BL and BLX <non-reg> are 4 bytes, all others 2.
- if (strncmp(Str, "blx", strlen("blx"))==0) {
- const char* p = Str+3;
- while (*p && isspace(*p))
- p++;
- if (*p == 'r' || *p=='R')
- Length += 2; // BLX reg
- else
- Length += 4; // BLX non-reg
- } else if (strncmp(Str, "bl", strlen("bl"))==0)
- Length += 4; // BL
- else
- Length += 2; // Thumb anything else
- }
- else
- Length += 4; // ARM
- }
- }
- if (*Str == '\n' || *Str == BaseTAI::SeparatorChar)
- atInsnStart = true;
- }
- free(s_copy);
- return Length;
-}
-
-// Instantiate default implementation.
-TEMPLATE_INSTANTIATION(class ARMTargetAsmInfo<TargetAsmInfo>);
diff --git a/lib/Target/ARM/ARMTargetAsmInfo.h b/lib/Target/ARM/ARMTargetAsmInfo.h
deleted file mode 100644
index d3f2da0..0000000
--- a/lib/Target/ARM/ARMTargetAsmInfo.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//=====-- ARMTargetAsmInfo.h - ARM asm properties -------------*- C++ -*--====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the ARMTargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ARMTARGETASMINFO_H
-#define ARMTARGETASMINFO_H
-
-#include "ARMTargetMachine.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/ELFTargetAsmInfo.h"
-#include "llvm/Target/DarwinTargetAsmInfo.h"
-#include "llvm/Support/Compiler.h"
-
-namespace llvm {
-
- extern const char *const arm_asm_table[];
-
- template <class BaseTAI>
- struct ARMTargetAsmInfo : public BaseTAI {
- explicit ARMTargetAsmInfo(const ARMBaseTargetMachine &TM) : BaseTAI(TM) {
- BaseTAI::AsmTransCBE = arm_asm_table;
-
- BaseTAI::AlignmentIsInBytes = false;
- BaseTAI::Data64bitsDirective = 0;
- BaseTAI::CommentString = "@";
- BaseTAI::ConstantPoolSection = "\t.text\n";
- BaseTAI::COMMDirectiveTakesAlignment = false;
- BaseTAI::InlineAsmStart = "@ InlineAsm Start";
- BaseTAI::InlineAsmEnd = "@ InlineAsm End";
- BaseTAI::LCOMMDirective = "\t.lcomm\t";
- }
-
- const ARMSubtarget *Subtarget;
-
- virtual unsigned getInlineAsmLength(const char *Str) const;
- unsigned countArguments(const char *p) const;
- unsigned countString(const char *p) const;
- };
-
- typedef ARMTargetAsmInfo<TargetAsmInfo> ARMGenericTargetAsmInfo;
-
- EXTERN_TEMPLATE_INSTANTIATION(class ARMTargetAsmInfo<TargetAsmInfo>);
-
- struct ARMDarwinTargetAsmInfo : public ARMTargetAsmInfo<DarwinTargetAsmInfo> {
- explicit ARMDarwinTargetAsmInfo(const ARMBaseTargetMachine &TM);
- };
-
- struct ARMELFTargetAsmInfo : public ARMTargetAsmInfo<ELFTargetAsmInfo> {
- explicit ARMELFTargetAsmInfo(const ARMBaseTargetMachine &TM);
- };
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/Alpha/AlphaTargetAsmInfo.cpp b/lib/Target/Alpha/AlphaTargetAsmInfo.cpp
deleted file mode 100644
index 6092ab6..0000000
--- a/lib/Target/Alpha/AlphaTargetAsmInfo.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//===-- AlphaTargetAsmInfo.cpp - Alpha asm properties -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the AlphaTargetAsmInfo properties.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AlphaTargetMachine.h"
-#include "AlphaTargetAsmInfo.h"
-
-using namespace llvm;
-
-AlphaTargetAsmInfo::AlphaTargetAsmInfo(const AlphaTargetMachine &TM)
- : TargetAsmInfo(TM) {
- AlignmentIsInBytes = false;
- PrivateGlobalPrefix = "$";
- JumpTableDirective = ".gprel32";
- JumpTableDataSection = "\t.section .rodata\n";
- WeakRefDirective = "\t.weak\t";
-}
-
-unsigned AlphaTargetAsmInfo::RelocBehaviour() const {
- return (TM.getRelocationModel() != Reloc::Static ?
- Reloc::LocalOrGlobal : Reloc::Global);
-}
diff --git a/lib/Target/Alpha/AlphaTargetAsmInfo.h b/lib/Target/Alpha/AlphaTargetAsmInfo.h
deleted file mode 100644
index 7675b26..0000000
--- a/lib/Target/Alpha/AlphaTargetAsmInfo.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//=====-- AlphaTargetAsmInfo.h - Alpha asm properties ---------*- C++ -*--====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the AlphaTargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ALPHATARGETASMINFO_H
-#define ALPHATARGETASMINFO_H
-
-#include "llvm/Target/TargetAsmInfo.h"
-
-namespace llvm {
-
- // Forward declaration.
- class AlphaTargetMachine;
-
- struct AlphaTargetAsmInfo : public TargetAsmInfo {
- explicit AlphaTargetAsmInfo(const AlphaTargetMachine &TM);
-
- virtual unsigned RelocBehaviour() const;
- };
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/CellSPU/SPUTargetAsmInfo.cpp b/lib/Target/CellSPU/SPUTargetAsmInfo.cpp
deleted file mode 100644
index 2868ff7..0000000
--- a/lib/Target/CellSPU/SPUTargetAsmInfo.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-//===-- SPUTargetAsmInfo.cpp - Cell SPU asm properties ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the SPUTargetAsmInfo properties.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SPUTargetAsmInfo.h"
-#include "SPUTargetMachine.h"
-#include "llvm/Function.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Dwarf.h"
-
-using namespace llvm;
-using namespace llvm::dwarf;
-
-SPULinuxTargetAsmInfo::SPULinuxTargetAsmInfo(const SPUTargetMachine &TM) :
- SPUTargetAsmInfo<ELFTargetAsmInfo>(TM) {
- PCSymbol = ".";
- CommentString = "#";
- GlobalPrefix = "";
- PrivateGlobalPrefix = ".L";
- // This corresponds to what the gcc SPU compiler emits, for consistency.
- CStringSection = ".rodata.str";
-
- // Has leb128, .loc and .file
- HasLEB128 = true;
- HasDotLocAndDotFile = true;
-
- // BSS section needs to be emitted as ".section"
- BSSSection = "\t.section\t.bss";
- BSSSection_ = getUnnamedSection("\t.section\t.bss",
- SectionFlags::Writeable | SectionFlags::BSS,
- true);
-
- SupportsDebugInformation = true;
- NeedsSet = true;
- DwarfAbbrevSection = "\t.section .debug_abbrev,\"\",@progbits";
- DwarfInfoSection = "\t.section .debug_info,\"\",@progbits";
- DwarfLineSection = "\t.section .debug_line,\"\",@progbits";
- DwarfFrameSection = "\t.section .debug_frame,\"\",@progbits";
- DwarfPubNamesSection = "\t.section .debug_pubnames,\"\",@progbits";
- DwarfPubTypesSection = "\t.section .debug_pubtypes,\"\",progbits";
- DwarfStrSection = "\t.section .debug_str,\"MS\",@progbits,1";
- DwarfLocSection = "\t.section .debug_loc,\"\",@progbits";
- DwarfARangesSection = "\t.section .debug_aranges,\"\",@progbits";
- DwarfRangesSection = "\t.section .debug_ranges,\"\",@progbits";
- DwarfMacroInfoSection = 0; // macro info not supported.
-
- // Exception handling is not supported on CellSPU (think about it: you only
- // have 256K for code+data. Would you support exception handling?)
- SupportsExceptionHandling = false;
-}
-
-/// PreferredEHDataFormat - This hook allows the target to select data
-/// format used for encoding pointers in exception handling data. Reason is
-/// 0 for data, 1 for code labels, 2 for function pointers. Global is true
-/// if the symbol can be relocated.
-unsigned
-SPULinuxTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const {
- // We really need to write something here.
- return TargetAsmInfo::PreferredEHDataFormat(Reason, Global);
-}
-
-// Instantiate default implementation.
-TEMPLATE_INSTANTIATION(class SPUTargetAsmInfo<TargetAsmInfo>);
diff --git a/lib/Target/CellSPU/SPUTargetAsmInfo.h b/lib/Target/CellSPU/SPUTargetAsmInfo.h
deleted file mode 100644
index d10a565..0000000
--- a/lib/Target/CellSPU/SPUTargetAsmInfo.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===-- SPUTargetAsmInfo.h - Cell SPU asm properties -----------*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the SPUTargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPUTARGETASMINFO_H
-#define SPUTARGETASMINFO_H
-
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/ELFTargetAsmInfo.h"
-#include "SPUTargetMachine.h"
-#include "SPUSubtarget.h"
-
-namespace llvm {
-
- // Forward declaration.
- class SPUTargetMachine;
-
- template <class BaseTAI>
- struct SPUTargetAsmInfo : public BaseTAI {
- explicit SPUTargetAsmInfo(const SPUTargetMachine &TM):
- BaseTAI(TM) {
- /* (unused today)
- * const SPUSubtarget *Subtarget = &TM.getSubtarget<SPUSubtarget>(); */
-
- BaseTAI::ZeroDirective = "\t.space\t";
- BaseTAI::SetDirective = "\t.set";
- BaseTAI::Data64bitsDirective = "\t.quad\t";
- BaseTAI::AlignmentIsInBytes = false;
- BaseTAI::LCOMMDirective = "\t.lcomm\t";
- BaseTAI::InlineAsmStart = "# InlineAsm Start";
- BaseTAI::InlineAsmEnd = "# InlineAsm End";
- }
- };
-
- struct SPULinuxTargetAsmInfo : public SPUTargetAsmInfo<ELFTargetAsmInfo> {
- explicit SPULinuxTargetAsmInfo(const SPUTargetMachine &TM);
- virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const;
- };
-} // namespace llvm
-
-#endif /* SPUTARGETASMINFO_H */
diff --git a/lib/Target/DarwinTargetAsmInfo.cpp b/lib/Target/DarwinTargetAsmInfo.cpp
deleted file mode 100644
index d7d675a..0000000
--- a/lib/Target/DarwinTargetAsmInfo.cpp
+++ /dev/null
@@ -1,216 +0,0 @@
-//===-- DarwinTargetAsmInfo.cpp - Darwin asm properties ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines target asm properties related what form asm statements
-// should take in general on Darwin-based targets
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Function.h"
-#include "llvm/GlobalVariable.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Target/DarwinTargetAsmInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetData.h"
-
-using namespace llvm;
-
-DarwinTargetAsmInfo::DarwinTargetAsmInfo(const TargetMachine &TM)
- : TargetAsmInfo(TM) {
-
- CStringSection_ = getUnnamedSection("\t.cstring",
- SectionFlags::Mergeable | SectionFlags::Strings);
- FourByteConstantSection = getUnnamedSection("\t.literal4\n",
- SectionFlags::Mergeable);
- EightByteConstantSection = getUnnamedSection("\t.literal8\n",
- SectionFlags::Mergeable);
-
- // Note: 16-byte constant section is subtarget specific and should be provided
- // there, if needed.
- SixteenByteConstantSection = 0;
-
- ReadOnlySection = getUnnamedSection("\t.const\n", SectionFlags::None);
-
- TextCoalSection =
- getNamedSection("\t__TEXT,__textcoal_nt,coalesced,pure_instructions",
- SectionFlags::Code);
- ConstTextCoalSection = getNamedSection("\t__TEXT,__const_coal,coalesced",
- SectionFlags::None);
- ConstDataCoalSection = getNamedSection("\t__DATA,__const_coal,coalesced",
- SectionFlags::None);
- ConstDataSection = getUnnamedSection(".const_data", SectionFlags::None);
- DataCoalSection = getNamedSection("\t__DATA,__datacoal_nt,coalesced",
- SectionFlags::Writeable);
-
-
- // Common settings for all Darwin targets.
- // Syntax:
- GlobalPrefix = "_";
- PrivateGlobalPrefix = "L";
- LessPrivateGlobalPrefix = "l"; // Marker for some ObjC metadata
- StringConstantPrefix = "\1LC";
- NeedsSet = true;
- NeedsIndirectEncoding = true;
- AllowQuotesInName = true;
- HasSingleParameterDotFile = false;
-
- // In non-PIC modes, emit a special label before jump tables so that the
- // linker can perform more accurate dead code stripping. We do not check the
- // relocation model here since it can be overridden later.
- JumpTableSpecialLabelPrefix = "l";
-
- // Directives:
- WeakDefDirective = "\t.weak_definition ";
- WeakRefDirective = "\t.weak_reference ";
- HiddenDirective = "\t.private_extern ";
-
- // Sections:
- CStringSection = "\t.cstring";
- JumpTableDataSection = "\t.const\n";
- BSSSection = 0;
-
- if (TM.getRelocationModel() == Reloc::Static) {
- StaticCtorsSection = ".constructor";
- StaticDtorsSection = ".destructor";
- } else {
- StaticCtorsSection = ".mod_init_func";
- StaticDtorsSection = ".mod_term_func";
- }
-
- DwarfAbbrevSection = ".section __DWARF,__debug_abbrev,regular,debug";
- DwarfInfoSection = ".section __DWARF,__debug_info,regular,debug";
- DwarfLineSection = ".section __DWARF,__debug_line,regular,debug";
- DwarfFrameSection = ".section __DWARF,__debug_frame,regular,debug";
- DwarfPubNamesSection = ".section __DWARF,__debug_pubnames,regular,debug";
- DwarfPubTypesSection = ".section __DWARF,__debug_pubtypes,regular,debug";
- DwarfStrSection = ".section __DWARF,__debug_str,regular,debug";
- DwarfLocSection = ".section __DWARF,__debug_loc,regular,debug";
- DwarfARangesSection = ".section __DWARF,__debug_aranges,regular,debug";
- DwarfRangesSection = ".section __DWARF,__debug_ranges,regular,debug";
- DwarfMacroInfoSection = ".section __DWARF,__debug_macinfo,regular,debug";
-}
-
-/// emitUsedDirectiveFor - On Darwin, internally linked data beginning with
-/// the PrivateGlobalPrefix or the LessPrivateGlobalPrefix does not have the
-/// directive emitted (this occurs in ObjC metadata).
-
-bool
-DarwinTargetAsmInfo::emitUsedDirectiveFor(const GlobalValue* GV,
- Mangler *Mang) const {
- if (GV==0)
- return false;
- if (GV->hasLocalLinkage() && !isa<Function>(GV) &&
- ((strlen(getPrivateGlobalPrefix()) != 0 &&
- Mang->getValueName(GV).substr(0,strlen(getPrivateGlobalPrefix())) ==
- getPrivateGlobalPrefix()) ||
- (strlen(getLessPrivateGlobalPrefix()) != 0 &&
- Mang->getValueName(GV).substr(0,strlen(getLessPrivateGlobalPrefix())) ==
- getLessPrivateGlobalPrefix())))
- return false;
- return true;
-}
-
-const Section*
-DarwinTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
- SectionKind::Kind Kind = SectionKindForGlobal(GV);
- bool isWeak = GV->isWeakForLinker();
- bool isNonStatic = TM.getRelocationModel() != Reloc::Static;
-
- switch (Kind) {
- case SectionKind::Text:
- if (isWeak)
- return TextCoalSection;
- else
- return TextSection;
- case SectionKind::Data:
- case SectionKind::ThreadData:
- case SectionKind::BSS:
- case SectionKind::ThreadBSS:
- if (cast<GlobalVariable>(GV)->isConstant())
- return (isWeak ? ConstDataCoalSection : ConstDataSection);
- else
- return (isWeak ? DataCoalSection : DataSection);
- case SectionKind::ROData:
- return (isWeak ? ConstDataCoalSection :
- (isNonStatic ? ConstDataSection : getReadOnlySection()));
- case SectionKind::RODataMergeStr:
- return (isWeak ?
- ConstTextCoalSection :
- MergeableStringSection(cast<GlobalVariable>(GV)));
- case SectionKind::RODataMergeConst:
- return (isWeak ?
- ConstDataCoalSection:
- MergeableConstSection(cast<GlobalVariable>(GV)));
- default:
- assert(0 && "Unsuported section kind for global");
- }
-
- // FIXME: Do we have any extra special weird cases?
- return NULL;
-}
-
-const Section*
-DarwinTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const {
- const TargetData *TD = TM.getTargetData();
- Constant *C = cast<GlobalVariable>(GV)->getInitializer();
- const Type *Ty = cast<ArrayType>(C->getType())->getElementType();
-
- unsigned Size = TD->getTypeAllocSize(Ty);
- if (Size) {
- unsigned Align = TD->getPreferredAlignment(GV);
- if (Align <= 32)
- return getCStringSection_();
- }
-
- return getReadOnlySection();
-}
-
-const Section*
-DarwinTargetAsmInfo::MergeableConstSection(const GlobalVariable *GV) const {
- Constant *C = GV->getInitializer();
-
- return MergeableConstSection(C->getType());
-}
-
-inline const Section*
-DarwinTargetAsmInfo::MergeableConstSection(const Type *Ty) const {
- const TargetData *TD = TM.getTargetData();
-
- unsigned Size = TD->getTypeAllocSize(Ty);
- if (Size == 4)
- return FourByteConstantSection;
- else if (Size == 8)
- return EightByteConstantSection;
- else if (Size == 16 && SixteenByteConstantSection)
- return SixteenByteConstantSection;
-
- return getReadOnlySection();
-}
-
-const Section*
-DarwinTargetAsmInfo::SelectSectionForMachineConst(const Type *Ty) const {
- const Section* S = MergeableConstSection(Ty);
-
- // Handle weird special case, when compiling PIC stuff.
- if (S == getReadOnlySection() &&
- TM.getRelocationModel() != Reloc::Static)
- return ConstDataSection;
-
- return S;
-}
-
-std::string
-DarwinTargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV,
- SectionKind::Kind kind) const {
- assert(0 && "Darwin does not use unique sections");
- return "";
-}
diff --git a/lib/Target/ELFTargetAsmInfo.cpp b/lib/Target/ELFTargetAsmInfo.cpp
deleted file mode 100644
index 8f6e96e..0000000
--- a/lib/Target/ELFTargetAsmInfo.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-//===-- ELFTargetAsmInfo.cpp - ELF asm properties ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines target asm properties related what form asm statements
-// should take in general on ELF-based targets
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Function.h"
-#include "llvm/GlobalVariable.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/Target/ELFTargetAsmInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetData.h"
-
-using namespace llvm;
-
-ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM)
- : TargetAsmInfo(TM) {
-
- BSSSection_ = getUnnamedSection("\t.bss",
- SectionFlags::Writeable | SectionFlags::BSS);
- ReadOnlySection = getNamedSection("\t.rodata", SectionFlags::None);
- TLSDataSection = getNamedSection("\t.tdata",
- SectionFlags::Writeable | SectionFlags::TLS);
- TLSBSSSection = getNamedSection("\t.tbss",
- SectionFlags::Writeable | SectionFlags::TLS | SectionFlags::BSS);
-
- DataRelSection = getNamedSection("\t.data.rel", SectionFlags::Writeable);
- DataRelLocalSection = getNamedSection("\t.data.rel.local",
- SectionFlags::Writeable);
- DataRelROSection = getNamedSection("\t.data.rel.ro",
- SectionFlags::Writeable);
- DataRelROLocalSection = getNamedSection("\t.data.rel.ro.local",
- SectionFlags::Writeable);
-}
-
-SectionKind::Kind
-ELFTargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const {
- SectionKind::Kind Kind = TargetAsmInfo::SectionKindForGlobal(GV);
-
- if (Kind != SectionKind::Data)
- return Kind;
-
- // Decide, whether we need data.rel stuff
- const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV);
- if (GVar->hasInitializer()) {
- Constant *C = GVar->getInitializer();
- bool isConstant = GVar->isConstant();
- unsigned Reloc = RelocBehaviour();
- if (Reloc != Reloc::None && C->ContainsRelocations(Reloc))
- return (C->ContainsRelocations(Reloc::Global) ?
- (isConstant ?
- SectionKind::DataRelRO : SectionKind::DataRel) :
- (isConstant ?
- SectionKind::DataRelROLocal : SectionKind::DataRelLocal));
- }
-
- return Kind;
-}
-
-const Section*
-ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
- SectionKind::Kind Kind = SectionKindForGlobal(GV);
-
- if (const Function *F = dyn_cast<Function>(GV)) {
- switch (F->getLinkage()) {
- default: assert(0 && "Unknown linkage type!");
- case Function::PrivateLinkage:
- case Function::InternalLinkage:
- case Function::DLLExportLinkage:
- case Function::ExternalLinkage:
- return TextSection;
- case Function::WeakAnyLinkage:
- case Function::WeakODRLinkage:
- case Function::LinkOnceAnyLinkage:
- case Function::LinkOnceODRLinkage:
- std::string Name = UniqueSectionForGlobal(GV, Kind);
- unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str());
- return getNamedSection(Name.c_str(), Flags);
- }
- } else if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
- if (GVar->isWeakForLinker()) {
- std::string Name = UniqueSectionForGlobal(GVar, Kind);
- unsigned Flags = SectionFlagsForGlobal(GVar, Name.c_str());
- return getNamedSection(Name.c_str(), Flags);
- } else {
- switch (Kind) {
- case SectionKind::Data:
- case SectionKind::SmallData:
- return DataSection;
- case SectionKind::DataRel:
- return DataRelSection;
- case SectionKind::DataRelLocal:
- return DataRelLocalSection;
- case SectionKind::DataRelRO:
- return DataRelROSection;
- case SectionKind::DataRelROLocal:
- return DataRelROLocalSection;
- case SectionKind::BSS:
- case SectionKind::SmallBSS:
- // ELF targets usually have BSS sections
- return getBSSSection_();
- case SectionKind::ROData:
- case SectionKind::SmallROData:
- return getReadOnlySection();
- case SectionKind::RODataMergeStr:
- return MergeableStringSection(GVar);
- case SectionKind::RODataMergeConst:
- return MergeableConstSection(GVar);
- case SectionKind::ThreadData:
- // ELF targets usually support TLS stuff
- return TLSDataSection;
- case SectionKind::ThreadBSS:
- return TLSBSSSection;
- default:
- assert(0 && "Unsuported section kind for global");
- }
- }
- } else
- assert(0 && "Unsupported global");
-
- return NULL;
-}
-
-const Section*
-ELFTargetAsmInfo::SelectSectionForMachineConst(const Type *Ty) const {
- // FIXME: Support data.rel stuff someday
- return MergeableConstSection(Ty);
-}
-
-const Section*
-ELFTargetAsmInfo::MergeableConstSection(const GlobalVariable *GV) const {
- Constant *C = GV->getInitializer();
- return MergeableConstSection(C->getType());
-}
-
-inline const Section*
-ELFTargetAsmInfo::MergeableConstSection(const Type *Ty) const {
- const TargetData *TD = TM.getTargetData();
-
- // FIXME: string here is temporary, until stuff will fully land in.
- // We cannot use {Four,Eight,Sixteen}ByteConstantSection here, since it's
- // currently directly used by asmprinter.
- unsigned Size = TD->getTypeAllocSize(Ty);
- if (Size == 4 || Size == 8 || Size == 16) {
- std::string Name = ".rodata.cst" + utostr(Size);
-
- return getNamedSection(Name.c_str(),
- SectionFlags::setEntitySize(SectionFlags::Mergeable,
- Size));
- }
-
- return getReadOnlySection();
-}
-
-const Section*
-ELFTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const {
- const TargetData *TD = TM.getTargetData();
- Constant *C = cast<GlobalVariable>(GV)->getInitializer();
- const Type *Ty = cast<ArrayType>(C->getType())->getElementType();
-
- unsigned Size = TD->getTypeAllocSize(Ty);
- if (Size <= 16) {
- assert(getCStringSection() && "Should have string section prefix");
-
- // We also need alignment here
- unsigned Align = TD->getPrefTypeAlignment(Ty);
- if (Align < Size)
- Align = Size;
-
- std::string Name = getCStringSection() + utostr(Size) + '.' + utostr(Align);
- unsigned Flags = SectionFlags::setEntitySize(SectionFlags::Mergeable |
- SectionFlags::Strings,
- Size);
- return getNamedSection(Name.c_str(), Flags);
- }
-
- return getReadOnlySection();
-}
-
-std::string ELFTargetAsmInfo::printSectionFlags(unsigned flags) const {
- std::string Flags = ",\"";
-
- if (!(flags & SectionFlags::Debug))
- Flags += 'a';
- if (flags & SectionFlags::Code)
- Flags += 'x';
- if (flags & SectionFlags::Writeable)
- Flags += 'w';
- if (flags & SectionFlags::Mergeable)
- Flags += 'M';
- if (flags & SectionFlags::Strings)
- Flags += 'S';
- if (flags & SectionFlags::TLS)
- Flags += 'T';
- if (flags & SectionFlags::Small)
- Flags += 's';
-
- Flags += "\",";
-
- // If comment string is '@', e.g. as on ARM - use '%' instead
- if (strcmp(CommentString, "@") == 0)
- Flags += '%';
- else
- Flags += '@';
-
- // FIXME: There can be exceptions here
- if (flags & SectionFlags::BSS)
- Flags += "nobits";
- else
- Flags += "progbits";
-
- if (unsigned entitySize = SectionFlags::getEntitySize(flags))
- Flags += "," + utostr(entitySize);
-
- return Flags;
-}
diff --git a/lib/Target/IA64/AsmPrinter/CMakeLists.txt b/lib/Target/IA64/AsmPrinter/CMakeLists.txt
deleted file mode 100644
index ffe0eed..0000000
--- a/lib/Target/IA64/AsmPrinter/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-include_directories(
- ${CMAKE_CURRENT_BINARY_DIR}/..
- ${CMAKE_CURRENT_SOURCE_DIR}/..
- )
-
-add_llvm_library(LLVMIA64AsmPrinter
- IA64AsmPrinter.cpp
- )
-add_dependencies(LLVMIA64AsmPrinter IA64CodeGenTable_gen) \ No newline at end of file
diff --git a/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp b/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp
deleted file mode 100644
index d85c0ea..0000000
--- a/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp
+++ /dev/null
@@ -1,389 +0,0 @@
-//===-- IA64AsmPrinter.cpp - Print out IA64 LLVM as assembly --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file 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 assembly accepted by the GNU binutils 'gas'
-// assembler. The Intel 'ias' and HP-UX 'as' assemblers *may* choke on this
-// output, but if so that's a bug I'd like to hear about: please file a bug
-// report in bugzilla. FYI, the not too bad 'ias' assembler is bundled with
-// the Intel C/C++ compiler for Itanium Linux.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "asm-printer"
-#include "IA64.h"
-#include "IA64TargetMachine.h"
-#include "llvm/Module.h"
-#include "llvm/MDNode.h"
-#include "llvm/Type.h"
-#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/ADT/Statistic.h"
-using namespace llvm;
-
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
-namespace {
- class IA64AsmPrinter : public AsmPrinter {
- std::set<std::string> ExternalFunctionNames, ExternalObjectNames;
- public:
- explicit IA64AsmPrinter(raw_ostream &O, TargetMachine &TM,
- const TargetAsmInfo *T, bool V)
- : AsmPrinter(O, TM, T, V) {}
-
- virtual const char *getPassName() const {
- return "IA64 Assembly Printer";
- }
-
- /// printInstruction - This method is automatically generated by tablegen
- /// from the instruction set description. This method returns true if the
- /// machine instruction was sufficiently described to print it, otherwise it
- /// returns false.
- bool printInstruction(const MachineInstr *MI);
-
- // This method is used by the tablegen'erated instruction printer.
- void printOperand(const MachineInstr *MI, unsigned OpNo){
- const MachineOperand &MO = MI->getOperand(OpNo);
- if (MO.getType() == MachineOperand::MO_Register) {
- assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
- "Not physref??");
- //XXX Bug Workaround: See note in Printer::doInitialization about %.
- O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
- } else {
- printOp(MO);
- }
- }
-
- void printS8ImmOperand(const MachineInstr *MI, unsigned OpNo) {
- int val=(unsigned int)MI->getOperand(OpNo).getImm();
- if(val>=128) val=val-256; // if negative, flip sign
- O << val;
- }
- void printS14ImmOperand(const MachineInstr *MI, unsigned OpNo) {
- int val=(unsigned int)MI->getOperand(OpNo).getImm();
- if(val>=8192) val=val-16384; // if negative, flip sign
- O << val;
- }
- void printS22ImmOperand(const MachineInstr *MI, unsigned OpNo) {
- int val=(unsigned int)MI->getOperand(OpNo).getImm();
- if(val>=2097152) val=val-4194304; // if negative, flip sign
- O << val;
- }
- void printU64ImmOperand(const MachineInstr *MI, unsigned OpNo) {
- O << (uint64_t)MI->getOperand(OpNo).getImm();
- }
- void printS64ImmOperand(const MachineInstr *MI, unsigned OpNo) {
-// XXX : nasty hack to avoid GPREL22 "relocation truncated to fit" linker
-// errors - instead of add rX = @gprel(CPI<whatever>), r1;; we now
-// emit movl rX = @gprel(CPI<whatever);;
-// add rX = rX, r1;
-// this gives us 64 bits instead of 22 (for the add long imm) to play
-// with, which shuts up the linker. The problem is that the constant
-// pool entries aren't immediates at this stage, so we check here.
-// If it's an immediate, print it the old fashioned way. If it's
-// not, we print it as a constant pool index.
- if (MI->getOperand(OpNo).isImm()) {
- O << (int64_t)MI->getOperand(OpNo).getImm();
- } else { // this is a constant pool reference: FIXME: assert this
- printOp(MI->getOperand(OpNo));
- }
- }
-
- void printGlobalOperand(const MachineInstr *MI, unsigned OpNo) {
- printOp(MI->getOperand(OpNo), false); // this is NOT a br.call instruction
- }
-
- void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
- printOp(MI->getOperand(OpNo), true); // this is a br.call instruction
- }
-
- void printMachineInstruction(const MachineInstr *MI);
- void printOp(const MachineOperand &MO, bool isBRCALLinsn= false);
- void printModuleLevelGV(const GlobalVariable* GVar);
- bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
- };
-} // end of anonymous namespace
-
-
-// Include the auto-generated portion of the assembly writer.
-#include "IA64GenAsmWriter.inc"
-
-/// runOnMachineFunction - This uses the printMachineInstruction()
-/// method to print assembly for each instruction.
-///
-bool IA64AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- this->MF = &MF;
-
- SetupMachineFunction(MF);
- O << "\n\n";
-
- // Print out constants referenced by the function
- EmitConstantPool(MF.getConstantPool());
-
- const Function *F = MF.getFunction();
- SwitchToSection(TAI->SectionForGlobal(F));
-
- // Print out labels for the function.
- EmitAlignment(MF.getAlignment());
- O << "\t.global\t" << CurrentFnName << '\n';
-
- printVisibility(CurrentFnName, F->getVisibility());
-
- O << "\t.type\t" << CurrentFnName << ", @function\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 if there are any predecessors.
- if (!I->pred_empty()) {
- printBasicBlockLabel(I, true, true);
- O << '\n';
- }
- for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II) {
- // Print the assembly for the instruction.
- printMachineInstruction(II);
- }
- }
-
- // We didn't modify anything.
- return false;
-}
-
-void IA64AsmPrinter::printOp(const MachineOperand &MO,
- bool isBRCALLinsn /* = false */) {
- const TargetRegisterInfo &RI = *TM.getRegisterInfo();
- switch (MO.getType()) {
- case MachineOperand::MO_Register:
- O << RI.get(MO.getReg()).AsmName;
- return;
-
- case MachineOperand::MO_Immediate:
- O << MO.getImm();
- return;
- case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
- return;
- case MachineOperand::MO_ConstantPoolIndex: {
- O << "@gprel(" << TAI->getPrivateGlobalPrefix()
- << "CPI" << getFunctionNumber() << "_" << MO.getIndex() << ")";
- return;
- }
-
- case MachineOperand::MO_GlobalAddress: {
-
- // functions need @ltoff(@fptr(fn_name)) form
- GlobalValue *GV = MO.getGlobal();
- Function *F = dyn_cast<Function>(GV);
-
- bool Needfptr=false; // if we're computing an address @ltoff(X), do
- // we need to decorate it so it becomes
- // @ltoff(@fptr(X)) ?
- if (F && !isBRCALLinsn /*&& F->isDeclaration()*/)
- Needfptr=true;
-
- // if this is the target of a call instruction, we should define
- // the function somewhere (GNU gas has no problem without this, but
- // Intel ias rightly complains of an 'undefined symbol')
-
- if (F /*&& isBRCALLinsn*/ && F->isDeclaration())
- ExternalFunctionNames.insert(Mang->getValueName(MO.getGlobal()));
- else
- if (GV->isDeclaration()) // e.g. stuff like 'stdin'
- ExternalObjectNames.insert(Mang->getValueName(MO.getGlobal()));
-
- if (!isBRCALLinsn)
- O << "@ltoff(";
- if (Needfptr)
- O << "@fptr(";
- O << Mang->getValueName(MO.getGlobal());
-
- if (Needfptr && !isBRCALLinsn)
- O << "#))"; // close both fptr( and ltoff(
- else {
- if (Needfptr)
- O << "#)"; // close only fptr(
- if (!isBRCALLinsn)
- O << "#)"; // close only ltoff(
- }
-
- int Offset = MO.getOffset();
- if (Offset > 0)
- O << " + " << Offset;
- else if (Offset < 0)
- O << " - " << -Offset;
- return;
- }
- case MachineOperand::MO_ExternalSymbol:
- O << MO.getSymbolName();
- ExternalFunctionNames.insert(MO.getSymbolName());
- return;
- default:
- O << "<AsmPrinter: unknown operand type: " << MO.getType() << " >"; return;
- }
-}
-
-/// printMachineInstruction -- Print out a single IA64 LLVM instruction
-/// MI to the current output stream.
-///
-void IA64AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
- ++EmittedInsts;
-
- // Call the autogenerated instruction printer routines.
- printInstruction(MI);
-}
-
-bool IA64AsmPrinter::doInitialization(Module &M) {
- bool Result = AsmPrinter::doInitialization(M);
-
- O << "\n.ident \"LLVM-ia64\"\n\n"
- << "\t.psr lsb\n" // should be "msb" on HP-UX, for starters
- << "\t.radix C\n"
- << "\t.psr abi64\n"; // we only support 64 bits for now
- return Result;
-}
-
-void IA64AsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer())
- return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar))
- return;
-
- O << "\n\n";
- std::string name = Mang->getValueName(GVar);
- Constant *C = GVar->getInitializer();
- if (isa<MDNode>(C) || isa<MDString>(C))
- return;
- unsigned Size = TD->getTypeAllocSize(C->getType());
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
-
- printVisibility(name, GVar->getVisibility());
-
- SwitchToSection(TAI->SectionForGlobal(GVar));
-
- if (C->isNullValue() && !GVar->hasSection()) {
- if (!GVar->isThreadLocal() &&
- (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (GVar->hasLocalLinkage()) {
- O << "\t.lcomm " << name << "#," << Size
- << ',' << (1 << Align);
- O << '\n';
- } else {
- O << "\t.common " << name << "#," << Size
- << ',' << (1 << Align);
- O << '\n';
- }
-
- return;
- }
- }
-
- switch (GVar->getLinkage()) {
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::CommonLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- // Nonnull linkonce -> weak
- O << "\t.weak " << name << '\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 << TAI->getGlobalDirective() << name << '\n';
- // FALL THROUGH
- case GlobalValue::InternalLinkage:
- case GlobalValue::PrivateLinkage:
- break;
- case GlobalValue::GhostLinkage:
- cerr << "GhostLinkage cannot appear in IA64AsmPrinter!\n";
- abort();
- case GlobalValue::DLLImportLinkage:
- cerr << "DLLImport linkage is not supported by this target!\n";
- abort();
- case GlobalValue::DLLExportLinkage:
- cerr << "DLLExport linkage is not supported by this target!\n";
- abort();
- default:
- assert(0 && "Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
-
- if (TAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type " << name << ",@object\n";
- O << "\t.size " << name << ',' << Size << '\n';
- }
-
- O << name << ":\n";
- EmitGlobalConstant(C);
-}
-
-
-bool IA64AsmPrinter::doFinalization(Module &M) {
- // Print out module-level global variables here.
- for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I)
- printModuleLevelGV(I);
-
- // we print out ".global X \n .type X, @function" for each external function
- O << "\n\n// br.call targets referenced (and not defined) above: \n";
- for (std::set<std::string>::iterator i = ExternalFunctionNames.begin(),
- e = ExternalFunctionNames.end(); i!=e; ++i) {
- O << "\t.global " << *i << "\n\t.type " << *i << ", @function\n";
- }
- O << "\n\n";
-
- // we print out ".global X \n .type X, @object" for each external object
- O << "\n\n// (external) symbols referenced (and not defined) above: \n";
- for (std::set<std::string>::iterator i = ExternalObjectNames.begin(),
- e = ExternalObjectNames.end(); i!=e; ++i) {
- O << "\t.global " << *i << "\n\t.type " << *i << ", @object\n";
- }
- O << "\n\n";
-
- return AsmPrinter::doFinalization(M);
-}
-
-/// createIA64CodePrinterPass - Returns a pass that prints the IA64
-/// assembly code for a MachineFunction to the given output stream, using
-/// the given target machine description.
-///
-FunctionPass *llvm::createIA64CodePrinterPass(raw_ostream &o,
- IA64TargetMachine &tm,
- bool verbose) {
- return new IA64AsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
-}
-
-namespace {
- static struct Register {
- Register() {
- IA64TargetMachine::registerAsmPrinter(createIA64CodePrinterPass);
- }
- } Registrator;
-}
-
-
-// Force static initialization.
-extern "C" void LLVMInitializeIA64AsmPrinter() { }
diff --git a/lib/Target/IA64/AsmPrinter/Makefile b/lib/Target/IA64/AsmPrinter/Makefile
deleted file mode 100644
index 12880f3..0000000
--- a/lib/Target/IA64/AsmPrinter/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-##===- lib/Target/IA64/AsmPrinter/Makefile -----------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../../..
-LIBRARYNAME = LLVMIA64AsmPrinter
-
-# Hack: we need to include 'main' IA64 target directory to grab
-# private headers
-CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
-
-include $(LEVEL)/Makefile.common
diff --git a/lib/Target/IA64/CMakeLists.txt b/lib/Target/IA64/CMakeLists.txt
deleted file mode 100644
index 638ed2e..0000000
--- a/lib/Target/IA64/CMakeLists.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-set(LLVM_TARGET_DEFINITIONS IA64.td)
-
-tablegen(IA64GenRegisterInfo.h.inc -gen-register-desc-header)
-tablegen(IA64GenRegisterNames.inc -gen-register-enums)
-tablegen(IA64GenRegisterInfo.inc -gen-register-desc)
-tablegen(IA64GenInstrNames.inc -gen-instr-enums)
-tablegen(IA64GenInstrInfo.inc -gen-instr-desc)
-tablegen(IA64GenAsmWriter.inc -gen-asm-writer)
-tablegen(IA64GenDAGISel.inc -gen-dag-isel)
-
-add_llvm_target(IA64CodeGen
- IA64Bundling.cpp
- IA64InstrInfo.cpp
- IA64ISelDAGToDAG.cpp
- IA64ISelLowering.cpp
- IA64RegisterInfo.cpp
- IA64Subtarget.cpp
- IA64TargetAsmInfo.cpp
- IA64TargetMachine.cpp
- )
-
-target_link_libraries (LLVMIA64CodeGen LLVMSelectionDAG)
diff --git a/lib/Target/IA64/IA64.h b/lib/Target/IA64/IA64.h
deleted file mode 100644
index 9c758fd..0000000
--- a/lib/Target/IA64/IA64.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//===-- IA64.h - Top-level interface for IA64 representation ------*- C++ -*-===//
-// The LLVM Compiler Infrastructure
-//
-// This file 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 IA64
-// target library, as used by the LLVM JIT.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef TARGET_IA64_H
-#define TARGET_IA64_H
-
-#include "llvm/Target/TargetMachine.h"
-
-namespace llvm {
-
-class IA64TargetMachine;
-class FunctionPass;
-class raw_ostream;
-
-/// createIA64DAGToDAGInstructionSelector - This pass converts an LLVM
-/// function into IA64 machine code in a sane, DAG->DAG transform.
-///
-FunctionPass *createIA64DAGToDAGInstructionSelector(IA64TargetMachine &TM);
-
-/// createIA64BundlingPass - This pass adds stop bits and bundles
-/// instructions.
-///
-FunctionPass *createIA64BundlingPass(IA64TargetMachine &TM);
-
-/// createIA64CodePrinterPass - Returns a pass that prints the IA64
-/// 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 *createIA64CodePrinterPass(raw_ostream &o,
- IA64TargetMachine &tm,
- bool verbose);
-
-} // End llvm namespace
-
-// Defines symbolic names for IA64 registers. This defines a mapping from
-// register name to register number.
-//
-#include "IA64GenRegisterNames.inc"
-
-// Defines symbolic names for the IA64 instructions.
-//
-#include "IA64GenInstrNames.inc"
-
-#endif
-
-
diff --git a/lib/Target/IA64/IA64.td b/lib/Target/IA64/IA64.td
deleted file mode 100644
index c469281..0000000
--- a/lib/Target/IA64/IA64.td
+++ /dev/null
@@ -1,39 +0,0 @@
-//===-- IA64.td - Target definition file for Intel IA64 -------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This is a target description file for the Intel IA64 architecture,
-// also known variously as ia64, IA-64, IPF, "the Itanium architecture" etc.
-//
-//===----------------------------------------------------------------------===//
-
-// Get the target-independent interfaces which we are implementing...
-//
-include "llvm/Target/Target.td"
-
-//===----------------------------------------------------------------------===//
-// Register File Description
-//===----------------------------------------------------------------------===//
-
-include "IA64RegisterInfo.td"
-
-//===----------------------------------------------------------------------===//
-// Instruction Descriptions
-//===----------------------------------------------------------------------===//
-
-include "IA64InstrInfo.td"
-
-def IA64InstrInfo : InstrInfo { }
-
-def IA64 : Target {
- // Our instruction set
- let InstructionSet = IA64InstrInfo;
-
-}
-
-
diff --git a/lib/Target/IA64/IA64Bundling.cpp b/lib/Target/IA64/IA64Bundling.cpp
deleted file mode 100644
index 3a9ba6c..0000000
--- a/lib/Target/IA64/IA64Bundling.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-//===-- IA64Bundling.cpp - IA-64 instruction bundling pass. ------------ --===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Add stops where required to prevent read-after-write and write-after-write
-// dependencies, for both registers and memory addresses. There are exceptions:
-//
-// - Compare instructions (cmp*, tbit, tnat, fcmp, frcpa) are OK with
-// WAW dependencies so long as they all target p0, or are of parallel
-// type (.and*/.or*)
-//
-// FIXME: bundling, for now, is left to the assembler.
-// FIXME: this might be an appropriate place to translate between different
-// instructions that do the same thing, if this helps bundling.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "ia64-codegen"
-#include "IA64.h"
-#include "IA64InstrInfo.h"
-#include "IA64TargetMachine.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/ADT/SetOperations.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/Debug.h"
-#include <set>
-using namespace llvm;
-
-STATISTIC(StopBitsAdded, "Number of stop bits added");
-
-namespace {
- struct IA64BundlingPass : public MachineFunctionPass {
- static char ID;
- /// Target machine description which we query for reg. names, data
- /// layout, etc.
- ///
- IA64TargetMachine &TM;
-
- IA64BundlingPass(IA64TargetMachine &tm)
- : MachineFunctionPass(&ID), TM(tm) { }
-
- virtual const char *getPassName() const {
- return "IA64 (Itanium) Bundling Pass";
- }
-
- 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;
- }
-
- // XXX: ugly global, but pending writes can cross basic blocks. Note that
- // taken branches end instruction groups. So we only need to worry about
- // 'fallthrough' code
- std::set<unsigned> PendingRegWrites;
- };
- char IA64BundlingPass::ID = 0;
-} // end of anonymous namespace
-
-/// createIA64BundlingPass - Returns a pass that adds STOP (;;) instructions
-/// and arranges the result into bundles.
-///
-FunctionPass *llvm::createIA64BundlingPass(IA64TargetMachine &tm) {
- return new IA64BundlingPass(tm);
-}
-
-/// runOnMachineBasicBlock - add stops and bundle this MBB.
-///
-bool IA64BundlingPass::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
- bool Changed = false;
-
- for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ) {
- MachineInstr *CurrentInsn = I++;
- std::set<unsigned> CurrentReads, CurrentWrites, OrigWrites;
-
- for(unsigned i=0; i < CurrentInsn->getNumOperands(); i++) {
- MachineOperand &MO=CurrentInsn->getOperand(i);
- if (MO.isReg()) {
- if(MO.isUse()) { // TODO: exclude p0
- CurrentReads.insert(MO.getReg());
- }
- if(MO.isDef()) { // TODO: exclude p0
- CurrentWrites.insert(MO.getReg());
- OrigWrites.insert(MO.getReg()); // FIXME: use a nondestructive
- // set_intersect instead?
- }
- }
- }
-
- // CurrentReads/CurrentWrites contain info for the current instruction.
- // Does it read or write any registers that are pending a write?
- // (i.e. not separated by a stop)
- set_intersect(CurrentReads, PendingRegWrites);
- set_intersect(CurrentWrites, PendingRegWrites);
-
- if(! (CurrentReads.empty() && CurrentWrites.empty()) ) {
- // there is a conflict, insert a stop and reset PendingRegWrites
- CurrentInsn = BuildMI(MBB, CurrentInsn, CurrentInsn->getDebugLoc(),
- TM.getInstrInfo()->get(IA64::STOP), 0);
- PendingRegWrites=OrigWrites; // carry over current writes to next insn
- Changed=true; StopBitsAdded++; // update stats
- } else { // otherwise, track additional pending writes
- set_union(PendingRegWrites, OrigWrites);
- }
- } // onto the next insn in the MBB
-
- return Changed;
-}
-
diff --git a/lib/Target/IA64/IA64ISelDAGToDAG.cpp b/lib/Target/IA64/IA64ISelDAGToDAG.cpp
deleted file mode 100644
index 9800c50..0000000
--- a/lib/Target/IA64/IA64ISelDAGToDAG.cpp
+++ /dev/null
@@ -1,575 +0,0 @@
-//===---- IA64ISelDAGToDAG.cpp - IA64 pattern matching inst selector ------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a pattern matching instruction selector for IA64,
-// converting a legalized dag to an IA64 dag.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "ia64-codegen"
-#include "IA64.h"
-#include "IA64TargetMachine.h"
-#include "IA64ISelLowering.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/SelectionDAG.h"
-#include "llvm/CodeGen/SelectionDAGISel.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Constants.h"
-#include "llvm/GlobalValue.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/MathExtras.h"
-using namespace llvm;
-
-namespace {
- //===--------------------------------------------------------------------===//
- /// IA64DAGToDAGISel - IA64 specific code to select IA64 machine
- /// instructions for SelectionDAG operations.
- ///
- class IA64DAGToDAGISel : public SelectionDAGISel {
- unsigned GlobalBaseReg;
- public:
- explicit IA64DAGToDAGISel(IA64TargetMachine &TM)
- : SelectionDAGISel(TM) {}
-
- virtual bool runOnFunction(Function &Fn) {
- // Make sure we re-emit a set of the global base reg if necessary
- GlobalBaseReg = 0;
- return SelectionDAGISel::runOnFunction(Fn);
- }
-
- /// getI64Imm - Return a target constant with the specified value, of type
- /// i64.
- inline SDValue getI64Imm(uint64_t Imm) {
- return CurDAG->getTargetConstant(Imm, MVT::i64);
- }
-
- /// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC
- /// base register. Return the virtual register that holds this value.
- // SDValue getGlobalBaseReg(); TODO: hmm
-
- // Select - Convert the specified operand from a target-independent to a
- // target-specific node if it hasn't already been changed.
- SDNode *Select(SDValue N);
-
- SDNode *SelectIntImmediateExpr(SDValue LHS, SDValue RHS,
- unsigned OCHi, unsigned OCLo,
- bool IsArithmetic = false,
- bool Negate = false);
- SDNode *SelectBitfieldInsert(SDNode *N);
-
- /// SelectCC - Select a comparison of the specified values with the
- /// specified condition code, returning the CR# of the expression.
- SDValue SelectCC(SDValue LHS, SDValue RHS, ISD::CondCode CC);
-
- /// SelectAddr - Given the specified address, return the two operands for a
- /// load/store instruction, and return true if it should be an indexed [r+r]
- /// operation.
- bool SelectAddr(SDValue Addr, SDValue &Op1, SDValue &Op2);
-
- /// InstructionSelect - This callback is invoked by
- /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
- virtual void InstructionSelect();
-
- virtual const char *getPassName() const {
- return "IA64 (Itanium) DAG->DAG Instruction Selector";
- }
-
-// Include the pieces autogenerated from the target description.
-#include "IA64GenDAGISel.inc"
-
-private:
- SDNode *SelectDIV(SDValue Op);
- };
-}
-
-/// InstructionSelect - This callback is invoked by
-/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
-void IA64DAGToDAGISel::InstructionSelect() {
- DEBUG(BB->dump());
-
- // Select target instructions for the DAG.
- SelectRoot(*CurDAG);
- CurDAG->RemoveDeadNodes();
-}
-
-SDNode *IA64DAGToDAGISel::SelectDIV(SDValue Op) {
- SDNode *N = Op.getNode();
- SDValue Chain = N->getOperand(0);
- SDValue Tmp1 = N->getOperand(0);
- SDValue Tmp2 = N->getOperand(1);
- DebugLoc dl = N->getDebugLoc();
-
- bool isFP=false;
-
- if(Tmp1.getValueType().isFloatingPoint())
- isFP=true;
-
- bool isModulus=false; // is it a division or a modulus?
- bool isSigned=false;
-
- switch(N->getOpcode()) {
- case ISD::FDIV:
- case ISD::SDIV: isModulus=false; isSigned=true; break;
- case ISD::UDIV: isModulus=false; isSigned=false; break;
- case ISD::FREM:
- case ISD::SREM: isModulus=true; isSigned=true; break;
- case ISD::UREM: isModulus=true; isSigned=false; break;
- }
-
- // TODO: check for integer divides by powers of 2 (or other simple patterns?)
-
- SDValue TmpPR, TmpPR2;
- SDValue TmpF1, TmpF2, TmpF3, TmpF4, TmpF5, TmpF6, TmpF7, TmpF8;
- SDValue TmpF9, TmpF10,TmpF11,TmpF12,TmpF13,TmpF14,TmpF15;
- SDNode *Result;
-
- // we'll need copies of F0 and F1
- SDValue F0 = CurDAG->getRegister(IA64::F0, MVT::f64);
- SDValue F1 = CurDAG->getRegister(IA64::F1, MVT::f64);
-
- // OK, emit some code:
-
- if(!isFP) {
- // first, load the inputs into FP regs.
- TmpF1 =
- SDValue(CurDAG->getTargetNode(IA64::SETFSIG, dl, MVT::f64, Tmp1), 0);
- Chain = TmpF1.getValue(1);
- TmpF2 =
- SDValue(CurDAG->getTargetNode(IA64::SETFSIG, dl, MVT::f64, Tmp2), 0);
- Chain = TmpF2.getValue(1);
-
- // next, convert the inputs to FP
- if(isSigned) {
- TmpF3 =
- SDValue(CurDAG->getTargetNode(IA64::FCVTXF, dl, MVT::f64, TmpF1), 0);
- Chain = TmpF3.getValue(1);
- TmpF4 =
- SDValue(CurDAG->getTargetNode(IA64::FCVTXF, dl, MVT::f64, TmpF2), 0);
- Chain = TmpF4.getValue(1);
- } else { // is unsigned
- TmpF3 =
- SDValue(CurDAG->getTargetNode(IA64::FCVTXUFS1, dl, MVT::f64, TmpF1),
- 0);
- Chain = TmpF3.getValue(1);
- TmpF4 =
- SDValue(CurDAG->getTargetNode(IA64::FCVTXUFS1, dl, MVT::f64, TmpF2),
- 0);
- Chain = TmpF4.getValue(1);
- }
-
- } else { // this is an FP divide/remainder, so we 'leak' some temp
- // regs and assign TmpF3=Tmp1, TmpF4=Tmp2
- TmpF3=Tmp1;
- TmpF4=Tmp2;
- }
-
- // we start by computing an approximate reciprocal (good to 9 bits?)
- // note, this instruction writes _both_ TmpF5 (answer) and TmpPR (predicate)
- if(isFP)
- TmpF5 = SDValue(CurDAG->getTargetNode(IA64::FRCPAS0, dl, MVT::f64,
- MVT::i1, TmpF3, TmpF4), 0);
- else
- TmpF5 = SDValue(CurDAG->getTargetNode(IA64::FRCPAS1, dl, MVT::f64,
- MVT::i1, TmpF3, TmpF4), 0);
-
- TmpPR = TmpF5.getValue(1);
- Chain = TmpF5.getValue(2);
-
- SDValue minusB;
- if(isModulus) { // for remainders, it'll be handy to have
- // copies of -input_b
- minusB = SDValue(CurDAG->getTargetNode(IA64::SUB, dl, MVT::i64,
- CurDAG->getRegister(IA64::r0, MVT::i64), Tmp2), 0);
- Chain = minusB.getValue(1);
- }
-
- SDValue TmpE0, TmpY1, TmpE1, TmpY2;
-
- SDValue OpsE0[] = { TmpF4, TmpF5, F1, TmpPR };
- TmpE0 = SDValue(CurDAG->getTargetNode(IA64::CFNMAS1, dl, MVT::f64,
- OpsE0, 4), 0);
- Chain = TmpE0.getValue(1);
- SDValue OpsY1[] = { TmpF5, TmpE0, TmpF5, TmpPR };
- TmpY1 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
- OpsY1, 4), 0);
- Chain = TmpY1.getValue(1);
- SDValue OpsE1[] = { TmpE0, TmpE0, F0, TmpPR };
- TmpE1 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
- OpsE1, 4), 0);
- Chain = TmpE1.getValue(1);
- SDValue OpsY2[] = { TmpY1, TmpE1, TmpY1, TmpPR };
- TmpY2 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
- OpsY2, 4), 0);
- Chain = TmpY2.getValue(1);
-
- if(isFP) { // if this is an FP divide, we finish up here and exit early
- if(isModulus)
- assert(0 && "Sorry, try another FORTRAN compiler.");
-
- SDValue TmpE2, TmpY3, TmpQ0, TmpR0;
-
- SDValue OpsE2[] = { TmpE1, TmpE1, F0, TmpPR };
- TmpE2 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
- OpsE2, 4), 0);
- Chain = TmpE2.getValue(1);
- SDValue OpsY3[] = { TmpY2, TmpE2, TmpY2, TmpPR };
- TmpY3 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
- OpsY3, 4), 0);
- Chain = TmpY3.getValue(1);
- SDValue OpsQ0[] = { Tmp1, TmpY3, F0, TmpPR };
- TmpQ0 =
- SDValue(CurDAG->getTargetNode(IA64::CFMADS1, dl, // double prec!
- MVT::f64, OpsQ0, 4), 0);
- Chain = TmpQ0.getValue(1);
- SDValue OpsR0[] = { Tmp2, TmpQ0, Tmp1, TmpPR };
- TmpR0 =
- SDValue(CurDAG->getTargetNode(IA64::CFNMADS1, dl, // double prec!
- MVT::f64, OpsR0, 4), 0);
- Chain = TmpR0.getValue(1);
-
-// we want Result to have the same target register as the frcpa, so
-// we two-address hack it. See the comment "for this to work..." on
-// page 48 of Intel application note #245415
- SDValue Ops[] = { TmpF5, TmpY3, TmpR0, TmpQ0, TmpPR };
- Result = CurDAG->getTargetNode(IA64::TCFMADS0, dl, // d.p. s0 rndg!
- MVT::f64, Ops, 5);
- Chain = SDValue(Result, 1);
- return Result; // XXX: early exit!
- } else { // this is *not* an FP divide, so there's a bit left to do:
-
- SDValue TmpQ2, TmpR2, TmpQ3, TmpQ;
-
- SDValue OpsQ2[] = { TmpF3, TmpY2, F0, TmpPR };
- TmpQ2 = SDValue(CurDAG->getTargetNode(IA64::CFMAS1, dl, MVT::f64,
- OpsQ2, 4), 0);
- Chain = TmpQ2.getValue(1);
- SDValue OpsR2[] = { TmpF4, TmpQ2, TmpF3, TmpPR };
- TmpR2 = SDValue(CurDAG->getTargetNode(IA64::CFNMAS1, dl, MVT::f64,
- OpsR2, 4), 0);
- Chain = TmpR2.getValue(1);
-
-// we want TmpQ3 to have the same target register as the frcpa? maybe we
-// should two-address hack it. See the comment "for this to work..." on page
-// 48 of Intel application note #245415
- SDValue OpsQ3[] = { TmpF5, TmpR2, TmpY2, TmpQ2, TmpPR };
- TmpQ3 = SDValue(CurDAG->getTargetNode(IA64::TCFMAS1, dl, MVT::f64,
- OpsQ3, 5), 0);
- Chain = TmpQ3.getValue(1);
-
- // STORY: without these two-address instructions (TCFMAS1 and TCFMADS0)
- // the FPSWA won't be able to help out in the case of large/tiny
- // arguments. Other fun bugs may also appear, e.g. 0/x = x, not 0.
-
- if(isSigned)
- TmpQ = SDValue(CurDAG->getTargetNode(IA64::FCVTFXTRUNCS1, dl,
- MVT::f64, TmpQ3), 0);
- else
- TmpQ = SDValue(CurDAG->getTargetNode(IA64::FCVTFXUTRUNCS1, dl,
- MVT::f64, TmpQ3), 0);
-
- Chain = TmpQ.getValue(1);
-
- if(isModulus) {
- SDValue FPminusB =
- SDValue(CurDAG->getTargetNode(IA64::SETFSIG, dl, MVT::f64, minusB),
- 0);
- Chain = FPminusB.getValue(1);
- SDValue Remainder =
- SDValue(CurDAG->getTargetNode(IA64::XMAL, dl, MVT::f64,
- TmpQ, FPminusB, TmpF1), 0);
- Chain = Remainder.getValue(1);
- Result = CurDAG->getTargetNode(IA64::GETFSIG, dl, MVT::i64, Remainder);
- Chain = SDValue(Result, 1);
- } else { // just an integer divide
- Result = CurDAG->getTargetNode(IA64::GETFSIG, dl, MVT::i64, TmpQ);
- Chain = SDValue(Result, 1);
- }
-
- return Result;
- } // wasn't an FP divide
-}
-
-// Select - Convert the specified operand from a target-independent to a
-// target-specific node if it hasn't already been changed.
-SDNode *IA64DAGToDAGISel::Select(SDValue Op) {
- SDNode *N = Op.getNode();
- if (N->isMachineOpcode())
- return NULL; // Already selected.
- DebugLoc dl = Op.getDebugLoc();
-
- switch (N->getOpcode()) {
- default: break;
-
- case IA64ISD::BRCALL: { // XXX: this is also a hack!
- SDValue Chain = N->getOperand(0);
- SDValue InFlag; // Null incoming flag value.
-
- if(N->getNumOperands()==3) { // we have an incoming chain, callee and flag
- InFlag = N->getOperand(2);
- }
-
- unsigned CallOpcode;
- SDValue CallOperand;
-
- // if we can call directly, do so
- if (GlobalAddressSDNode *GASD =
- dyn_cast<GlobalAddressSDNode>(N->getOperand(1))) {
- CallOpcode = IA64::BRCALL_IPREL_GA;
- CallOperand = CurDAG->getTargetGlobalAddress(GASD->getGlobal(), MVT::i64);
- } else if (isa<ExternalSymbolSDNode>(N->getOperand(1))) {
- // FIXME: we currently NEED this case for correctness, to avoid
- // "non-pic code with imm reloc.n against dynamic symbol" errors
- CallOpcode = IA64::BRCALL_IPREL_ES;
- CallOperand = N->getOperand(1);
- } else {
- // otherwise we need to load the function descriptor,
- // load the branch target (function)'s entry point and GP,
- // branch (call) then restore the GP
- SDValue FnDescriptor = N->getOperand(1);
-
- // load the branch target's entry point [mem] and
- // GP value [mem+8]
- SDValue targetEntryPoint=
- SDValue(CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64, MVT::Other,
- FnDescriptor, CurDAG->getEntryNode()), 0);
- Chain = targetEntryPoint.getValue(1);
- SDValue targetGPAddr=
- SDValue(CurDAG->getTargetNode(IA64::ADDS, dl, MVT::i64,
- FnDescriptor,
- CurDAG->getConstant(8, MVT::i64)), 0);
- Chain = targetGPAddr.getValue(1);
- SDValue targetGP =
- SDValue(CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64,MVT::Other,
- targetGPAddr, CurDAG->getEntryNode()), 0);
- Chain = targetGP.getValue(1);
-
- Chain = CurDAG->getCopyToReg(Chain, dl, IA64::r1, targetGP, InFlag);
- InFlag = Chain.getValue(1);
- Chain = CurDAG->getCopyToReg(Chain, dl, IA64::B6,
- targetEntryPoint, InFlag); // FLAG these?
- InFlag = Chain.getValue(1);
-
- CallOperand = CurDAG->getRegister(IA64::B6, MVT::i64);
- CallOpcode = IA64::BRCALL_INDIRECT;
- }
-
- // Finally, once everything is setup, emit the call itself
- if (InFlag.getNode())
- Chain = SDValue(CurDAG->getTargetNode(CallOpcode, dl, MVT::Other,
- MVT::Flag, CallOperand, InFlag), 0);
- else // there might be no arguments
- Chain = SDValue(CurDAG->getTargetNode(CallOpcode, dl, MVT::Other,
- MVT::Flag, CallOperand, Chain), 0);
- InFlag = Chain.getValue(1);
-
- std::vector<SDValue> CallResults;
-
- CallResults.push_back(Chain);
- CallResults.push_back(InFlag);
-
- for (unsigned i = 0, e = CallResults.size(); i != e; ++i)
- ReplaceUses(Op.getValue(i), CallResults[i]);
- return NULL;
- }
-
- case IA64ISD::GETFD: {
- SDValue Input = N->getOperand(0);
- return CurDAG->getTargetNode(IA64::GETFD, dl, MVT::i64, Input);
- }
-
- case ISD::FDIV:
- case ISD::SDIV:
- case ISD::UDIV:
- case ISD::SREM:
- case ISD::UREM:
- return SelectDIV(Op);
-
- case ISD::TargetConstantFP: {
- SDValue Chain = CurDAG->getEntryNode(); // this is a constant, so..
-
- SDValue V;
- ConstantFPSDNode* N2 = cast<ConstantFPSDNode>(N);
- if (N2->getValueAPF().isPosZero()) {
- V = CurDAG->getCopyFromReg(Chain, dl, IA64::F0, MVT::f64);
- } else if (N2->isExactlyValue(N2->getValueType(0) == MVT::f32 ?
- APFloat(+1.0f) : APFloat(+1.0))) {
- V = CurDAG->getCopyFromReg(Chain, dl, IA64::F1, MVT::f64);
- } else
- assert(0 && "Unexpected FP constant!");
-
- ReplaceUses(SDValue(N, 0), V);
- return 0;
- }
-
- case ISD::FrameIndex: { // TODO: reduce creepyness
- int FI = cast<FrameIndexSDNode>(N)->getIndex();
- if (N->hasOneUse())
- return CurDAG->SelectNodeTo(N, IA64::MOV, MVT::i64,
- CurDAG->getTargetFrameIndex(FI, MVT::i64));
- else
- return CurDAG->getTargetNode(IA64::MOV, dl, MVT::i64,
- CurDAG->getTargetFrameIndex(FI, MVT::i64));
- }
-
- case ISD::ConstantPool: { // TODO: nuke the constant pool
- // (ia64 doesn't need one)
- ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(N);
- Constant *C = CP->getConstVal();
- SDValue CPI = CurDAG->getTargetConstantPool(C, MVT::i64,
- CP->getAlignment());
- return CurDAG->getTargetNode(IA64::ADDL_GA, dl, MVT::i64, // ?
- CurDAG->getRegister(IA64::r1, MVT::i64), CPI);
- }
-
- case ISD::GlobalAddress: {
- GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
- SDValue GA = CurDAG->getTargetGlobalAddress(GV, MVT::i64);
- SDValue Tmp =
- SDValue(CurDAG->getTargetNode(IA64::ADDL_GA, dl, MVT::i64,
- CurDAG->getRegister(IA64::r1,
- MVT::i64), GA), 0);
- return CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64, MVT::Other, Tmp,
- CurDAG->getEntryNode());
- }
-
-/* XXX
- case ISD::ExternalSymbol: {
- SDValue EA = CurDAG->getTargetExternalSymbol(
- cast<ExternalSymbolSDNode>(N)->getSymbol(),
- MVT::i64);
- SDValue Tmp = CurDAG->getTargetNode(IA64::ADDL_EA, dl, MVT::i64,
- CurDAG->getRegister(IA64::r1,
- MVT::i64),
- EA);
- return CurDAG->getTargetNode(IA64::LD8, dl, MVT::i64, Tmp);
- }
-*/
-
- case ISD::LOAD: { // FIXME: load -1, not 1, for bools?
- LoadSDNode *LD = cast<LoadSDNode>(N);
- SDValue Chain = LD->getChain();
- SDValue Address = LD->getBasePtr();
-
- MVT TypeBeingLoaded = LD->getMemoryVT();
- unsigned Opc;
- switch (TypeBeingLoaded.getSimpleVT()) {
- default:
-#ifndef NDEBUG
- N->dump(CurDAG);
-#endif
- assert(0 && "Cannot load this type!");
- case MVT::i1: { // this is a bool
- Opc = IA64::LD1; // first we load a byte, then compare for != 0
- if(N->getValueType(0) == MVT::i1) { // XXX: early exit!
- return CurDAG->SelectNodeTo(N, IA64::CMPNE, MVT::i1, MVT::Other,
- SDValue(CurDAG->getTargetNode(Opc, dl,
- MVT::i64,
- Address), 0),
- CurDAG->getRegister(IA64::r0, MVT::i64),
- Chain);
- }
- /* otherwise, we want to load a bool into something bigger: LD1
- will do that for us, so we just fall through */
- }
- case MVT::i8: Opc = IA64::LD1; break;
- case MVT::i16: Opc = IA64::LD2; break;
- case MVT::i32: Opc = IA64::LD4; break;
- case MVT::i64: Opc = IA64::LD8; break;
-
- case MVT::f32: Opc = IA64::LDF4; break;
- case MVT::f64: Opc = IA64::LDF8; break;
- }
-
- // TODO: comment this
- return CurDAG->SelectNodeTo(N, Opc, N->getValueType(0), MVT::Other,
- Address, Chain);
- }
-
- case ISD::STORE: {
- StoreSDNode *ST = cast<StoreSDNode>(N);
- SDValue Address = ST->getBasePtr();
- SDValue Chain = ST->getChain();
-
- unsigned Opc;
- if (ISD::isNON_TRUNCStore(N)) {
- switch (N->getOperand(1).getValueType().getSimpleVT()) {
- default: assert(0 && "unknown type in store");
- case MVT::i1: { // this is a bool
- Opc = IA64::ST1; // we store either 0 or 1 as a byte
- // first load zero!
- SDValue Initial = CurDAG->getCopyFromReg(Chain, dl, IA64::r0, MVT::i64);
- Chain = Initial.getValue(1);
- // then load 1 into the same reg iff the predicate to store is 1
- SDValue Tmp = ST->getValue();
- Tmp =
- SDValue(CurDAG->getTargetNode(IA64::TPCADDS, dl, MVT::i64, Initial,
- CurDAG->getTargetConstant(1,
- MVT::i64),
- Tmp), 0);
- return CurDAG->SelectNodeTo(N, Opc, MVT::Other, Address, Tmp, Chain);
- }
- case MVT::i64: Opc = IA64::ST8; break;
- case MVT::f64: Opc = IA64::STF8; break;
- }
- } else { // Truncating store
- switch(ST->getMemoryVT().getSimpleVT()) {
- default: assert(0 && "unknown type in truncstore");
- case MVT::i8: Opc = IA64::ST1; break;
- case MVT::i16: Opc = IA64::ST2; break;
- case MVT::i32: Opc = IA64::ST4; break;
- case MVT::f32: Opc = IA64::STF4; break;
- }
- }
-
- SDValue N1 = N->getOperand(1);
- SDValue N2 = N->getOperand(2);
- return CurDAG->SelectNodeTo(N, Opc, MVT::Other, N2, N1, Chain);
- }
-
- case ISD::BRCOND: {
- SDValue Chain = N->getOperand(0);
- SDValue CC = N->getOperand(1);
- MachineBasicBlock *Dest =
- cast<BasicBlockSDNode>(N->getOperand(2))->getBasicBlock();
- //FIXME - we do NOT need long branches all the time
- return CurDAG->SelectNodeTo(N, IA64::BRLCOND_NOTCALL, MVT::Other, CC,
- CurDAG->getBasicBlock(Dest), Chain);
- }
-
- case ISD::CALLSEQ_START:
- case ISD::CALLSEQ_END: {
- int64_t Amt = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
- unsigned Opc = N->getOpcode() == ISD::CALLSEQ_START ?
- IA64::ADJUSTCALLSTACKDOWN : IA64::ADJUSTCALLSTACKUP;
- SDValue N0 = N->getOperand(0);
- return CurDAG->SelectNodeTo(N, Opc, MVT::Other, getI64Imm(Amt), N0);
- }
-
- case ISD::BR:
- // FIXME: we don't need long branches all the time!
- SDValue N0 = N->getOperand(0);
- return CurDAG->SelectNodeTo(N, IA64::BRL_NOTCALL, MVT::Other,
- N->getOperand(1), N0);
- }
-
- return SelectCode(Op);
-}
-
-
-/// createIA64DAGToDAGInstructionSelector - This pass converts a legalized DAG
-/// into an IA64-specific DAG, ready for instruction scheduling.
-///
-FunctionPass
-*llvm::createIA64DAGToDAGInstructionSelector(IA64TargetMachine &TM) {
- return new IA64DAGToDAGISel(TM);
-}
-
diff --git a/lib/Target/IA64/IA64ISelLowering.cpp b/lib/Target/IA64/IA64ISelLowering.cpp
deleted file mode 100644
index c622345..0000000
--- a/lib/Target/IA64/IA64ISelLowering.cpp
+++ /dev/null
@@ -1,632 +0,0 @@
-//===-- IA64ISelLowering.cpp - IA64 DAG Lowering Implementation -----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the IA64ISelLowering class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IA64ISelLowering.h"
-#include "IA64MachineFunctionInfo.h"
-#include "IA64TargetMachine.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/SelectionDAG.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Constants.h"
-#include "llvm/Function.h"
-using namespace llvm;
-
-IA64TargetLowering::IA64TargetLowering(TargetMachine &TM)
- : TargetLowering(TM) {
-
- // register class for general registers
- addRegisterClass(MVT::i64, IA64::GRRegisterClass);
-
- // register class for FP registers
- addRegisterClass(MVT::f64, IA64::FPRegisterClass);
-
- // register class for predicate registers
- addRegisterClass(MVT::i1, IA64::PRRegisterClass);
-
- setLoadExtAction(ISD::EXTLOAD , MVT::i1 , Promote);
-
- setLoadExtAction(ISD::ZEXTLOAD , MVT::i1 , Promote);
-
- setLoadExtAction(ISD::SEXTLOAD , MVT::i1 , Promote);
- setLoadExtAction(ISD::SEXTLOAD , MVT::i8 , Expand);
- setLoadExtAction(ISD::SEXTLOAD , MVT::i16 , Expand);
- setLoadExtAction(ISD::SEXTLOAD , MVT::i32 , Expand);
-
- setOperationAction(ISD::BRIND , MVT::Other, Expand);
- setOperationAction(ISD::BR_JT , MVT::Other, Expand);
- setOperationAction(ISD::BR_CC , MVT::Other, Expand);
- setOperationAction(ISD::FP_ROUND_INREG , MVT::f32 , Expand);
-
- // ia64 uses SELECT not SELECT_CC
- setOperationAction(ISD::SELECT_CC , MVT::Other, Expand);
-
- // We need to handle ISD::RET for void functions ourselves,
- // so we get a chance to restore ar.pfs before adding a
- // br.ret insn
- setOperationAction(ISD::RET, MVT::Other, Custom);
-
- setShiftAmountType(MVT::i64);
-
- setOperationAction(ISD::FREM , MVT::f32 , Expand);
- setOperationAction(ISD::FREM , MVT::f64 , Expand);
-
- setOperationAction(ISD::UREM , MVT::f32 , Expand);
- setOperationAction(ISD::UREM , MVT::f64 , Expand);
-
- setOperationAction(ISD::MEMBARRIER , MVT::Other, Expand);
-
- setOperationAction(ISD::SINT_TO_FP , MVT::i1 , Promote);
- setOperationAction(ISD::UINT_TO_FP , MVT::i1 , Promote);
-
- // We don't support sin/cos/sqrt/pow
- setOperationAction(ISD::FSIN , MVT::f64, Expand);
- setOperationAction(ISD::FCOS , MVT::f64, Expand);
- setOperationAction(ISD::FSQRT, MVT::f64, Expand);
- setOperationAction(ISD::FPOW , MVT::f64, Expand);
- setOperationAction(ISD::FSIN , MVT::f32, Expand);
- setOperationAction(ISD::FCOS , MVT::f32, Expand);
- setOperationAction(ISD::FSQRT, MVT::f32, Expand);
- setOperationAction(ISD::FPOW , MVT::f32, Expand);
-
- setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1 , Expand);
-
- // FIXME: IA64 supports fcopysign natively!
- setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
- setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
-
- // We don't have line number support yet.
- setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
- setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand);
- setOperationAction(ISD::DBG_LABEL, MVT::Other, Expand);
- setOperationAction(ISD::EH_LABEL, MVT::Other, Expand);
-
- // IA64 has ctlz in the form of the 'fnorm' instruction. The Legalizer
- // expansion for ctlz/cttz in terms of ctpop is much larger, but lower
- // latency.
- // FIXME: Custom lower CTLZ when compiling for size?
- setOperationAction(ISD::CTLZ , MVT::i64 , Expand);
- setOperationAction(ISD::CTTZ , MVT::i64 , Expand);
- setOperationAction(ISD::ROTL , MVT::i64 , Expand);
- setOperationAction(ISD::ROTR , MVT::i64 , Expand);
-
- // FIXME: IA64 has this, but is not implemented. should be mux @rev
- setOperationAction(ISD::BSWAP, MVT::i64 , Expand);
-
- // VASTART needs to be custom lowered to use the VarArgsFrameIndex
- setOperationAction(ISD::VAARG , MVT::Other, Custom);
- setOperationAction(ISD::VASTART , MVT::Other, Custom);
-
- // FIXME: These should be legal
- setOperationAction(ISD::BIT_CONVERT, MVT::i64, Expand);
- setOperationAction(ISD::BIT_CONVERT, MVT::f64, Expand);
-
- // Use the default implementation.
- setOperationAction(ISD::VACOPY , MVT::Other, Expand);
- setOperationAction(ISD::VAEND , MVT::Other, Expand);
- setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
- setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
- setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand);
-
- // Thread Local Storage
- setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
-
- setStackPointerRegisterToSaveRestore(IA64::r12);
-
- setJumpBufSize(704); // on ia64-linux, jmp_bufs are 704 bytes..
- setJumpBufAlignment(16); // ...and must be 16-byte aligned
-
- computeRegisterProperties();
-
- addLegalFPImmediate(APFloat(+0.0));
- addLegalFPImmediate(APFloat(-0.0));
- addLegalFPImmediate(APFloat(+1.0));
- addLegalFPImmediate(APFloat(-1.0));
-}
-
-const char *IA64TargetLowering::getTargetNodeName(unsigned Opcode) const {
- switch (Opcode) {
- default: return 0;
- case IA64ISD::GETFD: return "IA64ISD::GETFD";
- case IA64ISD::BRCALL: return "IA64ISD::BRCALL";
- case IA64ISD::RET_FLAG: return "IA64ISD::RET_FLAG";
- }
-}
-
-MVT IA64TargetLowering::getSetCCResultType(MVT VT) const {
- return MVT::i1;
-}
-
-/// getFunctionAlignment - Return the Log2 alignment of this function.
-unsigned IA64TargetLowering::getFunctionAlignment(const Function *) const {
- return 5;
-}
-
-void IA64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &ArgValues,
- DebugLoc dl) {
- //
- // add beautiful description of IA64 stack frame format
- // here (from intel 24535803.pdf most likely)
- //
- MachineFunction &MF = DAG.getMachineFunction();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
-
- GP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
- SP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
- RP = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
-
- MachineBasicBlock& BB = MF.front();
-
- unsigned args_int[] = {IA64::r32, IA64::r33, IA64::r34, IA64::r35,
- IA64::r36, IA64::r37, IA64::r38, IA64::r39};
-
- unsigned args_FP[] = {IA64::F8, IA64::F9, IA64::F10, IA64::F11,
- IA64::F12,IA64::F13,IA64::F14, IA64::F15};
-
- unsigned argVreg[8];
- unsigned argPreg[8];
- unsigned argOpc[8];
-
- unsigned used_FPArgs = 0; // how many FP args have been used so far?
-
- unsigned ArgOffset = 0;
- int count = 0;
-
- for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I)
- {
- SDValue newroot, argt;
- if(count < 8) { // need to fix this logic? maybe.
-
- switch (getValueType(I->getType()).getSimpleVT()) {
- default:
- assert(0 && "ERROR in LowerArgs: can't lower this type of arg.\n");
- case MVT::f32:
- // fixme? (well, will need to for weird FP structy stuff,
- // see intel ABI docs)
- case MVT::f64:
-//XXX BuildMI(&BB, IA64::IDEF, 0, args_FP[used_FPArgs]);
- MF.getRegInfo().addLiveIn(args_FP[used_FPArgs]);
- // mark this reg as liveIn
- // floating point args go into f8..f15 as-needed, the increment
- argVreg[count] = // is below..:
- MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::f64));
- // FP args go into f8..f15 as needed: (hence the ++)
- argPreg[count] = args_FP[used_FPArgs++];
- argOpc[count] = IA64::FMOV;
- argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), dl,
- argVreg[count], MVT::f64);
- if (I->getType() == Type::FloatTy)
- argt = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, argt,
- DAG.getIntPtrConstant(0));
- break;
- case MVT::i1: // NOTE: as far as C abi stuff goes,
- // bools are just boring old ints
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- case MVT::i64:
-//XXX BuildMI(&BB, IA64::IDEF, 0, args_int[count]);
- MF.getRegInfo().addLiveIn(args_int[count]);
- // mark this register as liveIn
- argVreg[count] =
- MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
- argPreg[count] = args_int[count];
- argOpc[count] = IA64::MOV;
- argt = newroot =
- DAG.getCopyFromReg(DAG.getRoot(), dl, argVreg[count], MVT::i64);
- if ( getValueType(I->getType()) != MVT::i64)
- argt = DAG.getNode(ISD::TRUNCATE, dl, getValueType(I->getType()),
- newroot);
- break;
- }
- } else { // more than 8 args go into the frame
- // Create the frame index object for this incoming parameter...
- ArgOffset = 16 + 8 * (count - 8);
- int FI = MFI->CreateFixedObject(8, ArgOffset);
-
- // Create the SelectionDAG nodes corresponding to a load
- //from this parameter
- SDValue FIN = DAG.getFrameIndex(FI, MVT::i64);
- argt = newroot = DAG.getLoad(getValueType(I->getType()), dl,
- DAG.getEntryNode(), FIN, NULL, 0);
- }
- ++count;
- DAG.setRoot(newroot.getValue(1));
- ArgValues.push_back(argt);
- }
-
-
- // Create a vreg to hold the output of (what will become)
- // the "alloc" instruction
- VirtGPR = MF.getRegInfo().createVirtualRegister(getRegClassFor(MVT::i64));
- BuildMI(&BB, dl, TII->get(IA64::PSEUDO_ALLOC), VirtGPR);
- // we create a PSEUDO_ALLOC (pseudo)instruction for now
-/*
- BuildMI(&BB, IA64::IDEF, 0, IA64::r1);
-
- // hmm:
- BuildMI(&BB, IA64::IDEF, 0, IA64::r12);
- BuildMI(&BB, IA64::IDEF, 0, IA64::rp);
- // ..hmm.
-
- BuildMI(&BB, IA64::MOV, 1, GP).addReg(IA64::r1);
-
- // hmm:
- BuildMI(&BB, IA64::MOV, 1, SP).addReg(IA64::r12);
- BuildMI(&BB, IA64::MOV, 1, RP).addReg(IA64::rp);
- // ..hmm.
-*/
-
- unsigned tempOffset=0;
-
- // if this is a varargs function, we simply lower llvm.va_start by
- // pointing to the first entry
- if(F.isVarArg()) {
- tempOffset=0;
- VarArgsFrameIndex = MFI->CreateFixedObject(8, tempOffset);
- }
-
- // here we actually do the moving of args, and store them to the stack
- // too if this is a varargs function:
- for (int i = 0; i < count && i < 8; ++i) {
- BuildMI(&BB, dl, TII->get(argOpc[i]), argVreg[i]).addReg(argPreg[i]);
- if(F.isVarArg()) {
- // if this is a varargs function, we copy the input registers to the stack
- int FI = MFI->CreateFixedObject(8, tempOffset);
- tempOffset+=8; //XXX: is it safe to use r22 like this?
- BuildMI(&BB, dl, TII->get(IA64::MOV), IA64::r22).addFrameIndex(FI);
- // FIXME: we should use st8.spill here, one day
- BuildMI(&BB, dl, TII->get(IA64::ST8), IA64::r22).addReg(argPreg[i]);
- }
- }
-
- // Finally, inform the code generator which regs we return values in.
- // (see the ISD::RET: case in the instruction selector)
- switch (getValueType(F.getReturnType()).getSimpleVT()) {
- default: assert(0 && "i have no idea where to return this type!");
- case MVT::isVoid: break;
- case MVT::i1:
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- case MVT::i64:
- MF.getRegInfo().addLiveOut(IA64::r8);
- break;
- case MVT::f32:
- case MVT::f64:
- MF.getRegInfo().addLiveOut(IA64::F8);
- break;
- }
-}
-
-std::pair<SDValue, SDValue>
-IA64TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
- bool RetSExt, bool RetZExt, bool isVarArg,
- bool isInreg, unsigned NumFixedArgs,
- unsigned CallingConv,
- bool isTailCall, SDValue Callee,
- ArgListTy &Args, SelectionDAG &DAG,
- DebugLoc dl) {
-
- MachineFunction &MF = DAG.getMachineFunction();
-
- unsigned NumBytes = 16;
- unsigned outRegsUsed = 0;
-
- if (Args.size() > 8) {
- NumBytes += (Args.size() - 8) * 8;
- outRegsUsed = 8;
- } else {
- outRegsUsed = Args.size();
- }
-
- // FIXME? this WILL fail if we ever try to pass around an arg that
- // consumes more than a single output slot (a 'real' double, int128
- // some sort of aggregate etc.), as we'll underestimate how many 'outX'
- // registers we use. Hopefully, the assembler will notice.
- MF.getInfo<IA64FunctionInfo>()->outRegsUsed=
- std::max(outRegsUsed, MF.getInfo<IA64FunctionInfo>()->outRegsUsed);
-
- // keep stack frame 16-byte aligned
- // assert(NumBytes==((NumBytes+15) & ~15) &&
- // "stack frame not 16-byte aligned!");
- NumBytes = (NumBytes+15) & ~15;
-
- Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true));
-
- SDValue StackPtr;
- std::vector<SDValue> Stores;
- std::vector<SDValue> Converts;
- std::vector<SDValue> RegValuesToPass;
- unsigned ArgOffset = 16;
-
- for (unsigned i = 0, e = Args.size(); i != e; ++i)
- {
- SDValue Val = Args[i].Node;
- MVT ObjectVT = Val.getValueType();
- SDValue ValToStore(0, 0), ValToConvert(0, 0);
- unsigned ObjSize=8;
- switch (ObjectVT.getSimpleVT()) {
- default: assert(0 && "unexpected argument type!");
- case MVT::i1:
- case MVT::i8:
- case MVT::i16:
- case MVT::i32: {
- //promote to 64-bits, sign/zero extending based on type
- //of the argument
- ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
- if (Args[i].isSExt)
- ExtendKind = ISD::SIGN_EXTEND;
- else if (Args[i].isZExt)
- ExtendKind = ISD::ZERO_EXTEND;
- Val = DAG.getNode(ExtendKind, dl, MVT::i64, Val);
- // XXX: fall through
- }
- case MVT::i64:
- //ObjSize = 8;
- if(RegValuesToPass.size() >= 8) {
- ValToStore = Val;
- } else {
- RegValuesToPass.push_back(Val);
- }
- break;
- case MVT::f32:
- //promote to 64-bits
- Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val);
- // XXX: fall through
- case MVT::f64:
- if(RegValuesToPass.size() >= 8) {
- ValToStore = Val;
- } else {
- RegValuesToPass.push_back(Val);
- if(1 /* TODO: if(calling external or varadic function)*/ ) {
- ValToConvert = Val; // additionally pass this FP value as an int
- }
- }
- break;
- }
-
- if(ValToStore.getNode()) {
- if(!StackPtr.getNode()) {
- StackPtr = DAG.getRegister(IA64::r12, MVT::i64);
- }
- SDValue PtrOff = DAG.getConstant(ArgOffset, getPointerTy());
- PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i64, StackPtr, PtrOff);
- Stores.push_back(DAG.getStore(Chain, dl, ValToStore, PtrOff, NULL, 0));
- ArgOffset += ObjSize;
- }
-
- if(ValToConvert.getNode()) {
- Converts.push_back(DAG.getNode(IA64ISD::GETFD, dl,
- MVT::i64, ValToConvert));
- }
- }
-
- // Emit all stores, make sure they occur before any copies into physregs.
- if (!Stores.empty())
- Chain = DAG.getNode(ISD::TokenFactor, dl,
- MVT::Other, &Stores[0],Stores.size());
-
- static const unsigned IntArgRegs[] = {
- IA64::out0, IA64::out1, IA64::out2, IA64::out3,
- IA64::out4, IA64::out5, IA64::out6, IA64::out7
- };
-
- static const unsigned FPArgRegs[] = {
- IA64::F8, IA64::F9, IA64::F10, IA64::F11,
- IA64::F12, IA64::F13, IA64::F14, IA64::F15
- };
-
- SDValue InFlag;
-
- // save the current GP, SP and RP : FIXME: do we need to do all 3 always?
- SDValue GPBeforeCall = DAG.getCopyFromReg(Chain, dl, IA64::r1,
- MVT::i64, InFlag);
- Chain = GPBeforeCall.getValue(1);
- InFlag = Chain.getValue(2);
- SDValue SPBeforeCall = DAG.getCopyFromReg(Chain, dl, IA64::r12,
- MVT::i64, InFlag);
- Chain = SPBeforeCall.getValue(1);
- InFlag = Chain.getValue(2);
- SDValue RPBeforeCall = DAG.getCopyFromReg(Chain, dl, IA64::rp,
- MVT::i64, InFlag);
- Chain = RPBeforeCall.getValue(1);
- InFlag = Chain.getValue(2);
-
- // Build a sequence of copy-to-reg nodes chained together with token chain
- // and flag operands which copy the outgoing integer args into regs out[0-7]
- // mapped 1:1 and the FP args into regs F8-F15 "lazily"
- // TODO: for performance, we should only copy FP args into int regs when we
- // know this is required (i.e. for varardic or external (unknown) functions)
-
- // first to the FP->(integer representation) conversions, these are
- // flagged for now, but shouldn't have to be (TODO)
- unsigned seenConverts = 0;
- for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
- if(RegValuesToPass[i].getValueType().isFloatingPoint()) {
- Chain = DAG.getCopyToReg(Chain, dl, IntArgRegs[i],
- Converts[seenConverts++], InFlag);
- InFlag = Chain.getValue(1);
- }
- }
-
- // next copy args into the usual places, these are flagged
- unsigned usedFPArgs = 0;
- for (unsigned i = 0, e = RegValuesToPass.size(); i != e; ++i) {
- Chain = DAG.getCopyToReg(Chain, dl,
- RegValuesToPass[i].getValueType().isInteger() ?
- IntArgRegs[i] : FPArgRegs[usedFPArgs++], RegValuesToPass[i], InFlag);
- InFlag = Chain.getValue(1);
- }
-
- // If the callee is a GlobalAddress node (quite common, every direct call is)
- // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
-/*
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i64);
- }
-*/
-
- std::vector<MVT> NodeTys;
- std::vector<SDValue> CallOperands;
- NodeTys.push_back(MVT::Other); // Returns a chain
- NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use.
- CallOperands.push_back(Chain);
- CallOperands.push_back(Callee);
-
- // emit the call itself
- if (InFlag.getNode())
- CallOperands.push_back(InFlag);
- else
- assert(0 && "this should never happen!\n");
-
- // to make way for a hack:
- Chain = DAG.getNode(IA64ISD::BRCALL, dl, NodeTys,
- &CallOperands[0], CallOperands.size());
- InFlag = Chain.getValue(1);
-
- // restore the GP, SP and RP after the call
- Chain = DAG.getCopyToReg(Chain, dl, IA64::r1, GPBeforeCall, InFlag);
- InFlag = Chain.getValue(1);
- Chain = DAG.getCopyToReg(Chain, dl, IA64::r12, SPBeforeCall, InFlag);
- InFlag = Chain.getValue(1);
- Chain = DAG.getCopyToReg(Chain, dl, IA64::rp, RPBeforeCall, InFlag);
- InFlag = Chain.getValue(1);
-
- std::vector<MVT> RetVals;
- RetVals.push_back(MVT::Other);
- RetVals.push_back(MVT::Flag);
-
- MVT RetTyVT = getValueType(RetTy);
- SDValue RetVal;
- if (RetTyVT != MVT::isVoid) {
- switch (RetTyVT.getSimpleVT()) {
- default: assert(0 && "Unknown value type to return!");
- case MVT::i1: { // bools are just like other integers (returned in r8)
- // we *could* fall through to the truncate below, but this saves a
- // few redundant predicate ops
- SDValue boolInR8 = DAG.getCopyFromReg(Chain, dl, IA64::r8,
- MVT::i64,InFlag);
- InFlag = boolInR8.getValue(2);
- Chain = boolInR8.getValue(1);
- SDValue zeroReg = DAG.getCopyFromReg(Chain, dl, IA64::r0,
- MVT::i64, InFlag);
- InFlag = zeroReg.getValue(2);
- Chain = zeroReg.getValue(1);
-
- RetVal = DAG.getSetCC(dl, MVT::i1, boolInR8, zeroReg, ISD::SETNE);
- break;
- }
- case MVT::i8:
- case MVT::i16:
- case MVT::i32:
- RetVal = DAG.getCopyFromReg(Chain, dl, IA64::r8, MVT::i64, InFlag);
- Chain = RetVal.getValue(1);
-
- // keep track of whether it is sign or zero extended (todo: bools?)
-/* XXX
- RetVal = DAG.getNode(RetTy->isSigned() ? ISD::AssertSext :ISD::AssertZext,
- dl, MVT::i64, RetVal, DAG.getValueType(RetTyVT));
-*/
- RetVal = DAG.getNode(ISD::TRUNCATE, dl, RetTyVT, RetVal);
- break;
- case MVT::i64:
- RetVal = DAG.getCopyFromReg(Chain, dl, IA64::r8, MVT::i64, InFlag);
- Chain = RetVal.getValue(1);
- InFlag = RetVal.getValue(2); // XXX dead
- break;
- case MVT::f32:
- RetVal = DAG.getCopyFromReg(Chain, dl, IA64::F8, MVT::f64, InFlag);
- Chain = RetVal.getValue(1);
- RetVal = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, RetVal,
- DAG.getIntPtrConstant(0));
- break;
- case MVT::f64:
- RetVal = DAG.getCopyFromReg(Chain, dl, IA64::F8, MVT::f64, InFlag);
- Chain = RetVal.getValue(1);
- InFlag = RetVal.getValue(2); // XXX dead
- break;
- }
- }
-
- Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true),
- DAG.getIntPtrConstant(0, true), SDValue());
- return std::make_pair(RetVal, Chain);
-}
-
-SDValue IA64TargetLowering::
-LowerOperation(SDValue Op, SelectionDAG &DAG) {
- DebugLoc dl = Op.getDebugLoc();
- switch (Op.getOpcode()) {
- default: assert(0 && "Should not custom lower this!");
- case ISD::GlobalTLSAddress:
- assert(0 && "TLS not implemented for IA64.");
- case ISD::RET: {
- SDValue AR_PFSVal, Copy;
-
- switch(Op.getNumOperands()) {
- default:
- assert(0 && "Do not know how to return this many arguments!");
- abort();
- case 1:
- AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), dl, VirtGPR, MVT::i64);
- AR_PFSVal = DAG.getCopyToReg(AR_PFSVal.getValue(1), dl, IA64::AR_PFS,
- AR_PFSVal);
- return DAG.getNode(IA64ISD::RET_FLAG, dl, MVT::Other, AR_PFSVal);
- case 3: {
- // Copy the result into the output register & restore ar.pfs
- MVT ArgVT = Op.getOperand(1).getValueType();
- unsigned ArgReg = ArgVT.isInteger() ? IA64::r8 : IA64::F8;
-
- AR_PFSVal = DAG.getCopyFromReg(Op.getOperand(0), dl, VirtGPR, MVT::i64);
- Copy = DAG.getCopyToReg(AR_PFSVal.getValue(1), dl, ArgReg,
- Op.getOperand(1), SDValue());
- AR_PFSVal = DAG.getCopyToReg(Copy.getValue(0), dl,
- IA64::AR_PFS, AR_PFSVal, Copy.getValue(1));
- return DAG.getNode(IA64ISD::RET_FLAG, dl, MVT::Other,
- AR_PFSVal, AR_PFSVal.getValue(1));
- }
- }
- return SDValue();
- }
- case ISD::VAARG: {
- MVT VT = getPointerTy();
- const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
- SDValue VAList = DAG.getLoad(VT, dl, Op.getOperand(0), Op.getOperand(1),
- SV, 0);
- // Increment the pointer, VAList, to the next vaarg
- SDValue VAIncr = DAG.getNode(ISD::ADD, dl, VT, VAList,
- DAG.getConstant(VT.getSizeInBits()/8,
- VT));
- // Store the incremented VAList to the legalized pointer
- VAIncr = DAG.getStore(VAList.getValue(1), dl, VAIncr,
- Op.getOperand(1), SV, 0);
- // Load the actual argument out of the pointer VAList
- return DAG.getLoad(Op.getValueType(), dl, VAIncr, VAList, NULL, 0);
- }
- case ISD::VASTART: {
- // vastart just stores the address of the VarArgsFrameIndex slot into the
- // memory location argument.
- SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64);
- const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
- return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0);
- }
- // Frame & Return address. Currently unimplemented
- case ISD::RETURNADDR: break;
- case ISD::FRAMEADDR: break;
- }
- return SDValue();
-}
diff --git a/lib/Target/IA64/IA64ISelLowering.h b/lib/Target/IA64/IA64ISelLowering.h
deleted file mode 100644
index b9c8bf2..0000000
--- a/lib/Target/IA64/IA64ISelLowering.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//===-- IA64ISelLowering.h - IA64 DAG Lowering Interface --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the interfaces that IA64 uses to lower LLVM code into a
-// selection DAG.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_IA64_IA64ISELLOWERING_H
-#define LLVM_TARGET_IA64_IA64ISELLOWERING_H
-
-#include "llvm/Target/TargetLowering.h"
-#include "llvm/CodeGen/SelectionDAG.h"
-#include "IA64.h"
-
-namespace llvm {
- namespace IA64ISD {
- enum NodeType {
- // Start the numbering where the builting ops and target ops leave off.
- FIRST_NUMBER = ISD::BUILTIN_OP_END,
-
- /// GETFD - the getf.d instruction takes a floating point operand and
- /// returns its 64-bit memory representation as an i64
- GETFD,
-
- // TODO: explain this hack
- BRCALL,
-
- // RET_FLAG - Return with a flag operand
- RET_FLAG
- };
- }
-
- class IA64TargetLowering : public TargetLowering {
- int VarArgsFrameIndex; // FrameIndex for start of varargs area.
- //int ReturnAddrIndex; // FrameIndex for return slot.
- unsigned GP, SP, RP; // FIXME - clean this mess up
- public:
- explicit IA64TargetLowering(TargetMachine &TM);
-
- unsigned VirtGPR; // this is public so it can be accessed in the selector
- // for ISD::RET. add an accessor instead? FIXME
- const char *getTargetNodeName(unsigned Opcode) const;
-
- /// getSetCCResultType: return ISD::SETCC's result type.
- virtual MVT getSetCCResultType(MVT VT) const;
-
- /// LowerArguments - This hook must be implemented to indicate how we should
- /// lower the arguments for the specified function, into the specified DAG.
- virtual void LowerArguments(Function &F, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &ArgValues,
- DebugLoc dl);
-
- /// LowerCallTo - This hook lowers an abstract call to a function into an
- /// actual call.
- virtual std::pair<SDValue, SDValue>
- LowerCallTo(SDValue Chain, const Type *RetTy,
- bool RetSExt, bool RetZExt, bool isVarArg, bool isInreg,
- unsigned NumFixedArgs, unsigned CC, bool isTailCall,
- SDValue Callee, ArgListTy &Args, SelectionDAG &DAG,
- DebugLoc dl);
-
- /// LowerOperation - for custom lowering specific ops
- /// (currently, only "ret void")
- virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
-
- /// getFunctionAlignment - Return the Log2 alignment of this function.
- virtual unsigned getFunctionAlignment(const Function *F) const;
- };
-}
-
-#endif // LLVM_TARGET_IA64_IA64ISELLOWERING_H
diff --git a/lib/Target/IA64/IA64InstrBuilder.h b/lib/Target/IA64/IA64InstrBuilder.h
deleted file mode 100644
index a5d4dca..0000000
--- a/lib/Target/IA64/IA64InstrBuilder.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===-- IA64PCInstrBuilder.h - Aids for building IA64 insts -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file exposes functions that may be used with BuildMI from the
-// MachineInstrBuilder.h file to simplify generating frame and constant pool
-// references.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef IA64_INSTRBUILDER_H
-#define IA64_INSTRBUILDER_H
-
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-
-namespace llvm {
-
-/// addFrameReference - This function is used to add a reference to the base of
-/// an abstract object on the stack frame of the current function. This
-/// reference has base register as the FrameIndex offset until it is resolved.
-/// This allows a constant offset to be specified as well...
-///
-inline const MachineInstrBuilder&
-addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset = 0,
- bool mem = true) {
- if (mem)
- return MIB.addImm(Offset).addFrameIndex(FI);
- else
- return MIB.addFrameIndex(FI).addImm(Offset);
-}
-
-} // End llvm namespace
-
-#endif
-
diff --git a/lib/Target/IA64/IA64InstrFormats.td b/lib/Target/IA64/IA64InstrFormats.td
deleted file mode 100644
index c465880..0000000
--- a/lib/Target/IA64/IA64InstrFormats.td
+++ /dev/null
@@ -1,80 +0,0 @@
-//===- IA64InstrFormats.td - IA64 Instruction Formats --*- tablegen -*-=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// - Warning: the stuff in here isn't really being used, so is mostly
-// junk. It'll get fixed as the JIT gets built.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Instruction format superclass
-//===----------------------------------------------------------------------===//
-
-class InstIA64<bits<4> op, dag OOL, dag IOL, string asmstr> : Instruction {
- // IA64 instruction baseline
- field bits<41> Inst;
- let Namespace = "IA64";
- let OutOperandList = OOL;
- let InOperandList = IOL;
- let AsmString = asmstr;
-
- let Inst{40-37} = op;
-}
-
-//"Each Itanium instruction is categorized into one of six types."
-//We should have:
-// A, I, M, F, B, L+X
-
-class AForm<bits<4> opcode, bits<6> qpReg, dag OOL, dag IOL, string asmstr> :
- InstIA64<opcode, OOL, IOL, asmstr> {
-
- let Inst{5-0} = qpReg;
-}
-
-class AForm_DAG<bits<4> opcode, bits<6> qpReg, dag OOL, dag IOL, string asmstr,
- list<dag> pattern> :
- InstIA64<opcode, OOL, IOL, asmstr> {
-
- let Pattern = pattern;
- let Inst{5-0} = qpReg;
-}
-
-let isBranch = 1, isTerminator = 1 in
-class BForm<bits<4> opcode, bits<6> x6, bits<3> btype, dag OOL, dag IOL, string asmstr> :
- InstIA64<opcode, OOL, IOL, asmstr> {
-
- let Inst{32-27} = x6;
- let Inst{8-6} = btype;
-}
-
-class MForm<bits<4> opcode, bits<6> x6, dag OOL, dag IOL, string asmstr> :
- InstIA64<opcode, OOL, IOL, asmstr> {
- bits<7> Ra;
- bits<7> Rb;
- bits<16> disp;
-
- let Inst{35-30} = x6;
-// let Inst{20-16} = Rb;
- let Inst{15-0} = disp;
-}
-
-class RawForm<bits<4> opcode, bits<26> rest, dag OOL, dag IOL, string asmstr> :
- InstIA64<opcode, OOL, IOL, asmstr> {
- let Inst{25-0} = rest;
-}
-
-// Pseudo instructions.
-class PseudoInstIA64<dag OOL, dag IOL, string nm> : InstIA64<0, OOL, IOL, nm> {
-}
-
-class PseudoInstIA64_DAG<dag OOL, dag IOL, string nm, list<dag> pattern>
- : InstIA64<0, OOL, IOL, nm> {
- let Pattern = pattern;
-}
-
diff --git a/lib/Target/IA64/IA64InstrInfo.cpp b/lib/Target/IA64/IA64InstrInfo.cpp
deleted file mode 100644
index 5f89d4f..0000000
--- a/lib/Target/IA64/IA64InstrInfo.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-//===- IA64InstrInfo.cpp - IA64 Instruction Information -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the IA64 implementation of the TargetInstrInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IA64InstrInfo.h"
-#include "IA64.h"
-#include "IA64InstrBuilder.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/ADT/SmallVector.h"
-#include "IA64GenInstrInfo.inc"
-using namespace llvm;
-
-IA64InstrInfo::IA64InstrInfo()
- : TargetInstrInfoImpl(IA64Insts, sizeof(IA64Insts)/sizeof(IA64Insts[0])),
- RI(*this) {
-}
-
-
-bool IA64InstrInfo::isMoveInstr(const MachineInstr& MI,
- unsigned& sourceReg,
- unsigned& destReg,
- unsigned& SrcSR, unsigned& DstSR) const {
- SrcSR = DstSR = 0; // No sub-registers.
-
- unsigned oc = MI.getOpcode();
- if (oc == IA64::MOV || oc == IA64::FMOV) {
- // TODO: this doesn't detect predicate moves
- assert(MI.getNumOperands() >= 2 &&
- /* MI.getOperand(0).isReg() &&
- MI.getOperand(1).isReg() && */
- "invalid register-register move instruction");
- if (MI.getOperand(0).isReg() &&
- MI.getOperand(1).isReg()) {
- // if both operands of the MOV/FMOV are registers, then
- // yes, this is a move instruction
- sourceReg = MI.getOperand(1).getReg();
- destReg = MI.getOperand(0).getReg();
- return true;
- }
- }
- return false; // we don't consider e.g. %regN = MOV <FrameIndex #x> a
- // move instruction
-}
-
-unsigned
-IA64InstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB,
- MachineBasicBlock *FBB,
- const SmallVectorImpl<MachineOperand> &Cond)const {
- // FIXME this should probably have a DebugLoc argument
- DebugLoc dl = DebugLoc::getUnknownLoc();
- // Can only insert uncond branches so far.
- assert(Cond.empty() && !FBB && TBB && "Can only handle uncond branches!");
- BuildMI(&MBB, dl, get(IA64::BRL_NOTCALL)).addMBB(TBB);
- return 1;
-}
-
-bool IA64InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned DestReg, unsigned SrcReg,
- const TargetRegisterClass *DestRC,
- const TargetRegisterClass *SrcRC) const {
- if (DestRC != SrcRC) {
- // Not yet supported!
- return false;
- }
-
- DebugLoc DL = DebugLoc::getUnknownLoc();
- if (MI != MBB.end()) DL = MI->getDebugLoc();
-
- if(DestRC == IA64::PRRegisterClass ) // if a bool, we use pseudocode
- // (SrcReg) DestReg = cmp.eq.unc(r0, r0)
- BuildMI(MBB, MI, DL, get(IA64::PCMPEQUNC), DestReg)
- .addReg(IA64::r0).addReg(IA64::r0).addReg(SrcReg);
- else // otherwise, MOV works (for both gen. regs and FP regs)
- BuildMI(MBB, MI, DL, get(IA64::MOV), DestReg).addReg(SrcReg);
-
- return true;
-}
-
-void IA64InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned SrcReg, bool isKill,
- int FrameIdx,
- const TargetRegisterClass *RC) const{
- DebugLoc DL = DebugLoc::getUnknownLoc();
- if (MI != MBB.end()) DL = MI->getDebugLoc();
-
- if (RC == IA64::FPRegisterClass) {
- BuildMI(MBB, MI, DL, get(IA64::STF_SPILL)).addFrameIndex(FrameIdx)
- .addReg(SrcReg, getKillRegState(isKill));
- } else if (RC == IA64::GRRegisterClass) {
- BuildMI(MBB, MI, DL, get(IA64::ST8)).addFrameIndex(FrameIdx)
- .addReg(SrcReg, getKillRegState(isKill));
- } else if (RC == IA64::PRRegisterClass) {
- /* we use IA64::r2 as a temporary register for doing this hackery. */
- // first we load 0:
- BuildMI(MBB, MI, DL, get(IA64::MOV), IA64::r2).addReg(IA64::r0);
- // then conditionally add 1:
- BuildMI(MBB, MI, DL, get(IA64::CADDIMM22), IA64::r2).addReg(IA64::r2)
- .addImm(1).addReg(SrcReg, getKillRegState(isKill));
- // and then store it to the stack
- BuildMI(MBB, MI, DL, get(IA64::ST8))
- .addFrameIndex(FrameIdx)
- .addReg(IA64::r2);
- } else assert(0 &&
- "sorry, I don't know how to store this sort of reg in the stack\n");
-}
-
-void IA64InstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg,
- bool isKill,
- SmallVectorImpl<MachineOperand> &Addr,
- const TargetRegisterClass *RC,
- SmallVectorImpl<MachineInstr*> &NewMIs) const {
- unsigned Opc = 0;
- if (RC == IA64::FPRegisterClass) {
- Opc = IA64::STF8;
- } else if (RC == IA64::GRRegisterClass) {
- Opc = IA64::ST8;
- } else if (RC == IA64::PRRegisterClass) {
- Opc = IA64::ST1;
- } else {
- assert(0 &&
- "sorry, I don't know how to store this sort of reg\n");
- }
-
- DebugLoc DL = DebugLoc::getUnknownLoc();
- MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc));
- for (unsigned i = 0, e = Addr.size(); i != e; ++i)
- MIB.addOperand(Addr[i]);
- MIB.addReg(SrcReg, getKillRegState(isKill));
- NewMIs.push_back(MIB);
- return;
-
-}
-
-void IA64InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned DestReg, int FrameIdx,
- const TargetRegisterClass *RC)const{
- DebugLoc DL = DebugLoc::getUnknownLoc();
- if (MI != MBB.end()) DL = MI->getDebugLoc();
-
- if (RC == IA64::FPRegisterClass) {
- BuildMI(MBB, MI, DL, get(IA64::LDF_FILL), DestReg).addFrameIndex(FrameIdx);
- } else if (RC == IA64::GRRegisterClass) {
- BuildMI(MBB, MI, DL, get(IA64::LD8), DestReg).addFrameIndex(FrameIdx);
- } else if (RC == IA64::PRRegisterClass) {
- // first we load a byte from the stack into r2, our 'predicate hackery'
- // scratch reg
- BuildMI(MBB, MI, DL, get(IA64::LD8), IA64::r2).addFrameIndex(FrameIdx);
- // then we compare it to zero. If it _is_ zero, compare-not-equal to
- // r0 gives us 0, which is what we want, so that's nice.
- BuildMI(MBB, MI, DL, get(IA64::CMPNE), DestReg)
- .addReg(IA64::r2)
- .addReg(IA64::r0);
- } else {
- assert(0 &&
- "sorry, I don't know how to load this sort of reg from the stack\n");
- }
-}
-
-void IA64InstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
- SmallVectorImpl<MachineOperand> &Addr,
- const TargetRegisterClass *RC,
- SmallVectorImpl<MachineInstr*> &NewMIs) const {
- unsigned Opc = 0;
- if (RC == IA64::FPRegisterClass) {
- Opc = IA64::LDF8;
- } else if (RC == IA64::GRRegisterClass) {
- Opc = IA64::LD8;
- } else if (RC == IA64::PRRegisterClass) {
- Opc = IA64::LD1;
- } else {
- assert(0 &&
- "sorry, I don't know how to load this sort of reg\n");
- }
-
- DebugLoc DL = DebugLoc::getUnknownLoc();
- MachineInstrBuilder MIB = BuildMI(MF, DL, get(Opc), DestReg);
- for (unsigned i = 0, e = Addr.size(); i != e; ++i)
- MIB.addOperand(Addr[i]);
- NewMIs.push_back(MIB);
- return;
-}
diff --git a/lib/Target/IA64/IA64InstrInfo.h b/lib/Target/IA64/IA64InstrInfo.h
deleted file mode 100644
index 79236c2..0000000
--- a/lib/Target/IA64/IA64InstrInfo.h
+++ /dev/null
@@ -1,70 +0,0 @@
-//===- IA64InstrInfo.h - IA64 Instruction Information ----------*- C++ -*- ===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the IA64 implementation of the TargetInstrInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef IA64INSTRUCTIONINFO_H
-#define IA64INSTRUCTIONINFO_H
-
-#include "llvm/Target/TargetInstrInfo.h"
-#include "IA64RegisterInfo.h"
-
-namespace llvm {
-
-class IA64InstrInfo : public TargetInstrInfoImpl {
- const IA64RegisterInfo RI;
-public:
- IA64InstrInfo();
-
- /// 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 IA64RegisterInfo &getRegisterInfo() const { return RI; }
-
- /// Return true if the instruction is a register to register move and return
- /// the source and dest operands and their sub-register indices by reference.
- virtual bool isMoveInstr(const MachineInstr &MI,
- unsigned &SrcReg, unsigned &DstReg,
- unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
- virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
- MachineBasicBlock *FBB,
- const SmallVectorImpl<MachineOperand> &Cond) const;
- virtual bool copyRegToReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned DestReg, unsigned SrcReg,
- const TargetRegisterClass *DestRC,
- const TargetRegisterClass *SrcRC) const;
- virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned SrcReg, bool isKill, int FrameIndex,
- const TargetRegisterClass *RC) const;
-
- virtual void storeRegToAddr(MachineFunction &MF, unsigned SrcReg, bool isKill,
- SmallVectorImpl<MachineOperand> &Addr,
- const TargetRegisterClass *RC,
- SmallVectorImpl<MachineInstr*> &NewMIs) const;
-
- virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned DestReg, int FrameIndex,
- const TargetRegisterClass *RC) const;
-
- virtual void loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
- SmallVectorImpl<MachineOperand> &Addr,
- const TargetRegisterClass *RC,
- SmallVectorImpl<MachineInstr*> &NewMIs) const;
-};
-
-} // End llvm namespace
-
-#endif
-
diff --git a/lib/Target/IA64/IA64InstrInfo.td b/lib/Target/IA64/IA64InstrInfo.td
deleted file mode 100644
index 2ab9897..0000000
--- a/lib/Target/IA64/IA64InstrInfo.td
+++ /dev/null
@@ -1,751 +0,0 @@
-//===- IA64InstrInfo.td - Describe the IA64 Instruction Set -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file describes the IA64 instruction set, defining the instructions, and
-// properties of the instructions which are needed for code generation, machine
-// code emission, and analysis.
-//
-//===----------------------------------------------------------------------===//
-
-include "IA64InstrFormats.td"
-
-//===----------------------------------------------------------------------===//
-// IA-64 specific DAG Nodes.
-//
-
-def IA64getfd : SDNode<"IA64ISD::GETFD", SDTFPToIntOp, []>;
-
-def retflag : SDNode<"IA64ISD::RET_FLAG", SDTNone,
- [SDNPHasChain, SDNPOptInFlag]>;
-
-//===---------
-// Instruction types
-
-class isA { bit A=1; } // I or M unit
-class isM { bit M=1; } // M unit
-class isI { bit I=1; } // I unit
-class isB { bit B=1; } // B unit
-class isF { bit F=1; } // F unit
-class isLX { bit LX=1; } // I/B
-
-//===---------
-
-def u2imm : Operand<i8>;
-def u6imm : Operand<i8>;
-def s8imm : Operand<i8> {
- let PrintMethod = "printS8ImmOperand";
-}
-def s14imm : Operand<i64> {
- let PrintMethod = "printS14ImmOperand";
-}
-def s22imm : Operand<i64> {
- let PrintMethod = "printS22ImmOperand";
-}
-def u64imm : Operand<i64> {
- let PrintMethod = "printU64ImmOperand";
-}
-def s64imm : Operand<i64> {
- let PrintMethod = "printS64ImmOperand";
-}
-
-let PrintMethod = "printGlobalOperand" in
- def globaladdress : Operand<i64>;
-
-// the asmprinter needs to know about calls
-let PrintMethod = "printCallOperand" in
- def calltarget : Operand<i64>;
-
-/* new daggy action!!! */
-
-def is32ones : PatLeaf<(i64 imm), [{
- // is32ones predicate - True if the immediate is 0x00000000FFFFFFFF
- // Used to create ZXT4s appropriately
- uint64_t v = (uint64_t)N->getZExtValue();
- return (v == 0x00000000FFFFFFFFLL);
-}]>;
-
-// isMIXable predicates - True if the immediate is
-// 0xFF00FF00FF00FF00, 0x00FF00FF00FF00FF
-// etc, through 0x00000000FFFFFFFF
-// Used to test for the suitability of mix*
-def isMIX1Lable: PatLeaf<(i64 imm), [{
- return((uint64_t)N->getZExtValue()==0xFF00FF00FF00FF00LL);
-}]>;
-def isMIX1Rable: PatLeaf<(i64 imm), [{
- return((uint64_t)N->getZExtValue()==0x00FF00FF00FF00FFLL);
-}]>;
-def isMIX2Lable: PatLeaf<(i64 imm), [{
- return((uint64_t)N->getZExtValue()==0xFFFF0000FFFF0000LL);
-}]>;
-def isMIX2Rable: PatLeaf<(i64 imm), [{
- return((uint64_t)N->getZExtValue()==0x0000FFFF0000FFFFLL);
-}]>;
-def isMIX4Lable: PatLeaf<(i64 imm), [{
- return((uint64_t)N->getZExtValue()==0xFFFFFFFF00000000LL);
-}]>;
-def isMIX4Rable: PatLeaf<(i64 imm), [{
- return((uint64_t)N->getZExtValue()==0x00000000FFFFFFFFLL);
-}]>;
-
-def isSHLADDimm: PatLeaf<(i64 imm), [{
- // isSHLADDimm predicate - True if the immediate is exactly 1, 2, 3 or 4
- // - 0 is *not* okay.
- // Used to create shladd instructions appropriately
- int64_t v = (int64_t)N->getZExtValue();
- return (v >= 1 && v <= 4);
-}]>;
-
-def immSExt14 : PatLeaf<(i64 imm), [{
- // immSExt14 predicate - True if the immediate fits in a 14-bit sign extended
- // field. Used by instructions like 'adds'.
- int64_t v = (int64_t)N->getZExtValue();
- return (v <= 8191 && v >= -8192);
-}]>;
-
-// imm64 predicate - True if the immediate fits in a 64-bit
-// field - i.e., true. used to keep movl happy
-def imm64 : PatLeaf<(i64 imm)>;
-
-def ADD : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "add $dst = $src1, $src2",
- [(set GR:$dst, (add GR:$src1, GR:$src2))]>, isA;
-
-def ADD1 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "add $dst = $src1, $src2, 1",
- [(set GR:$dst, (add (add GR:$src1, GR:$src2), 1))]>, isA;
-
-def ADDS : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, s14imm:$imm),
- "adds $dst = $imm, $src1",
- [(set GR:$dst, (add GR:$src1, immSExt14:$imm))]>, isA;
-
-def MOVL : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins s64imm:$imm),
- "movl $dst = $imm",
- [(set GR:$dst, imm64:$imm)]>, isLX;
-
-def ADDL_GA : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, globaladdress:$imm),
- "addl $dst = $imm, $src1",
- []>, isA;
-
-// hmm
-def ADDL_EA : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, calltarget:$imm),
- "addl $dst = $imm, $src1",
- []>, isA;
-
-def SUB : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "sub $dst = $src1, $src2",
- [(set GR:$dst, (sub GR:$src1, GR:$src2))]>, isA;
-
-def SUB1 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "sub $dst = $src1, $src2, 1",
- [(set GR:$dst, (add (sub GR: $src1, GR:$src2), -1))]>, isA;
-
-let isTwoAddress = 1 in {
-def TPCADDIMM22 : AForm<0x03, 0x0b,
- (outs GR:$dst), (ins GR:$src1, s22imm:$imm, PR:$qp),
- "($qp) add $dst = $imm, $dst">, isA;
-def TPCADDS : AForm_DAG<0x03, 0x0b,
- (outs GR:$dst), (ins GR:$src1, s14imm:$imm, PR:$qp),
- "($qp) adds $dst = $imm, $dst",
- []>, isA;
-def TPCMPIMM8NE : AForm<0x03, 0x0b,
- (outs PR:$dst), (ins PR:$src1, s22imm:$imm, GR:$src2, PR:$qp),
- "($qp) cmp.ne $dst , p0 = $imm, $src2">, isA;
-}
-
-// zero extend a bool (predicate reg) into an integer reg
-def ZXTb : Pat<(zext PR:$src),
- (TPCADDIMM22 (ADDS r0, 0), 1, PR:$src)>;
-def AXTb : Pat<(anyext PR:$src),
- (TPCADDIMM22 (ADDS r0, 0), 1, PR:$src)>;
-
-// normal sign/zero-extends
-def SXT1 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "sxt1 $dst = $src",
- [(set GR:$dst, (sext_inreg GR:$src, i8))]>, isI;
-def ZXT1 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "zxt1 $dst = $src",
- [(set GR:$dst, (and GR:$src, 255))]>, isI;
-def SXT2 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "sxt2 $dst = $src",
- [(set GR:$dst, (sext_inreg GR:$src, i16))]>, isI;
-def ZXT2 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "zxt2 $dst = $src",
- [(set GR:$dst, (and GR:$src, 65535))]>, isI;
-def SXT4 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "sxt4 $dst = $src",
- [(set GR:$dst, (sext_inreg GR:$src, i32))]>, isI;
-def ZXT4 : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "zxt4 $dst = $src",
- [(set GR:$dst, (and GR:$src, is32ones))]>, isI;
-
-// fixme: shrs vs shru?
-def MIX1L : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "mix1.l $dst = $src1, $src2",
- [(set GR:$dst, (or (and GR:$src1, isMIX1Lable),
- (and (srl GR:$src2, (i64 8)), isMIX1Lable)))]>, isI;
-
-def MIX2L : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "mix2.l $dst = $src1, $src2",
- [(set GR:$dst, (or (and GR:$src1, isMIX2Lable),
- (and (srl GR:$src2, (i64 16)), isMIX2Lable)))]>, isI;
-
-def MIX4L : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "mix4.l $dst = $src1, $src2",
- [(set GR:$dst, (or (and GR:$src1, isMIX4Lable),
- (and (srl GR:$src2, (i64 32)), isMIX4Lable)))]>, isI;
-
-def MIX1R : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "mix1.r $dst = $src1, $src2",
- [(set GR:$dst, (or (and (shl GR:$src1, (i64 8)), isMIX1Rable),
- (and GR:$src2, isMIX1Rable)))]>, isI;
-
-def MIX2R : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "mix2.r $dst = $src1, $src2",
- [(set GR:$dst, (or (and (shl GR:$src1, (i64 16)), isMIX2Rable),
- (and GR:$src2, isMIX2Rable)))]>, isI;
-
-def MIX4R : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "mix4.r $dst = $src1, $src2",
- [(set GR:$dst, (or (and (shl GR:$src1, (i64 32)), isMIX4Rable),
- (and GR:$src2, isMIX4Rable)))]>, isI;
-
-def GETFSIGD : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins FP:$src),
- "getf.sig $dst = $src",
- []>, isM;
-
-def SETFSIGD : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins GR:$src),
- "setf.sig $dst = $src",
- []>, isM;
-
-def XMALD : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
- "xma.l $dst = $src1, $src2, $src3",
- []>, isF;
-def XMAHD : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
- "xma.h $dst = $src1, $src2, $src3",
- []>, isF;
-def XMAHUD : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
- "xma.hu $dst = $src1, $src2, $src3",
- []>, isF;
-
-// pseudocode for integer multiplication
-def : Pat<(mul GR:$src1, GR:$src2),
- (GETFSIGD (XMALD (SETFSIGD GR:$src1), (SETFSIGD GR:$src2), F0))>;
-def : Pat<(mulhs GR:$src1, GR:$src2),
- (GETFSIGD (XMAHD (SETFSIGD GR:$src1), (SETFSIGD GR:$src2), F0))>;
-def : Pat<(mulhu GR:$src1, GR:$src2),
- (GETFSIGD (XMAHUD (SETFSIGD GR:$src1), (SETFSIGD GR:$src2), F0))>;
-
-// TODO: addp4 (addp4 dst = src, r0 is a 32-bit add)
-// has imm form, too
-
-// def ADDS : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, s14imm:$imm),
-// "adds $dst = $imm, $src1">;
-
-def AND : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "and $dst = $src1, $src2",
- [(set GR:$dst, (and GR:$src1, GR:$src2))]>, isA;
-def ANDCM : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "andcm $dst = $src1, $src2",
- [(set GR:$dst, (and GR:$src1, (not GR:$src2)))]>, isA;
-// TODO: and/andcm/or/xor/add/sub/shift immediate forms
-def OR : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "or $dst = $src1, $src2",
- [(set GR:$dst, (or GR:$src1, GR:$src2))]>, isA;
-
-def pOR : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2, PR:$qp),
- "($qp) or $dst = $src1, $src2">, isA;
-
-// the following are all a bit unfortunate: we throw away the complement
-// of the compare!
-def CMPEQ : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
- "cmp.eq $dst, p0 = $src1, $src2",
- [(set PR:$dst, (seteq GR:$src1, GR:$src2))]>, isA;
-def CMPGT : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
- "cmp.gt $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setgt GR:$src1, GR:$src2))]>, isA;
-def CMPGE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
- "cmp.ge $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setge GR:$src1, GR:$src2))]>, isA;
-def CMPLT : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
- "cmp.lt $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setlt GR:$src1, GR:$src2))]>, isA;
-def CMPLE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
- "cmp.le $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setle GR:$src1, GR:$src2))]>, isA;
-def CMPNE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
- "cmp.ne $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setne GR:$src1, GR:$src2))]>, isA;
-def CMPLTU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
- "cmp.ltu $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setult GR:$src1, GR:$src2))]>, isA;
-def CMPGTU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
- "cmp.gtu $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setugt GR:$src1, GR:$src2))]>, isA;
-def CMPLEU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
- "cmp.leu $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setule GR:$src1, GR:$src2))]>, isA;
-def CMPGEU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2),
- "cmp.geu $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setuge GR:$src1, GR:$src2))]>, isA;
-
-// and we do the whole thing again for FP compares!
-def FCMPEQ : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
- "fcmp.eq $dst, p0 = $src1, $src2",
- [(set PR:$dst, (seteq FP:$src1, FP:$src2))]>, isF;
-def FCMPGT : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
- "fcmp.gt $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setgt FP:$src1, FP:$src2))]>, isF;
-def FCMPGE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
- "fcmp.ge $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setge FP:$src1, FP:$src2))]>, isF;
-def FCMPLT : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
- "fcmp.lt $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setlt FP:$src1, FP:$src2))]>, isF;
-def FCMPLE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
- "fcmp.le $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setle FP:$src1, FP:$src2))]>, isF;
-def FCMPNE : AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
- "fcmp.neq $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setne FP:$src1, FP:$src2))]>, isF;
-def FCMPLTU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
- "fcmp.lt $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setult FP:$src1, FP:$src2))]>, isF;
-def FCMPGTU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
- "fcmp.gt $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setugt FP:$src1, FP:$src2))]>, isF;
-def FCMPLEU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
- "fcmp.le $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setule FP:$src1, FP:$src2))]>, isF;
-def FCMPGEU: AForm_DAG<0x03, 0x0b, (outs PR:$dst), (ins FP:$src1, FP:$src2),
- "fcmp.ge $dst, p0 = $src1, $src2",
- [(set PR:$dst, (setuge FP:$src1, FP:$src2))]>, isF;
-
-def PCMPEQUNCR0R0 : AForm<0x03, 0x0b, (outs PR:$dst), (ins PR:$qp),
- "($qp) cmp.eq.unc $dst, p0 = r0, r0">, isA;
-
-def : Pat<(trunc GR:$src), // truncate i64 to i1
- (CMPNE GR:$src, r0)>; // $src!=0? If so, PR:$dst=true
-
-let isTwoAddress=1 in {
- def TPCMPEQR0R0 : AForm<0x03, 0x0b, (outs PR:$dst), (ins PR:$bogus, PR:$qp),
- "($qp) cmp.eq $dst, p0 = r0, r0">, isA;
- def TPCMPNER0R0 : AForm<0x03, 0x0b, (outs PR:$dst), (ins PR:$bogus, PR:$qp),
- "($qp) cmp.ne $dst, p0 = r0, r0">, isA;
-}
-
-/* our pseudocode for OR on predicates is:
-pC = pA OR pB
--------------
-(pA) cmp.eq.unc pC,p0 = r0,r0 // pC = pA
- ;;
-(pB) cmp.eq pC,p0 = r0,r0 // if (pB) pC = 1 */
-
-def bOR : Pat<(or PR:$src1, PR:$src2),
- (TPCMPEQR0R0 (PCMPEQUNCR0R0 PR:$src1), PR:$src2)>;
-
-/* our pseudocode for AND on predicates is:
- *
-(pA) cmp.eq.unc pC,p0 = r0,r0 // pC = pA
- cmp.eq pTemp,p0 = r0,r0 // pTemp = NOT pB
- ;;
-(pB) cmp.ne pTemp,p0 = r0,r0
- ;;
-(pTemp)cmp.ne pC,p0 = r0,r0 // if (NOT pB) pC = 0 */
-
-def bAND : Pat<(and PR:$src1, PR:$src2),
- ( TPCMPNER0R0 (PCMPEQUNCR0R0 PR:$src1),
- (TPCMPNER0R0 (CMPEQ r0, r0), PR:$src2) )>;
-
-/* one possible routine for XOR on predicates is:
-
- // Compute px = py ^ pz
- // using sum of products: px = (py & !pz) | (pz & !py)
- // Uses 5 instructions in 3 cycles.
- // cycle 1
-(pz) cmp.eq.unc px = r0, r0 // px = pz
-(py) cmp.eq.unc pt = r0, r0 // pt = py
- ;;
- // cycle 2
-(pt) cmp.ne.and px = r0, r0 // px = px & !pt (px = pz & !pt)
-(pz) cmp.ne.and pt = r0, r0 // pt = pt & !pz
- ;;
- } { .mmi
- // cycle 3
-(pt) cmp.eq.or px = r0, r0 // px = px | pt
-
-*** Another, which we use here, requires one scratch GR. it is:
-
- mov rt = 0 // initialize rt off critical path
- ;;
-
- // cycle 1
-(pz) cmp.eq.unc px = r0, r0 // px = pz
-(pz) mov rt = 1 // rt = pz
- ;;
- // cycle 2
-(py) cmp.ne px = 1, rt // if (py) px = !pz
-
-.. these routines kindly provided by Jim Hull
-*/
-
-def bXOR : Pat<(xor PR:$src1, PR:$src2),
- (TPCMPIMM8NE (PCMPEQUNCR0R0 PR:$src2), 1,
- (TPCADDS (ADDS r0, 0), 1, PR:$src2),
- PR:$src1)>;
-
-def XOR : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "xor $dst = $src1, $src2",
- [(set GR:$dst, (xor GR:$src1, GR:$src2))]>, isA;
-
-def SHLADD: AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1,s64imm:$imm,GR:$src2),
- "shladd $dst = $src1, $imm, $src2",
- [(set GR:$dst, (add GR:$src2, (shl GR:$src1, isSHLADDimm:$imm)))]>, isA;
-
-def SHL : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "shl $dst = $src1, $src2",
- [(set GR:$dst, (shl GR:$src1, GR:$src2))]>, isI;
-
-def SHRU : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "shr.u $dst = $src1, $src2",
- [(set GR:$dst, (srl GR:$src1, GR:$src2))]>, isI;
-
-def SHRS : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, GR:$src2),
- "shr $dst = $src1, $src2",
- [(set GR:$dst, (sra GR:$src1, GR:$src2))]>, isI;
-
-def MOV : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src), "mov $dst = $src">, isA;
-def FMOV : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "mov $dst = $src">, isF; // XXX: there _is_ no fmov
-def PMOV : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src, PR:$qp),
- "($qp) mov $dst = $src">, isA;
-
-def SPILL_ALL_PREDICATES_TO_GR : AForm<0x03, 0x0b, (outs GR:$dst), (ins),
- "mov $dst = pr">, isI;
-def FILL_ALL_PREDICATES_FROM_GR : AForm<0x03, 0x0b, (outs), (ins GR:$src),
- "mov pr = $src">, isI;
-
-let isTwoAddress = 1 in {
- def CMOV : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src2, GR:$src, PR:$qp),
- "($qp) mov $dst = $src">, isA;
-}
-
-def PFMOV : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src, PR:$qp),
- "($qp) mov $dst = $src">, isF;
-
-let isTwoAddress = 1 in {
- def CFMOV : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src2, FP:$src, PR:$qp),
- "($qp) mov $dst = $src">, isF;
-}
-
-def SELECTINT : Pat<(select PR:$which, GR:$src1, GR:$src2),
- (CMOV (MOV GR:$src2), GR:$src1, PR:$which)>; // note order!
-def SELECTFP : Pat<(select PR:$which, FP:$src1, FP:$src2),
- (CFMOV (FMOV FP:$src2), FP:$src1, PR:$which)>; // note order!
-// TODO: can do this faster, w/o using any integer regs (see pattern isel)
-def SELECTBOOL : Pat<(select PR:$which, PR:$src1, PR:$src2), // note order!
- (CMPNE (CMOV
- (MOV (TPCADDIMM22 (ADDS r0, 0), 1, PR:$src2)),
- (TPCADDIMM22 (ADDS r0, 0), 1, PR:$src1), PR:$which), r0)>;
-
-// load constants of various sizes // FIXME: prettyprint -ve constants
-def : Pat<(i64 immSExt14:$imm), (ADDS r0, immSExt14:$imm)>;
-def : Pat<(i1 -1), (CMPEQ r0, r0)>; // TODO: this should just be a ref to p0
-def : Pat<(i1 0), (CMPNE r0, r0)>; // TODO: any instruction actually *using*
- // this predicate should be killed!
-
-// TODO: support postincrement (reg, imm9) loads+stores - this needs more
-// tablegen support
-
-def IUSE : PseudoInstIA64<(outs), (ins variable_ops), "// IUSE">;
-def ADJUSTCALLSTACKUP : PseudoInstIA64<(outs), (ins variable_ops),
- "// ADJUSTCALLSTACKUP">;
-def ADJUSTCALLSTACKDOWN : PseudoInstIA64<(outs), (ins variable_ops),
- "// ADJUSTCALLSTACKDOWN">;
-def PSEUDO_ALLOC : PseudoInstIA64<(outs), (ins GR:$foo), "// PSEUDO_ALLOC">;
-
-def ALLOC : AForm<0x03, 0x0b,
- (outs GR:$dst), (ins i8imm:$inputs, i8imm:$locals, i8imm:$outputs, i8imm:$rotating),
- "alloc $dst = ar.pfs,$inputs,$locals,$outputs,$rotating">, isM;
-
-let isTwoAddress = 1 in {
- def TCMPNE : AForm<0x03, 0x0b,
- (outs PR:$dst), (ins PR:$src2, GR:$src3, GR:$src4),
- "cmp.ne $dst, p0 = $src3, $src4">, isA;
-
- def TPCMPEQOR : AForm<0x03, 0x0b,
- (outs PR:$dst), (ins PR:$src2, GR:$src3, GR:$src4, PR:$qp),
- "($qp) cmp.eq.or $dst, p0 = $src3, $src4">, isA;
-
- def TPCMPNE : AForm<0x03, 0x0b,
- (outs PR:$dst), (ins PR:$src2, GR:$src3, GR:$src4, PR:$qp),
- "($qp) cmp.ne $dst, p0 = $src3, $src4">, isA;
-
- def TPCMPEQ : AForm<0x03, 0x0b,
- (outs PR:$dst), (ins PR:$src2, GR:$src3, GR:$src4, PR:$qp),
- "($qp) cmp.eq $dst, p0 = $src3, $src4">, isA;
-}
-
-def MOVSIMM14 : AForm<0x03, 0x0b, (outs GR:$dst), (ins s14imm:$imm),
- "mov $dst = $imm">, isA;
-def MOVSIMM22 : AForm<0x03, 0x0b, (outs GR:$dst), (ins s22imm:$imm),
- "mov $dst = $imm">, isA;
-def MOVLIMM64 : AForm<0x03, 0x0b, (outs GR:$dst), (ins s64imm:$imm),
- "movl $dst = $imm">, isLX;
-
-def SHLI : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, u6imm:$imm),
- "shl $dst = $src1, $imm">, isI;
-def SHRUI : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, u6imm:$imm),
- "shr.u $dst = $src1, $imm">, isI;
-def SHRSI : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, u6imm:$imm),
- "shr $dst = $src1, $imm">, isI;
-
-def EXTRU : AForm<0x03, 0x0b,
- (outs GR:$dst), (ins GR:$src1, u6imm:$imm1, u6imm:$imm2),
- "extr.u $dst = $src1, $imm1, $imm2">, isI;
-
-def DEPZ : AForm<0x03, 0x0b,
- (outs GR:$dst), (ins GR:$src1, u6imm:$imm1, u6imm:$imm2),
- "dep.z $dst = $src1, $imm1, $imm2">, isI;
-
-def PCMPEQOR : AForm<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2, PR:$qp),
- "($qp) cmp.eq.or $dst, p0 = $src1, $src2">, isA;
-def PCMPEQUNC : AForm<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2, PR:$qp),
- "($qp) cmp.eq.unc $dst, p0 = $src1, $src2">, isA;
-def PCMPNE : AForm<0x03, 0x0b, (outs PR:$dst), (ins GR:$src1, GR:$src2, PR:$qp),
- "($qp) cmp.ne $dst, p0 = $src1, $src2">, isA;
-
-// two destinations!
-def BCMPEQ : AForm<0x03, 0x0b, (outs PR:$dst1, PR:$dst2), (ins GR:$src1, GR:$src2),
- "cmp.eq $dst1, dst2 = $src1, $src2">, isA;
-
-def ADDIMM14 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, s14imm:$imm),
- "adds $dst = $imm, $src1">, isA;
-
-def ADDIMM22 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, s22imm:$imm),
- "add $dst = $imm, $src1">, isA;
-def CADDIMM22 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$src1, s22imm:$imm, PR:$qp),
- "($qp) add $dst = $imm, $src1">, isA;
-
-def SUBIMM8 : AForm<0x03, 0x0b, (outs GR:$dst), (ins s8imm:$imm, GR:$src2),
- "sub $dst = $imm, $src2">, isA;
-
-let mayStore = 1 in {
- def ST1 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, GR:$value),
- "st1 [$dstPtr] = $value">, isM;
- def ST2 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, GR:$value),
- "st2 [$dstPtr] = $value">, isM;
- def ST4 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, GR:$value),
- "st4 [$dstPtr] = $value">, isM;
- def ST8 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, GR:$value),
- "st8 [$dstPtr] = $value">, isM;
- def STF4 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, FP:$value),
- "stfs [$dstPtr] = $value">, isM;
- def STF8 : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, FP:$value),
- "stfd [$dstPtr] = $value">, isM;
- def STF_SPILL : AForm<0x03, 0x0b, (outs), (ins GR:$dstPtr, FP:$value),
- "stf.spill [$dstPtr] = $value">, isM;
-}
-
-let canFoldAsLoad = 1 in {
- def LD1 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$srcPtr),
- "ld1 $dst = [$srcPtr]">, isM;
- def LD2 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$srcPtr),
- "ld2 $dst = [$srcPtr]">, isM;
- def LD4 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$srcPtr),
- "ld4 $dst = [$srcPtr]">, isM;
- def LD8 : AForm<0x03, 0x0b, (outs GR:$dst), (ins GR:$srcPtr),
- "ld8 $dst = [$srcPtr]">, isM;
- def LDF4 : AForm<0x03, 0x0b, (outs FP:$dst), (ins GR:$srcPtr),
- "ldfs $dst = [$srcPtr]">, isM;
- def LDF8 : AForm<0x03, 0x0b, (outs FP:$dst), (ins GR:$srcPtr),
- "ldfd $dst = [$srcPtr]">, isM;
- def LDF_FILL : AForm<0x03, 0x0b, (outs FP:$dst), (ins GR:$srcPtr),
- "ldf.fill $dst = [$srcPtr]">, isM;
-}
-
-def POPCNT : AForm_DAG<0x03, 0x0b, (outs GR:$dst), (ins GR:$src),
- "popcnt $dst = $src",
- [(set GR:$dst, (ctpop GR:$src))]>, isI;
-
-// some FP stuff: // TODO: single-precision stuff?
-def FADD : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2),
- "fadd $dst = $src1, $src2",
- [(set FP:$dst, (fadd FP:$src1, FP:$src2))]>, isF;
-def FADDS: AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2),
- "fadd.s $dst = $src1, $src2">, isF;
-def FSUB : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2),
- "fsub $dst = $src1, $src2",
- [(set FP:$dst, (fsub FP:$src1, FP:$src2))]>, isF;
-def FMPY : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2),
- "fmpy $dst = $src1, $src2",
- [(set FP:$dst, (fmul FP:$src1, FP:$src2))]>, isF;
-def FMA : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
- "fma $dst = $src1, $src2, $src3",
- [(set FP:$dst, (fadd (fmul FP:$src1, FP:$src2), FP:$src3))]>, isF;
-def FMS : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
- "fms $dst = $src1, $src2, $src3",
- [(set FP:$dst, (fsub (fmul FP:$src1, FP:$src2), FP:$src3))]>, isF;
-def FNMA : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
- "fnma $dst = $src1, $src2, $src3",
- [(set FP:$dst, (fneg (fadd (fmul FP:$src1, FP:$src2), FP:$src3)))]>, isF;
-def FABS : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fabs $dst = $src",
- [(set FP:$dst, (fabs FP:$src))]>, isF;
-def FNEG : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fneg $dst = $src",
- [(set FP:$dst, (fneg FP:$src))]>, isF;
-def FNEGABS : AForm_DAG<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fnegabs $dst = $src",
- [(set FP:$dst, (fneg (fabs FP:$src)))]>, isF;
-
-let isTwoAddress=1 in {
-def TCFMAS1 : AForm<0x03, 0x0b,
- (outs FP:$dst), (ins FP:$bogussrc, FP:$src1, FP:$src2, FP:$src3, PR:$qp),
- "($qp) fma.s1 $dst = $src1, $src2, $src3">, isF;
-def TCFMADS0 : AForm<0x03, 0x0b,
- (outs FP:$dst), (ins FP:$bogussrc, FP:$src1, FP:$src2, FP:$src3, PR:$qp),
- "($qp) fma.d.s0 $dst = $src1, $src2, $src3">, isF;
-}
-
-def CFMAS1 : AForm<0x03, 0x0b,
- (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3, PR:$qp),
- "($qp) fma.s1 $dst = $src1, $src2, $src3">, isF;
-def CFNMAS1 : AForm<0x03, 0x0b,
- (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3, PR:$qp),
- "($qp) fnma.s1 $dst = $src1, $src2, $src3">, isF;
-
-def CFMADS1 : AForm<0x03, 0x0b,
- (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3, PR:$qp),
- "($qp) fma.d.s1 $dst = $src1, $src2, $src3">, isF;
-def CFMADS0 : AForm<0x03, 0x0b,
- (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3, PR:$qp),
- "($qp) fma.d.s0 $dst = $src1, $src2, $src3">, isF;
-def CFNMADS1 : AForm<0x03, 0x0b,
- (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3, PR:$qp),
- "($qp) fnma.d.s1 $dst = $src1, $src2, $src3">, isF;
-
-def FRCPAS0 : AForm<0x03, 0x0b, (outs FP:$dstFR, PR:$dstPR), (ins FP:$src1, FP:$src2),
- "frcpa.s0 $dstFR, $dstPR = $src1, $src2">, isF;
-def FRCPAS1 : AForm<0x03, 0x0b, (outs FP:$dstFR, PR:$dstPR), (ins FP:$src1, FP:$src2),
- "frcpa.s1 $dstFR, $dstPR = $src1, $src2">, isF;
-
-def XMAL : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src1, FP:$src2, FP:$src3),
- "xma.l $dst = $src1, $src2, $src3">, isF;
-
-def FCVTXF : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fcvt.xf $dst = $src">, isF;
-def FCVTXUF : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fcvt.xuf $dst = $src">, isF;
-def FCVTXUFS1 : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fcvt.xuf.s1 $dst = $src">, isF;
-def FCVTFX : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fcvt.fx $dst = $src">, isF;
-def FCVTFXU : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fcvt.fxu $dst = $src">, isF;
-
-def FCVTFXTRUNC : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fcvt.fx.trunc $dst = $src">, isF;
-def FCVTFXUTRUNC : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fcvt.fxu.trunc $dst = $src">, isF;
-
-def FCVTFXTRUNCS1 : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fcvt.fx.trunc.s1 $dst = $src">, isF;
-def FCVTFXUTRUNCS1 : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fcvt.fxu.trunc.s1 $dst = $src">, isF;
-
-def FNORMD : AForm<0x03, 0x0b, (outs FP:$dst), (ins FP:$src),
- "fnorm.d $dst = $src">, isF;
-
-def GETFD : AForm<0x03, 0x0b, (outs GR:$dst), (ins FP:$src),
- "getf.d $dst = $src">, isM;
-def SETFD : AForm<0x03, 0x0b, (outs FP:$dst), (ins GR:$src),
- "setf.d $dst = $src">, isM;
-
-def GETFSIG : AForm<0x03, 0x0b, (outs GR:$dst), (ins FP:$src),
- "getf.sig $dst = $src">, isM;
-def SETFSIG : AForm<0x03, 0x0b, (outs FP:$dst), (ins GR:$src),
- "setf.sig $dst = $src">, isM;
-
-// these four FP<->int conversion patterns need checking/cleaning
-def SINT_TO_FP : Pat<(sint_to_fp GR:$src),
- (FNORMD (FCVTXF (SETFSIG GR:$src)))>;
-def UINT_TO_FP : Pat<(uint_to_fp GR:$src),
- (FNORMD (FCVTXUF (SETFSIG GR:$src)))>;
-def FP_TO_SINT : Pat<(i64 (fp_to_sint FP:$src)),
- (GETFSIG (FCVTFXTRUNC FP:$src))>;
-def FP_TO_UINT : Pat<(i64 (fp_to_uint FP:$src)),
- (GETFSIG (FCVTFXUTRUNC FP:$src))>;
-
-def fpimm0 : PatLeaf<(fpimm), [{
- return N->isExactlyValue(+0.0);
-}]>;
-def fpimm1 : PatLeaf<(fpimm), [{
- return N->isExactlyValue(+1.0);
-}]>;
-def fpimmn0 : PatLeaf<(fpimm), [{
- return N->isExactlyValue(-0.0);
-}]>;
-def fpimmn1 : PatLeaf<(fpimm), [{
- return N->isExactlyValue(-1.0);
-}]>;
-
-def : Pat<(f64 fpimm0), (FMOV F0)>;
-def : Pat<(f64 fpimm1), (FMOV F1)>;
-def : Pat<(f64 fpimmn0), (FNEG F0)>;
-def : Pat<(f64 fpimmn1), (FNEG F1)>;
-
-let isTerminator = 1, isBranch = 1 in {
- def BRL_NOTCALL : RawForm<0x03, 0xb0, (outs), (ins i64imm:$dst),
- "(p0) brl.cond.sptk $dst">, isB;
- def BRLCOND_NOTCALL : RawForm<0x03, 0xb0, (outs), (ins PR:$qp, i64imm:$dst),
- "($qp) brl.cond.sptk $dst">, isB;
- def BRCOND_NOTCALL : RawForm<0x03, 0xb0, (outs), (ins PR:$qp, GR:$dst),
- "($qp) br.cond.sptk $dst">, isB;
-}
-
-let isCall = 1, /* isTerminator = 1, isBranch = 1, */
- Uses = [out0,out1,out2,out3,out4,out5,out6,out7],
-// all calls clobber non-callee-saved registers, and for now, they are these:
- Defs = [r2,r3,r8,r9,r10,r11,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,
- r25,r26,r27,r28,r29,r30,r31,
- p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,
- F6,F7,F8,F9,F10,F11,F12,F13,F14,F15,
- F32,F33,F34,F35,F36,F37,F38,F39,F40,F41,F42,F43,F44,F45,F46,F47,F48,F49,
- F50,F51,F52,F53,F54,F55,F56,
- F57,F58,F59,F60,F61,F62,F63,F64,F65,F66,F67,F68,F69,F70,F71,F72,F73,F74,
- F75,F76,F77,F78,F79,F80,F81,
- F82,F83,F84,F85,F86,F87,F88,F89,F90,F91,F92,F93,F94,F95,F96,F97,F98,F99,
- F100,F101,F102,F103,F104,F105,
- F106,F107,F108,F109,F110,F111,F112,F113,F114,F115,F116,F117,F118,F119,
- F120,F121,F122,F123,F124,F125,F126,F127,
- out0,out1,out2,out3,out4,out5,out6,out7] in {
-// old pattern call
- def BRCALL: RawForm<0x03, 0xb0, (outs), (ins calltarget:$dst),
- "br.call.sptk rp = $dst">, isB; // FIXME: teach llvm about branch regs?
-// new daggy stuff!
-
-// calls a globaladdress
- def BRCALL_IPREL_GA : RawForm<0x03, 0xb0, (outs), (ins calltarget:$dst),
- "br.call.sptk rp = $dst">, isB; // FIXME: teach llvm about branch regs?
-// calls an externalsymbol
- def BRCALL_IPREL_ES : RawForm<0x03, 0xb0, (outs), (ins calltarget:$dst),
- "br.call.sptk rp = $dst">, isB; // FIXME: teach llvm about branch regs?
-// calls through a function descriptor
- def BRCALL_INDIRECT : RawForm<0x03, 0xb0, (outs), (ins GR:$branchreg),
- "br.call.sptk rp = $branchreg">, isB; // FIXME: teach llvm about branch regs?
- def BRLCOND_CALL : RawForm<0x03, 0xb0, (outs), (ins PR:$qp, i64imm:$dst),
- "($qp) brl.cond.call.sptk $dst">, isB;
- def BRCOND_CALL : RawForm<0x03, 0xb0, (outs), (ins PR:$qp, GR:$dst),
- "($qp) br.cond.call.sptk $dst">, isB;
-}
-
-// Return branch:
-let isTerminator = 1, isReturn = 1 in
- def RET : AForm_DAG<0x03, 0x0b, (outs), (ins),
- "br.ret.sptk.many rp",
- [(retflag)]>, isB; // return
-def : Pat<(ret), (RET)>;
-
-// the evil stop bit of despair
-def STOP : PseudoInstIA64<(outs), (ins variable_ops), ";;">;
-
diff --git a/lib/Target/IA64/IA64MachineFunctionInfo.h b/lib/Target/IA64/IA64MachineFunctionInfo.h
deleted file mode 100644
index e6254d6..0000000
--- a/lib/Target/IA64/IA64MachineFunctionInfo.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===-- IA64MachineFunctionInfo.h - IA64-specific information ---*- C++ -*-===//
-//===-- for MachineFunction ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares IA64-specific per-machine-function information.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef IA64MACHINEFUNCTIONINFO_H
-#define IA64MACHINEFUNCTIONINFO_H
-
-#include "llvm/CodeGen/MachineFunction.h"
-//#include "IA64JITInfo.h"
-
-namespace llvm {
-
-class IA64FunctionInfo : public MachineFunctionInfo {
-
-public:
- unsigned outRegsUsed; // how many 'out' registers are used
- // by this machinefunction? (used to compute the appropriate
- // entry in the 'alloc' instruction at the top of the
- // machinefunction)
- explicit IA64FunctionInfo(MachineFunction& MF) { outRegsUsed=0; };
-
-};
-
-} // End llvm namespace
-
-#endif
-
diff --git a/lib/Target/IA64/IA64RegisterInfo.cpp b/lib/Target/IA64/IA64RegisterInfo.cpp
deleted file mode 100644
index 7ad6f51..0000000
--- a/lib/Target/IA64/IA64RegisterInfo.cpp
+++ /dev/null
@@ -1,319 +0,0 @@
-//===- IA64RegisterInfo.cpp - IA64 Register Information ---------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the IA64 implementation of the TargetRegisterInfo class.
-// This file is responsible for the frame pointer elimination optimization
-// on IA64.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IA64.h"
-#include "IA64RegisterInfo.h"
-#include "IA64InstrBuilder.h"
-#include "IA64MachineFunctionInfo.h"
-#include "llvm/Constants.h"
-#include "llvm/Type.h"
-#include "llvm/CodeGen/ValueTypes.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineLocation.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Target/TargetFrameInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/STLExtras.h"
-using namespace llvm;
-
-IA64RegisterInfo::IA64RegisterInfo(const TargetInstrInfo &tii)
- : IA64GenRegisterInfo(IA64::ADJUSTCALLSTACKDOWN, IA64::ADJUSTCALLSTACKUP),
- TII(tii) {}
-
-const unsigned* IA64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
- const {
- static const unsigned CalleeSavedRegs[] = {
- IA64::r5, 0
- };
- return CalleeSavedRegs;
-}
-
-const TargetRegisterClass* const*
-IA64RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
- static const TargetRegisterClass * const CalleeSavedRegClasses[] = {
- &IA64::GRRegClass, 0
- };
- return CalleeSavedRegClasses;
-}
-
-BitVector IA64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
- BitVector Reserved(getNumRegs());
- Reserved.set(IA64::r0);
- Reserved.set(IA64::r1);
- Reserved.set(IA64::r2);
- Reserved.set(IA64::r5);
- Reserved.set(IA64::r12);
- Reserved.set(IA64::r13);
- Reserved.set(IA64::r22);
- Reserved.set(IA64::rp);
- return Reserved;
-}
-
-//===----------------------------------------------------------------------===//
-// Stack Frame Processing methods
-//===----------------------------------------------------------------------===//
-
-// hasFP - Return true if the specified function should have a dedicated frame
-// pointer register. This is true if the function has variable sized allocas or
-// if frame pointer elimination is disabled.
-//
-bool IA64RegisterInfo::hasFP(const MachineFunction &MF) const {
- const MachineFrameInfo *MFI = MF.getFrameInfo();
- return NoFramePointerElim || MFI->hasVarSizedObjects();
-}
-
-void IA64RegisterInfo::
-eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I) const {
- if (hasFP(MF)) {
- // If we have a frame pointer, turn the adjcallstackup instruction into a
- // 'sub SP, <amt>' and the adjcallstackdown instruction into 'add SP,
- // <amt>'
- MachineInstr *Old = I;
- unsigned Amount = Old->getOperand(0).getImm();
- DebugLoc dl = Old->getDebugLoc();
- if (Amount != 0) {
- // We need to keep the stack aligned properly. To do this, we round the
- // amount of space needed for the outgoing arguments up to the next
- // alignment boundary.
- unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
- Amount = (Amount+Align-1)/Align*Align;
-
- // Replace the pseudo instruction with a new instruction...
- if (Old->getOpcode() == IA64::ADJUSTCALLSTACKDOWN) {
- BuildMI(MBB, I, dl, TII.get(IA64::ADDIMM22), IA64::r12)
- .addReg(IA64::r12).addImm(-Amount);
- } else {
- assert(Old->getOpcode() == IA64::ADJUSTCALLSTACKUP);
- BuildMI(MBB, I, dl, TII.get(IA64::ADDIMM22), IA64::r12)
- .addReg(IA64::r12).addImm(Amount);
- }
- }
- }
-
- MBB.erase(I);
-}
-
-void IA64RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
- int SPAdj, RegScavenger *RS)const{
- assert(SPAdj == 0 && "Unexpected");
-
- unsigned i = 0;
- MachineInstr &MI = *II;
- MachineBasicBlock &MBB = *MI.getParent();
- MachineFunction &MF = *MBB.getParent();
- DebugLoc dl = MI.getDebugLoc();
-
- bool FP = hasFP(MF);
-
- while (!MI.getOperand(i).isFI()) {
- ++i;
- assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
- }
-
- int FrameIndex = MI.getOperand(i).getIndex();
-
- // choose a base register: ( hasFP? framepointer : stack pointer )
- unsigned BaseRegister = FP ? IA64::r5 : IA64::r12;
- // Add the base register
- MI.getOperand(i).ChangeToRegister(BaseRegister, false);
-
- // Now add the frame object offset to the offset from r1.
- int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
-
- // If we're not using a Frame Pointer that has been set to the value of the
- // SP before having the stack size subtracted from it, then add the stack size
- // to Offset to get the correct offset.
- Offset += MF.getFrameInfo()->getStackSize();
-
- // XXX: we use 'r22' as another hack+slash temporary register here :(
- if (Offset <= 8191 && Offset >= -8192) { // smallish offset
- // Fix up the old:
- MI.getOperand(i).ChangeToRegister(IA64::r22, false);
- //insert the new
- BuildMI(MBB, II, dl, TII.get(IA64::ADDIMM22), IA64::r22)
- .addReg(BaseRegister).addImm(Offset);
- } else { // it's big
- //fix up the old:
- MI.getOperand(i).ChangeToRegister(IA64::r22, false);
- BuildMI(MBB, II, dl, TII.get(IA64::MOVLIMM64), IA64::r22).addImm(Offset);
- BuildMI(MBB, II, dl, TII.get(IA64::ADD), IA64::r22).addReg(BaseRegister)
- .addReg(IA64::r22);
- }
-
-}
-
-void IA64RegisterInfo::emitPrologue(MachineFunction &MF) const {
- MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
- MachineBasicBlock::iterator MBBI = MBB.begin();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- bool FP = hasFP(MF);
- DebugLoc dl = (MBBI != MBB.end() ?
- MBBI->getDebugLoc() : DebugLoc::getUnknownLoc());
-
- // first, we handle the 'alloc' instruction, that should be right up the
- // top of any function
- static const unsigned RegsInOrder[96] = { // there are 96 GPRs the
- // RSE worries about
- IA64::r32, IA64::r33, IA64::r34, IA64::r35,
- IA64::r36, IA64::r37, IA64::r38, IA64::r39, IA64::r40, IA64::r41,
- IA64::r42, IA64::r43, IA64::r44, IA64::r45, IA64::r46, IA64::r47,
- IA64::r48, IA64::r49, IA64::r50, IA64::r51, IA64::r52, IA64::r53,
- IA64::r54, IA64::r55, IA64::r56, IA64::r57, IA64::r58, IA64::r59,
- IA64::r60, IA64::r61, IA64::r62, IA64::r63, IA64::r64, IA64::r65,
- IA64::r66, IA64::r67, IA64::r68, IA64::r69, IA64::r70, IA64::r71,
- IA64::r72, IA64::r73, IA64::r74, IA64::r75, IA64::r76, IA64::r77,
- IA64::r78, IA64::r79, IA64::r80, IA64::r81, IA64::r82, IA64::r83,
- IA64::r84, IA64::r85, IA64::r86, IA64::r87, IA64::r88, IA64::r89,
- IA64::r90, IA64::r91, IA64::r92, IA64::r93, IA64::r94, IA64::r95,
- IA64::r96, IA64::r97, IA64::r98, IA64::r99, IA64::r100, IA64::r101,
- IA64::r102, IA64::r103, IA64::r104, IA64::r105, IA64::r106, IA64::r107,
- IA64::r108, IA64::r109, IA64::r110, IA64::r111, IA64::r112, IA64::r113,
- IA64::r114, IA64::r115, IA64::r116, IA64::r117, IA64::r118, IA64::r119,
- IA64::r120, IA64::r121, IA64::r122, IA64::r123, IA64::r124, IA64::r125,
- IA64::r126, IA64::r127 };
-
- unsigned numStackedGPRsUsed=0;
- for (int i=0; i != 96; i++) {
- if (MF.getRegInfo().isPhysRegUsed(RegsInOrder[i]))
- numStackedGPRsUsed=i+1; // (i+1 and not ++ - consider fn(fp, fp, int)
- }
-
- unsigned numOutRegsUsed=MF.getInfo<IA64FunctionInfo>()->outRegsUsed;
-
- // XXX FIXME : this code should be a bit more reliable (in case there _isn't_
- // a pseudo_alloc in the MBB)
- unsigned dstRegOfPseudoAlloc;
- for(MBBI = MBB.begin(); /*MBBI->getOpcode() != IA64::PSEUDO_ALLOC*/; ++MBBI) {
- assert(MBBI != MBB.end());
- if(MBBI->getOpcode() == IA64::PSEUDO_ALLOC) {
- dstRegOfPseudoAlloc=MBBI->getOperand(0).getReg();
- break;
- }
- }
-
- if (MBBI != MBB.end()) dl = MBBI->getDebugLoc();
-
- BuildMI(MBB, MBBI, dl, TII.get(IA64::ALLOC)).
- addReg(dstRegOfPseudoAlloc).addImm(0).
- addImm(numStackedGPRsUsed).addImm(numOutRegsUsed).addImm(0);
-
- // Get the number of bytes to allocate from the FrameInfo
- unsigned NumBytes = MFI->getStackSize();
-
- if(FP)
- NumBytes += 8; // reserve space for the old FP
-
- // Do we need to allocate space on the stack?
- if (NumBytes == 0)
- return;
-
- // Add 16 bytes at the bottom of the stack (scratch area)
- // and round the size to a multiple of the alignment.
- unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
- unsigned Size = 16 + (FP ? 8 : 0);
- NumBytes = (NumBytes+Size+Align-1)/Align*Align;
-
- // Update frame info to pretend that this is part of the stack...
- MFI->setStackSize(NumBytes);
-
- // adjust stack pointer: r12 -= numbytes
- if (NumBytes <= 8191) {
- BuildMI(MBB, MBBI, dl, TII.get(IA64::ADDIMM22),IA64::r12).addReg(IA64::r12).
- addImm(-NumBytes);
- } else { // we use r22 as a scratch register here
- // first load the decrement into r22
- BuildMI(MBB, MBBI, dl, TII.get(IA64::MOVLIMM64), IA64::r22).
- addImm(-NumBytes);
- // FIXME: MOVLSI32 expects a _u_32imm
- // then add (subtract) it to r12 (stack ptr)
- BuildMI(MBB, MBBI, dl, TII.get(IA64::ADD), IA64::r12)
- .addReg(IA64::r12).addReg(IA64::r22);
-
- }
-
- // now if we need to, save the old FP and set the new
- if (FP) {
- BuildMI(MBB, MBBI,dl,TII.get(IA64::ST8)).addReg(IA64::r12).addReg(IA64::r5);
- // this must be the last instr in the prolog ? (XXX: why??)
- BuildMI(MBB, MBBI, dl, TII.get(IA64::MOV), IA64::r5).addReg(IA64::r12);
- }
-
-}
-
-void IA64RegisterInfo::emitEpilogue(MachineFunction &MF,
- MachineBasicBlock &MBB) const {
- const MachineFrameInfo *MFI = MF.getFrameInfo();
- MachineBasicBlock::iterator MBBI = prior(MBB.end());
- assert(MBBI->getOpcode() == IA64::RET &&
- "Can only insert epilog into returning blocks");
- DebugLoc dl = MBBI->getDebugLoc();
- bool FP = hasFP(MF);
-
- // Get the number of bytes allocated from the FrameInfo...
- unsigned NumBytes = MFI->getStackSize();
-
- //now if we need to, restore the old FP
- if (FP) {
- //copy the FP into the SP (discards allocas)
- BuildMI(MBB, MBBI, dl, TII.get(IA64::MOV), IA64::r12).addReg(IA64::r5);
- //restore the FP
- BuildMI(MBB, MBBI, dl, TII.get(IA64::LD8), IA64::r5).addReg(IA64::r5);
- }
-
- if (NumBytes != 0) {
- if (NumBytes <= 8191) {
- BuildMI(MBB, MBBI, dl, TII.get(IA64::ADDIMM22),IA64::r12).
- addReg(IA64::r12).addImm(NumBytes);
- } else {
- BuildMI(MBB, MBBI, dl, TII.get(IA64::MOVLIMM64), IA64::r22).
- addImm(NumBytes);
- BuildMI(MBB, MBBI, dl, TII.get(IA64::ADD), IA64::r12).addReg(IA64::r12).
- addReg(IA64::r22);
- }
- }
-}
-
-unsigned IA64RegisterInfo::getRARegister() const {
- assert(0 && "What is the return address register");
- return 0;
-}
-
-unsigned IA64RegisterInfo::getFrameRegister(MachineFunction &MF) const {
- return hasFP(MF) ? IA64::r5 : IA64::r12;
-}
-
-unsigned IA64RegisterInfo::getEHExceptionRegister() const {
- assert(0 && "What is the exception register");
- return 0;
-}
-
-unsigned IA64RegisterInfo::getEHHandlerRegister() const {
- assert(0 && "What is the exception handler register");
- return 0;
-}
-
-int IA64RegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
- assert(0 && "What is the dwarf register number");
- return -1;
-}
-
-#include "IA64GenRegisterInfo.inc"
-
diff --git a/lib/Target/IA64/IA64RegisterInfo.h b/lib/Target/IA64/IA64RegisterInfo.h
deleted file mode 100644
index 0c5083e..0000000
--- a/lib/Target/IA64/IA64RegisterInfo.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===- IA64RegisterInfo.h - IA64 Register Information Impl ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the IA64 implementation of the TargetRegisterInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef IA64REGISTERINFO_H
-#define IA64REGISTERINFO_H
-
-#include "llvm/Target/TargetRegisterInfo.h"
-#include "IA64GenRegisterInfo.h.inc"
-
-namespace llvm {
-
-class TargetInstrInfo;
-
-struct IA64RegisterInfo : public IA64GenRegisterInfo {
- const TargetInstrInfo &TII;
-
- IA64RegisterInfo(const TargetInstrInfo &tii);
-
- /// Code Generation virtual methods...
- const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const;
-
- const TargetRegisterClass* const* getCalleeSavedRegClasses(
- const MachineFunction *MF = 0) const;
-
- BitVector getReservedRegs(const MachineFunction &MF) const;
-
- bool hasFP(const MachineFunction &MF) const;
-
- void eliminateCallFramePseudoInstr(MachineFunction &MF,
- MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI) const;
-
- void eliminateFrameIndex(MachineBasicBlock::iterator MI,
- int SPAdj, RegScavenger *RS = NULL) const;
-
- void emitPrologue(MachineFunction &MF) const;
- void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
-
- // Debug information queries.
- unsigned getRARegister() const;
- unsigned getFrameRegister(MachineFunction &MF) const;
-
- // Exception handling queries.
- unsigned getEHExceptionRegister() const;
- unsigned getEHHandlerRegister() const;
-
- int getDwarfRegNum(unsigned RegNum, bool isEH) const;
-};
-
-} // End llvm namespace
-
-#endif
-
diff --git a/lib/Target/IA64/IA64RegisterInfo.td b/lib/Target/IA64/IA64RegisterInfo.td
deleted file mode 100644
index dd72dc3..0000000
--- a/lib/Target/IA64/IA64RegisterInfo.td
+++ /dev/null
@@ -1,509 +0,0 @@
-//===- IA64RegisterInfo.td - Describe the IA64 Register File ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file describes the IA64 register file, defining the registers
-// themselves, aliases between the registers, and the register classes built
-// out of the registers.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Register definitions...
-//
-
-class IA64Register<string n> : Register<n> {
- let Namespace = "IA64";
-}
-
-// GR - One of 128 32-bit general registers
-class GR<bits<7> num, string n> : IA64Register<n> {
- field bits<7> Num = num;
-}
-
-// FP - One of 128 82-bit floating-point registers
-class FP<bits<7> num, string n> : IA64Register<n> {
- field bits<7> Num = num;
-}
-
-// PR - One of 64 1-bit predicate registers
-class PR<bits<6> num, string n> : IA64Register<n> {
- field bits<6> Num = num;
-}
-
-/* general registers */
-def r0 : GR< 0, "r0">, DwarfRegNum<[0]>;
-def r1 : GR< 1, "r1">, DwarfRegNum<[1]>;
-def r2 : GR< 2, "r2">, DwarfRegNum<[2]>;
-def r3 : GR< 3, "r3">, DwarfRegNum<[3]>;
-def r4 : GR< 4, "r4">, DwarfRegNum<[4]>;
-def r5 : GR< 5, "r5">, DwarfRegNum<[5]>;
-def r6 : GR< 6, "r6">, DwarfRegNum<[6]>;
-def r7 : GR< 7, "r7">, DwarfRegNum<[7]>;
-def r8 : GR< 8, "r8">, DwarfRegNum<[8]>;
-def r9 : GR< 9, "r9">, DwarfRegNum<[9]>;
-def r10 : GR< 10, "r10">, DwarfRegNum<[10]>;
-def r11 : GR< 11, "r11">, DwarfRegNum<[11]>;
-def r12 : GR< 12, "r12">, DwarfRegNum<[12]>;
-def r13 : GR< 13, "r13">, DwarfRegNum<[13]>;
-def r14 : GR< 14, "r14">, DwarfRegNum<[14]>;
-def r15 : GR< 15, "r15">, DwarfRegNum<[15]>;
-def r16 : GR< 16, "r16">, DwarfRegNum<[16]>;
-def r17 : GR< 17, "r17">, DwarfRegNum<[17]>;
-def r18 : GR< 18, "r18">, DwarfRegNum<[18]>;
-def r19 : GR< 19, "r19">, DwarfRegNum<[19]>;
-def r20 : GR< 20, "r20">, DwarfRegNum<[20]>;
-def r21 : GR< 21, "r21">, DwarfRegNum<[21]>;
-def r22 : GR< 22, "r22">, DwarfRegNum<[22]>;
-def r23 : GR< 23, "r23">, DwarfRegNum<[23]>;
-def r24 : GR< 24, "r24">, DwarfRegNum<[24]>;
-def r25 : GR< 25, "r25">, DwarfRegNum<[25]>;
-def r26 : GR< 26, "r26">, DwarfRegNum<[26]>;
-def r27 : GR< 27, "r27">, DwarfRegNum<[27]>;
-def r28 : GR< 28, "r28">, DwarfRegNum<[28]>;
-def r29 : GR< 29, "r29">, DwarfRegNum<[29]>;
-def r30 : GR< 30, "r30">, DwarfRegNum<[30]>;
-def r31 : GR< 31, "r31">, DwarfRegNum<[31]>;
-def r32 : GR< 32, "r32">, DwarfRegNum<[32]>;
-def r33 : GR< 33, "r33">, DwarfRegNum<[33]>;
-def r34 : GR< 34, "r34">, DwarfRegNum<[34]>;
-def r35 : GR< 35, "r35">, DwarfRegNum<[35]>;
-def r36 : GR< 36, "r36">, DwarfRegNum<[36]>;
-def r37 : GR< 37, "r37">, DwarfRegNum<[37]>;
-def r38 : GR< 38, "r38">, DwarfRegNum<[38]>;
-def r39 : GR< 39, "r39">, DwarfRegNum<[39]>;
-def r40 : GR< 40, "r40">, DwarfRegNum<[40]>;
-def r41 : GR< 41, "r41">, DwarfRegNum<[41]>;
-def r42 : GR< 42, "r42">, DwarfRegNum<[42]>;
-def r43 : GR< 43, "r43">, DwarfRegNum<[43]>;
-def r44 : GR< 44, "r44">, DwarfRegNum<[44]>;
-def r45 : GR< 45, "r45">, DwarfRegNum<[45]>;
-def r46 : GR< 46, "r46">, DwarfRegNum<[46]>;
-def r47 : GR< 47, "r47">, DwarfRegNum<[47]>;
-def r48 : GR< 48, "r48">, DwarfRegNum<[48]>;
-def r49 : GR< 49, "r49">, DwarfRegNum<[49]>;
-def r50 : GR< 50, "r50">, DwarfRegNum<[50]>;
-def r51 : GR< 51, "r51">, DwarfRegNum<[51]>;
-def r52 : GR< 52, "r52">, DwarfRegNum<[52]>;
-def r53 : GR< 53, "r53">, DwarfRegNum<[53]>;
-def r54 : GR< 54, "r54">, DwarfRegNum<[54]>;
-def r55 : GR< 55, "r55">, DwarfRegNum<[55]>;
-def r56 : GR< 56, "r56">, DwarfRegNum<[56]>;
-def r57 : GR< 57, "r57">, DwarfRegNum<[57]>;
-def r58 : GR< 58, "r58">, DwarfRegNum<[58]>;
-def r59 : GR< 59, "r59">, DwarfRegNum<[59]>;
-def r60 : GR< 60, "r60">, DwarfRegNum<[60]>;
-def r61 : GR< 61, "r61">, DwarfRegNum<[61]>;
-def r62 : GR< 62, "r62">, DwarfRegNum<[62]>;
-def r63 : GR< 63, "r63">, DwarfRegNum<[63]>;
-def r64 : GR< 64, "r64">, DwarfRegNum<[64]>;
-def r65 : GR< 65, "r65">, DwarfRegNum<[65]>;
-def r66 : GR< 66, "r66">, DwarfRegNum<[66]>;
-def r67 : GR< 67, "r67">, DwarfRegNum<[67]>;
-def r68 : GR< 68, "r68">, DwarfRegNum<[68]>;
-def r69 : GR< 69, "r69">, DwarfRegNum<[69]>;
-def r70 : GR< 70, "r70">, DwarfRegNum<[70]>;
-def r71 : GR< 71, "r71">, DwarfRegNum<[71]>;
-def r72 : GR< 72, "r72">, DwarfRegNum<[72]>;
-def r73 : GR< 73, "r73">, DwarfRegNum<[73]>;
-def r74 : GR< 74, "r74">, DwarfRegNum<[74]>;
-def r75 : GR< 75, "r75">, DwarfRegNum<[75]>;
-def r76 : GR< 76, "r76">, DwarfRegNum<[76]>;
-def r77 : GR< 77, "r77">, DwarfRegNum<[77]>;
-def r78 : GR< 78, "r78">, DwarfRegNum<[78]>;
-def r79 : GR< 79, "r79">, DwarfRegNum<[79]>;
-def r80 : GR< 80, "r80">, DwarfRegNum<[80]>;
-def r81 : GR< 81, "r81">, DwarfRegNum<[81]>;
-def r82 : GR< 82, "r82">, DwarfRegNum<[82]>;
-def r83 : GR< 83, "r83">, DwarfRegNum<[83]>;
-def r84 : GR< 84, "r84">, DwarfRegNum<[84]>;
-def r85 : GR< 85, "r85">, DwarfRegNum<[85]>;
-def r86 : GR< 86, "r86">, DwarfRegNum<[86]>;
-def r87 : GR< 87, "r87">, DwarfRegNum<[87]>;
-def r88 : GR< 88, "r88">, DwarfRegNum<[88]>;
-def r89 : GR< 89, "r89">, DwarfRegNum<[89]>;
-def r90 : GR< 90, "r90">, DwarfRegNum<[90]>;
-def r91 : GR< 91, "r91">, DwarfRegNum<[91]>;
-def r92 : GR< 92, "r92">, DwarfRegNum<[92]>;
-def r93 : GR< 93, "r93">, DwarfRegNum<[93]>;
-def r94 : GR< 94, "r94">, DwarfRegNum<[94]>;
-def r95 : GR< 95, "r95">, DwarfRegNum<[95]>;
-def r96 : GR< 96, "r96">, DwarfRegNum<[96]>;
-def r97 : GR< 97, "r97">, DwarfRegNum<[97]>;
-def r98 : GR< 98, "r98">, DwarfRegNum<[98]>;
-def r99 : GR< 99, "r99">, DwarfRegNum<[99]>;
-def r100 : GR< 100, "r100">, DwarfRegNum<[100]>;
-def r101 : GR< 101, "r101">, DwarfRegNum<[101]>;
-def r102 : GR< 102, "r102">, DwarfRegNum<[102]>;
-def r103 : GR< 103, "r103">, DwarfRegNum<[103]>;
-def r104 : GR< 104, "r104">, DwarfRegNum<[104]>;
-def r105 : GR< 105, "r105">, DwarfRegNum<[105]>;
-def r106 : GR< 106, "r106">, DwarfRegNum<[106]>;
-def r107 : GR< 107, "r107">, DwarfRegNum<[107]>;
-def r108 : GR< 108, "r108">, DwarfRegNum<[108]>;
-def r109 : GR< 109, "r109">, DwarfRegNum<[109]>;
-def r110 : GR< 110, "r110">, DwarfRegNum<[110]>;
-def r111 : GR< 111, "r111">, DwarfRegNum<[111]>;
-def r112 : GR< 112, "r112">, DwarfRegNum<[112]>;
-def r113 : GR< 113, "r113">, DwarfRegNum<[113]>;
-def r114 : GR< 114, "r114">, DwarfRegNum<[114]>;
-def r115 : GR< 115, "r115">, DwarfRegNum<[115]>;
-def r116 : GR< 116, "r116">, DwarfRegNum<[116]>;
-def r117 : GR< 117, "r117">, DwarfRegNum<[117]>;
-def r118 : GR< 118, "r118">, DwarfRegNum<[118]>;
-def r119 : GR< 119, "r119">, DwarfRegNum<[119]>;
-def r120 : GR< 120, "r120">, DwarfRegNum<[120]>;
-def r121 : GR< 121, "r121">, DwarfRegNum<[121]>;
-def r122 : GR< 122, "r122">, DwarfRegNum<[122]>;
-def r123 : GR< 123, "r123">, DwarfRegNum<[123]>;
-def r124 : GR< 124, "r124">, DwarfRegNum<[124]>;
-def r125 : GR< 125, "r125">, DwarfRegNum<[125]>;
-def r126 : GR< 126, "r126">, DwarfRegNum<[126]>;
-def r127 : GR< 127, "r127">, DwarfRegNum<[127]>;
-
-/* floating-point registers */
-def F0 : FP< 0, "f0">, DwarfRegNum<[128]>;
-def F1 : FP< 1, "f1">, DwarfRegNum<[129]>;
-def F2 : FP< 2, "f2">, DwarfRegNum<[130]>;
-def F3 : FP< 3, "f3">, DwarfRegNum<[131]>;
-def F4 : FP< 4, "f4">, DwarfRegNum<[132]>;
-def F5 : FP< 5, "f5">, DwarfRegNum<[133]>;
-def F6 : FP< 6, "f6">, DwarfRegNum<[134]>;
-def F7 : FP< 7, "f7">, DwarfRegNum<[135]>;
-def F8 : FP< 8, "f8">, DwarfRegNum<[136]>;
-def F9 : FP< 9, "f9">, DwarfRegNum<[137]>;
-def F10 : FP< 10, "f10">, DwarfRegNum<[138]>;
-def F11 : FP< 11, "f11">, DwarfRegNum<[139]>;
-def F12 : FP< 12, "f12">, DwarfRegNum<[140]>;
-def F13 : FP< 13, "f13">, DwarfRegNum<[141]>;
-def F14 : FP< 14, "f14">, DwarfRegNum<[142]>;
-def F15 : FP< 15, "f15">, DwarfRegNum<[143]>;
-def F16 : FP< 16, "f16">, DwarfRegNum<[144]>;
-def F17 : FP< 17, "f17">, DwarfRegNum<[145]>;
-def F18 : FP< 18, "f18">, DwarfRegNum<[146]>;
-def F19 : FP< 19, "f19">, DwarfRegNum<[147]>;
-def F20 : FP< 20, "f20">, DwarfRegNum<[148]>;
-def F21 : FP< 21, "f21">, DwarfRegNum<[149]>;
-def F22 : FP< 22, "f22">, DwarfRegNum<[150]>;
-def F23 : FP< 23, "f23">, DwarfRegNum<[151]>;
-def F24 : FP< 24, "f24">, DwarfRegNum<[152]>;
-def F25 : FP< 25, "f25">, DwarfRegNum<[153]>;
-def F26 : FP< 26, "f26">, DwarfRegNum<[154]>;
-def F27 : FP< 27, "f27">, DwarfRegNum<[155]>;
-def F28 : FP< 28, "f28">, DwarfRegNum<[156]>;
-def F29 : FP< 29, "f29">, DwarfRegNum<[157]>;
-def F30 : FP< 30, "f30">, DwarfRegNum<[158]>;
-def F31 : FP< 31, "f31">, DwarfRegNum<[159]>;
-def F32 : FP< 32, "f32">, DwarfRegNum<[160]>;
-def F33 : FP< 33, "f33">, DwarfRegNum<[161]>;
-def F34 : FP< 34, "f34">, DwarfRegNum<[162]>;
-def F35 : FP< 35, "f35">, DwarfRegNum<[163]>;
-def F36 : FP< 36, "f36">, DwarfRegNum<[164]>;
-def F37 : FP< 37, "f37">, DwarfRegNum<[165]>;
-def F38 : FP< 38, "f38">, DwarfRegNum<[166]>;
-def F39 : FP< 39, "f39">, DwarfRegNum<[167]>;
-def F40 : FP< 40, "f40">, DwarfRegNum<[168]>;
-def F41 : FP< 41, "f41">, DwarfRegNum<[169]>;
-def F42 : FP< 42, "f42">, DwarfRegNum<[170]>;
-def F43 : FP< 43, "f43">, DwarfRegNum<[171]>;
-def F44 : FP< 44, "f44">, DwarfRegNum<[172]>;
-def F45 : FP< 45, "f45">, DwarfRegNum<[173]>;
-def F46 : FP< 46, "f46">, DwarfRegNum<[174]>;
-def F47 : FP< 47, "f47">, DwarfRegNum<[175]>;
-def F48 : FP< 48, "f48">, DwarfRegNum<[176]>;
-def F49 : FP< 49, "f49">, DwarfRegNum<[177]>;
-def F50 : FP< 50, "f50">, DwarfRegNum<[178]>;
-def F51 : FP< 51, "f51">, DwarfRegNum<[179]>;
-def F52 : FP< 52, "f52">, DwarfRegNum<[180]>;
-def F53 : FP< 53, "f53">, DwarfRegNum<[181]>;
-def F54 : FP< 54, "f54">, DwarfRegNum<[182]>;
-def F55 : FP< 55, "f55">, DwarfRegNum<[183]>;
-def F56 : FP< 56, "f56">, DwarfRegNum<[184]>;
-def F57 : FP< 57, "f57">, DwarfRegNum<[185]>;
-def F58 : FP< 58, "f58">, DwarfRegNum<[186]>;
-def F59 : FP< 59, "f59">, DwarfRegNum<[187]>;
-def F60 : FP< 60, "f60">, DwarfRegNum<[188]>;
-def F61 : FP< 61, "f61">, DwarfRegNum<[189]>;
-def F62 : FP< 62, "f62">, DwarfRegNum<[190]>;
-def F63 : FP< 63, "f63">, DwarfRegNum<[191]>;
-def F64 : FP< 64, "f64">, DwarfRegNum<[192]>;
-def F65 : FP< 65, "f65">, DwarfRegNum<[193]>;
-def F66 : FP< 66, "f66">, DwarfRegNum<[194]>;
-def F67 : FP< 67, "f67">, DwarfRegNum<[195]>;
-def F68 : FP< 68, "f68">, DwarfRegNum<[196]>;
-def F69 : FP< 69, "f69">, DwarfRegNum<[197]>;
-def F70 : FP< 70, "f70">, DwarfRegNum<[198]>;
-def F71 : FP< 71, "f71">, DwarfRegNum<[199]>;
-def F72 : FP< 72, "f72">, DwarfRegNum<[200]>;
-def F73 : FP< 73, "f73">, DwarfRegNum<[201]>;
-def F74 : FP< 74, "f74">, DwarfRegNum<[202]>;
-def F75 : FP< 75, "f75">, DwarfRegNum<[203]>;
-def F76 : FP< 76, "f76">, DwarfRegNum<[204]>;
-def F77 : FP< 77, "f77">, DwarfRegNum<[205]>;
-def F78 : FP< 78, "f78">, DwarfRegNum<[206]>;
-def F79 : FP< 79, "f79">, DwarfRegNum<[207]>;
-def F80 : FP< 80, "f80">, DwarfRegNum<[208]>;
-def F81 : FP< 81, "f81">, DwarfRegNum<[209]>;
-def F82 : FP< 82, "f82">, DwarfRegNum<[210]>;
-def F83 : FP< 83, "f83">, DwarfRegNum<[211]>;
-def F84 : FP< 84, "f84">, DwarfRegNum<[212]>;
-def F85 : FP< 85, "f85">, DwarfRegNum<[213]>;
-def F86 : FP< 86, "f86">, DwarfRegNum<[214]>;
-def F87 : FP< 87, "f87">, DwarfRegNum<[215]>;
-def F88 : FP< 88, "f88">, DwarfRegNum<[216]>;
-def F89 : FP< 89, "f89">, DwarfRegNum<[217]>;
-def F90 : FP< 90, "f90">, DwarfRegNum<[218]>;
-def F91 : FP< 91, "f91">, DwarfRegNum<[219]>;
-def F92 : FP< 92, "f92">, DwarfRegNum<[220]>;
-def F93 : FP< 93, "f93">, DwarfRegNum<[221]>;
-def F94 : FP< 94, "f94">, DwarfRegNum<[222]>;
-def F95 : FP< 95, "f95">, DwarfRegNum<[223]>;
-def F96 : FP< 96, "f96">, DwarfRegNum<[224]>;
-def F97 : FP< 97, "f97">, DwarfRegNum<[225]>;
-def F98 : FP< 98, "f98">, DwarfRegNum<[226]>;
-def F99 : FP< 99, "f99">, DwarfRegNum<[227]>;
-def F100 : FP< 100, "f100">, DwarfRegNum<[228]>;
-def F101 : FP< 101, "f101">, DwarfRegNum<[229]>;
-def F102 : FP< 102, "f102">, DwarfRegNum<[230]>;
-def F103 : FP< 103, "f103">, DwarfRegNum<[231]>;
-def F104 : FP< 104, "f104">, DwarfRegNum<[232]>;
-def F105 : FP< 105, "f105">, DwarfRegNum<[233]>;
-def F106 : FP< 106, "f106">, DwarfRegNum<[234]>;
-def F107 : FP< 107, "f107">, DwarfRegNum<[235]>;
-def F108 : FP< 108, "f108">, DwarfRegNum<[236]>;
-def F109 : FP< 109, "f109">, DwarfRegNum<[237]>;
-def F110 : FP< 110, "f110">, DwarfRegNum<[238]>;
-def F111 : FP< 111, "f111">, DwarfRegNum<[239]>;
-def F112 : FP< 112, "f112">, DwarfRegNum<[240]>;
-def F113 : FP< 113, "f113">, DwarfRegNum<[241]>;
-def F114 : FP< 114, "f114">, DwarfRegNum<[242]>;
-def F115 : FP< 115, "f115">, DwarfRegNum<[243]>;
-def F116 : FP< 116, "f116">, DwarfRegNum<[244]>;
-def F117 : FP< 117, "f117">, DwarfRegNum<[245]>;
-def F118 : FP< 118, "f118">, DwarfRegNum<[246]>;
-def F119 : FP< 119, "f119">, DwarfRegNum<[247]>;
-def F120 : FP< 120, "f120">, DwarfRegNum<[248]>;
-def F121 : FP< 121, "f121">, DwarfRegNum<[249]>;
-def F122 : FP< 122, "f122">, DwarfRegNum<[250]>;
-def F123 : FP< 123, "f123">, DwarfRegNum<[251]>;
-def F124 : FP< 124, "f124">, DwarfRegNum<[252]>;
-def F125 : FP< 125, "f125">, DwarfRegNum<[253]>;
-def F126 : FP< 126, "f126">, DwarfRegNum<[254]>;
-def F127 : FP< 127, "f127">, DwarfRegNum<[255]>;
-
-/* predicate registers */
-def p0 : PR< 0, "p0">, DwarfRegNum<[256]>;
-def p1 : PR< 1, "p1">, DwarfRegNum<[257]>;
-def p2 : PR< 2, "p2">, DwarfRegNum<[258]>;
-def p3 : PR< 3, "p3">, DwarfRegNum<[259]>;
-def p4 : PR< 4, "p4">, DwarfRegNum<[260]>;
-def p5 : PR< 5, "p5">, DwarfRegNum<[261]>;
-def p6 : PR< 6, "p6">, DwarfRegNum<[262]>;
-def p7 : PR< 7, "p7">, DwarfRegNum<[263]>;
-def p8 : PR< 8, "p8">, DwarfRegNum<[264]>;
-def p9 : PR< 9, "p9">, DwarfRegNum<[265]>;
-def p10 : PR< 10, "p10">, DwarfRegNum<[266]>;
-def p11 : PR< 11, "p11">, DwarfRegNum<[267]>;
-def p12 : PR< 12, "p12">, DwarfRegNum<[268]>;
-def p13 : PR< 13, "p13">, DwarfRegNum<[269]>;
-def p14 : PR< 14, "p14">, DwarfRegNum<[270]>;
-def p15 : PR< 15, "p15">, DwarfRegNum<[271]>;
-def p16 : PR< 16, "p16">, DwarfRegNum<[272]>;
-def p17 : PR< 17, "p17">, DwarfRegNum<[273]>;
-def p18 : PR< 18, "p18">, DwarfRegNum<[274]>;
-def p19 : PR< 19, "p19">, DwarfRegNum<[275]>;
-def p20 : PR< 20, "p20">, DwarfRegNum<[276]>;
-def p21 : PR< 21, "p21">, DwarfRegNum<[277]>;
-def p22 : PR< 22, "p22">, DwarfRegNum<[278]>;
-def p23 : PR< 23, "p23">, DwarfRegNum<[279]>;
-def p24 : PR< 24, "p24">, DwarfRegNum<[280]>;
-def p25 : PR< 25, "p25">, DwarfRegNum<[281]>;
-def p26 : PR< 26, "p26">, DwarfRegNum<[282]>;
-def p27 : PR< 27, "p27">, DwarfRegNum<[283]>;
-def p28 : PR< 28, "p28">, DwarfRegNum<[284]>;
-def p29 : PR< 29, "p29">, DwarfRegNum<[285]>;
-def p30 : PR< 30, "p30">, DwarfRegNum<[286]>;
-def p31 : PR< 31, "p31">, DwarfRegNum<[287]>;
-def p32 : PR< 32, "p32">, DwarfRegNum<[288]>;
-def p33 : PR< 33, "p33">, DwarfRegNum<[289]>;
-def p34 : PR< 34, "p34">, DwarfRegNum<[290]>;
-def p35 : PR< 35, "p35">, DwarfRegNum<[291]>;
-def p36 : PR< 36, "p36">, DwarfRegNum<[292]>;
-def p37 : PR< 37, "p37">, DwarfRegNum<[293]>;
-def p38 : PR< 38, "p38">, DwarfRegNum<[294]>;
-def p39 : PR< 39, "p39">, DwarfRegNum<[295]>;
-def p40 : PR< 40, "p40">, DwarfRegNum<[296]>;
-def p41 : PR< 41, "p41">, DwarfRegNum<[297]>;
-def p42 : PR< 42, "p42">, DwarfRegNum<[298]>;
-def p43 : PR< 43, "p43">, DwarfRegNum<[299]>;
-def p44 : PR< 44, "p44">, DwarfRegNum<[300]>;
-def p45 : PR< 45, "p45">, DwarfRegNum<[301]>;
-def p46 : PR< 46, "p46">, DwarfRegNum<[302]>;
-def p47 : PR< 47, "p47">, DwarfRegNum<[303]>;
-def p48 : PR< 48, "p48">, DwarfRegNum<[304]>;
-def p49 : PR< 49, "p49">, DwarfRegNum<[305]>;
-def p50 : PR< 50, "p50">, DwarfRegNum<[306]>;
-def p51 : PR< 51, "p51">, DwarfRegNum<[307]>;
-def p52 : PR< 52, "p52">, DwarfRegNum<[308]>;
-def p53 : PR< 53, "p53">, DwarfRegNum<[309]>;
-def p54 : PR< 54, "p54">, DwarfRegNum<[310]>;
-def p55 : PR< 55, "p55">, DwarfRegNum<[311]>;
-def p56 : PR< 56, "p56">, DwarfRegNum<[312]>;
-def p57 : PR< 57, "p57">, DwarfRegNum<[313]>;
-def p58 : PR< 58, "p58">, DwarfRegNum<[314]>;
-def p59 : PR< 59, "p59">, DwarfRegNum<[315]>;
-def p60 : PR< 60, "p60">, DwarfRegNum<[316]>;
-def p61 : PR< 61, "p61">, DwarfRegNum<[317]>;
-def p62 : PR< 62, "p62">, DwarfRegNum<[318]>;
-def p63 : PR< 63, "p63">, DwarfRegNum<[319]>;
-
-// XXX : this is temporary, we'll eventually have the output registers
-// in the general purpose register class too?
-def out0 : GR<0, "out0">, DwarfRegNum<[120]>;
-def out1 : GR<1, "out1">, DwarfRegNum<[121]>;
-def out2 : GR<2, "out2">, DwarfRegNum<[122]>;
-def out3 : GR<3, "out3">, DwarfRegNum<[123]>;
-def out4 : GR<4, "out4">, DwarfRegNum<[124]>;
-def out5 : GR<5, "out5">, DwarfRegNum<[125]>;
-def out6 : GR<6, "out6">, DwarfRegNum<[126]>;
-def out7 : GR<7, "out7">, DwarfRegNum<[127]>;
-
-// application (special) registers:
-
-// "previous function state" application register
-def AR_PFS : GR<0, "ar.pfs">, DwarfRegNum<[331]>;
-
-// "return pointer" (this is really branch register b0)
-def rp : GR<0, "rp">, DwarfRegNum<[-1]>;
-
-// branch reg 6
-def B6 : GR<0, "b6">, DwarfRegNum<[326]>;
-
-//===----------------------------------------------------------------------===//
-// Register Class Definitions... now that we have all of the pieces, define the
-// top-level register classes. The order specified in the register list is
-// implicitly defined to be the register allocation order.
-//
-
-// these are the scratch (+stacked) general registers
-// FIXME/XXX we also reserve a frame pointer (r5)
-// FIXME/XXX we also reserve r2 for spilling/filling predicates
-// in IA64RegisterInfo.cpp
-// FIXME/XXX we also reserve r22 for calculating addresses
-// in IA64RegisterInfo.cpp
-
-def GR : RegisterClass<"IA64", [i64], 64,
- [
-
-//FIXME!: for both readability and performance, we don't want the out
-// registers to be the first ones allocated
-
- out7, out6, out5, out4, out3, out2, out1, out0,
- r3, r8, r9, r10, r11, r14, r15,
- r16, r17, r18, r19, r20, r21, r23,
- r24, r25, r26, r27, r28, r29, r30, r31,
- r32, r33, r34, r35, r36, r37, r38, r39,
- r40, r41, r42, r43, r44, r45, r46, r47,
- r48, r49, r50, r51, r52, r53, r54, r55,
- r56, r57, r58, r59, r60, r61, r62, r63,
- r64, r65, r66, r67, r68, r69, r70, r71,
- r72, r73, r74, r75, r76, r77, r78, r79,
- r80, r81, r82, r83, r84, r85, r86, r87,
- r88, r89, r90, r91, r92, r93, r94, r95,
- r96, r97, r98, r99, r100, r101, r102, r103,
- r104, r105, r106, r107, r108, r109, r110, r111,
- r112, r113, r114, r115, r116, r117, r118, r119,
- // last 17 are special (look down)
- r120, r121, r122, r123, r124, r125, r126, r127,
- r0, r1, r2, r5, r12, r13, r22, rp, AR_PFS]>
- {
- let MethodProtos = [{
- iterator allocation_order_begin(const MachineFunction &MF) const;
- iterator allocation_order_end(const MachineFunction &MF) const;
- }];
- let MethodBodies = [{
- GRClass::iterator
- GRClass::allocation_order_begin(const MachineFunction &MF) const {
- // hide the 8 out? registers appropriately:
- return begin()+(8-(MF.getInfo<IA64FunctionInfo>()->outRegsUsed));
- }
-
- GRClass::iterator
- GRClass::allocation_order_end(const MachineFunction &MF) const {
- // the 9 special registers r0,r1,r2,r5,r12,r13 etc
- int numReservedRegs=9;
-
- // we also can't allocate registers for use as locals if they're already
- // required as 'out' registers
- numReservedRegs+=MF.getInfo<IA64FunctionInfo>()->outRegsUsed;
- return end()-numReservedRegs; // hide registers appropriately
- }
- }];
-}
-
-
-// these are the scratch (+stacked) FP registers
-
-def FP : RegisterClass<"IA64", [f64], 64,
- [F6, F7,
- F8, F9, F10, F11, F12, F13, F14, F15,
- F32, F33, F34, F35, F36, F37, F38, F39,
- F40, F41, F42, F43, F44, F45, F46, F47,
- F48, F49, F50, F51, F52, F53, F54, F55,
- F56, F57, F58, F59, F60, F61, F62, F63,
- F64, F65, F66, F67, F68, F69, F70, F71,
- F72, F73, F74, F75, F76, F77, F78, F79,
- F80, F81, F82, F83, F84, F85, F86, F87,
- F88, F89, F90, F91, F92, F93, F94, F95,
- F96, F97, F98, F99, F100, F101, F102, F103,
- F104, F105, F106, F107, F108, F109, F110, F111,
- F112, F113, F114, F115, F116, F117, F118, F119,
- F120, F121, F122, F123, F124, F125, F126, F127,
- F0, F1]> // these last two are hidden
- {
-// the 128s here are to make stf.spill/ldf.fill happy,
-// when storing full (82-bit) FP regs to stack slots
-// we need to 16-byte align
- let Size=128;
- let Alignment=128;
-
- let MethodProtos = [{
- iterator allocation_order_begin(const MachineFunction &MF) const;
- iterator allocation_order_end(const MachineFunction &MF) const;
- }];
- let MethodBodies = [{
- FPClass::iterator
- FPClass::allocation_order_begin(const MachineFunction &MF) const {
- return begin(); // we don't hide any FP regs from the start
- }
-
- FPClass::iterator
- FPClass::allocation_order_end(const MachineFunction &MF) const {
- return end()-2; // we hide regs F0, F1 from the end
- }
- }];
-}
-
-// these are the predicate registers, p0 (1/TRUE) is not here
-def PR : RegisterClass<"IA64", [i1], 64,
-
-// for now, let's be wimps and only have the scratch predicate regs
- [p6, p7, p8, p9, p10, p11, p12, p13, p14, p15]> {
- let Size = 64;
- }
-
-/*
- [p1, p2, p3, p4, p5, p6, p7,
- p8, p9, p10, p11, p12, p13, p14, p15,
- p16, p17, p18, p19, p20, p21, p22, p23,
- p24, p25, p26, p27, p28, p29, p30, p31,
- p32, p33, p34, p35, p36, p37, p38, p39,
- p40, p41, p42, p43, p44, p45, p46, p47,
- p48, p49, p50, p51, p52, p53, p54, p55,
- p56, p57, p58, p59, p60, p61, p62, p63]>;
- */
diff --git a/lib/Target/IA64/IA64Subtarget.cpp b/lib/Target/IA64/IA64Subtarget.cpp
deleted file mode 100644
index 4eca50b..0000000
--- a/lib/Target/IA64/IA64Subtarget.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-//===-- IA64Subtarget.cpp - IA64 Subtarget Information ----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the IA64 specific subclass of TargetSubtarget.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "subtarget"
-#include "IA64Subtarget.h"
-using namespace llvm;
-
-IA64Subtarget::IA64Subtarget() {}
diff --git a/lib/Target/IA64/IA64Subtarget.h b/lib/Target/IA64/IA64Subtarget.h
deleted file mode 100644
index 0387af5..0000000
--- a/lib/Target/IA64/IA64Subtarget.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//====---- IA64Subtarget.h - Define Subtarget for the IA64 -----*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares the IA64 specific subclass of TargetSubtarget.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef IA64SUBTARGET_H
-#define IA64SUBTARGET_H
-
-#include "llvm/Target/TargetSubtarget.h"
-
-namespace llvm {
-
-class IA64Subtarget : public TargetSubtarget {
-public:
- IA64Subtarget();
-};
-
-} // End llvm namespace
-
-#endif
diff --git a/lib/Target/IA64/IA64TargetAsmInfo.cpp b/lib/Target/IA64/IA64TargetAsmInfo.cpp
deleted file mode 100644
index 2ae8beb..0000000
--- a/lib/Target/IA64/IA64TargetAsmInfo.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//===-- IA64TargetAsmInfo.cpp - IA64 asm properties -------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the IA64TargetAsmInfo properties.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IA64TargetAsmInfo.h"
-#include "llvm/Constants.h"
-#include "llvm/Target/TargetMachine.h"
-
-using namespace llvm;
-
-IA64TargetAsmInfo::IA64TargetAsmInfo(const TargetMachine &TM):
- ELFTargetAsmInfo(TM) {
- CommentString = "//";
- Data8bitsDirective = "\tdata1\t"; // FIXME: check that we are
- Data16bitsDirective = "\tdata2.ua\t"; // disabling auto-alignment
- Data32bitsDirective = "\tdata4.ua\t"; // properly
- Data64bitsDirective = "\tdata8.ua\t";
- ZeroDirective = "\t.skip\t";
- AsciiDirective = "\tstring\t";
-
- GlobalVarAddrPrefix="";
- GlobalVarAddrSuffix="";
- FunctionAddrPrefix="@fptr(";
- FunctionAddrSuffix=")";
-
- // FIXME: would be nice to have rodata (no 'w') when appropriate?
- ConstantPoolSection = "\n\t.section .data, \"aw\", \"progbits\"\n";
-}
-
-unsigned IA64TargetAsmInfo::RelocBehaviour() const {
- return (TM.getRelocationModel() != Reloc::Static ?
- Reloc::LocalOrGlobal : Reloc::Global);
-}
-
-// FIXME: Support small data/bss/rodata sections someday.
diff --git a/lib/Target/IA64/IA64TargetAsmInfo.h b/lib/Target/IA64/IA64TargetAsmInfo.h
deleted file mode 100644
index 130822e..0000000
--- a/lib/Target/IA64/IA64TargetAsmInfo.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//=====-- IA64TargetAsmInfo.h - IA64 asm properties -----------*- C++ -*--====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the IA64TargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef IA64TARGETASMINFO_H
-#define IA64TARGETASMINFO_H
-
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/ELFTargetAsmInfo.h"
-
-namespace llvm {
-
- // Forward declaration.
- class TargetMachine;
-
- struct IA64TargetAsmInfo : public ELFTargetAsmInfo {
- explicit IA64TargetAsmInfo(const TargetMachine &TM);
- virtual unsigned RelocBehaviour() const;
- };
-
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/IA64/IA64TargetMachine.cpp b/lib/Target/IA64/IA64TargetMachine.cpp
deleted file mode 100644
index 71a0a98..0000000
--- a/lib/Target/IA64/IA64TargetMachine.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-//===-- IA64TargetMachine.cpp - Define TargetMachine for IA64 -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the IA64 specific subclass of TargetMachine.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IA64TargetAsmInfo.h"
-#include "IA64TargetMachine.h"
-#include "IA64.h"
-#include "llvm/Module.h"
-#include "llvm/PassManager.h"
-#include "llvm/Target/TargetMachineRegistry.h"
-using namespace llvm;
-
-// Register the target
-static RegisterTarget<IA64TargetMachine> X("ia64",
- "IA-64 (Itanium) [experimental]");
-
-// No assembler printer by default
-IA64TargetMachine::AsmPrinterCtorFn IA64TargetMachine::AsmPrinterCtor = 0;
-
-// Force static initialization.
-extern "C" void LLVMInitializeIA64Target() { }
-
-const TargetAsmInfo *IA64TargetMachine::createTargetAsmInfo() const {
- return new IA64TargetAsmInfo(*this);
-}
-
-unsigned IA64TargetMachine::getModuleMatchQuality(const Module &M) {
- // we match [iI][aA]*64
- bool seenIA64=false;
- std::string TT = M.getTargetTriple();
-
- if (TT.size() >= 4) {
- if( (TT[0]=='i' || TT[0]=='I') &&
- (TT[1]=='a' || TT[1]=='A') ) {
- for(unsigned int i=2; i<(TT.size()-1); i++)
- if(TT[i]=='6' && TT[i+1]=='4')
- seenIA64=true;
- }
-
- if (seenIA64)
- return 20; // strong match
- }
- // If the target triple is something non-ia64, we don't match.
- if (!TT.empty()) return 0;
-
-#if defined(__ia64__) || defined(__IA64__)
- return 5;
-#else
- return 0;
-#endif
-}
-
-/// IA64TargetMachine ctor - Create an LP64 architecture model
-///
-IA64TargetMachine::IA64TargetMachine(const Module &M, const std::string &FS)
- : DataLayout("e-f80:128:128"),
- FrameInfo(TargetFrameInfo::StackGrowsDown, 16, 0),
- TLInfo(*this) { // FIXME? check this stuff
-}
-
-
-//===----------------------------------------------------------------------===//
-// Pass Pipeline Configuration
-//===----------------------------------------------------------------------===//
-
-bool IA64TargetMachine::addInstSelector(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel) {
- PM.add(createIA64DAGToDAGInstructionSelector(*this));
- return false;
-}
-
-bool IA64TargetMachine::addPreEmitPass(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel) {
- // Make sure everything is bundled happily
- PM.add(createIA64BundlingPass(*this));
- return true;
-}
-bool IA64TargetMachine::addAssemblyEmitter(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel,
- bool Verbose,
- raw_ostream &Out) {
- // Output assembly language.
- assert(AsmPrinterCtor && "AsmPrinter was not linked in");
- if (AsmPrinterCtor)
- PM.add(AsmPrinterCtor(Out, *this, Verbose));
- return false;
-}
-
diff --git a/lib/Target/IA64/IA64TargetMachine.h b/lib/Target/IA64/IA64TargetMachine.h
deleted file mode 100644
index 402d833..0000000
--- a/lib/Target/IA64/IA64TargetMachine.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//===-- IA64TargetMachine.h - Define TargetMachine for IA64 ---*- C++ -*---===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares the IA64 specific subclass of TargetMachine.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TARGET_IA64TARGETMACHINE_H
-#define LLVM_TARGET_IA64TARGETMACHINE_H
-
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetFrameInfo.h"
-#include "IA64InstrInfo.h"
-#include "IA64ISelLowering.h"
-#include "IA64Subtarget.h"
-
-namespace llvm {
-
-class IA64TargetMachine : public LLVMTargetMachine {
- IA64Subtarget Subtarget;
- const TargetData DataLayout; // Calculates type size & alignment
- IA64InstrInfo InstrInfo;
- TargetFrameInfo FrameInfo;
- //IA64JITInfo JITInfo;
- IA64TargetLowering TLInfo;
-
-protected:
- virtual const TargetAsmInfo *createTargetAsmInfo() const;
-
- // To avoid having target depend on the asmprinter stuff libraries, asmprinter
- // set this functions to ctor pointer at startup time if they are linked in.
- typedef FunctionPass *(*AsmPrinterCtorFn)(raw_ostream &o,
- IA64TargetMachine &tm,
- bool verbose);
- static AsmPrinterCtorFn AsmPrinterCtor;
-
-public:
- IA64TargetMachine(const Module &M, const std::string &FS);
-
- virtual const IA64InstrInfo *getInstrInfo() const { return &InstrInfo; }
- virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
- virtual const IA64Subtarget *getSubtargetImpl() const { return &Subtarget; }
- virtual IA64TargetLowering *getTargetLowering() const {
- return const_cast<IA64TargetLowering*>(&TLInfo);
- }
- virtual const IA64RegisterInfo *getRegisterInfo() const {
- return &InstrInfo.getRegisterInfo();
- }
- virtual const TargetData *getTargetData() const { return &DataLayout; }
-
- static unsigned getModuleMatchQuality(const Module &M);
-
- // Pass Pipeline Configuration
- virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
- virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
- virtual bool addAssemblyEmitter(PassManagerBase &PM,
- CodeGenOpt::Level OptLevel,
- bool Verbose, raw_ostream &Out);
-
- static void registerAsmPrinter(AsmPrinterCtorFn F) {
- AsmPrinterCtor = F;
- }
-};
-} // End llvm namespace
-
-#endif
-
-
diff --git a/lib/Target/IA64/Makefile b/lib/Target/IA64/Makefile
deleted file mode 100644
index d383254..0000000
--- a/lib/Target/IA64/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-##===- lib/Target/IA64/Makefile -----------------------------*- Makefile -*-===##
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-LEVEL = ../../..
-LIBRARYNAME = LLVMIA64CodeGen
-TARGET = IA64
-# Make sure that tblgen is run, first thing.
-BUILT_SOURCES = IA64GenRegisterInfo.h.inc IA64GenRegisterNames.inc \
- IA64GenRegisterInfo.inc IA64GenInstrNames.inc \
- IA64GenInstrInfo.inc IA64GenAsmWriter.inc \
- IA64GenDAGISel.inc
-
-DIRS = AsmPrinter
-
-include $(LEVEL)/Makefile.common
-
diff --git a/lib/Target/IA64/README b/lib/Target/IA64/README
deleted file mode 100644
index 60761ac..0000000
--- a/lib/Target/IA64/README
+++ /dev/null
@@ -1,48 +0,0 @@
-TODO:
- - Un-bitrot ISel
- - Hook up If-Conversion a la ARM target
- - Hook up all branch analysis functions
- - Instruction scheduling
- - Bundling
- - Dynamic Optimization
- - Testing and bugfixing
- - stop passing FP args in both FP *and* integer regs when not required
- - allocate low (nonstacked) registers more aggressively
- - clean up and thoroughly test the isel patterns.
- - fix stacked register allocation order: (for readability) we don't want
- the out? registers being the first ones used
- - fix up floating point
- (nb http://gcc.gnu.org/wiki?pagename=ia64%20floating%20point )
- - bundling!
- (we will avoid the mess that is:
- http://gcc.gnu.org/ml/gcc/2003-12/msg00832.html )
- - instruction scheduling (hmmmm! ;)
- - counted loop support
- - make integer + FP mul/div more clever (we have fixed pseudocode atm)
- - track and use comparison complements
-
-INFO:
- - we are strictly LP64 here, no support for ILP32 on HP-UX. Linux users
- don't need to worry about this.
- - i have instruction scheduling/bundling pseudocode, that really works
- (has been tested, albeit at the perl-script level).
- so, before you go write your own, send me an email!
-
-KNOWN DEFECTS AT THE CURRENT TIME:
- - C++ vtables contain naked function pointers, not function descriptors,
- which is bad. see http://llvm.cs.uiuc.edu/bugs/show_bug.cgi?id=406
- - varargs are broken
- - alloca doesn't work (indeed, stack frame layout is bogus)
- - no support for big-endian environments
- - (not really the backend, but...) the CFE has some issues on IA64.
- these will probably be fixed soon.
-
-ACKNOWLEDGEMENTS:
- - Chris Lattner (x100)
- - Other LLVM developers ("hey, that looks familiar")
-
-CONTACT:
- - You can email me at duraid@octopus.com.au. If you find a small bug,
- just email me. If you find a big bug, please file a bug report
- in bugzilla! http://llvm.cs.uiuc.edu is your one stop shop for all
- things LLVM.
diff --git a/lib/Target/MSP430/MSP430AsmPrinter.cpp b/lib/Target/MSP430/MSP430AsmPrinter.cpp
deleted file mode 100644
index b1fa3f0..0000000
--- a/lib/Target/MSP430/MSP430AsmPrinter.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-//===-- MSP430AsmPrinter.cpp - MSP430 LLVM assembly writer ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file 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 the MSP430 assembly language.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "asm-printer"
-#include "MSP430.h"
-#include "MSP430InstrInfo.h"
-#include "MSP430TargetMachine.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
-namespace {
- class VISIBILITY_HIDDEN MSP430AsmPrinter : public AsmPrinter {
- public:
- MSP430AsmPrinter(raw_ostream &O, MSP430TargetMachine &TM,
- const TargetAsmInfo *TAI, bool V)
- : AsmPrinter(O, TM, TAI, V) {}
-
- virtual const char *getPassName() const {
- return "MSP430 Assembly Printer";
- }
-
- void printOperand(const MachineInstr *MI, int OpNum,
- const char* Modifier = 0);
- void printSrcMemOperand(const MachineInstr *MI, int OpNum,
- const char* Modifier = 0);
- void printCCOperand(const MachineInstr *MI, int OpNum);
- bool printInstruction(const MachineInstr *MI); // autogenerated.
- void printMachineInstruction(const MachineInstr * MI);
-
- void emitFunctionHeader(const MachineFunction &MF);
- bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
-
- void getAnalysisUsage(AnalysisUsage &AU) const {
- AsmPrinter::getAnalysisUsage(AU);
- AU.setPreservesAll();
- }
- };
-} // end of anonymous namespace
-
-#include "MSP430GenAsmWriter.inc"
-
-/// createMSP430CodePrinterPass - Returns a pass that prints the MSP430
-/// 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::createMSP430CodePrinterPass(raw_ostream &o,
- MSP430TargetMachine &tm,
- bool verbose) {
- return new MSP430AsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
-}
-
-bool MSP430AsmPrinter::doInitialization(Module &M) {
- Mang = new Mangler(M, "", TAI->getPrivateGlobalPrefix());
- return false; // success
-}
-
-
-bool MSP430AsmPrinter::doFinalization(Module &M) {
- return AsmPrinter::doFinalization(M);
-}
-
-void MSP430AsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
- const Function *F = MF.getFunction();
-
- SwitchToSection(TAI->SectionForGlobal(F));
-
- unsigned FnAlign = MF.getAlignment();
- EmitAlignment(FnAlign, F);
-
- switch (F->getLinkage()) {
- default: assert(0 && "Unknown linkage type!");
- case Function::InternalLinkage: // Symbols default to internal.
- case Function::PrivateLinkage:
- break;
- case Function::ExternalLinkage:
- O << "\t.globl\t" << CurrentFnName << '\n';
- break;
- case Function::LinkOnceAnyLinkage:
- case Function::LinkOnceODRLinkage:
- case Function::WeakAnyLinkage:
- case Function::WeakODRLinkage:
- O << "\t.weak\t" << CurrentFnName << '\n';
- break;
- }
-
- printVisibility(CurrentFnName, F->getVisibility());
-
- O << "\t.type\t" << CurrentFnName << ",@function\n"
- << CurrentFnName << ":\n";
-}
-
-bool MSP430AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- SetupMachineFunction(MF);
- O << "\n\n";
-
- // Print the 'header' of function
- emitFunctionHeader(MF);
-
- // 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.
- if (!VerboseAsm && (I->pred_empty() || I->isOnlyReachableByFallthrough())) {
- // This is an entry block or a block that's only reachable via a
- // fallthrough edge. In non-VerboseAsm mode, don't print the label.
- } else {
- printBasicBlockLabel(I, true, true, VerboseAsm);
- O << '\n';
- }
-
- for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II)
- // Print the assembly for the instruction.
- printMachineInstruction(II);
- }
-
- if (TAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
-
- O.flush();
-
- // We didn't modify anything
- return false;
-}
-
-void MSP430AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
- ++EmittedInsts;
-
- // Call the autogenerated instruction printer routines.
- if (printInstruction(MI))
- return;
-
- assert(0 && "Should not happen");
-}
-
-void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
- const char* Modifier) {
- const MachineOperand &MO = MI->getOperand(OpNum);
- switch (MO.getType()) {
- case MachineOperand::MO_Register:
- assert (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
- "Virtual registers should be already mapped!");
- O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
- return;
- case MachineOperand::MO_Immediate:
- if (!Modifier || strcmp(Modifier, "nohash"))
- O << '#';
- O << MO.getImm();
- return;
- case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
- return;
- case MachineOperand::MO_GlobalAddress: {
- bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- bool isCallOp = Modifier && !strcmp(Modifier, "call");
- std::string Name = Mang->getValueName(MO.getGlobal());
- assert(MO.getOffset() == 0 && "No offsets allowed!");
-
- if (isCallOp)
- O << '#';
- else if (isMemOp)
- O << '&';
-
- O << Name;
-
- return;
- }
- case MachineOperand::MO_ExternalSymbol: {
- bool isCallOp = Modifier && !strcmp(Modifier, "call");
- std::string Name(TAI->getGlobalPrefix());
- Name += MO.getSymbolName();
- if (isCallOp)
- O << '#';
- O << Name;
- return;
- }
- default:
- assert(0 && "Not implemented yet!");
- }
-}
-
-void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
- const char* Modifier) {
- const MachineOperand &Base = MI->getOperand(OpNum);
- const MachineOperand &Disp = MI->getOperand(OpNum+1);
-
- if (Base.isGlobal())
- printOperand(MI, OpNum, "mem");
- else if (Disp.isImm() && !Base.getReg())
- printOperand(MI, OpNum);
- else if (Base.getReg()) {
- if (Disp.getImm()) {
- printOperand(MI, OpNum + 1, "nohash");
- O << '(';
- printOperand(MI, OpNum);
- O << ')';
- } else {
- O << '@';
- printOperand(MI, OpNum);
- }
- } else
- assert(0 && "Unsupported memory operand");
-}
-
-void MSP430AsmPrinter::printCCOperand(const MachineInstr *MI, int OpNum) {
- unsigned CC = MI->getOperand(OpNum).getImm();
-
- switch (CC) {
- default:
- assert(0 && "Unsupported CC code");
- break;
- case MSP430::COND_E:
- O << "eq";
- break;
- case MSP430::COND_NE:
- O << "ne";
- break;
- case MSP430::COND_HS:
- O << "hs";
- break;
- case MSP430::COND_LO:
- O << "lo";
- break;
- case MSP430::COND_GE:
- O << "ge";
- break;
- case MSP430::COND_L:
- O << 'l';
- break;
- }
-}
diff --git a/lib/Target/MSP430/MSP430TargetAsmInfo.cpp b/lib/Target/MSP430/MSP430TargetAsmInfo.cpp
deleted file mode 100644
index ab181de..0000000
--- a/lib/Target/MSP430/MSP430TargetAsmInfo.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//===-- MSP430TargetAsmInfo.cpp - MSP430 asm properties -------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the MSP430TargetAsmInfo properties.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MSP430TargetAsmInfo.h"
-#include "MSP430TargetMachine.h"
-
-using namespace llvm;
-
-MSP430TargetAsmInfo::MSP430TargetAsmInfo(const MSP430TargetMachine &TM)
- : ELFTargetAsmInfo(TM) {
- AlignmentIsInBytes = false;
-}
diff --git a/lib/Target/MSP430/MSP430TargetAsmInfo.h b/lib/Target/MSP430/MSP430TargetAsmInfo.h
deleted file mode 100644
index b58d5c9..0000000
--- a/lib/Target/MSP430/MSP430TargetAsmInfo.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//=====-- MSP430TargetAsmInfo.h - MSP430 asm properties -------*- C++ -*--====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the MSP430TargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MSP430TARGETASMINFO_H
-#define MSP430TARGETASMINFO_H
-
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/ELFTargetAsmInfo.h"
-
-namespace llvm {
-
- // Forward declaration.
- class MSP430TargetMachine;
-
- struct MSP430TargetAsmInfo : public ELFTargetAsmInfo {
- explicit MSP430TargetAsmInfo(const MSP430TargetMachine &TM);
- };
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/Mips/MipsTargetAsmInfo.cpp b/lib/Target/Mips/MipsTargetAsmInfo.cpp
deleted file mode 100644
index c197b0c..0000000
--- a/lib/Target/Mips/MipsTargetAsmInfo.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-//===-- MipsTargetAsmInfo.cpp - Mips asm properties -------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the MipsTargetAsmInfo properties.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsTargetAsmInfo.h"
-#include "MipsTargetMachine.h"
-#include "llvm/GlobalVariable.h"
-
-using namespace llvm;
-
-MipsTargetAsmInfo::MipsTargetAsmInfo(const MipsTargetMachine &TM):
- ELFTargetAsmInfo(TM) {
-
- Subtarget = &TM.getSubtarget<MipsSubtarget>();
-
- AlignmentIsInBytes = false;
- COMMDirectiveTakesAlignment = true;
- Data16bitsDirective = "\t.half\t";
- Data32bitsDirective = "\t.word\t";
- Data64bitsDirective = NULL;
- PrivateGlobalPrefix = "$";
- JumpTableDataSection = "\t.rdata";
- CommentString = "#";
- ZeroDirective = "\t.space\t";
- BSSSection = "\t.section\t.bss";
- CStringSection = ".rodata.str";
-
- if (!Subtarget->hasABICall()) {
- JumpTableDirective = "\t.word\t";
- SmallDataSection = getNamedSection("\t.sdata", SectionFlags::Writeable);
- SmallBSSSection = getNamedSection("\t.sbss",
- SectionFlags::Writeable |
- SectionFlags::BSS);
- } else
- JumpTableDirective = "\t.gpword\t";
-
-}
-
-unsigned MipsTargetAsmInfo::
-SectionFlagsForGlobal(const GlobalValue *GV, const char* Name) const {
- unsigned Flags = ELFTargetAsmInfo::SectionFlagsForGlobal(GV, Name);
- // Mask out Small Section flag bit, Mips doesnt support 's' section symbol
- // for its small sections.
- return (Flags & (~SectionFlags::Small));
-}
-
-SectionKind::Kind MipsTargetAsmInfo::
-SectionKindForGlobal(const GlobalValue *GV) const {
- SectionKind::Kind K = ELFTargetAsmInfo::SectionKindForGlobal(GV);
-
- if (Subtarget->hasABICall())
- return K;
-
- if (K != SectionKind::Data && K != SectionKind::BSS &&
- K != SectionKind::RODataMergeConst)
- return K;
-
- if (isa<GlobalVariable>(GV)) {
- const TargetData *TD = TM.getTargetData();
- unsigned Size = TD->getTypeAllocSize(GV->getType()->getElementType());
- unsigned Threshold = Subtarget->getSSectionThreshold();
-
- if (Size > 0 && Size <= Threshold) {
- if (K == SectionKind::BSS)
- return SectionKind::SmallBSS;
- else
- return SectionKind::SmallData;
- }
- }
-
- return K;
-}
-
-const Section* MipsTargetAsmInfo::
-SelectSectionForGlobal(const GlobalValue *GV) const {
- SectionKind::Kind K = SectionKindForGlobal(GV);
- const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV);
-
- if (GVA && (!GVA->isWeakForLinker()))
- switch (K) {
- case SectionKind::SmallData:
- return getSmallDataSection();
- case SectionKind::SmallBSS:
- return getSmallBSSSection();
- default: break;
- }
-
- return ELFTargetAsmInfo::SelectSectionForGlobal(GV);
-}
diff --git a/lib/Target/Mips/MipsTargetAsmInfo.h b/lib/Target/Mips/MipsTargetAsmInfo.h
deleted file mode 100644
index 2b5a739..0000000
--- a/lib/Target/Mips/MipsTargetAsmInfo.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//=====-- MipsTargetAsmInfo.h - Mips asm properties -----------*- C++ -*--====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the MipsTargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MIPSTARGETASMINFO_H
-#define MIPSTARGETASMINFO_H
-
-#include "MipsSubtarget.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/ELFTargetAsmInfo.h"
-
-namespace llvm {
-
- // Forward declaration.
- class GlobalValue;
- class MipsTargetMachine;
-
- struct MipsTargetAsmInfo : public ELFTargetAsmInfo {
- explicit MipsTargetAsmInfo(const MipsTargetMachine &TM);
-
- /// SectionKindForGlobal - This hook allows the target to select proper
- /// section kind used for global emission.
- virtual SectionKind::Kind
- SectionKindForGlobal(const GlobalValue *GV) const;
-
- /// SectionFlagsForGlobal - This hook allows the target to select proper
- /// section flags either for given global or for section.
- virtual unsigned
- SectionFlagsForGlobal(const GlobalValue *GV = NULL,
- const char* name = NULL) const;
-
- virtual const Section* SelectSectionForGlobal(const GlobalValue *GV) const;
-
- private:
- const MipsSubtarget *Subtarget;
- };
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp
deleted file mode 100644
index 1fc1cc1..0000000
--- a/lib/Target/PIC16/PIC16AsmPrinter.cpp
+++ /dev/null
@@ -1,442 +0,0 @@
-//===-- PIC16AsmPrinter.cpp - PIC16 LLVM assembly writer ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file 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 PIC16 assembly language.
-//
-//===----------------------------------------------------------------------===//
-
-#include "PIC16AsmPrinter.h"
-#include "PIC16TargetAsmInfo.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Function.h"
-#include "llvm/Module.h"
-#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-
-using namespace llvm;
-
-#include "PIC16GenAsmWriter.inc"
-
-bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
- printInstruction(MI);
- return true;
-}
-
-/// runOnMachineFunction - This emits the frame section, autos section and
-/// assembly for each instruction. Also takes care of function begin debug
-/// directive and file begin debug directive (if required) for the function.
-///
-bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- this->MF = &MF;
-
- // This calls the base class function required to be called at beginning
- // of runOnMachineFunction.
- SetupMachineFunction(MF);
-
- // Get the mangled name.
- const Function *F = MF.getFunction();
- CurrentFnName = Mang->getValueName(F);
-
- // Emit the function frame (args and temps).
- EmitFunctionFrame(MF);
-
- DbgInfo.BeginFunction(MF);
-
- // Emit the autos section of function.
- EmitAutos(CurrentFnName);
-
- // Now emit the instructions of function in its code section.
- const char *codeSection = PAN::getCodeSectionName(CurrentFnName).c_str();
-
- const Section *fCodeSection = TAI->getNamedSection(codeSection,
- SectionFlags::Code);
- // Start the Code Section.
- O << "\n";
- SwitchToSection (fCodeSection);
-
- // Emit the frame address of the function at the beginning of code.
- O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
- O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
-
- // Emit function start label.
- O << CurrentFnName << ":\n";
-
- DebugLoc CurDL;
- O << "\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.
- if (I != MF.begin()) {
- printBasicBlockLabel(I, true);
- O << '\n';
- }
-
- // Print a basic block.
- for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II) {
-
- // Emit the line directive if source line changed.
- const DebugLoc DL = II->getDebugLoc();
- if (!DL.isUnknown() && DL != CurDL) {
- DbgInfo.ChangeDebugLoc(MF, DL);
- CurDL = DL;
- }
-
- // Print the assembly for the instruction.
- printMachineInstruction(II);
- }
- }
-
- // Emit function end debug directives.
- DbgInfo.EndFunction(MF);
-
- return false; // we didn't modify anything.
-}
-
-/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16
-/// 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::createPIC16CodePrinterPass(raw_ostream &o,
- PIC16TargetMachine &tm,
- bool verbose) {
- return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
-}
-
-
-// printOperand - print operand of insn.
-void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
- const MachineOperand &MO = MI->getOperand(opNum);
-
- switch (MO.getType()) {
- case MachineOperand::MO_Register:
- if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
- O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
- else
- assert(0 && "not implemented");
- return;
-
- case MachineOperand::MO_Immediate:
- O << (int)MO.getImm();
- return;
-
- case MachineOperand::MO_GlobalAddress: {
- O << Mang->getValueName(MO.getGlobal());
- break;
- }
- case MachineOperand::MO_ExternalSymbol: {
- const char *Sname = MO.getSymbolName();
-
- // If its a libcall name, record it to decls section.
- if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) {
- LibcallDecls.push_back(Sname);
- }
-
- O << Sname;
- break;
- }
- case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
- return;
-
- default:
- assert(0 && " Operand type not supported.");
- }
-}
-
-/// printCCOperand - Print the cond code operand.
-///
-void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
- int CC = (int)MI->getOperand(opNum).getImm();
- O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
-}
-
-/// printLibcallDecls - print the extern declarations for compiler
-/// intrinsics.
-///
-void PIC16AsmPrinter::printLibcallDecls(void) {
- // If no libcalls used, return.
- if (LibcallDecls.empty()) return;
-
- O << TAI->getCommentString() << "External decls for libcalls - BEGIN." <<"\n";
- // Remove duplicate entries.
- LibcallDecls.sort();
- LibcallDecls.unique();
- for (std::list<const char*>::const_iterator I = LibcallDecls.begin();
- I != LibcallDecls.end(); I++) {
- O << TAI->getExternDirective() << *I << "\n";
- O << TAI->getExternDirective() << PAN::getArgsLabel(*I) << "\n";
- O << TAI->getExternDirective() << PAN::getRetvalLabel(*I) << "\n";
- }
- O << TAI->getCommentString() << "External decls for libcalls - END." <<"\n";
-}
-
-/// doInitialization - Perfrom Module level initializations here.
-/// One task that we do here is to sectionize all global variables.
-/// The MemSelOptimizer pass depends on the sectionizing.
-///
-bool PIC16AsmPrinter::doInitialization (Module &M) {
- bool Result = AsmPrinter::doInitialization(M);
-
- // FIXME:: This is temporary solution to generate the include file.
- // The processor should be passed to llc as in input and the header file
- // should be generated accordingly.
- O << "\n\t#include P16F1937.INC\n";
-
- // Set the section names for all globals.
- for (Module::global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I) {
- I->setSection(TAI->SectionForGlobal(I)->getName());
- }
-
- DbgInfo.BeginModule(M);
- EmitFunctionDecls(M);
- EmitUndefinedVars(M);
- EmitDefinedVars(M);
- EmitIData(M);
- EmitUData(M);
- EmitRomData(M);
- return Result;
-}
-
-/// Emit extern decls for functions imported from other modules, and emit
-/// global declarations for function defined in this module and which are
-/// available to other modules.
-///
-void PIC16AsmPrinter::EmitFunctionDecls (Module &M) {
- // Emit declarations for external functions.
- O <<"\n"<<TAI->getCommentString() << "Function Declarations - BEGIN." <<"\n";
- for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
- std::string Name = Mang->getValueName(I);
- if (Name.compare("@abort") == 0)
- continue;
-
- // If it is llvm intrinsic call then don't emit
- if (Name.find("llvm.") != std::string::npos)
- continue;
-
- if (! (I->isDeclaration() || I->hasExternalLinkage()))
- continue;
-
- const char *directive = I->isDeclaration() ? TAI->getExternDirective() :
- TAI->getGlobalDirective();
-
- O << directive << Name << "\n";
- O << directive << PAN::getRetvalLabel(Name) << "\n";
- O << directive << PAN::getArgsLabel(Name) << "\n";
- }
-
- O << TAI->getCommentString() << "Function Declarations - END." <<"\n";
-}
-
-// Emit variables imported from other Modules.
-void PIC16AsmPrinter::EmitUndefinedVars (Module &M)
-{
- std::vector<const GlobalVariable*> Items = PTAI->ExternalVarDecls->Items;
- if (! Items.size()) return;
-
- O << "\n" << TAI->getCommentString() << "Imported Variables - BEGIN" << "\n";
- for (unsigned j = 0; j < Items.size(); j++) {
- O << TAI->getExternDirective() << Mang->getValueName(Items[j]) << "\n";
- }
- O << TAI->getCommentString() << "Imported Variables - END" << "\n";
-}
-
-// Emit variables defined in this module and are available to other modules.
-void PIC16AsmPrinter::EmitDefinedVars (Module &M)
-{
- std::vector<const GlobalVariable*> Items = PTAI->ExternalVarDefs->Items;
- if (! Items.size()) return;
-
- O << "\n" << TAI->getCommentString() << "Exported Variables - BEGIN" << "\n";
- for (unsigned j = 0; j < Items.size(); j++) {
- O << TAI->getGlobalDirective() << Mang->getValueName(Items[j]) << "\n";
- }
- O << TAI->getCommentString() << "Exported Variables - END" << "\n";
-}
-
-// Emit initialized data placed in ROM.
-void PIC16AsmPrinter::EmitRomData (Module &M)
-{
-
- std::vector<const GlobalVariable*> Items = PTAI->ROSection->Items;
- if (! Items.size()) return;
-
- // Print ROData ection.
- O << "\n";
- SwitchToSection(PTAI->ROSection->S_);
- for (unsigned j = 0; j < Items.size(); j++) {
- O << Mang->getValueName(Items[j]);
- Constant *C = Items[j]->getInitializer();
- int AddrSpace = Items[j]->getType()->getAddressSpace();
- EmitGlobalConstant(C, AddrSpace);
- }
-}
-
-bool PIC16AsmPrinter::doFinalization(Module &M) {
- printLibcallDecls();
- EmitRemainingAutos();
- DbgInfo.EndModule(M);
- O << "\n\t" << "END\n";
- bool Result = AsmPrinter::doFinalization(M);
- return Result;
-}
-
-void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
- const Function *F = MF.getFunction();
- std::string FuncName = Mang->getValueName(F);
- const TargetData *TD = TM.getTargetData();
- // Emit the data section name.
- O << "\n";
- const char *SectionName = PAN::getFrameSectionName(CurrentFnName).c_str();
-
- const Section *fPDataSection = TAI->getNamedSection(SectionName,
- SectionFlags::Writeable);
- SwitchToSection(fPDataSection);
-
- // Emit function frame label
- O << PAN::getFrameLabel(CurrentFnName) << ":\n";
-
- const Type *RetType = F->getReturnType();
- unsigned RetSize = 0;
- if (RetType->getTypeID() != Type::VoidTyID)
- RetSize = TD->getTypeAllocSize(RetType);
-
- //Emit function return value space
- // FIXME: Do not emit RetvalLable when retsize is zero. To do this
- // we will need to avoid printing a global directive for Retval label
- // in emitExternandGloblas.
- if(RetSize > 0)
- O << PAN::getRetvalLabel(CurrentFnName) << " RES " << RetSize << "\n";
- else
- O << PAN::getRetvalLabel(CurrentFnName) << ": \n";
-
- // Emit variable to hold the space for function arguments
- unsigned ArgSize = 0;
- for (Function::const_arg_iterator argi = F->arg_begin(),
- arge = F->arg_end(); argi != arge ; ++argi) {
- const Type *Ty = argi->getType();
- ArgSize += TD->getTypeAllocSize(Ty);
- }
-
- O << PAN::getArgsLabel(CurrentFnName) << " RES " << ArgSize << "\n";
-
- // Emit temporary space
- int TempSize = PTLI->GetTmpSize();
- if (TempSize > 0 )
- O << PAN::getTempdataLabel(CurrentFnName) << " RES " << TempSize <<"\n";
-}
-
-void PIC16AsmPrinter::EmitIData (Module &M) {
-
- // Print all IDATA sections.
- std::vector <PIC16Section *>IDATASections = PTAI->IDATASections;
- for (unsigned i = 0; i < IDATASections.size(); i++) {
- O << "\n";
- SwitchToSection(IDATASections[i]->S_);
- std::vector<const GlobalVariable*> Items = IDATASections[i]->Items;
- for (unsigned j = 0; j < Items.size(); j++) {
- std::string Name = Mang->getValueName(Items[j]);
- Constant *C = Items[j]->getInitializer();
- int AddrSpace = Items[j]->getType()->getAddressSpace();
- O << Name;
- EmitGlobalConstant(C, AddrSpace);
- }
- }
-}
-
-void PIC16AsmPrinter::EmitUData (Module &M) {
- const TargetData *TD = TM.getTargetData();
-
- // Print all BSS sections.
- std::vector <PIC16Section *>BSSSections = PTAI->BSSSections;
- for (unsigned i = 0; i < BSSSections.size(); i++) {
- O << "\n";
- SwitchToSection(BSSSections[i]->S_);
- std::vector<const GlobalVariable*> Items = BSSSections[i]->Items;
- for (unsigned j = 0; j < Items.size(); j++) {
- std::string Name = Mang->getValueName(Items[j]);
- Constant *C = Items[j]->getInitializer();
- const Type *Ty = C->getType();
- unsigned Size = TD->getTypeAllocSize(Ty);
-
- O << Name << " " <<"RES"<< " " << Size ;
- O << "\n";
- }
- }
-}
-
-void PIC16AsmPrinter::EmitAutos (std::string FunctName)
-{
- // Section names for all globals are already set.
-
- const TargetData *TD = TM.getTargetData();
-
- // Now print Autos section for this function.
- std::string SectionName = PAN::getAutosSectionName(FunctName);
- std::vector <PIC16Section *>AutosSections = PTAI->AutosSections;
- for (unsigned i = 0; i < AutosSections.size(); i++) {
- O << "\n";
- if (AutosSections[i]->S_->getName() == SectionName) {
- // Set the printing status to true
- AutosSections[i]->setPrintedStatus(true);
- SwitchToSection(AutosSections[i]->S_);
- std::vector<const GlobalVariable*> Items = AutosSections[i]->Items;
- for (unsigned j = 0; j < Items.size(); j++) {
- std::string VarName = Mang->getValueName(Items[j]);
- Constant *C = Items[j]->getInitializer();
- const Type *Ty = C->getType();
- unsigned Size = TD->getTypeAllocSize(Ty);
- // Emit memory reserve directive.
- O << VarName << " RES " << Size << "\n";
- }
- break;
- }
- }
-}
-
-// Print autos that were not printed during the code printing of functions.
-// As the functions might themselves would have got deleted by the optimizer.
-void PIC16AsmPrinter::EmitRemainingAutos()
-{
- const TargetData *TD = TM.getTargetData();
-
- // Now print Autos section for this function.
- std::vector <PIC16Section *>AutosSections = PTAI->AutosSections;
- for (unsigned i = 0; i < AutosSections.size(); i++) {
-
- // if the section is already printed then don't print again
- if (AutosSections[i]->isPrinted())
- continue;
-
- // Set status as printed
- AutosSections[i]->setPrintedStatus(true);
-
- O << "\n";
- SwitchToSection(AutosSections[i]->S_);
- std::vector<const GlobalVariable*> Items = AutosSections[i]->Items;
- for (unsigned j = 0; j < Items.size(); j++) {
- std::string VarName = Mang->getValueName(Items[j]);
- Constant *C = Items[j]->getInitializer();
- const Type *Ty = C->getType();
- unsigned Size = TD->getTypeAllocSize(Ty);
- // Emit memory reserve directive.
- O << VarName << " RES " << Size << "\n";
- }
- }
-}
-
diff --git a/lib/Target/PIC16/PIC16AsmPrinter.h b/lib/Target/PIC16/PIC16AsmPrinter.h
deleted file mode 100644
index cb11687..0000000
--- a/lib/Target/PIC16/PIC16AsmPrinter.h
+++ /dev/null
@@ -1,70 +0,0 @@
-//===-- PIC16AsmPrinter.h - PIC16 LLVM assembly writer ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file 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 PIC16 assembly language.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef PIC16ASMPRINTER_H
-#define PIC16ASMPRINTER_H
-
-#include "PIC16.h"
-#include "PIC16TargetMachine.h"
-#include "PIC16DebugInfo.h"
-#include "llvm/Analysis/DebugInfo.h"
-#include "PIC16TargetAsmInfo.h"
-#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include <list>
-#include <string>
-
-namespace llvm {
- struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter {
- explicit PIC16AsmPrinter(raw_ostream &O, PIC16TargetMachine &TM,
- const TargetAsmInfo *T, bool V)
- : AsmPrinter(O, TM, T, V), DbgInfo(O, T) {
- PTLI = TM.getTargetLowering();
- PTAI = static_cast<const PIC16TargetAsmInfo *> (T);
- }
- private :
- virtual const char *getPassName() const {
- return "PIC16 Assembly Printer";
- }
-
- bool runOnMachineFunction(MachineFunction &F);
- void printOperand(const MachineInstr *MI, int opNum);
- void printCCOperand(const MachineInstr *MI, int opNum);
- bool printInstruction(const MachineInstr *MI); // definition autogenerated.
- bool printMachineInstruction(const MachineInstr *MI);
- void EmitFunctionDecls (Module &M);
- void EmitUndefinedVars (Module &M);
- void EmitDefinedVars (Module &M);
- void EmitIData (Module &M);
- void EmitUData (Module &M);
- void EmitAutos (std::string FunctName);
- void EmitRemainingAutos ();
- void EmitRomData (Module &M);
- void EmitFunctionFrame(MachineFunction &MF);
- void printLibcallDecls(void);
- protected:
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
-
- private:
- PIC16TargetLowering *PTLI;
- PIC16DbgInfo DbgInfo;
- const PIC16TargetAsmInfo *PTAI;
- std::list<const char *> LibcallDecls; // List of extern decls.
- };
-} // end of namespace
-
-#endif
diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp b/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
deleted file mode 100644
index d2657f0..0000000
--- a/lib/Target/PIC16/PIC16TargetAsmInfo.cpp
+++ /dev/null
@@ -1,264 +0,0 @@
-//===-- PIC16TargetAsmInfo.cpp - PIC16 asm properties ---------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the PIC16TargetAsmInfo properties.
-//
-//===----------------------------------------------------------------------===//
-
-#include "PIC16TargetAsmInfo.h"
-#include "PIC16TargetMachine.h"
-#include "llvm/GlobalValue.h"
-#include "llvm/GlobalVariable.h"
-#include "llvm/DerivedTypes.h"
-
-using namespace llvm;
-
-PIC16TargetAsmInfo::
-PIC16TargetAsmInfo(const PIC16TargetMachine &TM)
- : TargetAsmInfo(TM) {
- CommentString = ";";
- GlobalPrefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
- GlobalDirective = "\tglobal\t";
- ExternDirective = "\textern\t";
-
- Data8bitsDirective = " db ";
- Data16bitsDirective = " dw ";
- Data32bitsDirective = " dl ";
- RomData8bitsDirective = " dw ";
- RomData16bitsDirective = " rom_di ";
- RomData32bitsDirective = " rom_dl ";
- ZeroDirective = NULL;
- AsciiDirective = " dt ";
- AscizDirective = NULL;
- BSSSection_ = getNamedSection("udata.# UDATA",
- SectionFlags::Writeable | SectionFlags::BSS);
- ReadOnlySection = getNamedSection("romdata.# ROMDATA", SectionFlags::None);
- DataSection = getNamedSection("idata.# IDATA", SectionFlags::Writeable);
- SwitchToSectionDirective = "";
- // Need because otherwise a .text symbol is emitted by DwarfWriter
- // in BeginModule, and gpasm cribbs for that .text symbol.
- TextSection = getUnnamedSection("", SectionFlags::Code);
- ROSection = new PIC16Section(getReadOnlySection());
- ExternalVarDecls = new PIC16Section(getNamedSection("ExternalVarDecls"));
- ExternalVarDefs = new PIC16Section(getNamedSection("ExternalVarDefs"));
- // Set it to false because we weed to generate c file name and not bc file
- // name.
- HasSingleParameterDotFile = false;
-}
-
-const char *PIC16TargetAsmInfo::getRomDirective(unsigned size) const
-{
- if (size == 8)
- return RomData8bitsDirective;
- else if (size == 16)
- return RomData16bitsDirective;
- else if (size == 32)
- return RomData32bitsDirective;
- else
- return NULL;
-}
-
-
-const char *PIC16TargetAsmInfo::getASDirective(unsigned size,
- unsigned AS) const {
- if (AS == PIC16ISD::ROM_SPACE)
- return getRomDirective(size);
- else
- return NULL;
-}
-
-const Section *
-PIC16TargetAsmInfo::getBSSSectionForGlobal(const GlobalVariable *GV) const {
- assert (GV->hasInitializer() && "This global doesn't need space");
- Constant *C = GV->getInitializer();
- assert (C->isNullValue() && "Unitialized globals has non-zero initializer");
-
- // Find how much space this global needs.
- const TargetData *TD = TM.getTargetData();
- const Type *Ty = C->getType();
- unsigned ValSize = TD->getTypeAllocSize(Ty);
-
- // Go through all BSS Sections and assign this variable
- // to the first available section having enough space.
- PIC16Section *FoundBSS = NULL;
- for (unsigned i = 0; i < BSSSections.size(); i++) {
- if (DataBankSize - BSSSections[i]->Size >= ValSize) {
- FoundBSS = BSSSections[i];
- break;
- }
- }
-
- // No BSS section spacious enough was found. Crate a new one.
- if (! FoundBSS) {
- std::string name = PAN::getUdataSectionName(BSSSections.size());
- const Section *NewSection = getNamedSection (name.c_str());
-
- FoundBSS = new PIC16Section(NewSection);
-
- // Add this newly created BSS section to the list of BSSSections.
- BSSSections.push_back(FoundBSS);
- }
-
- // Insert the GV into this BSS.
- FoundBSS->Items.push_back(GV);
- FoundBSS->Size += ValSize;
-
- // We can't do this here because GV is const .
- // const std::string SName = FoundBSS->S_->getName();
- // GV->setSection(SName);
-
- return FoundBSS->S_;
-}
-
-const Section *
-PIC16TargetAsmInfo::getIDATASectionForGlobal(const GlobalVariable *GV) const {
- assert (GV->hasInitializer() && "This global doesn't need space");
- Constant *C = GV->getInitializer();
- assert (!C->isNullValue() && "initialized globals has zero initializer");
- assert (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
- "can split initialized RAM data only");
-
- // Find how much space this global needs.
- const TargetData *TD = TM.getTargetData();
- const Type *Ty = C->getType();
- unsigned ValSize = TD->getTypeAllocSize(Ty);
-
- // Go through all IDATA Sections and assign this variable
- // to the first available section having enough space.
- PIC16Section *FoundIDATA = NULL;
- for (unsigned i = 0; i < IDATASections.size(); i++) {
- if ( DataBankSize - IDATASections[i]->Size >= ValSize) {
- FoundIDATA = IDATASections[i];
- break;
- }
- }
-
- // No IDATA section spacious enough was found. Crate a new one.
- if (! FoundIDATA) {
- std::string name = PAN::getIdataSectionName(IDATASections.size());
- const Section *NewSection = getNamedSection (name.c_str());
-
- FoundIDATA = new PIC16Section(NewSection);
-
- // Add this newly created IDATA section to the list of IDATASections.
- IDATASections.push_back(FoundIDATA);
- }
-
- // Insert the GV into this IDATA.
- FoundIDATA->Items.push_back(GV);
- FoundIDATA->Size += ValSize;
-
- // We can't do this here because GV is const .
- // GV->setSection(FoundIDATA->S->getName());
-
- return FoundIDATA->S_;
-}
-
-// Get the section for an automatic variable of a function.
-// For PIC16 they are globals only with mangled names.
-const Section *
-PIC16TargetAsmInfo::getSectionForAuto(const GlobalVariable *GV) const {
-
- const std::string name = PAN::getSectionNameForSym(GV->getName());
-
- // Go through all Auto Sections and assign this variable
- // to the appropriate section.
- PIC16Section *FoundAutoSec = NULL;
- for (unsigned i = 0; i < AutosSections.size(); i++) {
- if ( AutosSections[i]->S_->getName() == name) {
- FoundAutoSec = AutosSections[i];
- break;
- }
- }
-
- // No Auto section was found. Crate a new one.
- if (! FoundAutoSec) {
- const Section *NewSection = getNamedSection (name.c_str());
-
- FoundAutoSec = new PIC16Section(NewSection);
-
- // Add this newly created autos section to the list of AutosSections.
- AutosSections.push_back(FoundAutoSec);
- }
-
- // Insert the auto into this section.
- FoundAutoSec->Items.push_back(GV);
-
- return FoundAutoSec->S_;
-}
-
-
-// Override default implementation to put the true globals into
-// multiple data sections if required.
-const Section*
-PIC16TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV1) const {
- // We select the section based on the initializer here, so it really
- // has to be a GlobalVariable.
- const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
-
- if (!GV)
- return TargetAsmInfo::SelectSectionForGlobal(GV1);
-
- // Record Exteranl Var Decls.
- if (GV->isDeclaration()) {
- ExternalVarDecls->Items.push_back(GV);
- return ExternalVarDecls->S_;
- }
-
- assert (GV->hasInitializer() && "A def without initializer?");
-
- // First, if this is an automatic variable for a function, get the section
- // name for it and return.
- const std::string name = GV->getName();
- if (PAN::isLocalName(name)) {
- return getSectionForAuto(GV);
- }
-
- // Record Exteranl Var Defs.
- if (GV->hasExternalLinkage() || GV->hasCommonLinkage()) {
- ExternalVarDefs->Items.push_back(GV);
- }
-
- // See if this is an uninitialized global.
- const Constant *C = GV->getInitializer();
- if (C->isNullValue())
- return getBSSSectionForGlobal(GV);
-
- // If this is initialized data in RAM. Put it in the correct IDATA section.
- if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
- return getIDATASectionForGlobal(GV);
-
- // This is initialized data in rom, put it in the readonly section.
- if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) {
- ROSection->Items.push_back(GV);
- return ROSection->S_;
- }
-
- // Else let the default implementation take care of it.
- return TargetAsmInfo::SelectSectionForGlobal(GV);
-}
-
-PIC16TargetAsmInfo::~PIC16TargetAsmInfo() {
-
- for (unsigned i = 0; i < BSSSections.size(); i++) {
- delete BSSSections[i];
- }
-
- for (unsigned i = 0; i < IDATASections.size(); i++) {
- delete IDATASections[i];
- }
-
- for (unsigned i = 0; i < AutosSections.size(); i++) {
- delete AutosSections[i];
- }
-
- delete ROSection;
- delete ExternalVarDecls;
- delete ExternalVarDefs;
-}
diff --git a/lib/Target/PIC16/PIC16TargetAsmInfo.h b/lib/Target/PIC16/PIC16TargetAsmInfo.h
deleted file mode 100644
index b7292b8..0000000
--- a/lib/Target/PIC16/PIC16TargetAsmInfo.h
+++ /dev/null
@@ -1,83 +0,0 @@
-//=====-- PIC16TargetAsmInfo.h - PIC16 asm properties ---------*- C++ -*--====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the PIC16TargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef PIC16TARGETASMINFO_H
-#define PIC16TARGETASMINFO_H
-
-#include "PIC16.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include <vector>
-#include "llvm/Module.h"
-#define DataBankSize 80
-namespace llvm {
-
- // Forward declaration.
- class PIC16TargetMachine;
- class GlobalVariable;
-
- // PIC16 Splits the global data into mulitple udata and idata sections.
- // Each udata and idata section needs to contain a list of globals that
- // they contain, in order to avoid scanning over all the global values
- // again and printing only those that match the current section.
- // Keeping values inside the sections make printing a section much easier.
- struct PIC16Section {
- const Section *S_; // Connection to actual Section.
- unsigned Size; // Total size of the objects contained.
- bool SectionPrinted;
- std::vector<const GlobalVariable*> Items;
-
- PIC16Section (const Section *s) { S_ = s; Size = 0;
- SectionPrinted = false;}
- bool isPrinted() { return SectionPrinted ; }
- void setPrintedStatus(bool status) { SectionPrinted = status ;}
- };
-
- struct PIC16TargetAsmInfo : public TargetAsmInfo {
- std::string getSectionNameForSym(const std::string &Sym) const;
- PIC16TargetAsmInfo(const PIC16TargetMachine &TM);
- mutable std::vector<PIC16Section *> BSSSections;
- mutable std::vector<PIC16Section *> IDATASections;
- mutable std::vector<PIC16Section *> AutosSections;
- mutable PIC16Section *ROSection;
- mutable PIC16Section *ExternalVarDecls;
- mutable PIC16Section *ExternalVarDefs;
- virtual ~PIC16TargetAsmInfo();
-
- private:
- const char *RomData8bitsDirective;
- const char *RomData16bitsDirective;
- const char *RomData32bitsDirective;
- const char *getRomDirective(unsigned size) const;
- virtual const char *getASDirective(unsigned size, unsigned AS) const;
- const Section *getBSSSectionForGlobal(const GlobalVariable *GV) const;
- const Section *getIDATASectionForGlobal(const GlobalVariable *GV) const;
- const Section *getSectionForAuto(const GlobalVariable *GV) const;
- virtual const Section *SelectSectionForGlobal(const GlobalValue *GV) const;
-
-
- public:
- void SetSectionForGVs(Module &M);
- std::vector<PIC16Section *> getBSSSections() const {
- return BSSSections;
- }
- std::vector<PIC16Section *> getIDATASections() const {
- return IDATASections;
- }
- std::vector<PIC16Section *> getAutosSections() const {
- return AutosSections;
- }
- };
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/PowerPC/PPCTargetAsmInfo.cpp b/lib/Target/PowerPC/PPCTargetAsmInfo.cpp
deleted file mode 100644
index ebffd69..0000000
--- a/lib/Target/PowerPC/PPCTargetAsmInfo.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-//===-- PPCTargetAsmInfo.cpp - PPC asm properties ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the DarwinTargetAsmInfo properties.
-//
-//===----------------------------------------------------------------------===//
-
-#include "PPCTargetAsmInfo.h"
-#include "PPCTargetMachine.h"
-#include "llvm/Function.h"
-#include "llvm/Support/Dwarf.h"
-
-using namespace llvm;
-using namespace llvm::dwarf;
-
-PPCDarwinTargetAsmInfo::PPCDarwinTargetAsmInfo(const PPCTargetMachine &TM) :
- PPCTargetAsmInfo<DarwinTargetAsmInfo>(TM) {
- PCSymbol = ".";
- CommentString = ";";
- ConstantPoolSection = "\t.const\t";
- UsedDirective = "\t.no_dead_strip\t";
- SupportsExceptionHandling = true;
-
- DwarfEHFrameSection =
- ".section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support";
- DwarfExceptionSection = ".section __DATA,__gcc_except_tab";
- GlobalEHDirective = "\t.globl\t";
- SupportsWeakOmittedEHFrame = false;
-}
-
-/// PreferredEHDataFormat - This hook allows the target to select data
-/// format used for encoding pointers in exception handling data. Reason is
-/// 0 for data, 1 for code labels, 2 for function pointers. Global is true
-/// if the symbol can be relocated.
-unsigned
-PPCDarwinTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const {
- if (Reason == DwarfEncoding::Functions && Global)
- return (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4);
- else if (Reason == DwarfEncoding::CodeLabels || !Global)
- return DW_EH_PE_pcrel;
- else
- return DW_EH_PE_absptr;
-}
-
-const char *
-PPCDarwinTargetAsmInfo::getEHGlobalPrefix() const
-{
- const PPCSubtarget* Subtarget = &TM.getSubtarget<PPCSubtarget>();
- if (Subtarget->getDarwinVers() > 9)
- return PrivateGlobalPrefix;
- else
- return "";
-}
-
-PPCLinuxTargetAsmInfo::PPCLinuxTargetAsmInfo(const PPCTargetMachine &TM) :
- PPCTargetAsmInfo<ELFTargetAsmInfo>(TM) {
- CommentString = "#";
- GlobalPrefix = "";
- PrivateGlobalPrefix = ".L";
- ConstantPoolSection = "\t.section .rodata.cst4\t";
- JumpTableDataSection = ".section .rodata.cst4";
- CStringSection = ".rodata.str";
- StaticCtorsSection = ".section\t.ctors,\"aw\",@progbits";
- StaticDtorsSection = ".section\t.dtors,\"aw\",@progbits";
- UsedDirective = "\t# .no_dead_strip\t";
- WeakRefDirective = "\t.weak\t";
- BSSSection = "\t.section\t\".sbss\",\"aw\",@nobits";
-
- // PPC/Linux normally uses named section for BSS.
- BSSSection_ = getNamedSection("\t.bss",
- SectionFlags::Writeable | SectionFlags::BSS,
- /* Override */ true);
-
- // Debug Information
- AbsoluteDebugSectionOffsets = true;
- SupportsDebugInformation = true;
- DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"\",@progbits";
- DwarfInfoSection = "\t.section\t.debug_info,\"\",@progbits";
- DwarfLineSection = "\t.section\t.debug_line,\"\",@progbits";
- DwarfFrameSection = "\t.section\t.debug_frame,\"\",@progbits";
- DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"\",@progbits";
- DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"\",@progbits";
- DwarfStrSection = "\t.section\t.debug_str,\"\",@progbits";
- DwarfLocSection = "\t.section\t.debug_loc,\"\",@progbits";
- DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits";
- DwarfRangesSection = "\t.section\t.debug_ranges,\"\",@progbits";
- DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
-
- PCSymbol = ".";
-
- // Set up DWARF directives
- HasLEB128 = true; // Target asm supports leb128 directives (little-endian)
-
- // Exceptions handling
- if (!TM.getSubtargetImpl()->isPPC64())
- SupportsExceptionHandling = true;
- AbsoluteEHSectionOffsets = false;
- DwarfEHFrameSection = "\t.section\t.eh_frame,\"aw\",@progbits";
- DwarfExceptionSection = "\t.section\t.gcc_except_table,\"a\",@progbits";
-}
-
-/// PreferredEHDataFormat - This hook allows the target to select data
-/// format used for encoding pointers in exception handling data. Reason is
-/// 0 for data, 1 for code labels, 2 for function pointers. Global is true
-/// if the symbol can be relocated.
-unsigned
-PPCLinuxTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const {
- // We really need to write something here.
- return TargetAsmInfo::PreferredEHDataFormat(Reason, Global);
-}
-
-// Instantiate default implementation.
-TEMPLATE_INSTANTIATION(class PPCTargetAsmInfo<TargetAsmInfo>);
diff --git a/lib/Target/PowerPC/PPCTargetAsmInfo.h b/lib/Target/PowerPC/PPCTargetAsmInfo.h
deleted file mode 100644
index edf40c9..0000000
--- a/lib/Target/PowerPC/PPCTargetAsmInfo.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//=====-- PPCTargetAsmInfo.h - PPC asm properties -------------*- C++ -*--====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the DarwinTargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef PPCTARGETASMINFO_H
-#define PPCTARGETASMINFO_H
-
-#include "PPCTargetMachine.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/DarwinTargetAsmInfo.h"
-#include "llvm/Target/ELFTargetAsmInfo.h"
-#include "llvm/Support/Compiler.h"
-
-namespace llvm {
-
- template <class BaseTAI>
- struct PPCTargetAsmInfo : public BaseTAI {
- explicit PPCTargetAsmInfo(const PPCTargetMachine &TM):
- BaseTAI(TM) {
- const PPCSubtarget *Subtarget = &TM.getSubtarget<PPCSubtarget>();
- bool isPPC64 = Subtarget->isPPC64();
-
- BaseTAI::ZeroDirective = "\t.space\t";
- BaseTAI::SetDirective = "\t.set";
- BaseTAI::Data64bitsDirective = isPPC64 ? "\t.quad\t" : 0;
- BaseTAI::AlignmentIsInBytes = false;
- BaseTAI::LCOMMDirective = "\t.lcomm\t";
- BaseTAI::InlineAsmStart = "# InlineAsm Start";
- BaseTAI::InlineAsmEnd = "# InlineAsm End";
- BaseTAI::AssemblerDialect = Subtarget->getAsmFlavor();
- }
- };
-
- typedef PPCTargetAsmInfo<TargetAsmInfo> PPCGenericTargetAsmInfo;
-
- EXTERN_TEMPLATE_INSTANTIATION(class PPCTargetAsmInfo<TargetAsmInfo>);
-
- struct PPCDarwinTargetAsmInfo : public PPCTargetAsmInfo<DarwinTargetAsmInfo> {
- explicit PPCDarwinTargetAsmInfo(const PPCTargetMachine &TM);
- virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const;
- virtual const char *getEHGlobalPrefix() const;
- };
-
- struct PPCLinuxTargetAsmInfo : public PPCTargetAsmInfo<ELFTargetAsmInfo> {
- explicit PPCLinuxTargetAsmInfo(const PPCTargetMachine &TM);
- virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const;
- };
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/Sparc/SparcTargetAsmInfo.cpp b/lib/Target/Sparc/SparcTargetAsmInfo.cpp
deleted file mode 100644
index c13d45c..0000000
--- a/lib/Target/Sparc/SparcTargetAsmInfo.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-//===-- SparcTargetAsmInfo.cpp - Sparc asm properties -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the SparcTargetAsmInfo properties.
-//
-//===----------------------------------------------------------------------===//
-
-#include "SparcTargetAsmInfo.h"
-
-using namespace llvm;
-
-SparcELFTargetAsmInfo::SparcELFTargetAsmInfo(const TargetMachine &TM):
- ELFTargetAsmInfo(TM) {
- Data16bitsDirective = "\t.half\t";
- Data32bitsDirective = "\t.word\t";
- Data64bitsDirective = 0; // .xword is only supported by V9.
- ZeroDirective = "\t.skip\t";
- CommentString = "!";
- ConstantPoolSection = "\t.section \".rodata\",#alloc\n";
- COMMDirectiveTakesAlignment = true;
- CStringSection=".rodata.str";
-
- // Sparc normally uses named section for BSS.
- BSSSection_ = getNamedSection("\t.bss",
- SectionFlags::Writeable | SectionFlags::BSS,
- /* Override */ true);
-}
-
-std::string SparcELFTargetAsmInfo::printSectionFlags(unsigned flags) const {
- if (flags & SectionFlags::Mergeable)
- return ELFTargetAsmInfo::printSectionFlags(flags);
-
- std::string Flags;
- if (!(flags & SectionFlags::Debug))
- Flags += ",#alloc";
- if (flags & SectionFlags::Code)
- Flags += ",#execinstr";
- if (flags & SectionFlags::Writeable)
- Flags += ",#write";
- if (flags & SectionFlags::TLS)
- Flags += ",#tls";
-
- return Flags;
-}
diff --git a/lib/Target/Sparc/SparcTargetAsmInfo.h b/lib/Target/Sparc/SparcTargetAsmInfo.h
deleted file mode 100644
index 1af5d80..0000000
--- a/lib/Target/Sparc/SparcTargetAsmInfo.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//=====-- SparcTargetAsmInfo.h - Sparc asm properties ---------*- C++ -*--====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the SparcTargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SPARCTARGETASMINFO_H
-#define SPARCTARGETASMINFO_H
-
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/ELFTargetAsmInfo.h"
-
-namespace llvm {
-
- // Forward declaration.
- class TargetMachine;
-
- struct SparcELFTargetAsmInfo : public ELFTargetAsmInfo {
- explicit SparcELFTargetAsmInfo(const TargetMachine &TM);
-
- std::string printSectionFlags(unsigned flags) const;
- };
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp
deleted file mode 100644
index 3f5f1bd..0000000
--- a/lib/Target/TargetAsmInfo.cpp
+++ /dev/null
@@ -1,456 +0,0 @@
-//===-- TargetAsmInfo.cpp - Asm Info ---------------------------------------==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines target asm properties related what form asm statements
-// should take.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/GlobalVariable.h"
-#include "llvm/Function.h"
-#include "llvm/Module.h"
-#include "llvm/Type.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetOptions.h"
-#include "llvm/Support/Dwarf.h"
-#include <cctype>
-#include <cstring>
-using namespace llvm;
-
-TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm)
-: TM(tm) {
- BSSSection = "\t.bss";
- BSSSection_ = 0;
- ReadOnlySection = 0;
- SmallDataSection = 0;
- SmallBSSSection = 0;
- SmallRODataSection = 0;
- TLSDataSection = 0;
- TLSBSSSection = 0;
- ZeroFillDirective = 0;
- NonexecutableStackDirective = 0;
- NeedsSet = false;
- MaxInstLength = 4;
- PCSymbol = "$";
- SeparatorChar = ';';
- CommentString = "#";
- GlobalPrefix = "";
- PrivateGlobalPrefix = ".";
- LessPrivateGlobalPrefix = "";
- JumpTableSpecialLabelPrefix = 0;
- GlobalVarAddrPrefix = "";
- GlobalVarAddrSuffix = "";
- FunctionAddrPrefix = "";
- FunctionAddrSuffix = "";
- PersonalityPrefix = "";
- PersonalitySuffix = "";
- NeedsIndirectEncoding = false;
- InlineAsmStart = "#APP";
- InlineAsmEnd = "#NO_APP";
- AssemblerDialect = 0;
- StringConstantPrefix = ".str";
- AllowQuotesInName = false;
- ZeroDirective = "\t.zero\t";
- ZeroDirectiveSuffix = 0;
- AsciiDirective = "\t.ascii\t";
- AscizDirective = "\t.asciz\t";
- Data8bitsDirective = "\t.byte\t";
- Data16bitsDirective = "\t.short\t";
- Data32bitsDirective = "\t.long\t";
- Data64bitsDirective = "\t.quad\t";
- AlignDirective = "\t.align\t";
- AlignmentIsInBytes = true;
- TextAlignFillValue = 0;
- SwitchToSectionDirective = "\t.section\t";
- TextSectionStartSuffix = "";
- DataSectionStartSuffix = "";
- SectionEndDirectiveSuffix = 0;
- ConstantPoolSection = "\t.section .rodata";
- JumpTableDataSection = "\t.section .rodata";
- JumpTableDirective = 0;
- CStringSection = 0;
- CStringSection_ = 0;
- // FIXME: Flags are ELFish - replace with normal section stuff.
- StaticCtorsSection = "\t.section .ctors,\"aw\",@progbits";
- StaticDtorsSection = "\t.section .dtors,\"aw\",@progbits";
- GlobalDirective = "\t.globl\t";
- SetDirective = 0;
- LCOMMDirective = 0;
- COMMDirective = "\t.comm\t";
- COMMDirectiveTakesAlignment = true;
- HasDotTypeDotSizeDirective = true;
- HasSingleParameterDotFile = true;
- UsedDirective = 0;
- WeakRefDirective = 0;
- WeakDefDirective = 0;
- // FIXME: These are ELFish - move to ELFTAI.
- HiddenDirective = "\t.hidden\t";
- ProtectedDirective = "\t.protected\t";
- AbsoluteDebugSectionOffsets = false;
- AbsoluteEHSectionOffsets = false;
- HasLEB128 = false;
- HasDotLocAndDotFile = false;
- SupportsDebugInformation = false;
- SupportsExceptionHandling = false;
- DwarfRequiresFrameSection = true;
- DwarfUsesInlineInfoSection = false;
- NonLocalEHFrameLabel = false;
- GlobalEHDirective = 0;
- SupportsWeakOmittedEHFrame = true;
- DwarfSectionOffsetDirective = 0;
- DwarfAbbrevSection = ".debug_abbrev";
- DwarfInfoSection = ".debug_info";
- DwarfLineSection = ".debug_line";
- DwarfFrameSection = ".debug_frame";
- DwarfPubNamesSection = ".debug_pubnames";
- DwarfPubTypesSection = ".debug_pubtypes";
- DwarfDebugInlineSection = ".debug_inlined";
- DwarfStrSection = ".debug_str";
- DwarfLocSection = ".debug_loc";
- DwarfARangesSection = ".debug_aranges";
- DwarfRangesSection = ".debug_ranges";
- DwarfMacroInfoSection = ".debug_macinfo";
- DwarfEHFrameSection = ".eh_frame";
- DwarfExceptionSection = ".gcc_except_table";
- AsmTransCBE = 0;
- TextSection = getUnnamedSection("\t.text", SectionFlags::Code);
- DataSection = getUnnamedSection("\t.data", SectionFlags::Writeable);
-}
-
-TargetAsmInfo::~TargetAsmInfo() {
-}
-
-/// Measure the specified inline asm to determine an approximation of its
-/// length.
-/// Comments (which run till the next SeparatorChar or newline) do not
-/// count as an instruction.
-/// Any other non-whitespace text is considered an instruction, with
-/// multiple instructions separated by SeparatorChar or newlines.
-/// Variable-length instructions are not handled here; this function
-/// may be overloaded in the target code to do that.
-unsigned TargetAsmInfo::getInlineAsmLength(const char *Str) const {
- // Count the number of instructions in the asm.
- bool atInsnStart = true;
- unsigned Length = 0;
- for (; *Str; ++Str) {
- if (*Str == '\n' || *Str == SeparatorChar)
- atInsnStart = true;
- if (atInsnStart && !isspace(*Str)) {
- Length += MaxInstLength;
- atInsnStart = false;
- }
- if (atInsnStart && strncmp(Str, CommentString, strlen(CommentString))==0)
- atInsnStart = false;
- }
-
- return Length;
-}
-
-unsigned TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const {
- return dwarf::DW_EH_PE_absptr;
-}
-
-static bool isSuitableForBSS(const GlobalVariable *GV) {
- if (!GV->hasInitializer())
- return true;
-
- // Leave constant zeros in readonly constant sections, so they can be shared
- Constant *C = GV->getInitializer();
- return (C->isNullValue() && !GV->isConstant() && !NoZerosInBSS);
-}
-
-static bool isConstantString(const Constant *C) {
- // First check: is we have constant array of i8 terminated with zero
- const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
- // Check, if initializer is a null-terminated string
- if (CVA && CVA->isCString())
- return true;
-
- // Another possibility: [1 x i8] zeroinitializer
- if (isa<ConstantAggregateZero>(C)) {
- if (const ArrayType *Ty = dyn_cast<ArrayType>(C->getType())) {
- return (Ty->getElementType() == Type::Int8Ty &&
- Ty->getNumElements() == 1);
- }
- }
-
- return false;
-}
-
-unsigned TargetAsmInfo::RelocBehaviour() const {
- // By default - all relocations in PIC mode would force symbol to be
- // placed in r/w section.
- return (TM.getRelocationModel() != Reloc::Static ?
- Reloc::LocalOrGlobal : Reloc::None);
-}
-
-SectionKind::Kind
-TargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const {
- // Early exit - functions should be always in text sections.
- if (isa<Function>(GV))
- return SectionKind::Text;
-
- const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV);
- bool isThreadLocal = GVar->isThreadLocal();
- assert(GVar && "Invalid global value for section selection");
-
- if (isSuitableForBSS(GVar)) {
- // Variable can be easily put to BSS section.
- return (isThreadLocal ? SectionKind::ThreadBSS : SectionKind::BSS);
- } else if (GVar->isConstant() && !isThreadLocal) {
- // Now we know, that varible has initializer and it is constant. We need to
- // check its initializer to decide, which section to output it into. Also
- // note, there is no thread-local r/o section.
- Constant *C = GVar->getInitializer();
- if (C->ContainsRelocations(Reloc::LocalOrGlobal)) {
- // Decide, whether it is still possible to put symbol into r/o section.
- unsigned Reloc = RelocBehaviour();
-
- // We already did a query for 'all' relocs, thus - early exits.
- if (Reloc == Reloc::LocalOrGlobal)
- return SectionKind::Data;
- else if (Reloc == Reloc::None)
- return SectionKind::ROData;
- else {
- // Ok, target wants something funny. Honour it.
- return (C->ContainsRelocations(Reloc) ?
- SectionKind::Data : SectionKind::ROData);
- }
- } else {
- // Check, if initializer is a null-terminated string
- if (isConstantString(C))
- return SectionKind::RODataMergeStr;
- else
- return SectionKind::RODataMergeConst;
- }
- }
-
- // Variable either is not constant or thread-local - output to data section.
- return (isThreadLocal ? SectionKind::ThreadData : SectionKind::Data);
-}
-
-unsigned
-TargetAsmInfo::SectionFlagsForGlobal(const GlobalValue *GV,
- const char* Name) const {
- unsigned Flags = SectionFlags::None;
-
- // Decode flags from global itself.
- if (GV) {
- SectionKind::Kind Kind = SectionKindForGlobal(GV);
- switch (Kind) {
- case SectionKind::Text:
- Flags |= SectionFlags::Code;
- break;
- case SectionKind::ThreadData:
- case SectionKind::ThreadBSS:
- Flags |= SectionFlags::TLS;
- // FALLS THROUGH
- case SectionKind::Data:
- case SectionKind::DataRel:
- case SectionKind::DataRelLocal:
- case SectionKind::DataRelRO:
- case SectionKind::DataRelROLocal:
- case SectionKind::BSS:
- Flags |= SectionFlags::Writeable;
- break;
- case SectionKind::ROData:
- case SectionKind::RODataMergeStr:
- case SectionKind::RODataMergeConst:
- // No additional flags here
- break;
- case SectionKind::SmallData:
- case SectionKind::SmallBSS:
- Flags |= SectionFlags::Writeable;
- // FALLS THROUGH
- case SectionKind::SmallROData:
- Flags |= SectionFlags::Small;
- break;
- default:
- assert(0 && "Unexpected section kind!");
- }
-
- if (GV->isWeakForLinker())
- Flags |= SectionFlags::Linkonce;
- }
-
- // Add flags from sections, if any.
- if (Name && *Name) {
- Flags |= SectionFlags::Named;
-
- // Some lame default implementation based on some magic section names.
- if (strncmp(Name, ".gnu.linkonce.b.", 16) == 0 ||
- strncmp(Name, ".llvm.linkonce.b.", 17) == 0 ||
- strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 ||
- strncmp(Name, ".llvm.linkonce.sb.", 18) == 0)
- Flags |= SectionFlags::BSS;
- else if (strcmp(Name, ".tdata") == 0 ||
- strncmp(Name, ".tdata.", 7) == 0 ||
- strncmp(Name, ".gnu.linkonce.td.", 17) == 0 ||
- strncmp(Name, ".llvm.linkonce.td.", 18) == 0)
- Flags |= SectionFlags::TLS;
- else if (strcmp(Name, ".tbss") == 0 ||
- strncmp(Name, ".tbss.", 6) == 0 ||
- strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 ||
- strncmp(Name, ".llvm.linkonce.tb.", 18) == 0)
- Flags |= SectionFlags::BSS | SectionFlags::TLS;
- }
-
- return Flags;
-}
-
-const Section*
-TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
- const Section* S;
- // Select section name
- if (GV->hasSection()) {
- // Honour section already set, if any
- unsigned Flags = SectionFlagsForGlobal(GV,
- GV->getSection().c_str());
- S = getNamedSection(GV->getSection().c_str(), Flags);
- } else {
- // Use default section depending on the 'type' of global
- S = SelectSectionForGlobal(GV);
- }
-
- return S;
-}
-
-// Lame default implementation. Calculate the section name for global.
-const Section*
-TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
- SectionKind::Kind Kind = SectionKindForGlobal(GV);
-
- if (GV->isWeakForLinker()) {
- std::string Name = UniqueSectionForGlobal(GV, Kind);
- unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str());
- return getNamedSection(Name.c_str(), Flags);
- } else {
- if (Kind == SectionKind::Text)
- return getTextSection();
- else if (isBSS(Kind) && getBSSSection_())
- return getBSSSection_();
- else if (getReadOnlySection() && SectionKind::isReadOnly(Kind))
- return getReadOnlySection();
- }
-
- return getDataSection();
-}
-
-// Lame default implementation. Calculate the section name for machine const.
-const Section*
-TargetAsmInfo::SelectSectionForMachineConst(const Type *Ty) const {
- // FIXME: Support data.rel stuff someday
- return getDataSection();
-}
-
-std::string
-TargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV,
- SectionKind::Kind Kind) const {
- switch (Kind) {
- case SectionKind::Text:
- return ".gnu.linkonce.t." + GV->getName();
- case SectionKind::Data:
- return ".gnu.linkonce.d." + GV->getName();
- case SectionKind::DataRel:
- return ".gnu.linkonce.d.rel" + GV->getName();
- case SectionKind::DataRelLocal:
- return ".gnu.linkonce.d.rel.local" + GV->getName();
- case SectionKind::DataRelRO:
- return ".gnu.linkonce.d.rel.ro" + GV->getName();
- case SectionKind::DataRelROLocal:
- return ".gnu.linkonce.d.rel.ro.local" + GV->getName();
- case SectionKind::SmallData:
- return ".gnu.linkonce.s." + GV->getName();
- case SectionKind::BSS:
- return ".gnu.linkonce.b." + GV->getName();
- case SectionKind::SmallBSS:
- return ".gnu.linkonce.sb." + GV->getName();
- case SectionKind::ROData:
- case SectionKind::RODataMergeConst:
- case SectionKind::RODataMergeStr:
- return ".gnu.linkonce.r." + GV->getName();
- case SectionKind::SmallROData:
- return ".gnu.linkonce.s2." + GV->getName();
- case SectionKind::ThreadData:
- return ".gnu.linkonce.td." + GV->getName();
- case SectionKind::ThreadBSS:
- return ".gnu.linkonce.tb." + GV->getName();
- default:
- assert(0 && "Unknown section kind");
- }
- return NULL;
-}
-
-const Section*
-TargetAsmInfo::getNamedSection(const char *Name, unsigned Flags,
- bool Override) const {
- Section& S = Sections[Name];
-
- // This is newly-created section, set it up properly.
- if (S.Flags == SectionFlags::Invalid || Override) {
- S.Flags = Flags | SectionFlags::Named;
- S.Name = Name;
- }
-
- return &S;
-}
-
-const Section*
-TargetAsmInfo::getUnnamedSection(const char *Directive, unsigned Flags,
- bool Override) const {
- Section& S = Sections[Directive];
-
- // This is newly-created section, set it up properly.
- if (S.Flags == SectionFlags::Invalid || Override) {
- S.Flags = Flags & ~SectionFlags::Named;
- S.Name = Directive;
- }
-
- return &S;
-}
-
-const std::string&
-TargetAsmInfo::getSectionFlags(unsigned Flags) const {
- SectionFlags::FlagsStringsMapType::iterator I = FlagsStrings.find(Flags);
-
- // We didn't print these flags yet, print and save them to map. This reduces
- // amount of heap trashing due to std::string construction / concatenation.
- if (I == FlagsStrings.end())
- I = FlagsStrings.insert(std::make_pair(Flags,
- printSectionFlags(Flags))).first;
-
- return I->second;
-}
-
-unsigned TargetAsmInfo::getULEB128Size(unsigned Value) {
- unsigned Size = 0;
- do {
- Value >>= 7;
- Size += sizeof(int8_t);
- } while (Value);
- return Size;
-}
-
-unsigned TargetAsmInfo::getSLEB128Size(int Value) {
- unsigned Size = 0;
- int Sign = Value >> (8 * sizeof(Value) - 1);
- bool IsMore;
-
- do {
- unsigned Byte = Value & 0x7f;
- Value >>= 7;
- IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
- Size += sizeof(int8_t);
- } while (IsMore);
- return Size;
-}
diff --git a/lib/Target/TargetMachineRegistry.cpp b/lib/Target/TargetMachineRegistry.cpp
deleted file mode 100644
index c1a4777..0000000
--- a/lib/Target/TargetMachineRegistry.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-//===-- TargetMachineRegistry.cpp - Target Auto Registration Impl ---------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file exposes the RegisterTarget class, which TargetMachine
-// implementations should use to register themselves with the system. This file
-// also exposes the TargetMachineRegistry class, which allows tools to inspect
-// all of registered targets.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Target/TargetMachineRegistry.h"
-#include <algorithm>
-using namespace llvm;
-
-/// getClosestStaticTargetForModule - Given an LLVM module, pick the best target
-/// that is compatible with the module. If no close target can be found, this
-/// returns null and sets the Error string to a reason.
-const TargetMachineRegistry::entry *
-TargetMachineRegistry::getClosestStaticTargetForModule(const Module &M,
- std::string &Error) {
- std::vector<std::pair<unsigned, const entry *> > UsableTargets;
- for (Registry<TargetMachine>::iterator I = begin(), E = end(); I != E; ++I)
- if (unsigned Qual = I->ModuleMatchQualityFn(M))
- UsableTargets.push_back(std::make_pair(Qual, &*I));
-
- if (UsableTargets.empty()) {
- Error = "No available targets are compatible with this module";
- return 0;
- } else if (UsableTargets.size() == 1)
- return UsableTargets.back().second;
-
- // Otherwise, take the best target, but make sure we don't have two equally
- // good best targets.
- std::sort(UsableTargets.begin(), UsableTargets.end());
- if (UsableTargets.back().first ==UsableTargets[UsableTargets.size()-2].first){
- Error = "Cannot choose between targets \"" +
- std::string(UsableTargets.back().second->Name) + "\" and \"" +
- std::string(UsableTargets[UsableTargets.size()-2].second->Name) + "\"";
- return 0;
- }
- return UsableTargets.back().second;
-}
-
-/// getClosestTargetForJIT - Pick the best target that is compatible with
-/// the current host. If no close target can be found, this returns null
-/// and sets the Error string to a reason.
-const TargetMachineRegistry::entry *
-TargetMachineRegistry::getClosestTargetForJIT(std::string &Error) {
- std::vector<std::pair<unsigned, const entry *> > UsableTargets;
- for (Registry<TargetMachine>::iterator I = begin(), E = end(); I != E; ++I)
- if (unsigned Qual = I->JITMatchQualityFn())
- UsableTargets.push_back(std::make_pair(Qual, &*I));
-
- if (UsableTargets.empty()) {
- Error = "No JIT is available for this host";
- return 0;
- } else if (UsableTargets.size() == 1)
- return UsableTargets.back().second;
-
- // Otherwise, take the best target. If there is a tie, just pick one.
- unsigned MaxQual = UsableTargets.front().first;
- const entry *MaxQualTarget = UsableTargets.front().second;
-
- for (unsigned i = 1, e = UsableTargets.size(); i != e; ++i)
- if (UsableTargets[i].first > MaxQual) {
- MaxQual = UsableTargets[i].first;
- MaxQualTarget = UsableTargets[i].second;
- }
-
- return MaxQualTarget;
-}
-
diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
deleted file mode 100644
index 127f228..0000000
--- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
+++ /dev/null
@@ -1,1108 +0,0 @@
-//===-- X86ATTAsmPrinter.cpp - Convert X86 LLVM code to AT&T assembly -----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file 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 AT&T format assembly
-// language. This printer is the output mechanism used by `llc'.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "asm-printer"
-#include "X86ATTAsmPrinter.h"
-#include "X86.h"
-#include "X86COFF.h"
-#include "X86MachineFunctionInfo.h"
-#include "X86TargetMachine.h"
-#include "X86TargetAsmInfo.h"
-#include "llvm/CallingConv.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/MDNode.h"
-#include "llvm/Type.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineJumpTableInfo.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetOptions.h"
-using namespace llvm;
-
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
-static cl::opt<bool> NewAsmPrinter("experimental-asm-printer",
- cl::Hidden);
-
-//===----------------------------------------------------------------------===//
-// Primitive Helper Functions.
-//===----------------------------------------------------------------------===//
-
-void X86ATTAsmPrinter::PrintPICBaseSymbol() const {
- if (Subtarget->isTargetDarwin())
- O << "\"L" << getFunctionNumber() << "$pb\"";
- else if (Subtarget->isTargetELF())
- O << ".Lllvm$" << getFunctionNumber() << "." "$piclabel";
- else
- assert(0 && "Don't know how to print PIC label!\n");
-}
-
-/// PrintUnmangledNameSafely - Print out the printable characters in the name.
-/// Don't print things like \\n or \\0.
-static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
- for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
- Name != E; ++Name)
- if (isprint(*Name))
- OS << *Name;
-}
-
-static X86MachineFunctionInfo calculateFunctionInfo(const Function *F,
- const TargetData *TD) {
- X86MachineFunctionInfo Info;
- uint64_t Size = 0;
-
- switch (F->getCallingConv()) {
- case CallingConv::X86_StdCall:
- Info.setDecorationStyle(StdCall);
- break;
- case CallingConv::X86_FastCall:
- Info.setDecorationStyle(FastCall);
- break;
- default:
- return Info;
- }
-
- unsigned argNum = 1;
- for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
- AI != AE; ++AI, ++argNum) {
- const Type* Ty = AI->getType();
-
- // 'Dereference' type in case of byval parameter attribute
- if (F->paramHasAttr(argNum, Attribute::ByVal))
- Ty = cast<PointerType>(Ty)->getElementType();
-
- // Size should be aligned to DWORD boundary
- Size += ((TD->getTypeAllocSize(Ty) + 3)/4)*4;
- }
-
- // We're not supporting tooooo huge arguments :)
- Info.setBytesToPopOnReturn((unsigned int)Size);
- return Info;
-}
-
-/// decorateName - Query FunctionInfoMap and use this information for various
-/// name decoration.
-void X86ATTAsmPrinter::decorateName(std::string &Name,
- const GlobalValue *GV) {
- const Function *F = dyn_cast<Function>(GV);
- if (!F) return;
-
- // We don't want to decorate non-stdcall or non-fastcall functions right now
- unsigned CC = F->getCallingConv();
- if (CC != CallingConv::X86_StdCall && CC != CallingConv::X86_FastCall)
- return;
-
- // Decorate names only when we're targeting Cygwin/Mingw32 targets
- if (!Subtarget->isTargetCygMing())
- return;
-
- FMFInfoMap::const_iterator info_item = FunctionInfoMap.find(F);
-
- const X86MachineFunctionInfo *Info;
- if (info_item == FunctionInfoMap.end()) {
- // Calculate apropriate function info and populate map
- FunctionInfoMap[F] = calculateFunctionInfo(F, TM.getTargetData());
- Info = &FunctionInfoMap[F];
- } else {
- Info = &info_item->second;
- }
-
- const FunctionType *FT = F->getFunctionType();
- switch (Info->getDecorationStyle()) {
- case None:
- break;
- case StdCall:
- // "Pure" variadic functions do not receive @0 suffix.
- if (!FT->isVarArg() || (FT->getNumParams() == 0) ||
- (FT->getNumParams() == 1 && F->hasStructRetAttr()))
- Name += '@' + utostr_32(Info->getBytesToPopOnReturn());
- break;
- case FastCall:
- // "Pure" variadic functions do not receive @0 suffix.
- if (!FT->isVarArg() || (FT->getNumParams() == 0) ||
- (FT->getNumParams() == 1 && F->hasStructRetAttr()))
- Name += '@' + utostr_32(Info->getBytesToPopOnReturn());
-
- if (Name[0] == '_') {
- Name[0] = '@';
- } else {
- Name = '@' + Name;
- }
- break;
- default:
- assert(0 && "Unsupported DecorationStyle");
- }
-}
-
-void X86ATTAsmPrinter::emitFunctionHeader(const MachineFunction &MF) {
- unsigned FnAlign = MF.getAlignment();
- const Function *F = MF.getFunction();
-
- decorateName(CurrentFnName, F);
-
- SwitchToSection(TAI->SectionForGlobal(F));
- switch (F->getLinkage()) {
- default: assert(0 && "Unknown linkage type!");
- case Function::InternalLinkage: // Symbols default to internal.
- case Function::PrivateLinkage:
- EmitAlignment(FnAlign, F);
- break;
- case Function::DLLExportLinkage:
- case Function::ExternalLinkage:
- EmitAlignment(FnAlign, F);
- O << "\t.globl\t" << CurrentFnName << '\n';
- break;
- case Function::LinkOnceAnyLinkage:
- case Function::LinkOnceODRLinkage:
- case Function::WeakAnyLinkage:
- case Function::WeakODRLinkage:
- EmitAlignment(FnAlign, F);
- if (Subtarget->isTargetDarwin()) {
- O << "\t.globl\t" << CurrentFnName << '\n';
- O << TAI->getWeakDefDirective() << CurrentFnName << '\n';
- } else if (Subtarget->isTargetCygMing()) {
- O << "\t.globl\t" << CurrentFnName << "\n"
- "\t.linkonce discard\n";
- } else {
- O << "\t.weak\t" << CurrentFnName << '\n';
- }
- break;
- }
-
- printVisibility(CurrentFnName, F->getVisibility());
-
- if (Subtarget->isTargetELF())
- O << "\t.type\t" << CurrentFnName << ",@function\n";
- else if (Subtarget->isTargetCygMing()) {
- O << "\t.def\t " << CurrentFnName
- << ";\t.scl\t" <<
- (F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT)
- << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT)
- << ";\t.endef\n";
- }
-
- O << CurrentFnName << ":\n";
- // Add some workaround for linkonce linkage on Cygwin\MinGW
- if (Subtarget->isTargetCygMing() &&
- (F->hasLinkOnceLinkage() || F->hasWeakLinkage()))
- O << "Lllvm$workaround$fake$stub$" << CurrentFnName << ":\n";
-}
-
-/// runOnMachineFunction - This uses the printMachineInstruction()
-/// method to print assembly for each instruction.
-///
-bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- const Function *F = MF.getFunction();
- this->MF = &MF;
- unsigned CC = F->getCallingConv();
-
- SetupMachineFunction(MF);
- O << "\n\n";
-
- // Populate function information map. Actually, We don't want to populate
- // non-stdcall or non-fastcall functions' information right now.
- if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall)
- FunctionInfoMap[F] = *MF.getInfo<X86MachineFunctionInfo>();
-
- // Print out constants referenced by the function
- EmitConstantPool(MF.getConstantPool());
-
- if (F->hasDLLExportLinkage())
- DLLExportedFns.insert(Mang->makeNameProper(F->getName(), ""));
-
- // Print the 'header' of function
- emitFunctionHeader(MF);
-
- // Emit pre-function debug and/or EH information.
- if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling())
- DW->BeginFunction(&MF);
-
- // Print out code for the function.
- bool hasAnyRealCode = false;
- for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
- I != E; ++I) {
- // Print a label for the basic block.
- if (!VerboseAsm && (I->pred_empty() || I->isOnlyReachableByFallthrough())) {
- // This is an entry block or a block that's only reachable via a
- // fallthrough edge. In non-VerboseAsm mode, don't print the label.
- } else {
- printBasicBlockLabel(I, true, true, VerboseAsm);
- O << '\n';
- }
- for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
- II != IE; ++II) {
- // Print the assembly for the instruction.
- if (!II->isLabel())
- hasAnyRealCode = true;
- printMachineInstruction(II);
- }
- }
-
- if (Subtarget->isTargetDarwin() && !hasAnyRealCode) {
- // If the function is empty, then we need to emit *something*. Otherwise,
- // the function's label might be associated with something that it wasn't
- // meant to be associated with. We emit a noop in this situation.
- // We are assuming inline asms are code.
- O << "\tnop\n";
- }
-
- if (TAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
-
- // Emit post-function debug information.
- if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling())
- DW->EndFunction(&MF);
-
- // Print out jump tables referenced by the function.
- EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
-
- O.flush();
-
- // We didn't modify anything.
- return false;
-}
-
-static inline bool shouldPrintPLT(TargetMachine &TM, const X86Subtarget* ST) {
- return ST->isTargetELF() && TM.getRelocationModel() == Reloc::PIC_;
-}
-
-static inline bool shouldPrintStub(TargetMachine &TM, const X86Subtarget* ST) {
- return ST->isPICStyleStub() && TM.getRelocationModel() != Reloc::Static;
-}
-
-/// print_pcrel_imm - This is used to print an immediate value that ends up
-/// being encoded as a pc-relative value. These print slightly differently, for
-/// example, a $ is not emitted.
-void X86ATTAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
- const MachineOperand &MO = MI->getOperand(OpNo);
- switch (MO.getType()) {
- default: assert(0 && "Unknown pcrel immediate operand");
- case MachineOperand::MO_Immediate:
- O << MO.getImm();
- return;
- case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
- return;
-
- case MachineOperand::MO_GlobalAddress: {
- const GlobalValue *GV = MO.getGlobal();
- std::string Name = Mang->getValueName(GV);
- decorateName(Name, GV);
-
- bool needCloseParen = false;
- if (Name[0] == '$') {
- // The name begins with a dollar-sign. In order to avoid having it look
- // like an integer immediate to the assembler, enclose it in parens.
- O << '(';
- needCloseParen = true;
- }
-
- if (shouldPrintStub(TM, Subtarget)) {
- // DARWIN/X86-32 in != static mode.
-
- // Link-once, declaration, or Weakly-linked global variables need
- // non-lazily-resolved stubs
- if (GV->isDeclaration() || GV->isWeakForLinker()) {
- // Dynamically-resolved functions need a stub for the function.
- if (isa<Function>(GV)) {
- // Function stubs are no longer needed for Mac OS X 10.5 and up.
- if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) {
- O << Name;
- } else {
- FnStubs.insert(Name);
- printSuffixedName(Name, "$stub");
- }
- } else if (GV->hasHiddenVisibility()) {
- if (!GV->isDeclaration() && !GV->hasCommonLinkage())
- // Definition is not definitely in the current translation unit.
- O << Name;
- else {
- HiddenGVStubs.insert(Name);
- printSuffixedName(Name, "$non_lazy_ptr");
- }
- } else {
- GVStubs.insert(Name);
- printSuffixedName(Name, "$non_lazy_ptr");
- }
- } else {
- if (GV->hasDLLImportLinkage())
- O << "__imp_";
- O << Name;
- }
- } else {
- if (GV->hasDLLImportLinkage())
- O << "__imp_";
- O << Name;
-
- if (shouldPrintPLT(TM, Subtarget)) {
- // Assemble call via PLT for externally visible symbols
- if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
- !GV->hasLocalLinkage())
- O << "@PLT";
- }
- if (Subtarget->isTargetCygMing() && GV->isDeclaration())
- // Save function name for later type emission
- FnStubs.insert(Name);
- }
-
- printOffset(MO.getOffset());
-
- if (needCloseParen)
- O << ')';
- return;
- }
-
- case MachineOperand::MO_ExternalSymbol: {
- bool needCloseParen = false;
- std::string Name(TAI->getGlobalPrefix());
- Name += MO.getSymbolName();
- // Print function stub suffix unless it's Mac OS X 10.5 and up.
- if (shouldPrintStub(TM, Subtarget) &&
- // DARWIN/X86-32 in != static mode.
- !(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) {
-
- FnStubs.insert(Name);
- printSuffixedName(Name, "$stub");
- return;
- }
-
- if (Name[0] == '$') {
- // The name begins with a dollar-sign. In order to avoid having it look
- // like an integer immediate to the assembler, enclose it in parens.
- O << '(';
- needCloseParen = true;
- }
-
- O << Name;
-
- if (MO.getTargetFlags() == X86II::MO_GOT_ABSOLUTE_ADDRESS) {
- O << " + [.-";
- PrintPICBaseSymbol();
- O << ']';
- }
-
- if (shouldPrintPLT(TM, Subtarget))
- O << "@PLT";
-
- if (needCloseParen)
- O << ')';
-
- return;
- }
- }
-}
-
-void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
- const char *Modifier) {
- const MachineOperand &MO = MI->getOperand(OpNo);
- switch (MO.getType()) {
- default: assert(0 && "unknown operand type!");
- case MachineOperand::MO_Register: {
- assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
- "Virtual registers should not make it this far!");
- O << '%';
- unsigned Reg = MO.getReg();
- if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
- MVT VT = (strcmp(Modifier+6,"64") == 0) ?
- MVT::i64 : ((strcmp(Modifier+6, "32") == 0) ? MVT::i32 :
- ((strcmp(Modifier+6,"16") == 0) ? MVT::i16 : MVT::i8));
- Reg = getX86SubSuperRegister(Reg, VT);
- }
- O << TRI->getAsmName(Reg);
- return;
- }
-
- case MachineOperand::MO_Immediate:
- if (!Modifier || (strcmp(Modifier, "debug") &&
- strcmp(Modifier, "mem")))
- O << '$';
- O << MO.getImm();
- return;
- case MachineOperand::MO_JumpTableIndex: {
- bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- if (!isMemOp) O << '$';
- O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() << '_'
- << MO.getIndex();
- break;
- }
- case MachineOperand::MO_ConstantPoolIndex: {
- bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- if (!isMemOp) O << '$';
- O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
- << MO.getIndex();
-
- printOffset(MO.getOffset());
- break;
- }
- case MachineOperand::MO_GlobalAddress: {
- bool isMemOp = Modifier && !strcmp(Modifier, "mem");
-
- const GlobalValue *GV = MO.getGlobal();
- std::string Name = Mang->getValueName(GV);
- decorateName(Name, GV);
-
- bool needCloseParen = false;
- if (!isMemOp)
- O << '$';
- else if (Name[0] == '$') {
- // The name begins with a dollar-sign. In order to avoid having it look
- // like an integer immediate to the assembler, enclose it in parens.
- O << '(';
- needCloseParen = true;
- }
-
- if (shouldPrintStub(TM, Subtarget)) {
- // DARWIN/X86-32 in != static mode.
-
- // Link-once, declaration, or Weakly-linked global variables need
- // non-lazily-resolved stubs
- if (GV->isDeclaration() || GV->isWeakForLinker()) {
- // Dynamically-resolved functions need a stub for the function.
- if (GV->hasHiddenVisibility()) {
- if (!GV->isDeclaration() && !GV->hasCommonLinkage())
- // Definition is not definitely in the current translation unit.
- O << Name;
- else {
- HiddenGVStubs.insert(Name);
- printSuffixedName(Name, "$non_lazy_ptr");
- }
- } else {
- GVStubs.insert(Name);
- printSuffixedName(Name, "$non_lazy_ptr");
- }
- } else {
- if (GV->hasDLLImportLinkage())
- O << "__imp_";
- O << Name;
- }
-
- if (TM.getRelocationModel() == Reloc::PIC_) {
- O << '-';
- PrintPICBaseSymbol();
- }
- } else {
- if (GV->hasDLLImportLinkage())
- O << "__imp_";
- O << Name;
- }
-
- printOffset(MO.getOffset());
-
- if (needCloseParen)
- O << ')';
-
- break;
- }
- case MachineOperand::MO_ExternalSymbol:
- /// NOTE: MO_ExternalSymbol in a non-pcrel_imm context is *only* generated
- /// by _GLOBAL_OFFSET_TABLE_ on X86-32. All others are call operands, which
- /// are pcrel_imm's.
- assert(!Subtarget->is64Bit() && !Subtarget->isPICStyleRIPRel());
- // These are never used as memory operands.
- assert(!(Modifier && !strcmp(Modifier, "mem")));
-
- O << '$';
- O << TAI->getGlobalPrefix();
- O << MO.getSymbolName();
- break;
- }
-
- switch (MO.getTargetFlags()) {
- default:
- assert(0 && "Unknown target flag on GV operand");
- case X86II::MO_NO_FLAG:
- break;
- case X86II::MO_GOT_ABSOLUTE_ADDRESS:
- O << " + [.-";
- PrintPICBaseSymbol();
- O << ']';
- break;
- case X86II::MO_PIC_BASE_OFFSET:
- O << '-';
- PrintPICBaseSymbol();
- break;
- case X86II::MO_TLSGD: O << "@TLSGD"; break;
- case X86II::MO_GOTTPOFF: O << "@GOTTPOFF"; break;
- case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break;
- case X86II::MO_TPOFF: O << "@TPOFF"; break;
- case X86II::MO_NTPOFF: O << "@NTPOFF"; break;
- case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break;
- case X86II::MO_GOT: O << "@GOT"; break;
- case X86II::MO_GOTOFF: O << "@GOTOFF"; break;
- }
-}
-
-void X86ATTAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
- unsigned char value = MI->getOperand(Op).getImm();
- assert(value <= 7 && "Invalid ssecc argument!");
- switch (value) {
- case 0: O << "eq"; break;
- case 1: O << "lt"; break;
- case 2: O << "le"; break;
- case 3: O << "unord"; break;
- case 4: O << "neq"; break;
- case 5: O << "nlt"; break;
- case 6: O << "nle"; break;
- case 7: O << "ord"; break;
- }
-}
-
-void X86ATTAsmPrinter::printLeaMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier) {
- MachineOperand BaseReg = MI->getOperand(Op);
- MachineOperand IndexReg = MI->getOperand(Op+2);
- const MachineOperand &DispSpec = MI->getOperand(Op+3);
-
- if (DispSpec.isGlobal() ||
- DispSpec.isCPI() ||
- DispSpec.isJTI() ||
- DispSpec.isSymbol()) {
- printOperand(MI, Op+3, "mem");
- } else {
- int DispVal = DispSpec.getImm();
- if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
- O << DispVal;
- }
-
- if ((IndexReg.getReg() || BaseReg.getReg()) &&
- (Modifier == 0 || strcmp(Modifier, "no-rip"))) {
- unsigned ScaleVal = MI->getOperand(Op+1).getImm();
- unsigned BaseRegOperand = 0, IndexRegOperand = 2;
-
- // There are cases where we can end up with ESP/RSP in the indexreg slot.
- // If this happens, swap the base/index register to support assemblers that
- // don't work when the index is *SP.
- if (IndexReg.getReg() == X86::ESP || IndexReg.getReg() == X86::RSP) {
- assert(ScaleVal == 1 && "Scale not supported for stack pointer!");
- std::swap(BaseReg, IndexReg);
- std::swap(BaseRegOperand, IndexRegOperand);
- }
-
- O << '(';
- if (BaseReg.getReg())
- printOperand(MI, Op+BaseRegOperand, Modifier);
-
- if (IndexReg.getReg()) {
- O << ',';
- printOperand(MI, Op+IndexRegOperand, Modifier);
- if (ScaleVal != 1)
- O << ',' << ScaleVal;
- }
- O << ')';
- }
-}
-
-void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier) {
- assert(isMem(MI, Op) && "Invalid memory reference!");
- MachineOperand Segment = MI->getOperand(Op+4);
- if (Segment.getReg()) {
- printOperand(MI, Op+4, Modifier);
- O << ':';
- }
- printLeaMemReference(MI, Op, Modifier);
-}
-
-void X86ATTAsmPrinter::printPICJumpTableSetLabel(unsigned uid,
- const MachineBasicBlock *MBB) const {
- if (!TAI->getSetDirective())
- return;
-
- // We don't need .set machinery if we have GOT-style relocations
- if (Subtarget->isPICStyleGOT())
- return;
-
- O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix()
- << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',';
- printBasicBlockLabel(MBB, false, false, false);
- if (Subtarget->isPICStyleRIPRel())
- O << '-' << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << uid << '\n';
- else {
- O << '-';
- PrintPICBaseSymbol();
- O << '\n';
- }
-}
-
-
-void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
- PrintPICBaseSymbol();
- O << '\n';
- PrintPICBaseSymbol();
- O << ':';
-}
-
-
-void X86ATTAsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
- const MachineBasicBlock *MBB,
- unsigned uid) const
-{
- const char *JTEntryDirective = MJTI->getEntrySize() == 4 ?
- TAI->getData32bitsDirective() : TAI->getData64bitsDirective();
-
- O << JTEntryDirective << ' ';
-
- if (TM.getRelocationModel() == Reloc::PIC_) {
- if (Subtarget->isPICStyleRIPRel() || Subtarget->isPICStyleStub()) {
- O << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
- << '_' << uid << "_set_" << MBB->getNumber();
- } else if (Subtarget->isPICStyleGOT()) {
- printBasicBlockLabel(MBB, false, false, false);
- O << "@GOTOFF";
- } else
- assert(0 && "Don't know how to print MBB label for this PIC mode");
- } else
- printBasicBlockLabel(MBB, false, false, false);
-}
-
-bool X86ATTAsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode) {
- unsigned Reg = MO.getReg();
- switch (Mode) {
- default: return true; // Unknown mode.
- case 'b': // Print QImode register
- Reg = getX86SubSuperRegister(Reg, MVT::i8);
- break;
- case 'h': // Print QImode high register
- Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
- break;
- case 'w': // Print HImode register
- Reg = getX86SubSuperRegister(Reg, MVT::i16);
- break;
- case 'k': // Print SImode register
- Reg = getX86SubSuperRegister(Reg, MVT::i32);
- break;
- case 'q': // Print DImode register
- Reg = getX86SubSuperRegister(Reg, MVT::i64);
- break;
- }
-
- O << '%'<< TRI->getAsmName(Reg);
- return false;
-}
-
-/// PrintAsmOperand - Print out an operand for an inline asm expression.
-///
-bool X86ATTAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant,
- const char *ExtraCode) {
- // Does this asm operand have a single letter operand modifier?
- if (ExtraCode && ExtraCode[0]) {
- if (ExtraCode[1] != 0) return true; // Unknown modifier.
-
- switch (ExtraCode[0]) {
- default: return true; // Unknown modifier.
- case 'c': // Don't print "$" before a global var name or constant.
- printOperand(MI, OpNo, "mem");
- return false;
- case 'b': // Print QImode register
- case 'h': // Print QImode high register
- case 'w': // Print HImode register
- case 'k': // Print SImode register
- case 'q': // Print DImode register
- if (MI->getOperand(OpNo).isReg())
- return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]);
- printOperand(MI, OpNo);
- return false;
-
- case 'P': // Don't print @PLT, but do print as memory.
- printOperand(MI, OpNo, "mem");
- return false;
-
- case 'n': { // Negate the immediate or print a '-' before the operand.
- // Note: this is a temporary solution. It should be handled target
- // independently as part of the 'MC' work.
- const MachineOperand &MO = MI->getOperand(OpNo);
- if (MO.isImm()) {
- O << -MO.getImm();
- return false;
- }
- O << '-';
- }
- }
- }
-
- printOperand(MI, OpNo);
- return false;
-}
-
-bool X86ATTAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
- unsigned OpNo,
- unsigned AsmVariant,
- const char *ExtraCode) {
- if (ExtraCode && ExtraCode[0]) {
- if (ExtraCode[1] != 0) return true; // Unknown modifier.
-
- switch (ExtraCode[0]) {
- default: return true; // Unknown modifier.
- case 'b': // Print QImode register
- case 'h': // Print QImode high register
- case 'w': // Print HImode register
- case 'k': // Print SImode register
- case 'q': // Print SImode register
- // These only apply to registers, ignore on mem.
- break;
- case 'P': // Don't print @PLT, but do print as memory.
- printMemReference(MI, OpNo, "no-rip");
- return false;
- }
- }
- printMemReference(MI, OpNo);
- return false;
-}
-
-static void lower_lea64_32mem(MCInst *MI, unsigned OpNo) {
- // Convert registers in the addr mode according to subreg64.
- for (unsigned i = 0; i != 4; ++i) {
- if (!MI->getOperand(i).isReg()) continue;
-
- unsigned Reg = MI->getOperand(i).getReg();
- if (Reg == 0) continue;
-
- MI->getOperand(i).setReg(getX86SubSuperRegister(Reg, MVT::i64));
- }
-}
-
-/// printMachineInstruction -- Print out a single X86 LLVM instruction MI in
-/// AT&T syntax to the current output stream.
-///
-void X86ATTAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
- ++EmittedInsts;
-
- if (NewAsmPrinter) {
- if (MI->getOpcode() == TargetInstrInfo::INLINEASM) {
- O << "\t";
- printInlineAsm(MI);
- return;
- } else if (MI->isLabel()) {
- printLabel(MI);
- return;
- } else if (MI->getOpcode() == TargetInstrInfo::DECLARE) {
- printDeclare(MI);
- return;
- } else if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
- printImplicitDef(MI);
- return;
- }
-
- O << "NEW: ";
- MCInst TmpInst;
-
- TmpInst.setOpcode(MI->getOpcode());
-
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- const MachineOperand &MO = MI->getOperand(i);
-
- MCOperand MCOp;
- if (MO.isReg()) {
- MCOp.MakeReg(MO.getReg());
- } else if (MO.isImm()) {
- MCOp.MakeImm(MO.getImm());
- } else if (MO.isMBB()) {
- MCOp.MakeMBBLabel(getFunctionNumber(), MO.getMBB()->getNumber());
- } else {
- assert(0 && "Unimp");
- }
-
- TmpInst.addOperand(MCOp);
- }
-
- switch (TmpInst.getOpcode()) {
- case X86::LEA64_32r:
- // Handle the 'subreg rewriting' for the lea64_32mem operand.
- lower_lea64_32mem(&TmpInst, 1);
- break;
- }
-
- // FIXME: Convert TmpInst.
- printInstruction(&TmpInst);
- O << "OLD: ";
- }
-
- // Call the autogenerated instruction printer routines.
- printInstruction(MI);
-}
-
-/// doInitialization
-bool X86ATTAsmPrinter::doInitialization(Module &M) {
- if (NewAsmPrinter) {
- Context = new MCContext();
- // FIXME: Send this to "O" instead of outs(). For now, we force it to
- // stdout to make it easy to compare.
- Streamer = createAsmStreamer(*Context, outs());
- }
-
- return AsmPrinter::doInitialization(M);
-}
-
-void X86ATTAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
- const TargetData *TD = TM.getTargetData();
-
- if (!GVar->hasInitializer())
- return; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GVar)) {
- if (Subtarget->isTargetDarwin() &&
- TM.getRelocationModel() == Reloc::Static) {
- if (GVar->getName() == "llvm.global_ctors")
- O << ".reference .constructors_used\n";
- else if (GVar->getName() == "llvm.global_dtors")
- O << ".reference .destructors_used\n";
- }
- return;
- }
-
- std::string name = Mang->getValueName(GVar);
- Constant *C = GVar->getInitializer();
- if (isa<MDNode>(C) || isa<MDString>(C))
- return;
- const Type *Type = C->getType();
- unsigned Size = TD->getTypeAllocSize(Type);
- unsigned Align = TD->getPreferredAlignmentLog(GVar);
-
- printVisibility(name, GVar->getVisibility());
-
- if (Subtarget->isTargetELF())
- O << "\t.type\t" << name << ",@object\n";
-
- SwitchToSection(TAI->SectionForGlobal(GVar));
-
- if (C->isNullValue() && !GVar->hasSection() &&
- !(Subtarget->isTargetDarwin() &&
- TAI->SectionKindForGlobal(GVar) == SectionKind::RODataMergeStr)) {
- // FIXME: This seems to be pretty darwin-specific
- if (GVar->hasExternalLinkage()) {
- if (const char *Directive = TAI->getZeroFillDirective()) {
- O << "\t.globl " << name << '\n';
- O << Directive << "__DATA, __common, " << name << ", "
- << Size << ", " << Align << '\n';
- return;
- }
- }
-
- if (!GVar->isThreadLocal() &&
- (GVar->hasLocalLinkage() || GVar->isWeakForLinker())) {
- if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
-
- if (TAI->getLCOMMDirective() != NULL) {
- if (GVar->hasLocalLinkage()) {
- O << TAI->getLCOMMDirective() << name << ',' << Size;
- if (Subtarget->isTargetDarwin())
- O << ',' << Align;
- } else if (Subtarget->isTargetDarwin() && !GVar->hasCommonLinkage()) {
- O << "\t.globl " << name << '\n'
- << TAI->getWeakDefDirective() << name << '\n';
- EmitAlignment(Align, GVar);
- O << name << ":";
- if (VerboseAsm) {
- O << "\t\t\t\t" << TAI->getCommentString() << ' ';
- PrintUnmangledNameSafely(GVar, O);
- }
- O << '\n';
- EmitGlobalConstant(C);
- return;
- } else {
- O << TAI->getCOMMDirective() << name << ',' << Size;
- if (TAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
- }
- } else {
- if (!Subtarget->isTargetCygMing()) {
- if (GVar->hasLocalLinkage())
- O << "\t.local\t" << name << '\n';
- }
- O << TAI->getCOMMDirective() << name << ',' << Size;
- if (TAI->getCOMMDirectiveTakesAlignment())
- O << ',' << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
- }
- if (VerboseAsm) {
- O << "\t\t" << TAI->getCommentString() << ' ';
- PrintUnmangledNameSafely(GVar, O);
- }
- O << '\n';
- return;
- }
- }
-
- switch (GVar->getLinkage()) {
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- if (Subtarget->isTargetDarwin()) {
- O << "\t.globl " << name << '\n'
- << TAI->getWeakDefDirective() << name << '\n';
- } else if (Subtarget->isTargetCygMing()) {
- O << "\t.globl\t" << name << "\n"
- "\t.linkonce same_size\n";
- } else {
- O << "\t.weak\t" << name << '\n';
- }
- break;
- case GlobalValue::DLLExportLinkage:
- 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::PrivateLinkage:
- case GlobalValue::InternalLinkage:
- break;
- default:
- assert(0 && "Unknown linkage type!");
- }
-
- EmitAlignment(Align, GVar);
- O << name << ":";
- if (VerboseAsm){
- O << "\t\t\t\t" << TAI->getCommentString() << ' ';
- PrintUnmangledNameSafely(GVar, O);
- }
- O << '\n';
- if (TAI->hasDotTypeDotSizeDirective())
- O << "\t.size\t" << name << ", " << Size << '\n';
-
- EmitGlobalConstant(C);
-}
-
-bool X86ATTAsmPrinter::doFinalization(Module &M) {
- // Print out module-level global variables here.
- for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I) {
- printModuleLevelGV(I);
-
- if (I->hasDLLExportLinkage())
- DLLExportedGVs.insert(Mang->makeNameProper(I->getName(),""));
- }
-
- if (Subtarget->isTargetDarwin()) {
- SwitchToDataSection("");
-
- // Add the (possibly multiple) personalities to the set of global value
- // stubs. Only referenced functions get into the Personalities list.
- if (TAI->doesSupportExceptionHandling() && MMI && !Subtarget->is64Bit()) {
- const std::vector<Function*> &Personalities = MMI->getPersonalities();
- for (unsigned i = 0, e = Personalities.size(); i != e; ++i) {
- if (Personalities[i] == 0)
- continue;
- std::string Name = Mang->getValueName(Personalities[i]);
- decorateName(Name, Personalities[i]);
- GVStubs.insert(Name);
- }
- }
-
- // Output stubs for dynamically-linked functions
- if (!FnStubs.empty()) {
- for (StringSet<>::iterator I = FnStubs.begin(), E = FnStubs.end();
- I != E; ++I) {
- SwitchToDataSection("\t.section __IMPORT,__jump_table,symbol_stubs,"
- "self_modifying_code+pure_instructions,5", 0);
- const char *Name = I->getKeyData();
- printSuffixedName(Name, "$stub");
- O << ":\n"
- "\t.indirect_symbol " << Name << "\n"
- "\thlt ; hlt ; hlt ; hlt ; hlt\n";
- }
- O << '\n';
- }
-
- // Output stubs for external and common global variables.
- if (!GVStubs.empty()) {
- SwitchToDataSection(
- "\t.section __IMPORT,__pointers,non_lazy_symbol_pointers");
- for (StringSet<>::iterator I = GVStubs.begin(), E = GVStubs.end();
- I != E; ++I) {
- const char *Name = I->getKeyData();
- printSuffixedName(Name, "$non_lazy_ptr");
- O << ":\n\t.indirect_symbol " << Name << "\n\t.long\t0\n";
- }
- }
-
- if (!HiddenGVStubs.empty()) {
- SwitchToSection(TAI->getDataSection());
- EmitAlignment(2);
- for (StringSet<>::iterator I = HiddenGVStubs.begin(),
- E = HiddenGVStubs.end(); I != E; ++I) {
- const char *Name = I->getKeyData();
- printSuffixedName(Name, "$non_lazy_ptr");
- O << ":\n" << TAI->getData32bitsDirective() << Name << '\n';
- }
- }
-
- // Funny Darwin hack: This flag tells the linker that no global symbols
- // contain code that falls through to other global symbols (e.g. the obvious
- // implementation of multiple entry points). If this doesn't occur, the
- // linker can safely perform dead code stripping. Since LLVM never
- // generates code that does this, it is always safe to set.
- O << "\t.subsections_via_symbols\n";
- } else if (Subtarget->isTargetCygMing()) {
- // Emit type information for external functions
- for (StringSet<>::iterator i = FnStubs.begin(), e = FnStubs.end();
- i != e; ++i) {
- O << "\t.def\t " << i->getKeyData()
- << ";\t.scl\t" << COFF::C_EXT
- << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT)
- << ";\t.endef\n";
- }
- }
-
-
- // Output linker support code for dllexported globals on windows.
- if (!DLLExportedGVs.empty()) {
- SwitchToDataSection(".section .drectve");
-
- for (StringSet<>::iterator i = DLLExportedGVs.begin(),
- e = DLLExportedGVs.end(); i != e; ++i)
- O << "\t.ascii \" -export:" << i->getKeyData() << ",data\"\n";
- }
-
- if (!DLLExportedFns.empty()) {
- SwitchToDataSection(".section .drectve");
-
- for (StringSet<>::iterator i = DLLExportedFns.begin(),
- e = DLLExportedFns.end();
- i != e; ++i)
- O << "\t.ascii \" -export:" << i->getKeyData() << "\"\n";
- }
-
- // Do common shutdown.
- bool Changed = AsmPrinter::doFinalization(M);
-
- if (NewAsmPrinter) {
- Streamer->Finish();
-
- delete Streamer;
- delete Context;
- Streamer = 0;
- Context = 0;
- }
-
- return Changed;
-}
-
-// Include the auto-generated portion of the assembly writer.
-#include "X86GenAsmWriter.inc"
diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h
deleted file mode 100644
index f47daf1..0000000
--- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h
+++ /dev/null
@@ -1,226 +0,0 @@
-//===-- X86ATTAsmPrinter.h - Convert X86 LLVM code to AT&T assembly -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// AT&T assembly code printer class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef X86ATTASMPRINTER_H
-#define X86ATTASMPRINTER_H
-
-#include "../X86.h"
-#include "../X86MachineFunctionInfo.h"
-#include "../X86TargetMachine.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/ValueTypes.h"
-#include "llvm/Support/Compiler.h"
-
-namespace llvm {
-
-class MachineJumpTableInfo;
-class MCContext;
-class MCInst;
-class MCStreamer;
-
-class VISIBILITY_HIDDEN X86ATTAsmPrinter : public AsmPrinter {
- const X86Subtarget *Subtarget;
-
- MCContext *Context;
- MCStreamer *Streamer;
- public:
- explicit X86ATTAsmPrinter(raw_ostream &O, X86TargetMachine &TM,
- const TargetAsmInfo *T, bool V)
- : AsmPrinter(O, TM, T, V) {
- Subtarget = &TM.getSubtarget<X86Subtarget>();
- Context = 0;
- Streamer = 0;
- }
-
- virtual const char *getPassName() const {
- return "X86 AT&T-Style Assembly Printer";
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- if (Subtarget->isTargetDarwin() ||
- Subtarget->isTargetELF() ||
- Subtarget->isTargetCygMing()) {
- AU.addRequired<MachineModuleInfo>();
- }
- AU.addRequired<DwarfWriter>();
- AsmPrinter::getAnalysisUsage(AU);
- }
-
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
-
- /// printInstruction - This method is automatically generated by tablegen
- /// from the instruction set description. This method returns true if the
- /// machine instruction was sufficiently described to print it, otherwise it
- /// returns false.
- bool printInstruction(const MachineInstr *MI);
-
-
- // New MCInst printing stuff.
- bool printInstruction(const MCInst *MI);
-
- void printOperand(const MCInst *MI, unsigned OpNo,
- const char *Modifier = 0);
- void printMemReference(const MCInst *MI, unsigned Op);
- void printLeaMemReference(const MCInst *MI, unsigned Op);
- void printSSECC(const MCInst *MI, unsigned Op);
- void printPICLabel(const MCInst *MI, unsigned Op);
- void print_pcrel_imm(const MCInst *MI, unsigned OpNo);
-
- void printi8mem(const MCInst *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printi16mem(const MCInst *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printi32mem(const MCInst *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printi64mem(const MCInst *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printi128mem(const MCInst *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printf32mem(const MCInst *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printf64mem(const MCInst *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printf80mem(const MCInst *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printf128mem(const MCInst *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printlea32mem(const MCInst *MI, unsigned OpNo) {
- printLeaMemReference(MI, OpNo);
- }
- void printlea64mem(const MCInst *MI, unsigned OpNo) {
- printLeaMemReference(MI, OpNo);
- }
- void printlea64_32mem(const MCInst *MI, unsigned OpNo) {
- printLeaMemReference(MI, OpNo);
- }
-
-
-
- // These methods are used by the tablegen'erated instruction printer.
- void printOperand(const MachineInstr *MI, unsigned OpNo,
- const char *Modifier = 0);
- void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo);
- void printi8mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printi16mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printi32mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printi64mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printi128mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printi256mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printf32mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printf64mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printf80mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printf128mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printf256mem(const MachineInstr *MI, unsigned OpNo) {
- printMemReference(MI, OpNo);
- }
- void printlea32mem(const MachineInstr *MI, unsigned OpNo) {
- printLeaMemReference(MI, OpNo);
- }
- void printlea64mem(const MachineInstr *MI, unsigned OpNo) {
- printLeaMemReference(MI, OpNo);
- }
- void printlea64_32mem(const MachineInstr *MI, unsigned OpNo) {
- printLeaMemReference(MI, OpNo, "subreg64");
- }
-
- bool printAsmMRegister(const MachineOperand &MO, char Mode);
- bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant, const char *ExtraCode);
- bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant, const char *ExtraCode);
-
- void printMachineInstruction(const MachineInstr *MI);
- void printSSECC(const MachineInstr *MI, unsigned Op);
- void printMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier=NULL);
- void printLeaMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier=NULL);
- void printPICJumpTableSetLabel(unsigned uid,
- const MachineBasicBlock *MBB) const;
- void printPICJumpTableSetLabel(unsigned uid, unsigned uid2,
- const MachineBasicBlock *MBB) const {
- AsmPrinter::printPICJumpTableSetLabel(uid, uid2, MBB);
- }
- void printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
- const MachineBasicBlock *MBB,
- unsigned uid) const;
-
- void printPICLabel(const MachineInstr *MI, unsigned Op);
- void printModuleLevelGV(const GlobalVariable* GVar);
-
- void PrintPICBaseSymbol() const;
-
- bool runOnMachineFunction(MachineFunction &F);
-
- void emitFunctionHeader(const MachineFunction &MF);
-
- // Necessary for Darwin to print out the apprioriate types of linker stubs
- StringSet<> FnStubs, GVStubs, HiddenGVStubs;
-
- // Necessary for dllexport support
- StringSet<> DLLExportedFns, DLLExportedGVs;
-
- // We have to propagate some information about MachineFunction to
- // AsmPrinter. It's ok, when we're printing the function, since we have
- // access to MachineFunction and can get the appropriate MachineFunctionInfo.
- // Unfortunately, this is not possible when we're printing reference to
- // Function (e.g. calling it and so on). Even more, there is no way to get the
- // corresponding MachineFunctions: it can even be not created at all. That's
- // why we should use additional structure, when we're collecting all necessary
- // information.
- //
- // This structure is using e.g. for name decoration for stdcall & fastcall'ed
- // function, since we have to use arguments' size for decoration.
- typedef std::map<const Function*, X86MachineFunctionInfo> FMFInfoMap;
- FMFInfoMap FunctionInfoMap;
-
- void decorateName(std::string& Name, const GlobalValue* GV);
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp
deleted file mode 100644
index 9d4df93..0000000
--- a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp
+++ /dev/null
@@ -1,633 +0,0 @@
-//===-- X86IntelAsmPrinter.cpp - Convert X86 LLVM code to Intel assembly --===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file 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 Intel format assembly language.
-// This printer is the output mechanism used by `llc'.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "asm-printer"
-#include "X86IntelAsmPrinter.h"
-#include "X86InstrInfo.h"
-#include "X86TargetAsmInfo.h"
-#include "X86.h"
-#include "llvm/CallingConv.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Assembly/Writer.h"
-#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetOptions.h"
-using namespace llvm;
-
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
-static X86MachineFunctionInfo calculateFunctionInfo(const Function *F,
- const TargetData *TD) {
- X86MachineFunctionInfo Info;
- uint64_t Size = 0;
-
- switch (F->getCallingConv()) {
- case CallingConv::X86_StdCall:
- Info.setDecorationStyle(StdCall);
- break;
- case CallingConv::X86_FastCall:
- Info.setDecorationStyle(FastCall);
- break;
- default:
- return Info;
- }
-
- unsigned argNum = 1;
- for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
- AI != AE; ++AI, ++argNum) {
- const Type* Ty = AI->getType();
-
- // 'Dereference' type in case of byval parameter attribute
- if (F->paramHasAttr(argNum, Attribute::ByVal))
- Ty = cast<PointerType>(Ty)->getElementType();
-
- // Size should be aligned to DWORD boundary
- Size += ((TD->getTypeAllocSize(Ty) + 3)/4)*4;
- }
-
- // We're not supporting tooooo huge arguments :)
- Info.setBytesToPopOnReturn((unsigned int)Size);
- return Info;
-}
-
-
-/// decorateName - Query FunctionInfoMap and use this information for various
-/// name decoration.
-void X86IntelAsmPrinter::decorateName(std::string &Name,
- const GlobalValue *GV) {
- const Function *F = dyn_cast<Function>(GV);
- if (!F) return;
-
- // We don't want to decorate non-stdcall or non-fastcall functions right now
- unsigned CC = F->getCallingConv();
- if (CC != CallingConv::X86_StdCall && CC != CallingConv::X86_FastCall)
- return;
-
- FMFInfoMap::const_iterator info_item = FunctionInfoMap.find(F);
-
- const X86MachineFunctionInfo *Info;
- if (info_item == FunctionInfoMap.end()) {
- // Calculate apropriate function info and populate map
- FunctionInfoMap[F] = calculateFunctionInfo(F, TM.getTargetData());
- Info = &FunctionInfoMap[F];
- } else {
- Info = &info_item->second;
- }
-
- const FunctionType *FT = F->getFunctionType();
- switch (Info->getDecorationStyle()) {
- case None:
- break;
- case StdCall:
- // "Pure" variadic functions do not receive @0 suffix.
- if (!FT->isVarArg() || (FT->getNumParams() == 0) ||
- (FT->getNumParams() == 1 && F->hasStructRetAttr()))
- Name += '@' + utostr_32(Info->getBytesToPopOnReturn());
- break;
- case FastCall:
- // "Pure" variadic functions do not receive @0 suffix.
- if (!FT->isVarArg() || (FT->getNumParams() == 0) ||
- (FT->getNumParams() == 1 && F->hasStructRetAttr()))
- Name += '@' + utostr_32(Info->getBytesToPopOnReturn());
-
- if (Name[0] == '_')
- Name[0] = '@';
- else
- Name = '@' + Name;
-
- break;
- default:
- assert(0 && "Unsupported DecorationStyle");
- }
-}
-
-/// runOnMachineFunction - This uses the printMachineInstruction()
-/// method to print assembly for each instruction.
-///
-bool X86IntelAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
- this->MF = &MF;
- SetupMachineFunction(MF);
- O << "\n\n";
-
- // Print out constants referenced by the function
- EmitConstantPool(MF.getConstantPool());
-
- // Print out labels for the function.
- const Function *F = MF.getFunction();
- unsigned CC = F->getCallingConv();
- unsigned FnAlign = MF.getAlignment();
-
- // Populate function information map. Actually, We don't want to populate
- // non-stdcall or non-fastcall functions' information right now.
- if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall)
- FunctionInfoMap[F] = *MF.getInfo<X86MachineFunctionInfo>();
-
- decorateName(CurrentFnName, F);
-
- SwitchToTextSection("_text", F);
- switch (F->getLinkage()) {
- default: assert(0 && "Unsupported linkage type!");
- case Function::PrivateLinkage:
- case Function::InternalLinkage:
- EmitAlignment(FnAlign);
- break;
- case Function::DLLExportLinkage:
- DLLExportedFns.insert(CurrentFnName);
- //FALLS THROUGH
- case Function::ExternalLinkage:
- O << "\tpublic " << CurrentFnName << "\n";
- EmitAlignment(FnAlign);
- break;
- }
-
- O << CurrentFnName << "\tproc near\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 if there are any predecessors.
- if (!I->pred_empty()) {
- printBasicBlockLabel(I, true, true);
- O << '\n';
- }
- for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II) {
- // Print the assembly for the instruction.
- printMachineInstruction(II);
- }
- }
-
- // Print out jump tables referenced by the function.
- EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
-
- O << CurrentFnName << "\tendp\n";
-
- O.flush();
-
- // We didn't modify anything.
- return false;
-}
-
-void X86IntelAsmPrinter::printSSECC(const MachineInstr *MI, unsigned Op) {
- unsigned char value = MI->getOperand(Op).getImm();
- assert(value <= 7 && "Invalid ssecc argument!");
- switch (value) {
- case 0: O << "eq"; break;
- case 1: O << "lt"; break;
- case 2: O << "le"; break;
- case 3: O << "unord"; break;
- case 4: O << "neq"; break;
- case 5: O << "nlt"; break;
- case 6: O << "nle"; break;
- case 7: O << "ord"; break;
- }
-}
-
-void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
- const char *Modifier) {
- switch (MO.getType()) {
- case MachineOperand::MO_Register: {
- if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) {
- unsigned Reg = MO.getReg();
- if (Modifier && strncmp(Modifier, "subreg", strlen("subreg")) == 0) {
- MVT VT = (strcmp(Modifier,"subreg64") == 0) ?
- MVT::i64 : ((strcmp(Modifier, "subreg32") == 0) ? MVT::i32 :
- ((strcmp(Modifier,"subreg16") == 0) ? MVT::i16 :MVT::i8));
- Reg = getX86SubSuperRegister(Reg, VT);
- }
- O << TRI->getName(Reg);
- } else
- O << "reg" << MO.getReg();
- return;
- }
- case MachineOperand::MO_Immediate:
- O << MO.getImm();
- return;
- case MachineOperand::MO_JumpTableIndex: {
- bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- if (!isMemOp) O << "OFFSET ";
- O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << "_" << MO.getIndex();
- return;
- }
- case MachineOperand::MO_ConstantPoolIndex: {
- bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- if (!isMemOp) O << "OFFSET ";
- O << "[" << TAI->getPrivateGlobalPrefix() << "CPI"
- << getFunctionNumber() << "_" << MO.getIndex();
- printOffset(MO.getOffset());
- O << "]";
- return;
- }
- case MachineOperand::MO_GlobalAddress: {
- bool isMemOp = Modifier && !strcmp(Modifier, "mem");
- GlobalValue *GV = MO.getGlobal();
- std::string Name = Mang->getValueName(GV);
-
- decorateName(Name, GV);
-
- if (!isMemOp) O << "OFFSET ";
- if (GV->hasDLLImportLinkage()) {
- // FIXME: This should be fixed with full support of stdcall & fastcall
- // CC's
- O << "__imp_";
- }
- O << Name;
- printOffset(MO.getOffset());
- return;
- }
- case MachineOperand::MO_ExternalSymbol: {
- O << TAI->getGlobalPrefix() << MO.getSymbolName();
- return;
- }
- default:
- O << "<unknown operand type>"; return;
- }
-}
-
-void X86IntelAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo){
- const MachineOperand &MO = MI->getOperand(OpNo);
- switch (MO.getType()) {
- default: assert(0 && "Unknown pcrel immediate operand");
- case MachineOperand::MO_Immediate:
- O << MO.getImm();
- return;
- case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
- return;
-
- case MachineOperand::MO_GlobalAddress: {
- GlobalValue *GV = MO.getGlobal();
- std::string Name = Mang->getValueName(GV);
- decorateName(Name, GV);
-
- if (GV->hasDLLImportLinkage()) {
- // FIXME: This should be fixed with full support of stdcall & fastcall
- // CC's
- O << "__imp_";
- }
- O << Name;
- printOffset(MO.getOffset());
- return;
- }
-
- case MachineOperand::MO_ExternalSymbol:
- O << TAI->getGlobalPrefix() << MO.getSymbolName();
- return;
- }
-}
-
-
-void X86IntelAsmPrinter::printLeaMemReference(const MachineInstr *MI,
- unsigned Op,
- const char *Modifier) {
- const MachineOperand &BaseReg = MI->getOperand(Op);
- int ScaleVal = MI->getOperand(Op+1).getImm();
- const MachineOperand &IndexReg = MI->getOperand(Op+2);
- const MachineOperand &DispSpec = MI->getOperand(Op+3);
-
- O << "[";
- bool NeedPlus = false;
- if (BaseReg.getReg()) {
- printOp(BaseReg, Modifier);
- NeedPlus = true;
- }
-
- if (IndexReg.getReg()) {
- if (NeedPlus) O << " + ";
- if (ScaleVal != 1)
- O << ScaleVal << "*";
- printOp(IndexReg, Modifier);
- NeedPlus = true;
- }
-
- if (DispSpec.isGlobal() || DispSpec.isCPI() ||
- DispSpec.isJTI()) {
- if (NeedPlus)
- O << " + ";
- printOp(DispSpec, "mem");
- } else {
- int DispVal = DispSpec.getImm();
- if (DispVal || (!BaseReg.getReg() && !IndexReg.getReg())) {
- if (NeedPlus) {
- if (DispVal > 0)
- O << " + ";
- else {
- O << " - ";
- DispVal = -DispVal;
- }
- }
- O << DispVal;
- }
- }
- O << "]";
-}
-
-void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier) {
- assert(isMem(MI, Op) && "Invalid memory reference!");
- MachineOperand Segment = MI->getOperand(Op+4);
- if (Segment.getReg()) {
- printOperand(MI, Op+4, Modifier);
- O << ':';
- }
- printLeaMemReference(MI, Op, Modifier);
-}
-
-void X86IntelAsmPrinter::printPICJumpTableSetLabel(unsigned uid,
- const MachineBasicBlock *MBB) const {
- if (!TAI->getSetDirective())
- return;
-
- O << TAI->getSetDirective() << ' ' << TAI->getPrivateGlobalPrefix()
- << getFunctionNumber() << '_' << uid << "_set_" << MBB->getNumber() << ',';
- printBasicBlockLabel(MBB, false, false, false);
- O << '-' << "\"L" << getFunctionNumber() << "$pb\"'\n";
-}
-
-void X86IntelAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
- O << "L" << getFunctionNumber() << "$pb\n";
- O << "L" << getFunctionNumber() << "$pb:";
-}
-
-bool X86IntelAsmPrinter::printAsmMRegister(const MachineOperand &MO,
- const char Mode) {
- unsigned Reg = MO.getReg();
- switch (Mode) {
- default: return true; // Unknown mode.
- case 'b': // Print QImode register
- Reg = getX86SubSuperRegister(Reg, MVT::i8);
- break;
- case 'h': // Print QImode high register
- Reg = getX86SubSuperRegister(Reg, MVT::i8, true);
- break;
- case 'w': // Print HImode register
- Reg = getX86SubSuperRegister(Reg, MVT::i16);
- break;
- case 'k': // Print SImode register
- Reg = getX86SubSuperRegister(Reg, MVT::i32);
- break;
- }
-
- O << TRI->getName(Reg);
- return false;
-}
-
-/// PrintAsmOperand - Print out an operand for an inline asm expression.
-///
-bool X86IntelAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant,
- const char *ExtraCode) {
- // Does this asm operand have a single letter operand modifier?
- if (ExtraCode && ExtraCode[0]) {
- if (ExtraCode[1] != 0) return true; // Unknown modifier.
-
- switch (ExtraCode[0]) {
- default: return true; // Unknown modifier.
- case 'b': // Print QImode register
- case 'h': // Print QImode high register
- case 'w': // Print HImode register
- case 'k': // Print SImode register
- return printAsmMRegister(MI->getOperand(OpNo), ExtraCode[0]);
- }
- }
-
- printOperand(MI, OpNo);
- return false;
-}
-
-bool X86IntelAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
- unsigned OpNo,
- unsigned AsmVariant,
- const char *ExtraCode) {
- if (ExtraCode && ExtraCode[0])
- return true; // Unknown modifier.
- printMemReference(MI, OpNo);
- return false;
-}
-
-/// printMachineInstruction -- Print out a single X86 LLVM instruction
-/// MI in Intel syntax to the current output stream.
-///
-void X86IntelAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
- ++EmittedInsts;
-
- // Call the autogenerated instruction printer routines.
- printInstruction(MI);
-}
-
-bool X86IntelAsmPrinter::doInitialization(Module &M) {
- bool Result = AsmPrinter::doInitialization(M);
-
- Mang->markCharUnacceptable('.');
-
- O << "\t.686\n\t.MMX\n\t.XMM\n\t.model flat\n\n";
-
- // Emit declarations for external functions.
- for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
- if (I->isDeclaration()) {
- std::string Name = Mang->getValueName(I);
- decorateName(Name, I);
-
- O << "\tEXTERN " ;
- if (I->hasDLLImportLinkage()) {
- O << "__imp_";
- }
- O << Name << ":near\n";
- }
-
- // Emit declarations for external globals. Note that VC++ always declares
- // external globals to have type byte, and if that's good enough for VC++...
- for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I) {
- if (I->isDeclaration()) {
- std::string Name = Mang->getValueName(I);
-
- O << "\tEXTERN " ;
- if (I->hasDLLImportLinkage()) {
- O << "__imp_";
- }
- O << Name << ":byte\n";
- }
- }
-
- return Result;
-}
-
-bool X86IntelAsmPrinter::doFinalization(Module &M) {
- const TargetData *TD = TM.getTargetData();
-
- // Print out module-level global variables here.
- for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I) {
- if (I->isDeclaration()) continue; // External global require no code
-
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(I))
- continue;
-
- std::string name = Mang->getValueName(I);
- Constant *C = I->getInitializer();
- unsigned Align = TD->getPreferredAlignmentLog(I);
- bool bCustomSegment = false;
-
- switch (I->getLinkage()) {
- case GlobalValue::CommonLinkage:
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- SwitchToDataSection("");
- O << name << "?\tSEGEMNT PARA common 'COMMON'\n";
- bCustomSegment = true;
- // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256
- // are also available.
- break;
- case GlobalValue::AppendingLinkage:
- SwitchToDataSection("");
- O << name << "?\tSEGMENT PARA public 'DATA'\n";
- bCustomSegment = true;
- // FIXME: the default alignment is 16 bytes, but 1, 2, 4, and 256
- // are also available.
- break;
- case GlobalValue::DLLExportLinkage:
- DLLExportedGVs.insert(name);
- // FALL THROUGH
- case GlobalValue::ExternalLinkage:
- O << "\tpublic " << name << "\n";
- // FALL THROUGH
- case GlobalValue::InternalLinkage:
- SwitchToSection(TAI->getDataSection());
- break;
- default:
- assert(0 && "Unknown linkage type!");
- }
-
- if (!bCustomSegment)
- EmitAlignment(Align, I);
-
- O << name << ":";
- if (VerboseAsm)
- O << "\t\t\t\t" << TAI->getCommentString()
- << " " << I->getName();
- O << '\n';
-
- EmitGlobalConstant(C);
-
- if (bCustomSegment)
- O << name << "?\tends\n";
- }
-
- // Output linker support code for dllexported globals
- if (!DLLExportedGVs.empty() || !DLLExportedFns.empty()) {
- SwitchToDataSection("");
- O << "; WARNING: The following code is valid only with MASM v8.x"
- << "and (possible) higher\n"
- << "; This version of MASM is usually shipped with Microsoft "
- << "Visual Studio 2005\n"
- << "; or (possible) further versions. Unfortunately, there is no "
- << "way to support\n"
- << "; dllexported symbols in the earlier versions of MASM in fully "
- << "automatic way\n\n";
- O << "_drectve\t segment info alias('.drectve')\n";
- }
-
- for (StringSet<>::iterator i = DLLExportedGVs.begin(),
- e = DLLExportedGVs.end();
- i != e; ++i)
- O << "\t db ' /EXPORT:" << i->getKeyData() << ",data'\n";
-
- for (StringSet<>::iterator i = DLLExportedFns.begin(),
- e = DLLExportedFns.end();
- i != e; ++i)
- O << "\t db ' /EXPORT:" << i->getKeyData() << "'\n";
-
- if (!DLLExportedGVs.empty() || !DLLExportedFns.empty())
- O << "_drectve\t ends\n";
-
- // Bypass X86SharedAsmPrinter::doFinalization().
- bool Result = AsmPrinter::doFinalization(M);
- SwitchToDataSection("");
- O << "\tend\n";
- return Result;
-}
-
-void X86IntelAsmPrinter::EmitString(const ConstantArray *CVA) const {
- unsigned NumElts = CVA->getNumOperands();
- if (NumElts) {
- // ML does not have escape sequences except '' for '. It also has a maximum
- // string length of 255.
- unsigned len = 0;
- bool inString = false;
- for (unsigned i = 0; i < NumElts; i++) {
- int n = cast<ConstantInt>(CVA->getOperand(i))->getZExtValue() & 255;
- if (len == 0)
- O << "\tdb ";
-
- if (n >= 32 && n <= 127) {
- if (!inString) {
- if (len > 0) {
- O << ",'";
- len += 2;
- } else {
- O << "'";
- len++;
- }
- inString = true;
- }
- if (n == '\'') {
- O << "'";
- len++;
- }
- O << char(n);
- } else {
- if (inString) {
- O << "'";
- len++;
- inString = false;
- }
- if (len > 0) {
- O << ",";
- len++;
- }
- O << n;
- len += 1 + (n > 9) + (n > 99);
- }
-
- if (len > 60) {
- if (inString) {
- O << "'";
- inString = false;
- }
- O << "\n";
- len = 0;
- }
- }
-
- if (len > 0) {
- if (inString)
- O << "'";
- O << "\n";
- }
- }
-}
-
-// Include the auto-generated portion of the assembly writer.
-#include "X86GenAsmWriter1.inc"
diff --git a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h b/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h
deleted file mode 100644
index a724c3c..0000000
--- a/lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h
+++ /dev/null
@@ -1,162 +0,0 @@
-//===-- X86IntelAsmPrinter.h - Convert X86 LLVM code to Intel assembly ----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Intel assembly code printer class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef X86INTELASMPRINTER_H
-#define X86INTELASMPRINTER_H
-
-#include "../X86.h"
-#include "../X86MachineFunctionInfo.h"
-#include "../X86TargetMachine.h"
-#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-struct VISIBILITY_HIDDEN X86IntelAsmPrinter : public AsmPrinter {
- explicit X86IntelAsmPrinter(raw_ostream &O, X86TargetMachine &TM,
- const TargetAsmInfo *T, bool V)
- : AsmPrinter(O, TM, T, V) {}
-
- virtual const char *getPassName() const {
- return "X86 Intel-Style Assembly Printer";
- }
-
- /// printInstruction - This method is automatically generated by tablegen
- /// from the instruction set description. This method returns true if the
- /// machine instruction was sufficiently described to print it, otherwise it
- /// returns false.
- bool printInstruction(const MachineInstr *MI);
-
- // This method is used by the tablegen'erated instruction printer.
- void printOperand(const MachineInstr *MI, unsigned OpNo,
- const char *Modifier = 0) {
- const MachineOperand &MO = MI->getOperand(OpNo);
- if (MO.isReg()) {
- assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
- "Not physreg??");
- O << TM.getRegisterInfo()->get(MO.getReg()).Name; // Capitalized names
- } else {
- printOp(MO, Modifier);
- }
- }
-
- void print_pcrel_imm(const MachineInstr *MI, unsigned OpNo);
-
-
- void printi8mem(const MachineInstr *MI, unsigned OpNo) {
- O << "BYTE PTR ";
- printMemReference(MI, OpNo);
- }
- void printi16mem(const MachineInstr *MI, unsigned OpNo) {
- O << "WORD PTR ";
- printMemReference(MI, OpNo);
- }
- void printi32mem(const MachineInstr *MI, unsigned OpNo) {
- O << "DWORD PTR ";
- printMemReference(MI, OpNo);
- }
- void printi64mem(const MachineInstr *MI, unsigned OpNo) {
- O << "QWORD PTR ";
- printMemReference(MI, OpNo);
- }
- void printi128mem(const MachineInstr *MI, unsigned OpNo) {
- O << "XMMWORD PTR ";
- printMemReference(MI, OpNo);
- }
- void printi256mem(const MachineInstr *MI, unsigned OpNo) {
- O << "YMMWORD PTR ";
- printMemReference(MI, OpNo);
- }
- void printf32mem(const MachineInstr *MI, unsigned OpNo) {
- O << "DWORD PTR ";
- printMemReference(MI, OpNo);
- }
- void printf64mem(const MachineInstr *MI, unsigned OpNo) {
- O << "QWORD PTR ";
- printMemReference(MI, OpNo);
- }
- void printf80mem(const MachineInstr *MI, unsigned OpNo) {
- O << "XWORD PTR ";
- printMemReference(MI, OpNo);
- }
- void printf128mem(const MachineInstr *MI, unsigned OpNo) {
- O << "XMMWORD PTR ";
- printMemReference(MI, OpNo);
- }
- void printf256mem(const MachineInstr *MI, unsigned OpNo) {
- O << "YMMWORD PTR ";
- printMemReference(MI, OpNo);
- }
- void printlea32mem(const MachineInstr *MI, unsigned OpNo) {
- O << "DWORD PTR ";
- printLeaMemReference(MI, OpNo);
- }
- void printlea64mem(const MachineInstr *MI, unsigned OpNo) {
- O << "QWORD PTR ";
- printLeaMemReference(MI, OpNo);
- }
- void printlea64_32mem(const MachineInstr *MI, unsigned OpNo) {
- O << "QWORD PTR ";
- printLeaMemReference(MI, OpNo, "subreg64");
- }
-
- bool printAsmMRegister(const MachineOperand &MO, const char Mode);
- bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant, const char *ExtraCode);
- bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant, const char *ExtraCode);
- void printMachineInstruction(const MachineInstr *MI);
- void printOp(const MachineOperand &MO, const char *Modifier = 0);
- void printSSECC(const MachineInstr *MI, unsigned Op);
- void printMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier=NULL);
- void printLeaMemReference(const MachineInstr *MI, unsigned Op,
- const char *Modifier=NULL);
- void printPICJumpTableSetLabel(unsigned uid,
- const MachineBasicBlock *MBB) const;
- void printPICJumpTableSetLabel(unsigned uid, unsigned uid2,
- const MachineBasicBlock *MBB) const {
- AsmPrinter::printPICJumpTableSetLabel(uid, uid2, MBB);
- }
- void printPICLabel(const MachineInstr *MI, unsigned Op);
- bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
-
- // We have to propagate some information about MachineFunction to
- // AsmPrinter. It's ok, when we're printing the function, since we have
- // access to MachineFunction and can get the appropriate MachineFunctionInfo.
- // Unfortunately, this is not possible when we're printing reference to
- // Function (e.g. calling it and so on). Even more, there is no way to get the
- // corresponding MachineFunctions: it can even be not created at all. That's
- // why we should use additional structure, when we're collecting all necessary
- // information.
- //
- // This structure is using e.g. for name decoration for stdcall & fastcall'ed
- // function, since we have to use arguments' size for decoration.
- typedef std::map<const Function*, X86MachineFunctionInfo> FMFInfoMap;
- FMFInfoMap FunctionInfoMap;
-
- void decorateName(std::string& Name, const GlobalValue* GV);
-
- virtual void EmitString(const ConstantArray *CVA) const;
-
- // Necessary for dllexport support
- StringSet<> DLLExportedFns, DLLExportedGVs;
-};
-
-} // end namespace llvm
-
-#endif
diff --git a/lib/Target/X86/X86TargetAsmInfo.cpp b/lib/Target/X86/X86TargetAsmInfo.cpp
deleted file mode 100644
index f49ca15..0000000
--- a/lib/Target/X86/X86TargetAsmInfo.cpp
+++ /dev/null
@@ -1,429 +0,0 @@
-//===-- X86TargetAsmInfo.cpp - X86 asm properties ---------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the X86TargetAsmInfo properties.
-//
-//===----------------------------------------------------------------------===//
-
-#include "X86TargetAsmInfo.h"
-#include "X86TargetMachine.h"
-#include "X86Subtarget.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/InlineAsm.h"
-#include "llvm/Instructions.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/Module.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Dwarf.h"
-
-using namespace llvm;
-using namespace llvm::dwarf;
-
-const char *const llvm::x86_asm_table[] = {
- "{si}", "S",
- "{di}", "D",
- "{ax}", "a",
- "{cx}", "c",
- "{memory}", "memory",
- "{flags}", "",
- "{dirflag}", "",
- "{fpsr}", "",
- "{cc}", "cc",
- 0,0};
-
-X86DarwinTargetAsmInfo::X86DarwinTargetAsmInfo(const X86TargetMachine &TM):
- X86TargetAsmInfo<DarwinTargetAsmInfo>(TM) {
- const X86Subtarget* Subtarget = &TM.getSubtarget<X86Subtarget>();
- bool is64Bit = Subtarget->is64Bit();
-
- AlignmentIsInBytes = false;
- TextAlignFillValue = 0x90;
-
-
- if (!is64Bit)
- Data64bitsDirective = 0; // we can't emit a 64-bit unit
- ZeroDirective = "\t.space\t"; // ".space N" emits N zeros.
- ZeroFillDirective = "\t.zerofill\t"; // Uses .zerofill
- if (TM.getRelocationModel() != Reloc::Static)
- ConstantPoolSection = "\t.const_data";
- else
- ConstantPoolSection = "\t.const\n";
- // FIXME: Why don't we always use this section?
- if (is64Bit)
- SixteenByteConstantSection = getUnnamedSection("\t.literal16\n",
- SectionFlags::Mergeable);
- LCOMMDirective = "\t.lcomm\t";
- // Leopard and above support aligned common symbols.
- COMMDirectiveTakesAlignment = (Subtarget->getDarwinVers() >= 9);
- HasDotTypeDotSizeDirective = false;
- NonLocalEHFrameLabel = true;
- if (is64Bit) {
- PersonalityPrefix = "";
- PersonalitySuffix = "+4@GOTPCREL";
- } else {
- PersonalityPrefix = "L";
- PersonalitySuffix = "$non_lazy_ptr";
- }
- InlineAsmStart = "## InlineAsm Start";
- InlineAsmEnd = "## InlineAsm End";
- CommentString = "##";
- SetDirective = "\t.set";
- PCSymbol = ".";
- UsedDirective = "\t.no_dead_strip\t";
- ProtectedDirective = "\t.globl\t";
-
- SupportsDebugInformation = true;
-
- DwarfDebugInlineSection = ".section __DWARF,__debug_inlined,regular,debug";
- DwarfUsesInlineInfoSection = true;
-
- // Exceptions handling
- SupportsExceptionHandling = true;
- GlobalEHDirective = "\t.globl\t";
- SupportsWeakOmittedEHFrame = false;
- AbsoluteEHSectionOffsets = false;
- DwarfEHFrameSection =
- ".section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support";
- DwarfExceptionSection = ".section __DATA,__gcc_except_tab";
-}
-
-unsigned
-X86DarwinTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const {
- if (Reason == DwarfEncoding::Functions && Global)
- return (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4);
- else if (Reason == DwarfEncoding::CodeLabels || !Global)
- return DW_EH_PE_pcrel;
- else
- return DW_EH_PE_absptr;
-}
-
-const char *
-X86DarwinTargetAsmInfo::getEHGlobalPrefix() const
-{
- const X86Subtarget* Subtarget = &TM.getSubtarget<X86Subtarget>();
- if (Subtarget->getDarwinVers() > 9)
- return PrivateGlobalPrefix;
- else
- return "";
-}
-
-X86ELFTargetAsmInfo::X86ELFTargetAsmInfo(const X86TargetMachine &TM):
- X86TargetAsmInfo<ELFTargetAsmInfo>(TM) {
-
- CStringSection = ".rodata.str";
- PrivateGlobalPrefix = ".L";
- WeakRefDirective = "\t.weak\t";
- SetDirective = "\t.set\t";
- PCSymbol = ".";
-
- // Set up DWARF directives
- HasLEB128 = true; // Target asm supports leb128 directives (little-endian)
-
- // Debug Information
- AbsoluteDebugSectionOffsets = true;
- SupportsDebugInformation = true;
- DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"\",@progbits";
- DwarfInfoSection = "\t.section\t.debug_info,\"\",@progbits";
- DwarfLineSection = "\t.section\t.debug_line,\"\",@progbits";
- DwarfFrameSection = "\t.section\t.debug_frame,\"\",@progbits";
- DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"\",@progbits";
- DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"\",@progbits";
- DwarfStrSection = "\t.section\t.debug_str,\"\",@progbits";
- DwarfLocSection = "\t.section\t.debug_loc,\"\",@progbits";
- DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits";
- DwarfRangesSection = "\t.section\t.debug_ranges,\"\",@progbits";
- DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
-
- // Exceptions handling
- SupportsExceptionHandling = true;
- AbsoluteEHSectionOffsets = false;
- DwarfEHFrameSection = "\t.section\t.eh_frame,\"aw\",@progbits";
- DwarfExceptionSection = "\t.section\t.gcc_except_table,\"a\",@progbits";
-
- // On Linux we must declare when we can use a non-executable stack.
- if (TM.getSubtarget<X86Subtarget>().isLinux())
- NonexecutableStackDirective = "\t.section\t.note.GNU-stack,\"\",@progbits";
-}
-
-unsigned
-X86ELFTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const {
- CodeModel::Model CM = TM.getCodeModel();
- bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit();
-
- if (TM.getRelocationModel() == Reloc::PIC_) {
- unsigned Format = 0;
-
- if (!is64Bit)
- // 32 bit targets always encode pointers as 4 bytes
- Format = DW_EH_PE_sdata4;
- else {
- // 64 bit targets encode pointers in 4 bytes iff:
- // - code model is small OR
- // - code model is medium and we're emitting externally visible symbols
- // or any code symbols
- if (CM == CodeModel::Small ||
- (CM == CodeModel::Medium && (Global ||
- Reason != DwarfEncoding::Data)))
- Format = DW_EH_PE_sdata4;
- else
- Format = DW_EH_PE_sdata8;
- }
-
- if (Global)
- Format |= DW_EH_PE_indirect;
-
- return (Format | DW_EH_PE_pcrel);
- } else {
- if (is64Bit &&
- (CM == CodeModel::Small ||
- (CM == CodeModel::Medium && Reason != DwarfEncoding::Data)))
- return DW_EH_PE_udata4;
- else
- return DW_EH_PE_absptr;
- }
-}
-
-X86COFFTargetAsmInfo::X86COFFTargetAsmInfo(const X86TargetMachine &TM):
- X86GenericTargetAsmInfo(TM) {
-
- GlobalPrefix = "_";
- LCOMMDirective = "\t.lcomm\t";
- COMMDirectiveTakesAlignment = false;
- HasDotTypeDotSizeDirective = false;
- HasSingleParameterDotFile = false;
- StaticCtorsSection = "\t.section .ctors,\"aw\"";
- StaticDtorsSection = "\t.section .dtors,\"aw\"";
- HiddenDirective = NULL;
- PrivateGlobalPrefix = "L"; // Prefix for private global symbols
- WeakRefDirective = "\t.weak\t";
- SetDirective = "\t.set\t";
-
- // Set up DWARF directives
- HasLEB128 = true; // Target asm supports leb128 directives (little-endian)
- AbsoluteDebugSectionOffsets = true;
- AbsoluteEHSectionOffsets = false;
- SupportsDebugInformation = true;
- DwarfSectionOffsetDirective = "\t.secrel32\t";
- DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"dr\"";
- DwarfInfoSection = "\t.section\t.debug_info,\"dr\"";
- DwarfLineSection = "\t.section\t.debug_line,\"dr\"";
- DwarfFrameSection = "\t.section\t.debug_frame,\"dr\"";
- DwarfPubNamesSection ="\t.section\t.debug_pubnames,\"dr\"";
- DwarfPubTypesSection ="\t.section\t.debug_pubtypes,\"dr\"";
- DwarfStrSection = "\t.section\t.debug_str,\"dr\"";
- DwarfLocSection = "\t.section\t.debug_loc,\"dr\"";
- DwarfARangesSection = "\t.section\t.debug_aranges,\"dr\"";
- DwarfRangesSection = "\t.section\t.debug_ranges,\"dr\"";
- DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"dr\"";
-}
-
-unsigned
-X86COFFTargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const {
- CodeModel::Model CM = TM.getCodeModel();
- bool is64Bit = TM.getSubtarget<X86Subtarget>().is64Bit();
-
- if (TM.getRelocationModel() == Reloc::PIC_) {
- unsigned Format = 0;
-
- if (!is64Bit)
- // 32 bit targets always encode pointers as 4 bytes
- Format = DW_EH_PE_sdata4;
- else {
- // 64 bit targets encode pointers in 4 bytes iff:
- // - code model is small OR
- // - code model is medium and we're emitting externally visible symbols
- // or any code symbols
- if (CM == CodeModel::Small ||
- (CM == CodeModel::Medium && (Global ||
- Reason != DwarfEncoding::Data)))
- Format = DW_EH_PE_sdata4;
- else
- Format = DW_EH_PE_sdata8;
- }
-
- if (Global)
- Format |= DW_EH_PE_indirect;
-
- return (Format | DW_EH_PE_pcrel);
- } else {
- if (is64Bit &&
- (CM == CodeModel::Small ||
- (CM == CodeModel::Medium && Reason != DwarfEncoding::Data)))
- return DW_EH_PE_udata4;
- else
- return DW_EH_PE_absptr;
- }
-}
-
-std::string
-X86COFFTargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV,
- SectionKind::Kind kind) const {
- switch (kind) {
- case SectionKind::Text:
- return ".text$linkonce" + GV->getName();
- case SectionKind::Data:
- case SectionKind::BSS:
- case SectionKind::ThreadData:
- case SectionKind::ThreadBSS:
- return ".data$linkonce" + GV->getName();
- case SectionKind::ROData:
- case SectionKind::RODataMergeConst:
- case SectionKind::RODataMergeStr:
- return ".rdata$linkonce" + GV->getName();
- default:
- assert(0 && "Unknown section kind");
- }
- return NULL;
-}
-
-std::string X86COFFTargetAsmInfo::printSectionFlags(unsigned flags) const {
- std::string Flags = ",\"";
-
- if (flags & SectionFlags::Code)
- Flags += 'x';
- if (flags & SectionFlags::Writeable)
- Flags += 'w';
-
- Flags += "\"";
-
- return Flags;
-}
-
-X86WinTargetAsmInfo::X86WinTargetAsmInfo(const X86TargetMachine &TM):
- X86GenericTargetAsmInfo(TM) {
- GlobalPrefix = "_";
- CommentString = ";";
-
- InlineAsmStart = "; InlineAsm Start";
- InlineAsmEnd = "; InlineAsm End";
-
- PrivateGlobalPrefix = "$";
- AlignDirective = "\tALIGN\t";
- ZeroDirective = "\tdb\t";
- ZeroDirectiveSuffix = " dup(0)";
- AsciiDirective = "\tdb\t";
- AscizDirective = 0;
- Data8bitsDirective = "\tdb\t";
- Data16bitsDirective = "\tdw\t";
- Data32bitsDirective = "\tdd\t";
- Data64bitsDirective = "\tdq\t";
- HasDotTypeDotSizeDirective = false;
- HasSingleParameterDotFile = false;
-
- AlignmentIsInBytes = true;
-
- TextSection = getUnnamedSection("_text", SectionFlags::Code);
- DataSection = getUnnamedSection("_data", SectionFlags::Writeable);
-
- JumpTableDataSection = NULL;
- SwitchToSectionDirective = "";
- TextSectionStartSuffix = "\tSEGMENT PARA 'CODE'";
- DataSectionStartSuffix = "\tSEGMENT PARA 'DATA'";
- SectionEndDirectiveSuffix = "\tends\n";
-}
-
-template <class BaseTAI>
-bool X86TargetAsmInfo<BaseTAI>::LowerToBSwap(CallInst *CI) const {
- // FIXME: this should verify that we are targetting a 486 or better. If not,
- // we will turn this bswap into something that will be lowered to logical ops
- // instead of emitting the bswap asm. For now, we don't support 486 or lower
- // so don't worry about this.
-
- // Verify this is a simple bswap.
- if (CI->getNumOperands() != 2 ||
- CI->getType() != CI->getOperand(1)->getType() ||
- !CI->getType()->isInteger())
- return false;
-
- const IntegerType *Ty = dyn_cast<IntegerType>(CI->getType());
- if (!Ty || Ty->getBitWidth() % 16 != 0)
- return false;
-
- // Okay, we can do this xform, do so now.
- const Type *Tys[] = { Ty };
- Module *M = CI->getParent()->getParent()->getParent();
- Constant *Int = Intrinsic::getDeclaration(M, Intrinsic::bswap, Tys, 1);
-
- Value *Op = CI->getOperand(1);
- Op = CallInst::Create(Int, Op, CI->getName(), CI);
-
- CI->replaceAllUsesWith(Op);
- CI->eraseFromParent();
- return true;
-}
-
-template <class BaseTAI>
-bool X86TargetAsmInfo<BaseTAI>::ExpandInlineAsm(CallInst *CI) const {
- InlineAsm *IA = cast<InlineAsm>(CI->getCalledValue());
- std::vector<InlineAsm::ConstraintInfo> Constraints = IA->ParseConstraints();
-
- std::string AsmStr = IA->getAsmString();
-
- // TODO: should remove alternatives from the asmstring: "foo {a|b}" -> "foo a"
- std::vector<std::string> AsmPieces;
- SplitString(AsmStr, AsmPieces, "\n"); // ; as separator?
-
- switch (AsmPieces.size()) {
- default: return false;
- case 1:
- AsmStr = AsmPieces[0];
- AsmPieces.clear();
- SplitString(AsmStr, AsmPieces, " \t"); // Split with whitespace.
-
- // bswap $0
- if (AsmPieces.size() == 2 &&
- (AsmPieces[0] == "bswap" ||
- AsmPieces[0] == "bswapq" ||
- AsmPieces[0] == "bswapl") &&
- (AsmPieces[1] == "$0" ||
- AsmPieces[1] == "${0:q}")) {
- // No need to check constraints, nothing other than the equivalent of
- // "=r,0" would be valid here.
- return LowerToBSwap(CI);
- }
- // rorw $$8, ${0:w} --> llvm.bswap.i16
- if (CI->getType() == Type::Int16Ty &&
- AsmPieces.size() == 3 &&
- AsmPieces[0] == "rorw" &&
- AsmPieces[1] == "$$8," &&
- AsmPieces[2] == "${0:w}" &&
- IA->getConstraintString() == "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}") {
- return LowerToBSwap(CI);
- }
- break;
- case 3:
- if (CI->getType() == Type::Int64Ty && Constraints.size() >= 2 &&
- Constraints[0].Codes.size() == 1 && Constraints[0].Codes[0] == "A" &&
- Constraints[1].Codes.size() == 1 && Constraints[1].Codes[0] == "0") {
- // bswap %eax / bswap %edx / xchgl %eax, %edx -> llvm.bswap.i64
- std::vector<std::string> Words;
- SplitString(AsmPieces[0], Words, " \t");
- if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%eax") {
- Words.clear();
- SplitString(AsmPieces[1], Words, " \t");
- if (Words.size() == 2 && Words[0] == "bswap" && Words[1] == "%edx") {
- Words.clear();
- SplitString(AsmPieces[2], Words, " \t,");
- if (Words.size() == 3 && Words[0] == "xchgl" && Words[1] == "%eax" &&
- Words[2] == "%edx") {
- return LowerToBSwap(CI);
- }
- }
- }
- }
- break;
- }
- return false;
-}
-
-// Instantiate default implementation.
-TEMPLATE_INSTANTIATION(class X86TargetAsmInfo<TargetAsmInfo>);
diff --git a/lib/Target/X86/X86TargetAsmInfo.h b/lib/Target/X86/X86TargetAsmInfo.h
deleted file mode 100644
index f89171d..0000000
--- a/lib/Target/X86/X86TargetAsmInfo.h
+++ /dev/null
@@ -1,75 +0,0 @@
-//=====-- X86TargetAsmInfo.h - X86 asm properties -------------*- C++ -*--====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the X86TargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef X86TARGETASMINFO_H
-#define X86TARGETASMINFO_H
-
-#include "X86TargetMachine.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/ELFTargetAsmInfo.h"
-#include "llvm/Target/DarwinTargetAsmInfo.h"
-#include "llvm/Support/Compiler.h"
-
-namespace llvm {
-
- extern const char *const x86_asm_table[];
-
- template <class BaseTAI>
- struct X86TargetAsmInfo : public BaseTAI {
- explicit X86TargetAsmInfo(const X86TargetMachine &TM):
- BaseTAI(TM) {
- const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
-
- BaseTAI::AsmTransCBE = x86_asm_table;
- BaseTAI::AssemblerDialect = Subtarget->getAsmFlavor();
- }
-
- virtual bool ExpandInlineAsm(CallInst *CI) const;
-
- private:
- bool LowerToBSwap(CallInst *CI) const;
- };
-
- typedef X86TargetAsmInfo<TargetAsmInfo> X86GenericTargetAsmInfo;
-
- EXTERN_TEMPLATE_INSTANTIATION(class X86TargetAsmInfo<TargetAsmInfo>);
-
- struct X86DarwinTargetAsmInfo : public X86TargetAsmInfo<DarwinTargetAsmInfo> {
- explicit X86DarwinTargetAsmInfo(const X86TargetMachine &TM);
- virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const;
- virtual const char *getEHGlobalPrefix() const;
- };
-
- struct X86ELFTargetAsmInfo : public X86TargetAsmInfo<ELFTargetAsmInfo> {
- explicit X86ELFTargetAsmInfo(const X86TargetMachine &TM);
- virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const;
- };
-
- struct X86COFFTargetAsmInfo : public X86GenericTargetAsmInfo {
- explicit X86COFFTargetAsmInfo(const X86TargetMachine &TM);
- virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
- bool Global) const;
- virtual std::string UniqueSectionForGlobal(const GlobalValue* GV,
- SectionKind::Kind kind) const;
- virtual std::string printSectionFlags(unsigned flags) const;
- };
-
- struct X86WinTargetAsmInfo : public X86GenericTargetAsmInfo {
- explicit X86WinTargetAsmInfo(const X86TargetMachine &TM);
- };
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp
deleted file mode 100644
index 67cb0c8..0000000
--- a/lib/Target/XCore/XCoreAsmPrinter.cpp
+++ /dev/null
@@ -1,438 +0,0 @@
-//===-- XCoreAsmPrinter.cpp - XCore LLVM assembly writer ------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file 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 the XAS-format XCore assembly language.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "asm-printer"
-#include "XCore.h"
-#include "XCoreInstrInfo.h"
-#include "XCoreSubtarget.h"
-#include "XCoreTargetMachine.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/CodeGen/DwarfWriter.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineConstantPool.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Support/Mangler.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cctype>
-using namespace llvm;
-
-STATISTIC(EmittedInsts, "Number of machine instrs printed");
-
-static cl::opt<std::string> FileDirective("xcore-file-directive", cl::Optional,
- cl::desc("Output a file directive into the assembly file"),
- cl::Hidden,
- cl::value_desc("filename"),
- cl::init(""));
-
-static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional,
- cl::desc("Maximum number of threads (for emulation thread-local storage)"),
- cl::Hidden,
- cl::value_desc("number"),
- cl::init(8));
-
-namespace {
- class VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter {
- DwarfWriter *DW;
- const XCoreSubtarget &Subtarget;
- public:
- explicit XCoreAsmPrinter(raw_ostream &O, XCoreTargetMachine &TM,
- const TargetAsmInfo *T, bool V)
- : AsmPrinter(O, TM, T, V), DW(0),
- Subtarget(*TM.getSubtargetImpl()) {}
-
- virtual const char *getPassName() const {
- return "XCore Assembly Printer";
- }
-
- void printMemOperand(const MachineInstr *MI, int opNum);
- void printOperand(const MachineInstr *MI, int opNum);
- bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant, const char *ExtraCode);
-
- void emitFileDirective(const std::string &filename);
- void emitGlobalDirective(const std::string &name);
- void emitExternDirective(const std::string &name);
-
- void emitArrayBound(const std::string &name, const GlobalVariable *GV);
- void emitGlobal(const GlobalVariable *GV);
-
- void emitFunctionStart(MachineFunction &MF);
- void emitFunctionEnd(MachineFunction &MF);
-
- bool printInstruction(const MachineInstr *MI); // autogenerated.
- void printMachineInstruction(const MachineInstr *MI);
- bool runOnMachineFunction(MachineFunction &F);
- bool doInitialization(Module &M);
- bool doFinalization(Module &M);
-
- void getAnalysisUsage(AnalysisUsage &AU) const {
- AsmPrinter::getAnalysisUsage(AU);
- AU.setPreservesAll();
- AU.addRequired<MachineModuleInfo>();
- AU.addRequired<DwarfWriter>();
- }
- };
-} // end of anonymous namespace
-
-#include "XCoreGenAsmWriter.inc"
-
-/// createXCoreCodePrinterPass - Returns a pass that prints the XCore
-/// 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::createXCoreCodePrinterPass(raw_ostream &o,
- XCoreTargetMachine &tm,
- bool verbose) {
- return new XCoreAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose);
-}
-
-// PrintEscapedString - Print each character of the specified string, escaping
-// it if it is not printable or if it is an escape char.
-static void PrintEscapedString(const std::string &Str, raw_ostream &Out) {
- for (unsigned i = 0, e = Str.size(); i != e; ++i) {
- unsigned char C = Str[i];
- if (isprint(C) && C != '"' && C != '\\') {
- Out << C;
- } else {
- Out << '\\'
- << (char) ((C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A'))
- << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'));
- }
- }
-}
-
-void XCoreAsmPrinter::
-emitFileDirective(const std::string &name)
-{
- O << "\t.file\t\"";
- PrintEscapedString(name, O);
- O << "\"\n";
-}
-
-void XCoreAsmPrinter::
-emitGlobalDirective(const std::string &name)
-{
- O << TAI->getGlobalDirective() << name;
- O << "\n";
-}
-
-void XCoreAsmPrinter::
-emitExternDirective(const std::string &name)
-{
- O << "\t.extern\t" << name;
- O << '\n';
-}
-
-void XCoreAsmPrinter::
-emitArrayBound(const std::string &name, const GlobalVariable *GV)
-{
- assert(((GV->hasExternalLinkage() ||
- GV->hasWeakLinkage()) ||
- GV->hasLinkOnceLinkage()) && "Unexpected linkage");
- if (const ArrayType *ATy = dyn_cast<ArrayType>(
- cast<PointerType>(GV->getType())->getElementType()))
- {
- O << TAI->getGlobalDirective() << name << ".globound" << "\n";
- O << TAI->getSetDirective() << name << ".globound" << ","
- << ATy->getNumElements() << "\n";
- if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
- // TODO Use COMDAT groups for LinkOnceLinkage
- O << TAI->getWeakDefDirective() << name << ".globound" << "\n";
- }
- }
-}
-
-void XCoreAsmPrinter::
-emitGlobal(const GlobalVariable *GV)
-{
- const TargetData *TD = TM.getTargetData();
-
- if (GV->hasInitializer()) {
- // Check to see if this is a special global used by LLVM, if so, emit it.
- if (EmitSpecialLLVMGlobal(GV))
- return;
-
- SwitchToSection(TAI->SectionForGlobal(GV));
-
- std::string name = Mang->getValueName(GV);
- Constant *C = GV->getInitializer();
- unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
-
- // Mark the start of the global
- O << "\t.cc_top " << name << ".data," << name << "\n";
-
- switch (GV->getLinkage()) {
- case GlobalValue::AppendingLinkage:
- cerr << "AppendingLinkage is not supported by this target!\n";
- abort();
- case GlobalValue::LinkOnceAnyLinkage:
- case GlobalValue::LinkOnceODRLinkage:
- case GlobalValue::WeakAnyLinkage:
- case GlobalValue::WeakODRLinkage:
- case GlobalValue::ExternalLinkage:
- emitArrayBound(name, GV);
- emitGlobalDirective(name);
- // TODO Use COMDAT groups for LinkOnceLinkage
- if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
- O << TAI->getWeakDefDirective() << name << "\n";
- }
- // FALL THROUGH
- case GlobalValue::InternalLinkage:
- case GlobalValue::PrivateLinkage:
- break;
- case GlobalValue::GhostLinkage:
- cerr << "Should not have any unmaterialized functions!\n";
- abort();
- case GlobalValue::DLLImportLinkage:
- cerr << "DLLImport linkage is not supported by this target!\n";
- abort();
- case GlobalValue::DLLExportLinkage:
- cerr << "DLLExport linkage is not supported by this target!\n";
- abort();
- default:
- assert(0 && "Unknown linkage type!");
- }
-
- EmitAlignment(Align, GV, 2);
-
- unsigned Size = TD->getTypeAllocSize(C->getType());
- if (GV->isThreadLocal()) {
- Size *= MaxThreads;
- }
- if (TAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type " << name << ",@object\n";
- O << "\t.size " << name << "," << Size << "\n";
- }
- O << name << ":\n";
-
- EmitGlobalConstant(C);
- if (GV->isThreadLocal()) {
- for (unsigned i = 1; i < MaxThreads; ++i) {
- EmitGlobalConstant(C);
- }
- }
- if (Size < 4) {
- // The ABI requires that unsigned scalar types smaller than 32 bits
- // are are padded to 32 bits.
- EmitZeros(4 - Size);
- }
-
- // Mark the end of the global
- O << "\t.cc_bottom " << name << ".data\n";
- }
-}
-
-/// Emit the directives on the start of functions
-void XCoreAsmPrinter::
-emitFunctionStart(MachineFunction &MF)
-{
- // Print out the label for the function.
- const Function *F = MF.getFunction();
-
- SwitchToSection(TAI->SectionForGlobal(F));
-
- // Mark the start of the function
- O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n";
-
- switch (F->getLinkage()) {
- default: assert(0 && "Unknown linkage type!");
- case Function::InternalLinkage: // Symbols default to internal.
- case Function::PrivateLinkage:
- break;
- case Function::ExternalLinkage:
- emitGlobalDirective(CurrentFnName);
- break;
- case Function::LinkOnceAnyLinkage:
- case Function::LinkOnceODRLinkage:
- case Function::WeakAnyLinkage:
- case Function::WeakODRLinkage:
- // TODO Use COMDAT groups for LinkOnceLinkage
- O << TAI->getGlobalDirective() << CurrentFnName << "\n";
- O << TAI->getWeakDefDirective() << CurrentFnName << "\n";
- break;
- }
- // (1 << 1) byte aligned
- EmitAlignment(MF.getAlignment(), F, 1);
- if (TAI->hasDotTypeDotSizeDirective()) {
- O << "\t.type " << CurrentFnName << ",@function\n";
- }
- O << CurrentFnName << ":\n";
-}
-
-/// Emit the directives on the end of functions
-void XCoreAsmPrinter::
-emitFunctionEnd(MachineFunction &MF)
-{
- // Mark the end of the function
- O << "\t.cc_bottom " << CurrentFnName << ".function\n";
-}
-
-/// runOnMachineFunction - This uses the printMachineInstruction()
-/// method to print assembly for each instruction.
-///
-bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF)
-{
- this->MF = &MF;
-
- SetupMachineFunction(MF);
-
- // Print out constants referenced by the function
- EmitConstantPool(MF.getConstantPool());
-
- // Print out jump tables referenced by the function
- EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
-
- // Emit the function start directives
- emitFunctionStart(MF);
-
- // Emit pre-function debug information.
- DW->BeginFunction(&MF);
-
- // 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.
- if (I != MF.begin()) {
- printBasicBlockLabel(I, true , true);
- O << '\n';
- }
-
- for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
- II != E; ++II) {
- // Print the assembly for the instruction.
- O << "\t";
- printMachineInstruction(II);
- }
-
- // Each Basic Block is separated by a newline
- O << '\n';
- }
-
- // Emit function end directives
- emitFunctionEnd(MF);
-
- // Emit post-function debug information.
- DW->EndFunction(&MF);
-
- // We didn't modify anything.
- return false;
-}
-
-void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum)
-{
- printOperand(MI, opNum);
-
- if (MI->getOperand(opNum+1).isImm()
- && MI->getOperand(opNum+1).getImm() == 0)
- return;
-
- O << "+";
- printOperand(MI, opNum+1);
-}
-
-void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
- const MachineOperand &MO = MI->getOperand(opNum);
- switch (MO.getType()) {
- case MachineOperand::MO_Register:
- if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
- O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
- else
- assert(0 && "not implemented");
- break;
- case MachineOperand::MO_Immediate:
- O << MO.getImm();
- break;
- case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB());
- break;
- case MachineOperand::MO_GlobalAddress:
- O << Mang->getValueName(MO.getGlobal());
- break;
- case MachineOperand::MO_ExternalSymbol:
- O << MO.getSymbolName();
- break;
- case MachineOperand::MO_ConstantPoolIndex:
- O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
- << '_' << MO.getIndex();
- break;
- case MachineOperand::MO_JumpTableIndex:
- O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
- << '_' << MO.getIndex();
- break;
- default:
- assert(0 && "not implemented");
- }
-}
-
-/// PrintAsmOperand - Print out an operand for an inline asm expression.
-///
-bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant,
- const char *ExtraCode) {
- printOperand(MI, OpNo);
- return false;
-}
-
-void XCoreAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
- ++EmittedInsts;
-
- // Check for mov mnemonic
- unsigned src, dst, srcSR, dstSR;
- if (TM.getInstrInfo()->isMoveInstr(*MI, src, dst, srcSR, dstSR)) {
- O << "\tmov ";
- O << TM.getRegisterInfo()->get(dst).AsmName;
- O << ", ";
- O << TM.getRegisterInfo()->get(src).AsmName;
- O << "\n";
- return;
- }
- if (printInstruction(MI)) {
- return;
- }
- assert(0 && "Unhandled instruction in asm writer!");
-}
-
-bool XCoreAsmPrinter::doInitialization(Module &M) {
- bool Result = AsmPrinter::doInitialization(M);
- DW = getAnalysisIfAvailable<DwarfWriter>();
-
- if (!FileDirective.empty())
- emitFileDirective(FileDirective);
-
- return Result;
-}
-
-bool XCoreAsmPrinter::doFinalization(Module &M) {
-
- // Print out module-level global variables.
- for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I) {
- emitGlobal(I);
- }
-
- return AsmPrinter::doFinalization(M);
-}
diff --git a/lib/Target/XCore/XCoreTargetAsmInfo.cpp b/lib/Target/XCore/XCoreTargetAsmInfo.cpp
deleted file mode 100644
index 59ad624..0000000
--- a/lib/Target/XCore/XCoreTargetAsmInfo.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-//===-- XCoreTargetAsmInfo.cpp - XCore asm properties -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declarations of the XCoreTargetAsmInfo properties.
-// We use the small section flag for the CP relative and DP relative
-// flags. If a section is small and writable then it is DP relative. If a
-// section is small and not writable then it is CP relative.
-//
-//===----------------------------------------------------------------------===//
-
-#include "XCoreTargetAsmInfo.h"
-#include "XCoreTargetMachine.h"
-#include "llvm/GlobalVariable.h"
-#include "llvm/ADT/StringExtras.h"
-
-using namespace llvm;
-
-XCoreTargetAsmInfo::XCoreTargetAsmInfo(const XCoreTargetMachine &TM)
- : ELFTargetAsmInfo(TM),
- Subtarget(TM.getSubtargetImpl()) {
- SupportsDebugInformation = true;
- TextSection = getUnnamedSection("\t.text", SectionFlags::Code);
- DataSection = getNamedSection("\t.dp.data", SectionFlags::Writeable |
- SectionFlags::Small);
- BSSSection_ = getNamedSection("\t.dp.bss", SectionFlags::Writeable |
- SectionFlags::BSS | SectionFlags::Small);
- if (Subtarget->isXS1A()) {
- ReadOnlySection = getNamedSection("\t.dp.rodata", SectionFlags::None |
- SectionFlags::Writeable |
- SectionFlags::Small);
- } else {
- ReadOnlySection = getNamedSection("\t.cp.rodata", SectionFlags::None |
- SectionFlags::Small);
- }
- Data16bitsDirective = "\t.short\t";
- Data32bitsDirective = "\t.long\t";
- Data64bitsDirective = 0;
- ZeroDirective = "\t.space\t";
- CommentString = "#";
- ConstantPoolSection = "\t.section\t.cp.rodata,\"ac\",@progbits";
- JumpTableDataSection = "\t.section\t.dp.data,\"awd\",@progbits";
- PrivateGlobalPrefix = ".L";
- AscizDirective = ".asciiz";
- WeakDefDirective = "\t.weak\t";
- WeakRefDirective = "\t.weak\t";
- SetDirective = "\t.set\t";
-
- // Debug
- HasLEB128 = true;
- AbsoluteDebugSectionOffsets = true;
-
- DwarfAbbrevSection = "\t.section\t.debug_abbrev,\"\",@progbits";
- DwarfInfoSection = "\t.section\t.debug_info,\"\",@progbits";
- DwarfLineSection = "\t.section\t.debug_line,\"\",@progbits";
- DwarfFrameSection = "\t.section\t.debug_frame,\"\",@progbits";
- DwarfPubNamesSection = "\t.section\t.debug_pubnames,\"\",@progbits";
- DwarfPubTypesSection = "\t.section\t.debug_pubtypes,\"\",@progbits";
- DwarfStrSection = "\t.section\t.debug_str,\"\",@progbits";
- DwarfLocSection = "\t.section\t.debug_loc,\"\",@progbits";
- DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits";
- DwarfRangesSection = "\t.section\t.debug_ranges,\"\",@progbits";
- DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
-}
-
-const Section*
-XCoreTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
- SectionKind::Kind Kind = SectionKindForGlobal(GV);
-
- if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
- {
- if (!GVar->isWeakForLinker()) {
- switch (Kind) {
- case SectionKind::RODataMergeStr:
- return MergeableStringSection(GVar);
- case SectionKind::RODataMergeConst:
- return getReadOnlySection();
- case SectionKind::ThreadData:
- return DataSection;
- case SectionKind::ThreadBSS:
- return getBSSSection_();
- default:
- break;
- }
- }
- }
- return ELFTargetAsmInfo::SelectSectionForGlobal(GV);
-}
-
-const Section*
-XCoreTargetAsmInfo::SelectSectionForMachineConst(const Type *Ty) const {
- return MergeableConstSection(Ty);
-}
-
-const Section*
-XCoreTargetAsmInfo::MergeableConstSection(const GlobalVariable *GV) const {
- Constant *C = GV->getInitializer();
- return MergeableConstSection(C->getType());
-}
-
-inline const Section*
-XCoreTargetAsmInfo::MergeableConstSection(const Type *Ty) const {
- const TargetData *TD = TM.getTargetData();
-
- unsigned Size = TD->getTypeAllocSize(Ty);
- if (Size == 4 || Size == 8 || Size == 16) {
- std::string Name = ".cp.const" + utostr(Size);
-
- return getNamedSection(Name.c_str(),
- SectionFlags::setEntitySize(SectionFlags::Mergeable |
- SectionFlags::Small,
- Size));
- }
-
- return getReadOnlySection();
-}
-
-const Section* XCoreTargetAsmInfo::
-MergeableStringSection(const GlobalVariable *GV) const {
- // FIXME insert in correct mergable section
- return getReadOnlySection();
-}
-
-unsigned XCoreTargetAsmInfo::
-SectionFlagsForGlobal(const GlobalValue *GV,
- const char* Name) const {
- unsigned Flags = ELFTargetAsmInfo::SectionFlagsForGlobal(GV, Name);
- // Mask out unsupported flags
- Flags &= ~(SectionFlags::Small | SectionFlags::TLS);
-
- // Set CP / DP relative flags
- if (GV) {
- SectionKind::Kind Kind = SectionKindForGlobal(GV);
- switch (Kind) {
- case SectionKind::ThreadData:
- case SectionKind::ThreadBSS:
- case SectionKind::Data:
- case SectionKind::BSS:
- case SectionKind::SmallData:
- case SectionKind::SmallBSS:
- Flags |= SectionFlags::Small;
- break;
- case SectionKind::ROData:
- case SectionKind::RODataMergeStr:
- case SectionKind::SmallROData:
- if (Subtarget->isXS1A()) {
- Flags |= SectionFlags::Writeable;
- }
- Flags |=SectionFlags::Small;
- break;
- case SectionKind::RODataMergeConst:
- Flags |=SectionFlags::Small;
- default:
- break;
- }
- }
-
- return Flags;
-}
-
-std::string XCoreTargetAsmInfo::
-printSectionFlags(unsigned flags) const {
- std::string Flags = ",\"";
-
- if (!(flags & SectionFlags::Debug))
- Flags += 'a';
- if (flags & SectionFlags::Code)
- Flags += 'x';
- if (flags & SectionFlags::Writeable)
- Flags += 'w';
- if (flags & SectionFlags::Mergeable)
- Flags += 'M';
- if (flags & SectionFlags::Strings)
- Flags += 'S';
- if (flags & SectionFlags::TLS)
- Flags += 'T';
- if (flags & SectionFlags::Small) {
- if (flags & SectionFlags::Writeable)
- Flags += 'd'; // DP relative
- else
- Flags += 'c'; // CP relative
- }
-
- Flags += "\",";
-
- Flags += '@';
-
- if (flags & SectionFlags::BSS)
- Flags += "nobits";
- else
- Flags += "progbits";
-
- if (unsigned entitySize = SectionFlags::getEntitySize(flags))
- Flags += "," + utostr(entitySize);
-
- return Flags;
-}
diff --git a/lib/Target/XCore/XCoreTargetAsmInfo.h b/lib/Target/XCore/XCoreTargetAsmInfo.h
deleted file mode 100644
index 79fd36a..0000000
--- a/lib/Target/XCore/XCoreTargetAsmInfo.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//=====-- XCoreTargetAsmInfo.h - XCore asm properties ---------*- C++ -*--====//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains the declaration of the XCoreTargetAsmInfo class.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef XCORETARGETASMINFO_H
-#define XCORETARGETASMINFO_H
-
-#include "llvm/Target/ELFTargetAsmInfo.h"
-
-namespace llvm {
-
- // Forward declarations.
- class XCoreTargetMachine;
- class XCoreSubtarget;
-
- class XCoreTargetAsmInfo : public ELFTargetAsmInfo {
- private:
- const XCoreSubtarget *Subtarget;
- public:
- explicit XCoreTargetAsmInfo(const XCoreTargetMachine &TM);
-
- virtual const Section* SelectSectionForGlobal(const GlobalValue *GV) const;
- virtual std::string printSectionFlags(unsigned flags) const;
- const Section* MergeableConstSection(const GlobalVariable *GV) const;
- inline const Section* MergeableConstSection(const Type *Ty) const;
- const Section* MergeableStringSection(const GlobalVariable *GV) const;
- virtual const Section*
- SelectSectionForMachineConst(const Type *Ty) const;
- virtual unsigned
- SectionFlagsForGlobal(const GlobalValue *GV = NULL,
- const char* name = NULL) const;
- };
-
-} // namespace llvm
-
-#endif
diff --git a/lib/Transforms/Scalar/GVNPRE.cpp b/lib/Transforms/Scalar/GVNPRE.cpp
deleted file mode 100644
index 0f3153f..0000000
--- a/lib/Transforms/Scalar/GVNPRE.cpp
+++ /dev/null
@@ -1,1892 +0,0 @@
-//===- GVNPRE.cpp - Eliminate redundant values and expressions ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This pass performs a hybrid of global value numbering and partial redundancy
-// elimination, known as GVN-PRE. It performs partial redundancy elimination on
-// values, rather than lexical expressions, allowing a more comprehensive view
-// the optimization. It replaces redundant values with uses of earlier
-// occurences of the same value. While this is beneficial in that it eliminates
-// unneeded computation, it also increases register pressure by creating large
-// live ranges, and should be used with caution on platforms that are very
-// sensitive to register pressure.
-//
-// Note that this pass does the value numbering itself, it does not use the
-// ValueNumbering analysis passes.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "gvnpre"
-#include "llvm/Value.h"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Instructions.h"
-#include "llvm/Function.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Analysis/Dominators.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DepthFirstIterator.h"
-#include "llvm/ADT/PostOrderIterator.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Debug.h"
-#include <algorithm>
-#include <deque>
-#include <map>
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// ValueTable Class
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-/// This class holds the mapping between values and value numbers. It is used
-/// as an efficient mechanism to determine the expression-wise equivalence of
-/// two values.
-
-struct Expression {
- enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL,
- UDIV, SDIV, FDIV, UREM, SREM,
- FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ,
- ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE,
- ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ,
- FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE,
- FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE,
- FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT,
- SHUFFLE, SELECT, TRUNC, ZEXT, SEXT, FPTOUI,
- FPTOSI, UITOFP, SITOFP, FPTRUNC, FPEXT,
- PTRTOINT, INTTOPTR, BITCAST, GEP, EMPTY,
- TOMBSTONE };
-
- ExpressionOpcode opcode;
- const Type* type;
- uint32_t firstVN;
- uint32_t secondVN;
- uint32_t thirdVN;
- SmallVector<uint32_t, 4> varargs;
-
- Expression() { }
- explicit Expression(ExpressionOpcode o) : opcode(o) { }
-
- bool operator==(const Expression &other) const {
- if (opcode != other.opcode)
- return false;
- else if (opcode == EMPTY || opcode == TOMBSTONE)
- return true;
- else if (type != other.type)
- return false;
- else if (firstVN != other.firstVN)
- return false;
- else if (secondVN != other.secondVN)
- return false;
- else if (thirdVN != other.thirdVN)
- return false;
- else {
- if (varargs.size() != other.varargs.size())
- return false;
-
- for (size_t i = 0; i < varargs.size(); ++i)
- if (varargs[i] != other.varargs[i])
- return false;
-
- return true;
- }
- }
-
- bool operator!=(const Expression &other) const {
- if (opcode != other.opcode)
- return true;
- else if (opcode == EMPTY || opcode == TOMBSTONE)
- return false;
- else if (type != other.type)
- return true;
- else if (firstVN != other.firstVN)
- return true;
- else if (secondVN != other.secondVN)
- return true;
- else if (thirdVN != other.thirdVN)
- return true;
- else {
- if (varargs.size() != other.varargs.size())
- return true;
-
- for (size_t i = 0; i < varargs.size(); ++i)
- if (varargs[i] != other.varargs[i])
- return true;
-
- return false;
- }
- }
-};
-
-}
-
-namespace {
- class VISIBILITY_HIDDEN ValueTable {
- private:
- DenseMap<Value*, uint32_t> valueNumbering;
- DenseMap<Expression, uint32_t> expressionNumbering;
-
- uint32_t nextValueNumber;
-
- Expression::ExpressionOpcode getOpcode(BinaryOperator* BO);
- Expression::ExpressionOpcode getOpcode(CmpInst* C);
- Expression::ExpressionOpcode getOpcode(CastInst* C);
- Expression create_expression(BinaryOperator* BO);
- Expression create_expression(CmpInst* C);
- Expression create_expression(ShuffleVectorInst* V);
- Expression create_expression(ExtractElementInst* C);
- Expression create_expression(InsertElementInst* V);
- Expression create_expression(SelectInst* V);
- Expression create_expression(CastInst* C);
- Expression create_expression(GetElementPtrInst* G);
- public:
- ValueTable() { nextValueNumber = 1; }
- uint32_t lookup_or_add(Value* V);
- uint32_t lookup(Value* V) const;
- void add(Value* V, uint32_t num);
- void clear();
- void erase(Value* v);
- unsigned size();
- };
-}
-
-namespace llvm {
-template <> struct DenseMapInfo<Expression> {
- static inline Expression getEmptyKey() {
- return Expression(Expression::EMPTY);
- }
-
- static inline Expression getTombstoneKey() {
- return Expression(Expression::TOMBSTONE);
- }
-
- static unsigned getHashValue(const Expression e) {
- unsigned hash = e.opcode;
-
- hash = e.firstVN + hash * 37;
- hash = e.secondVN + hash * 37;
- hash = e.thirdVN + hash * 37;
-
- hash = ((unsigned)((uintptr_t)e.type >> 4) ^
- (unsigned)((uintptr_t)e.type >> 9)) +
- hash * 37;
-
- for (SmallVector<uint32_t, 4>::const_iterator I = e.varargs.begin(),
- E = e.varargs.end(); I != E; ++I)
- hash = *I + hash * 37;
-
- return hash;
- }
- static bool isEqual(const Expression &LHS, const Expression &RHS) {
- return LHS == RHS;
- }
- static bool isPod() { return true; }
-};
-}
-
-//===----------------------------------------------------------------------===//
-// ValueTable Internal Functions
-//===----------------------------------------------------------------------===//
-Expression::ExpressionOpcode
- ValueTable::getOpcode(BinaryOperator* BO) {
- switch(BO->getOpcode()) {
- case Instruction::Add:
- return Expression::ADD;
- case Instruction::FAdd:
- return Expression::FADD;
- case Instruction::Sub:
- return Expression::SUB;
- case Instruction::FSub:
- return Expression::FSUB;
- case Instruction::Mul:
- return Expression::MUL;
- case Instruction::FMul:
- return Expression::FMUL;
- case Instruction::UDiv:
- return Expression::UDIV;
- case Instruction::SDiv:
- return Expression::SDIV;
- case Instruction::FDiv:
- return Expression::FDIV;
- case Instruction::URem:
- return Expression::UREM;
- case Instruction::SRem:
- return Expression::SREM;
- case Instruction::FRem:
- return Expression::FREM;
- case Instruction::Shl:
- return Expression::SHL;
- case Instruction::LShr:
- return Expression::LSHR;
- case Instruction::AShr:
- return Expression::ASHR;
- case Instruction::And:
- return Expression::AND;
- case Instruction::Or:
- return Expression::OR;
- case Instruction::Xor:
- return Expression::XOR;
-
- // THIS SHOULD NEVER HAPPEN
- default:
- assert(0 && "Binary operator with unknown opcode?");
- return Expression::ADD;
- }
-}
-
-Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) {
- if (C->getOpcode() == Instruction::ICmp) {
- switch (C->getPredicate()) {
- case ICmpInst::ICMP_EQ:
- return Expression::ICMPEQ;
- case ICmpInst::ICMP_NE:
- return Expression::ICMPNE;
- case ICmpInst::ICMP_UGT:
- return Expression::ICMPUGT;
- case ICmpInst::ICMP_UGE:
- return Expression::ICMPUGE;
- case ICmpInst::ICMP_ULT:
- return Expression::ICMPULT;
- case ICmpInst::ICMP_ULE:
- return Expression::ICMPULE;
- case ICmpInst::ICMP_SGT:
- return Expression::ICMPSGT;
- case ICmpInst::ICMP_SGE:
- return Expression::ICMPSGE;
- case ICmpInst::ICMP_SLT:
- return Expression::ICMPSLT;
- case ICmpInst::ICMP_SLE:
- return Expression::ICMPSLE;
-
- // THIS SHOULD NEVER HAPPEN
- default:
- assert(0 && "Comparison with unknown predicate?");
- return Expression::ICMPEQ;
- }
- } else {
- switch (C->getPredicate()) {
- case FCmpInst::FCMP_OEQ:
- return Expression::FCMPOEQ;
- case FCmpInst::FCMP_OGT:
- return Expression::FCMPOGT;
- case FCmpInst::FCMP_OGE:
- return Expression::FCMPOGE;
- case FCmpInst::FCMP_OLT:
- return Expression::FCMPOLT;
- case FCmpInst::FCMP_OLE:
- return Expression::FCMPOLE;
- case FCmpInst::FCMP_ONE:
- return Expression::FCMPONE;
- case FCmpInst::FCMP_ORD:
- return Expression::FCMPORD;
- case FCmpInst::FCMP_UNO:
- return Expression::FCMPUNO;
- case FCmpInst::FCMP_UEQ:
- return Expression::FCMPUEQ;
- case FCmpInst::FCMP_UGT:
- return Expression::FCMPUGT;
- case FCmpInst::FCMP_UGE:
- return Expression::FCMPUGE;
- case FCmpInst::FCMP_ULT:
- return Expression::FCMPULT;
- case FCmpInst::FCMP_ULE:
- return Expression::FCMPULE;
- case FCmpInst::FCMP_UNE:
- return Expression::FCMPUNE;
-
- // THIS SHOULD NEVER HAPPEN
- default:
- assert(0 && "Comparison with unknown predicate?");
- return Expression::FCMPOEQ;
- }
- }
-}
-
-Expression::ExpressionOpcode
- ValueTable::getOpcode(CastInst* C) {
- switch(C->getOpcode()) {
- case Instruction::Trunc:
- return Expression::TRUNC;
- case Instruction::ZExt:
- return Expression::ZEXT;
- case Instruction::SExt:
- return Expression::SEXT;
- case Instruction::FPToUI:
- return Expression::FPTOUI;
- case Instruction::FPToSI:
- return Expression::FPTOSI;
- case Instruction::UIToFP:
- return Expression::UITOFP;
- case Instruction::SIToFP:
- return Expression::SITOFP;
- case Instruction::FPTrunc:
- return Expression::FPTRUNC;
- case Instruction::FPExt:
- return Expression::FPEXT;
- case Instruction::PtrToInt:
- return Expression::PTRTOINT;
- case Instruction::IntToPtr:
- return Expression::INTTOPTR;
- case Instruction::BitCast:
- return Expression::BITCAST;
-
- // THIS SHOULD NEVER HAPPEN
- default:
- assert(0 && "Cast operator with unknown opcode?");
- return Expression::BITCAST;
- }
-}
-
-Expression ValueTable::create_expression(BinaryOperator* BO) {
- Expression e;
-
- e.firstVN = lookup_or_add(BO->getOperand(0));
- e.secondVN = lookup_or_add(BO->getOperand(1));
- e.thirdVN = 0;
- e.type = BO->getType();
- e.opcode = getOpcode(BO);
-
- return e;
-}
-
-Expression ValueTable::create_expression(CmpInst* C) {
- Expression e;
-
- e.firstVN = lookup_or_add(C->getOperand(0));
- e.secondVN = lookup_or_add(C->getOperand(1));
- e.thirdVN = 0;
- e.type = C->getType();
- e.opcode = getOpcode(C);
-
- return e;
-}
-
-Expression ValueTable::create_expression(CastInst* C) {
- Expression e;
-
- e.firstVN = lookup_or_add(C->getOperand(0));
- e.secondVN = 0;
- e.thirdVN = 0;
- e.type = C->getType();
- e.opcode = getOpcode(C);
-
- return e;
-}
-
-Expression ValueTable::create_expression(ShuffleVectorInst* S) {
- Expression e;
-
- e.firstVN = lookup_or_add(S->getOperand(0));
- e.secondVN = lookup_or_add(S->getOperand(1));
- e.thirdVN = lookup_or_add(S->getOperand(2));
- e.type = S->getType();
- e.opcode = Expression::SHUFFLE;
-
- return e;
-}
-
-Expression ValueTable::create_expression(ExtractElementInst* E) {
- Expression e;
-
- e.firstVN = lookup_or_add(E->getOperand(0));
- e.secondVN = lookup_or_add(E->getOperand(1));
- e.thirdVN = 0;
- e.type = E->getType();
- e.opcode = Expression::EXTRACT;
-
- return e;
-}
-
-Expression ValueTable::create_expression(InsertElementInst* I) {
- Expression e;
-
- e.firstVN = lookup_or_add(I->getOperand(0));
- e.secondVN = lookup_or_add(I->getOperand(1));
- e.thirdVN = lookup_or_add(I->getOperand(2));
- e.type = I->getType();
- e.opcode = Expression::INSERT;
-
- return e;
-}
-
-Expression ValueTable::create_expression(SelectInst* I) {
- Expression e;
-
- e.firstVN = lookup_or_add(I->getCondition());
- e.secondVN = lookup_or_add(I->getTrueValue());
- e.thirdVN = lookup_or_add(I->getFalseValue());
- e.type = I->getType();
- e.opcode = Expression::SELECT;
-
- return e;
-}
-
-Expression ValueTable::create_expression(GetElementPtrInst* G) {
- Expression e;
-
- e.firstVN = lookup_or_add(G->getPointerOperand());
- e.secondVN = 0;
- e.thirdVN = 0;
- e.type = G->getType();
- e.opcode = Expression::GEP;
-
- for (GetElementPtrInst::op_iterator I = G->idx_begin(), E = G->idx_end();
- I != E; ++I)
- e.varargs.push_back(lookup_or_add(*I));
-
- return e;
-}
-
-//===----------------------------------------------------------------------===//
-// ValueTable External Functions
-//===----------------------------------------------------------------------===//
-
-/// lookup_or_add - Returns the value number for the specified value, assigning
-/// it a new number if it did not have one before.
-uint32_t ValueTable::lookup_or_add(Value* V) {
- DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V);
- if (VI != valueNumbering.end())
- return VI->second;
-
-
- if (BinaryOperator* BO = dyn_cast<BinaryOperator>(V)) {
- Expression e = create_expression(BO);
-
- DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
- if (EI != expressionNumbering.end()) {
- valueNumbering.insert(std::make_pair(V, EI->second));
- return EI->second;
- } else {
- expressionNumbering.insert(std::make_pair(e, nextValueNumber));
- valueNumbering.insert(std::make_pair(V, nextValueNumber));
-
- return nextValueNumber++;
- }
- } else if (CmpInst* C = dyn_cast<CmpInst>(V)) {
- Expression e = create_expression(C);
-
- DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
- if (EI != expressionNumbering.end()) {
- valueNumbering.insert(std::make_pair(V, EI->second));
- return EI->second;
- } else {
- expressionNumbering.insert(std::make_pair(e, nextValueNumber));
- valueNumbering.insert(std::make_pair(V, nextValueNumber));
-
- return nextValueNumber++;
- }
- } else if (ShuffleVectorInst* U = dyn_cast<ShuffleVectorInst>(V)) {
- Expression e = create_expression(U);
-
- DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
- if (EI != expressionNumbering.end()) {
- valueNumbering.insert(std::make_pair(V, EI->second));
- return EI->second;
- } else {
- expressionNumbering.insert(std::make_pair(e, nextValueNumber));
- valueNumbering.insert(std::make_pair(V, nextValueNumber));
-
- return nextValueNumber++;
- }
- } else if (ExtractElementInst* U = dyn_cast<ExtractElementInst>(V)) {
- Expression e = create_expression(U);
-
- DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
- if (EI != expressionNumbering.end()) {
- valueNumbering.insert(std::make_pair(V, EI->second));
- return EI->second;
- } else {
- expressionNumbering.insert(std::make_pair(e, nextValueNumber));
- valueNumbering.insert(std::make_pair(V, nextValueNumber));
-
- return nextValueNumber++;
- }
- } else if (InsertElementInst* U = dyn_cast<InsertElementInst>(V)) {
- Expression e = create_expression(U);
-
- DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
- if (EI != expressionNumbering.end()) {
- valueNumbering.insert(std::make_pair(V, EI->second));
- return EI->second;
- } else {
- expressionNumbering.insert(std::make_pair(e, nextValueNumber));
- valueNumbering.insert(std::make_pair(V, nextValueNumber));
-
- return nextValueNumber++;
- }
- } else if (SelectInst* U = dyn_cast<SelectInst>(V)) {
- Expression e = create_expression(U);
-
- DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
- if (EI != expressionNumbering.end()) {
- valueNumbering.insert(std::make_pair(V, EI->second));
- return EI->second;
- } else {
- expressionNumbering.insert(std::make_pair(e, nextValueNumber));
- valueNumbering.insert(std::make_pair(V, nextValueNumber));
-
- return nextValueNumber++;
- }
- } else if (CastInst* U = dyn_cast<CastInst>(V)) {
- Expression e = create_expression(U);
-
- DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
- if (EI != expressionNumbering.end()) {
- valueNumbering.insert(std::make_pair(V, EI->second));
- return EI->second;
- } else {
- expressionNumbering.insert(std::make_pair(e, nextValueNumber));
- valueNumbering.insert(std::make_pair(V, nextValueNumber));
-
- return nextValueNumber++;
- }
- } else if (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(V)) {
- Expression e = create_expression(U);
-
- DenseMap<Expression, uint32_t>::iterator EI = expressionNumbering.find(e);
- if (EI != expressionNumbering.end()) {
- valueNumbering.insert(std::make_pair(V, EI->second));
- return EI->second;
- } else {
- expressionNumbering.insert(std::make_pair(e, nextValueNumber));
- valueNumbering.insert(std::make_pair(V, nextValueNumber));
-
- return nextValueNumber++;
- }
- } else {
- valueNumbering.insert(std::make_pair(V, nextValueNumber));
- return nextValueNumber++;
- }
-}
-
-/// lookup - Returns the value number of the specified value. Fails if
-/// the value has not yet been numbered.
-uint32_t ValueTable::lookup(Value* V) const {
- DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V);
- if (VI != valueNumbering.end())
- return VI->second;
- else
- assert(0 && "Value not numbered?");
-
- return 0;
-}
-
-/// add - Add the specified value with the given value number, removing
-/// its old number, if any
-void ValueTable::add(Value* V, uint32_t num) {
- DenseMap<Value*, uint32_t>::iterator VI = valueNumbering.find(V);
- if (VI != valueNumbering.end())
- valueNumbering.erase(VI);
- valueNumbering.insert(std::make_pair(V, num));
-}
-
-/// clear - Remove all entries from the ValueTable
-void ValueTable::clear() {
- valueNumbering.clear();
- expressionNumbering.clear();
- nextValueNumber = 1;
-}
-
-/// erase - Remove a value from the value numbering
-void ValueTable::erase(Value* V) {
- valueNumbering.erase(V);
-}
-
-/// size - Return the number of assigned value numbers
-unsigned ValueTable::size() {
- // NOTE: zero is never assigned
- return nextValueNumber;
-}
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// ValueNumberedSet Class
-//===----------------------------------------------------------------------===//
-
-class ValueNumberedSet {
- private:
- SmallPtrSet<Value*, 8> contents;
- BitVector numbers;
- public:
- ValueNumberedSet() { numbers.resize(1); }
- ValueNumberedSet(const ValueNumberedSet& other) {
- numbers = other.numbers;
- contents = other.contents;
- }
-
- typedef SmallPtrSet<Value*, 8>::iterator iterator;
-
- iterator begin() { return contents.begin(); }
- iterator end() { return contents.end(); }
-
- bool insert(Value* v) { return contents.insert(v); }
- void insert(iterator I, iterator E) { contents.insert(I, E); }
- void erase(Value* v) { contents.erase(v); }
- unsigned count(Value* v) { return contents.count(v); }
- size_t size() { return contents.size(); }
-
- void set(unsigned i) {
- if (i >= numbers.size())
- numbers.resize(i+1);
-
- numbers.set(i);
- }
-
- void operator=(const ValueNumberedSet& other) {
- contents = other.contents;
- numbers = other.numbers;
- }
-
- void reset(unsigned i) {
- if (i < numbers.size())
- numbers.reset(i);
- }
-
- bool test(unsigned i) {
- if (i >= numbers.size())
- return false;
-
- return numbers.test(i);
- }
-
- void clear() {
- contents.clear();
- numbers.clear();
- }
-};
-
-}
-
-//===----------------------------------------------------------------------===//
-// GVNPRE Pass
-//===----------------------------------------------------------------------===//
-
-namespace {
-
- class VISIBILITY_HIDDEN GVNPRE : public FunctionPass {
- bool runOnFunction(Function &F);
- public:
- static char ID; // Pass identification, replacement for typeid
- GVNPRE() : FunctionPass(&ID) {}
-
- private:
- ValueTable VN;
- SmallVector<Instruction*, 8> createdExpressions;
-
- DenseMap<BasicBlock*, ValueNumberedSet> availableOut;
- DenseMap<BasicBlock*, ValueNumberedSet> anticipatedIn;
- DenseMap<BasicBlock*, ValueNumberedSet> generatedPhis;
-
- // This transformation requires dominator postdominator info
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesCFG();
- AU.addRequiredID(BreakCriticalEdgesID);
- AU.addRequired<UnifyFunctionExitNodes>();
- AU.addRequired<DominatorTree>();
- }
-
- // Helper fuctions
- // FIXME: eliminate or document these better
- void dump(ValueNumberedSet& s) const ;
- void clean(ValueNumberedSet& set) ;
- Value* find_leader(ValueNumberedSet& vals, uint32_t v) ;
- Value* phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) ;
- void phi_translate_set(ValueNumberedSet& anticIn, BasicBlock* pred,
- BasicBlock* succ, ValueNumberedSet& out) ;
-
- void topo_sort(ValueNumberedSet& set,
- SmallVector<Value*, 8>& vec) ;
-
- void cleanup() ;
- bool elimination() ;
-
- void val_insert(ValueNumberedSet& s, Value* v) ;
- void val_replace(ValueNumberedSet& s, Value* v) ;
- bool dependsOnInvoke(Value* V) ;
- void buildsets_availout(BasicBlock::iterator I,
- ValueNumberedSet& currAvail,
- ValueNumberedSet& currPhis,
- ValueNumberedSet& currExps,
- SmallPtrSet<Value*, 16>& currTemps);
- bool buildsets_anticout(BasicBlock* BB,
- ValueNumberedSet& anticOut,
- SmallPtrSet<BasicBlock*, 8>& visited);
- unsigned buildsets_anticin(BasicBlock* BB,
- ValueNumberedSet& anticOut,
- ValueNumberedSet& currExps,
- SmallPtrSet<Value*, 16>& currTemps,
- SmallPtrSet<BasicBlock*, 8>& visited);
- void buildsets(Function& F) ;
-
- void insertion_pre(Value* e, BasicBlock* BB,
- DenseMap<BasicBlock*, Value*>& avail,
- std::map<BasicBlock*,ValueNumberedSet>& new_set);
- unsigned insertion_mergepoint(SmallVector<Value*, 8>& workList,
- df_iterator<DomTreeNode*>& D,
- std::map<BasicBlock*, ValueNumberedSet>& new_set);
- bool insertion(Function& F) ;
-
- };
-
- char GVNPRE::ID = 0;
-
-}
-
-// createGVNPREPass - The public interface to this file...
-FunctionPass *llvm::createGVNPREPass() { return new GVNPRE(); }
-
-static RegisterPass<GVNPRE> X("gvnpre",
- "Global Value Numbering/Partial Redundancy Elimination");
-
-
-STATISTIC(NumInsertedVals, "Number of values inserted");
-STATISTIC(NumInsertedPhis, "Number of PHI nodes inserted");
-STATISTIC(NumEliminated, "Number of redundant instructions eliminated");
-
-/// find_leader - Given a set and a value number, return the first
-/// element of the set with that value number, or 0 if no such element
-/// is present
-Value* GVNPRE::find_leader(ValueNumberedSet& vals, uint32_t v) {
- if (!vals.test(v))
- return 0;
-
- for (ValueNumberedSet::iterator I = vals.begin(), E = vals.end();
- I != E; ++I)
- if (v == VN.lookup(*I))
- return *I;
-
- assert(0 && "No leader found, but present bit is set?");
- return 0;
-}
-
-/// val_insert - Insert a value into a set only if there is not a value
-/// with the same value number already in the set
-void GVNPRE::val_insert(ValueNumberedSet& s, Value* v) {
- uint32_t num = VN.lookup(v);
- if (!s.test(num))
- s.insert(v);
-}
-
-/// val_replace - Insert a value into a set, replacing any values already in
-/// the set that have the same value number
-void GVNPRE::val_replace(ValueNumberedSet& s, Value* v) {
- if (s.count(v)) return;
-
- uint32_t num = VN.lookup(v);
- Value* leader = find_leader(s, num);
- if (leader != 0)
- s.erase(leader);
- s.insert(v);
- s.set(num);
-}
-
-/// phi_translate - Given a value, its parent block, and a predecessor of its
-/// parent, translate the value into legal for the predecessor block. This
-/// means translating its operands (and recursively, their operands) through
-/// any phi nodes in the parent into values available in the predecessor
-Value* GVNPRE::phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) {
- if (V == 0)
- return 0;
-
- // Unary Operations
- if (CastInst* U = dyn_cast<CastInst>(V)) {
- Value* newOp1 = 0;
- if (isa<Instruction>(U->getOperand(0)))
- newOp1 = phi_translate(U->getOperand(0), pred, succ);
- else
- newOp1 = U->getOperand(0);
-
- if (newOp1 == 0)
- return 0;
-
- if (newOp1 != U->getOperand(0)) {
- Instruction* newVal = 0;
- if (CastInst* C = dyn_cast<CastInst>(U))
- newVal = CastInst::Create(C->getOpcode(),
- newOp1, C->getType(),
- C->getName()+".expr");
-
- uint32_t v = VN.lookup_or_add(newVal);
-
- Value* leader = find_leader(availableOut[pred], v);
- if (leader == 0) {
- createdExpressions.push_back(newVal);
- return newVal;
- } else {
- VN.erase(newVal);
- delete newVal;
- return leader;
- }
- }
-
- // Binary Operations
- } if (isa<BinaryOperator>(V) || isa<CmpInst>(V) ||
- isa<ExtractElementInst>(V)) {
- User* U = cast<User>(V);
-
- Value* newOp1 = 0;
- if (isa<Instruction>(U->getOperand(0)))
- newOp1 = phi_translate(U->getOperand(0), pred, succ);
- else
- newOp1 = U->getOperand(0);
-
- if (newOp1 == 0)
- return 0;
-
- Value* newOp2 = 0;
- if (isa<Instruction>(U->getOperand(1)))
- newOp2 = phi_translate(U->getOperand(1), pred, succ);
- else
- newOp2 = U->getOperand(1);
-
- if (newOp2 == 0)
- return 0;
-
- if (newOp1 != U->getOperand(0) || newOp2 != U->getOperand(1)) {
- Instruction* newVal = 0;
- if (BinaryOperator* BO = dyn_cast<BinaryOperator>(U))
- newVal = BinaryOperator::Create(BO->getOpcode(),
- newOp1, newOp2,
- BO->getName()+".expr");
- else if (CmpInst* C = dyn_cast<CmpInst>(U))
- newVal = CmpInst::Create(C->getOpcode(),
- C->getPredicate(),
- newOp1, newOp2,
- C->getName()+".expr");
- else if (ExtractElementInst* E = dyn_cast<ExtractElementInst>(U))
- newVal = new ExtractElementInst(newOp1, newOp2, E->getName()+".expr");
-
- uint32_t v = VN.lookup_or_add(newVal);
-
- Value* leader = find_leader(availableOut[pred], v);
- if (leader == 0) {
- createdExpressions.push_back(newVal);
- return newVal;
- } else {
- VN.erase(newVal);
- delete newVal;
- return leader;
- }
- }
-
- // Ternary Operations
- } else if (isa<ShuffleVectorInst>(V) || isa<InsertElementInst>(V) ||
- isa<SelectInst>(V)) {
- User* U = cast<User>(V);
-
- Value* newOp1 = 0;
- if (isa<Instruction>(U->getOperand(0)))
- newOp1 = phi_translate(U->getOperand(0), pred, succ);
- else
- newOp1 = U->getOperand(0);
-
- if (newOp1 == 0)
- return 0;
-
- Value* newOp2 = 0;
- if (isa<Instruction>(U->getOperand(1)))
- newOp2 = phi_translate(U->getOperand(1), pred, succ);
- else
- newOp2 = U->getOperand(1);
-
- if (newOp2 == 0)
- return 0;
-
- Value* newOp3 = 0;
- if (isa<Instruction>(U->getOperand(2)))
- newOp3 = phi_translate(U->getOperand(2), pred, succ);
- else
- newOp3 = U->getOperand(2);
-
- if (newOp3 == 0)
- return 0;
-
- if (newOp1 != U->getOperand(0) ||
- newOp2 != U->getOperand(1) ||
- newOp3 != U->getOperand(2)) {
- Instruction* newVal = 0;
- if (ShuffleVectorInst* S = dyn_cast<ShuffleVectorInst>(U))
- newVal = new ShuffleVectorInst(newOp1, newOp2, newOp3,
- S->getName() + ".expr");
- else if (InsertElementInst* I = dyn_cast<InsertElementInst>(U))
- newVal = InsertElementInst::Create(newOp1, newOp2, newOp3,
- I->getName() + ".expr");
- else if (SelectInst* I = dyn_cast<SelectInst>(U))
- newVal = SelectInst::Create(newOp1, newOp2, newOp3,
- I->getName() + ".expr");
-
- uint32_t v = VN.lookup_or_add(newVal);
-
- Value* leader = find_leader(availableOut[pred], v);
- if (leader == 0) {
- createdExpressions.push_back(newVal);
- return newVal;
- } else {
- VN.erase(newVal);
- delete newVal;
- return leader;
- }
- }
-
- // Varargs operators
- } else if (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(V)) {
- Value* newOp1 = 0;
- if (isa<Instruction>(U->getPointerOperand()))
- newOp1 = phi_translate(U->getPointerOperand(), pred, succ);
- else
- newOp1 = U->getPointerOperand();
-
- if (newOp1 == 0)
- return 0;
-
- bool changed_idx = false;
- SmallVector<Value*, 4> newIdx;
- for (GetElementPtrInst::op_iterator I = U->idx_begin(), E = U->idx_end();
- I != E; ++I)
- if (isa<Instruction>(*I)) {
- Value* newVal = phi_translate(*I, pred, succ);
- newIdx.push_back(newVal);
- if (newVal != *I)
- changed_idx = true;
- } else {
- newIdx.push_back(*I);
- }
-
- if (newOp1 != U->getPointerOperand() || changed_idx) {
- Instruction* newVal =
- GetElementPtrInst::Create(newOp1,
- newIdx.begin(), newIdx.end(),
- U->getName()+".expr");
-
- uint32_t v = VN.lookup_or_add(newVal);
-
- Value* leader = find_leader(availableOut[pred], v);
- if (leader == 0) {
- createdExpressions.push_back(newVal);
- return newVal;
- } else {
- VN.erase(newVal);
- delete newVal;
- return leader;
- }
- }
-
- // PHI Nodes
- } else if (PHINode* P = dyn_cast<PHINode>(V)) {
- if (P->getParent() == succ)
- return P->getIncomingValueForBlock(pred);
- }
-
- return V;
-}
-
-/// phi_translate_set - Perform phi translation on every element of a set
-void GVNPRE::phi_translate_set(ValueNumberedSet& anticIn,
- BasicBlock* pred, BasicBlock* succ,
- ValueNumberedSet& out) {
- for (ValueNumberedSet::iterator I = anticIn.begin(),
- E = anticIn.end(); I != E; ++I) {
- Value* V = phi_translate(*I, pred, succ);
- if (V != 0 && !out.test(VN.lookup_or_add(V))) {
- out.insert(V);
- out.set(VN.lookup(V));
- }
- }
-}
-
-/// dependsOnInvoke - Test if a value has an phi node as an operand, any of
-/// whose inputs is an invoke instruction. If this is true, we cannot safely
-/// PRE the instruction or anything that depends on it.
-bool GVNPRE::dependsOnInvoke(Value* V) {
- if (PHINode* p = dyn_cast<PHINode>(V)) {
- for (PHINode::op_iterator I = p->op_begin(), E = p->op_end(); I != E; ++I)
- if (isa<InvokeInst>(*I))
- return true;
- return false;
- } else {
- return false;
- }
-}
-
-/// clean - Remove all non-opaque values from the set whose operands are not
-/// themselves in the set, as well as all values that depend on invokes (see
-/// above)
-void GVNPRE::clean(ValueNumberedSet& set) {
- SmallVector<Value*, 8> worklist;
- worklist.reserve(set.size());
- topo_sort(set, worklist);
-
- for (unsigned i = 0; i < worklist.size(); ++i) {
- Value* v = worklist[i];
-
- // Handle unary ops
- if (CastInst* U = dyn_cast<CastInst>(v)) {
- bool lhsValid = !isa<Instruction>(U->getOperand(0));
- lhsValid |= set.test(VN.lookup(U->getOperand(0)));
- if (lhsValid)
- lhsValid = !dependsOnInvoke(U->getOperand(0));
-
- if (!lhsValid) {
- set.erase(U);
- set.reset(VN.lookup(U));
- }
-
- // Handle binary ops
- } else if (isa<BinaryOperator>(v) || isa<CmpInst>(v) ||
- isa<ExtractElementInst>(v)) {
- User* U = cast<User>(v);
-
- bool lhsValid = !isa<Instruction>(U->getOperand(0));
- lhsValid |= set.test(VN.lookup(U->getOperand(0)));
- if (lhsValid)
- lhsValid = !dependsOnInvoke(U->getOperand(0));
-
- bool rhsValid = !isa<Instruction>(U->getOperand(1));
- rhsValid |= set.test(VN.lookup(U->getOperand(1)));
- if (rhsValid)
- rhsValid = !dependsOnInvoke(U->getOperand(1));
-
- if (!lhsValid || !rhsValid) {
- set.erase(U);
- set.reset(VN.lookup(U));
- }
-
- // Handle ternary ops
- } else if (isa<ShuffleVectorInst>(v) || isa<InsertElementInst>(v) ||
- isa<SelectInst>(v)) {
- User* U = cast<User>(v);
-
- bool lhsValid = !isa<Instruction>(U->getOperand(0));
- lhsValid |= set.test(VN.lookup(U->getOperand(0)));
- if (lhsValid)
- lhsValid = !dependsOnInvoke(U->getOperand(0));
-
- bool rhsValid = !isa<Instruction>(U->getOperand(1));
- rhsValid |= set.test(VN.lookup(U->getOperand(1)));
- if (rhsValid)
- rhsValid = !dependsOnInvoke(U->getOperand(1));
-
- bool thirdValid = !isa<Instruction>(U->getOperand(2));
- thirdValid |= set.test(VN.lookup(U->getOperand(2)));
- if (thirdValid)
- thirdValid = !dependsOnInvoke(U->getOperand(2));
-
- if (!lhsValid || !rhsValid || !thirdValid) {
- set.erase(U);
- set.reset(VN.lookup(U));
- }
-
- // Handle varargs ops
- } else if (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(v)) {
- bool ptrValid = !isa<Instruction>(U->getPointerOperand());
- ptrValid |= set.test(VN.lookup(U->getPointerOperand()));
- if (ptrValid)
- ptrValid = !dependsOnInvoke(U->getPointerOperand());
-
- bool varValid = true;
- for (GetElementPtrInst::op_iterator I = U->idx_begin(), E = U->idx_end();
- I != E; ++I)
- if (varValid) {
- varValid &= !isa<Instruction>(*I) || set.test(VN.lookup(*I));
- varValid &= !dependsOnInvoke(*I);
- }
-
- if (!ptrValid || !varValid) {
- set.erase(U);
- set.reset(VN.lookup(U));
- }
- }
- }
-}
-
-/// topo_sort - Given a set of values, sort them by topological
-/// order into the provided vector.
-void GVNPRE::topo_sort(ValueNumberedSet& set, SmallVector<Value*, 8>& vec) {
- SmallPtrSet<Value*, 16> visited;
- SmallVector<Value*, 8> stack;
- for (ValueNumberedSet::iterator I = set.begin(), E = set.end();
- I != E; ++I) {
- if (visited.count(*I) == 0)
- stack.push_back(*I);
-
- while (!stack.empty()) {
- Value* e = stack.back();
-
- // Handle unary ops
- if (CastInst* U = dyn_cast<CastInst>(e)) {
- Value* l = find_leader(set, VN.lookup(U->getOperand(0)));
-
- if (l != 0 && isa<Instruction>(l) &&
- visited.count(l) == 0)
- stack.push_back(l);
- else {
- vec.push_back(e);
- visited.insert(e);
- stack.pop_back();
- }
-
- // Handle binary ops
- } else if (isa<BinaryOperator>(e) || isa<CmpInst>(e) ||
- isa<ExtractElementInst>(e)) {
- User* U = cast<User>(e);
- Value* l = find_leader(set, VN.lookup(U->getOperand(0)));
- Value* r = find_leader(set, VN.lookup(U->getOperand(1)));
-
- if (l != 0 && isa<Instruction>(l) &&
- visited.count(l) == 0)
- stack.push_back(l);
- else if (r != 0 && isa<Instruction>(r) &&
- visited.count(r) == 0)
- stack.push_back(r);
- else {
- vec.push_back(e);
- visited.insert(e);
- stack.pop_back();
- }
-
- // Handle ternary ops
- } else if (isa<InsertElementInst>(e) || isa<ShuffleVectorInst>(e) ||
- isa<SelectInst>(e)) {
- User* U = cast<User>(e);
- Value* l = find_leader(set, VN.lookup(U->getOperand(0)));
- Value* r = find_leader(set, VN.lookup(U->getOperand(1)));
- Value* m = find_leader(set, VN.lookup(U->getOperand(2)));
-
- if (l != 0 && isa<Instruction>(l) &&
- visited.count(l) == 0)
- stack.push_back(l);
- else if (r != 0 && isa<Instruction>(r) &&
- visited.count(r) == 0)
- stack.push_back(r);
- else if (m != 0 && isa<Instruction>(m) &&
- visited.count(m) == 0)
- stack.push_back(m);
- else {
- vec.push_back(e);
- visited.insert(e);
- stack.pop_back();
- }
-
- // Handle vararg ops
- } else if (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(e)) {
- Value* p = find_leader(set, VN.lookup(U->getPointerOperand()));
-
- if (p != 0 && isa<Instruction>(p) &&
- visited.count(p) == 0)
- stack.push_back(p);
- else {
- bool push_va = false;
- for (GetElementPtrInst::op_iterator I = U->idx_begin(),
- E = U->idx_end(); I != E; ++I) {
- Value * v = find_leader(set, VN.lookup(*I));
- if (v != 0 && isa<Instruction>(v) && visited.count(v) == 0) {
- stack.push_back(v);
- push_va = true;
- }
- }
-
- if (!push_va) {
- vec.push_back(e);
- visited.insert(e);
- stack.pop_back();
- }
- }
-
- // Handle opaque ops
- } else {
- visited.insert(e);
- vec.push_back(e);
- stack.pop_back();
- }
- }
-
- stack.clear();
- }
-}
-
-/// dump - Dump a set of values to standard error
-void GVNPRE::dump(ValueNumberedSet& s) const {
- DOUT << "{ ";
- for (ValueNumberedSet::iterator I = s.begin(), E = s.end();
- I != E; ++I) {
- DOUT << "" << VN.lookup(*I) << ": ";
- DEBUG((*I)->dump());
- }
- DOUT << "}\n\n";
-}
-
-/// elimination - Phase 3 of the main algorithm. Perform full redundancy
-/// elimination by walking the dominator tree and removing any instruction that
-/// is dominated by another instruction with the same value number.
-bool GVNPRE::elimination() {
- bool changed_function = false;
-
- SmallVector<std::pair<Instruction*, Value*>, 8> replace;
- SmallVector<Instruction*, 8> erase;
-
- DominatorTree& DT = getAnalysis<DominatorTree>();
-
- for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()),
- E = df_end(DT.getRootNode()); DI != E; ++DI) {
- BasicBlock* BB = DI->getBlock();
-
- for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
- BI != BE; ++BI) {
-
- if (isa<BinaryOperator>(BI) || isa<CmpInst>(BI) ||
- isa<ShuffleVectorInst>(BI) || isa<InsertElementInst>(BI) ||
- isa<ExtractElementInst>(BI) || isa<SelectInst>(BI) ||
- isa<CastInst>(BI) || isa<GetElementPtrInst>(BI)) {
-
- if (availableOut[BB].test(VN.lookup(BI)) &&
- !availableOut[BB].count(BI)) {
- Value *leader = find_leader(availableOut[BB], VN.lookup(BI));
- if (Instruction* Instr = dyn_cast<Instruction>(leader))
- if (Instr->getParent() != 0 && Instr != BI) {
- replace.push_back(std::make_pair(BI, leader));
- erase.push_back(BI);
- ++NumEliminated;
- }
- }
- }
- }
- }
-
- while (!replace.empty()) {
- std::pair<Instruction*, Value*> rep = replace.back();
- replace.pop_back();
- rep.first->replaceAllUsesWith(rep.second);
- changed_function = true;
- }
-
- for (SmallVector<Instruction*, 8>::iterator I = erase.begin(),
- E = erase.end(); I != E; ++I)
- (*I)->eraseFromParent();
-
- return changed_function;
-}
-
-/// cleanup - Delete any extraneous values that were created to represent
-/// expressions without leaders.
-void GVNPRE::cleanup() {
- while (!createdExpressions.empty()) {
- Instruction* I = createdExpressions.back();
- createdExpressions.pop_back();
-
- delete I;
- }
-}
-
-/// buildsets_availout - When calculating availability, handle an instruction
-/// by inserting it into the appropriate sets
-void GVNPRE::buildsets_availout(BasicBlock::iterator I,
- ValueNumberedSet& currAvail,
- ValueNumberedSet& currPhis,
- ValueNumberedSet& currExps,
- SmallPtrSet<Value*, 16>& currTemps) {
- // Handle PHI nodes
- if (PHINode* p = dyn_cast<PHINode>(I)) {
- unsigned num = VN.lookup_or_add(p);
-
- currPhis.insert(p);
- currPhis.set(num);
-
- // Handle unary ops
- } else if (CastInst* U = dyn_cast<CastInst>(I)) {
- Value* leftValue = U->getOperand(0);
-
- unsigned num = VN.lookup_or_add(U);
-
- if (isa<Instruction>(leftValue))
- if (!currExps.test(VN.lookup(leftValue))) {
- currExps.insert(leftValue);
- currExps.set(VN.lookup(leftValue));
- }
-
- if (!currExps.test(num)) {
- currExps.insert(U);
- currExps.set(num);
- }
-
- // Handle binary ops
- } else if (isa<BinaryOperator>(I) || isa<CmpInst>(I) ||
- isa<ExtractElementInst>(I)) {
- User* U = cast<User>(I);
- Value* leftValue = U->getOperand(0);
- Value* rightValue = U->getOperand(1);
-
- unsigned num = VN.lookup_or_add(U);
-
- if (isa<Instruction>(leftValue))
- if (!currExps.test(VN.lookup(leftValue))) {
- currExps.insert(leftValue);
- currExps.set(VN.lookup(leftValue));
- }
-
- if (isa<Instruction>(rightValue))
- if (!currExps.test(VN.lookup(rightValue))) {
- currExps.insert(rightValue);
- currExps.set(VN.lookup(rightValue));
- }
-
- if (!currExps.test(num)) {
- currExps.insert(U);
- currExps.set(num);
- }
-
- // Handle ternary ops
- } else if (isa<InsertElementInst>(I) || isa<ShuffleVectorInst>(I) ||
- isa<SelectInst>(I)) {
- User* U = cast<User>(I);
- Value* leftValue = U->getOperand(0);
- Value* rightValue = U->getOperand(1);
- Value* thirdValue = U->getOperand(2);
-
- VN.lookup_or_add(U);
-
- unsigned num = VN.lookup_or_add(U);
-
- if (isa<Instruction>(leftValue))
- if (!currExps.test(VN.lookup(leftValue))) {
- currExps.insert(leftValue);
- currExps.set(VN.lookup(leftValue));
- }
- if (isa<Instruction>(rightValue))
- if (!currExps.test(VN.lookup(rightValue))) {
- currExps.insert(rightValue);
- currExps.set(VN.lookup(rightValue));
- }
- if (isa<Instruction>(thirdValue))
- if (!currExps.test(VN.lookup(thirdValue))) {
- currExps.insert(thirdValue);
- currExps.set(VN.lookup(thirdValue));
- }
-
- if (!currExps.test(num)) {
- currExps.insert(U);
- currExps.set(num);
- }
-
- // Handle vararg ops
- } else if (GetElementPtrInst* U = dyn_cast<GetElementPtrInst>(I)) {
- Value* ptrValue = U->getPointerOperand();
-
- VN.lookup_or_add(U);
-
- unsigned num = VN.lookup_or_add(U);
-
- if (isa<Instruction>(ptrValue))
- if (!currExps.test(VN.lookup(ptrValue))) {
- currExps.insert(ptrValue);
- currExps.set(VN.lookup(ptrValue));
- }
-
- for (GetElementPtrInst::op_iterator OI = U->idx_begin(), OE = U->idx_end();
- OI != OE; ++OI)
- if (isa<Instruction>(*OI) && !currExps.test(VN.lookup(*OI))) {
- currExps.insert(*OI);
- currExps.set(VN.lookup(*OI));
- }
-
- if (!currExps.test(VN.lookup(U))) {
- currExps.insert(U);
- currExps.set(num);
- }
-
- // Handle opaque ops
- } else if (!I->isTerminator()){
- VN.lookup_or_add(I);
-
- currTemps.insert(I);
- }
-
- if (!I->isTerminator())
- if (!currAvail.test(VN.lookup(I))) {
- currAvail.insert(I);
- currAvail.set(VN.lookup(I));
- }
-}
-
-/// buildsets_anticout - When walking the postdom tree, calculate the ANTIC_OUT
-/// set as a function of the ANTIC_IN set of the block's predecessors
-bool GVNPRE::buildsets_anticout(BasicBlock* BB,
- ValueNumberedSet& anticOut,
- SmallPtrSet<BasicBlock*, 8>& visited) {
- if (BB->getTerminator()->getNumSuccessors() == 1) {
- if (BB->getTerminator()->getSuccessor(0) != BB &&
- visited.count(BB->getTerminator()->getSuccessor(0)) == 0) {
- return true;
- }
- else {
- phi_translate_set(anticipatedIn[BB->getTerminator()->getSuccessor(0)],
- BB, BB->getTerminator()->getSuccessor(0), anticOut);
- }
- } else if (BB->getTerminator()->getNumSuccessors() > 1) {
- BasicBlock* first = BB->getTerminator()->getSuccessor(0);
- for (ValueNumberedSet::iterator I = anticipatedIn[first].begin(),
- E = anticipatedIn[first].end(); I != E; ++I) {
- anticOut.insert(*I);
- anticOut.set(VN.lookup(*I));
- }
-
- for (unsigned i = 1; i < BB->getTerminator()->getNumSuccessors(); ++i) {
- BasicBlock* currSucc = BB->getTerminator()->getSuccessor(i);
- ValueNumberedSet& succAnticIn = anticipatedIn[currSucc];
-
- SmallVector<Value*, 16> temp;
-
- for (ValueNumberedSet::iterator I = anticOut.begin(),
- E = anticOut.end(); I != E; ++I)
- if (!succAnticIn.test(VN.lookup(*I)))
- temp.push_back(*I);
-
- for (SmallVector<Value*, 16>::iterator I = temp.begin(), E = temp.end();
- I != E; ++I) {
- anticOut.erase(*I);
- anticOut.reset(VN.lookup(*I));
- }
- }
- }
-
- return false;
-}
-
-/// buildsets_anticin - Walk the postdom tree, calculating ANTIC_OUT for
-/// each block. ANTIC_IN is then a function of ANTIC_OUT and the GEN
-/// sets populated in buildsets_availout
-unsigned GVNPRE::buildsets_anticin(BasicBlock* BB,
- ValueNumberedSet& anticOut,
- ValueNumberedSet& currExps,
- SmallPtrSet<Value*, 16>& currTemps,
- SmallPtrSet<BasicBlock*, 8>& visited) {
- ValueNumberedSet& anticIn = anticipatedIn[BB];
- unsigned old = anticIn.size();
-
- bool defer = buildsets_anticout(BB, anticOut, visited);
- if (defer)
- return 0;
-
- anticIn.clear();
-
- for (ValueNumberedSet::iterator I = anticOut.begin(),
- E = anticOut.end(); I != E; ++I) {
- anticIn.insert(*I);
- anticIn.set(VN.lookup(*I));
- }
- for (ValueNumberedSet::iterator I = currExps.begin(),
- E = currExps.end(); I != E; ++I) {
- if (!anticIn.test(VN.lookup(*I))) {
- anticIn.insert(*I);
- anticIn.set(VN.lookup(*I));
- }
- }
-
- for (SmallPtrSet<Value*, 16>::iterator I = currTemps.begin(),
- E = currTemps.end(); I != E; ++I) {
- anticIn.erase(*I);
- anticIn.reset(VN.lookup(*I));
- }
-
- clean(anticIn);
- anticOut.clear();
-
- if (old != anticIn.size())
- return 2;
- else
- return 1;
-}
-
-/// buildsets - Phase 1 of the main algorithm. Construct the AVAIL_OUT
-/// and the ANTIC_IN sets.
-void GVNPRE::buildsets(Function& F) {
- DenseMap<BasicBlock*, ValueNumberedSet> generatedExpressions;
- DenseMap<BasicBlock*, SmallPtrSet<Value*, 16> > generatedTemporaries;
-
- DominatorTree &DT = getAnalysis<DominatorTree>();
-
- // Phase 1, Part 1: calculate AVAIL_OUT
-
- // Top-down walk of the dominator tree
- for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()),
- E = df_end(DT.getRootNode()); DI != E; ++DI) {
-
- // Get the sets to update for this block
- ValueNumberedSet& currExps = generatedExpressions[DI->getBlock()];
- ValueNumberedSet& currPhis = generatedPhis[DI->getBlock()];
- SmallPtrSet<Value*, 16>& currTemps = generatedTemporaries[DI->getBlock()];
- ValueNumberedSet& currAvail = availableOut[DI->getBlock()];
-
- BasicBlock* BB = DI->getBlock();
-
- // A block inherits AVAIL_OUT from its dominator
- if (DI->getIDom() != 0)
- currAvail = availableOut[DI->getIDom()->getBlock()];
-
- for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
- BI != BE; ++BI)
- buildsets_availout(BI, currAvail, currPhis, currExps,
- currTemps);
-
- }
-
- // Phase 1, Part 2: calculate ANTIC_IN
-
- SmallPtrSet<BasicBlock*, 8> visited;
- SmallPtrSet<BasicBlock*, 4> block_changed;
- for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI)
- block_changed.insert(FI);
-
- bool changed = true;
- unsigned iterations = 0;
-
- while (changed) {
- changed = false;
- ValueNumberedSet anticOut;
-
- // Postorder walk of the CFG
- for (po_iterator<BasicBlock*> BBI = po_begin(&F.getEntryBlock()),
- BBE = po_end(&F.getEntryBlock()); BBI != BBE; ++BBI) {
- BasicBlock* BB = *BBI;
-
- if (block_changed.count(BB) != 0) {
- unsigned ret = buildsets_anticin(BB, anticOut,generatedExpressions[BB],
- generatedTemporaries[BB], visited);
-
- if (ret == 0) {
- changed = true;
- continue;
- } else {
- visited.insert(BB);
-
- if (ret == 2)
- for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
- PI != PE; ++PI) {
- block_changed.insert(*PI);
- }
- else
- block_changed.erase(BB);
-
- changed |= (ret == 2);
- }
- }
- }
-
- iterations++;
- }
-}
-
-/// insertion_pre - When a partial redundancy has been identified, eliminate it
-/// by inserting appropriate values into the predecessors and a phi node in
-/// the main block
-void GVNPRE::insertion_pre(Value* e, BasicBlock* BB,
- DenseMap<BasicBlock*, Value*>& avail,
- std::map<BasicBlock*, ValueNumberedSet>& new_sets) {
- for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) {
- Value* e2 = avail[*PI];
- if (!availableOut[*PI].test(VN.lookup(e2))) {
- User* U = cast<User>(e2);
-
- Value* s1 = 0;
- if (isa<BinaryOperator>(U->getOperand(0)) ||
- isa<CmpInst>(U->getOperand(0)) ||
- isa<ShuffleVectorInst>(U->getOperand(0)) ||
- isa<ExtractElementInst>(U->getOperand(0)) ||
- isa<InsertElementInst>(U->getOperand(0)) ||
- isa<SelectInst>(U->getOperand(0)) ||
- isa<CastInst>(U->getOperand(0)) ||
- isa<GetElementPtrInst>(U->getOperand(0)))
- s1 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(0)));
- else
- s1 = U->getOperand(0);
-
- Value* s2 = 0;
-
- if (isa<BinaryOperator>(U) ||
- isa<CmpInst>(U) ||
- isa<ShuffleVectorInst>(U) ||
- isa<ExtractElementInst>(U) ||
- isa<InsertElementInst>(U) ||
- isa<SelectInst>(U)) {
- if (isa<BinaryOperator>(U->getOperand(1)) ||
- isa<CmpInst>(U->getOperand(1)) ||
- isa<ShuffleVectorInst>(U->getOperand(1)) ||
- isa<ExtractElementInst>(U->getOperand(1)) ||
- isa<InsertElementInst>(U->getOperand(1)) ||
- isa<SelectInst>(U->getOperand(1)) ||
- isa<CastInst>(U->getOperand(1)) ||
- isa<GetElementPtrInst>(U->getOperand(1))) {
- s2 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(1)));
- } else {
- s2 = U->getOperand(1);
- }
- }
-
- // Ternary Operators
- Value* s3 = 0;
- if (isa<ShuffleVectorInst>(U) ||
- isa<InsertElementInst>(U) ||
- isa<SelectInst>(U)) {
- if (isa<BinaryOperator>(U->getOperand(2)) ||
- isa<CmpInst>(U->getOperand(2)) ||
- isa<ShuffleVectorInst>(U->getOperand(2)) ||
- isa<ExtractElementInst>(U->getOperand(2)) ||
- isa<InsertElementInst>(U->getOperand(2)) ||
- isa<SelectInst>(U->getOperand(2)) ||
- isa<CastInst>(U->getOperand(2)) ||
- isa<GetElementPtrInst>(U->getOperand(2))) {
- s3 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(2)));
- } else {
- s3 = U->getOperand(2);
- }
- }
-
- // Vararg operators
- SmallVector<Value*, 4> sVarargs;
- if (GetElementPtrInst* G = dyn_cast<GetElementPtrInst>(U)) {
- for (GetElementPtrInst::op_iterator OI = G->idx_begin(),
- OE = G->idx_end(); OI != OE; ++OI) {
- if (isa<BinaryOperator>(*OI) ||
- isa<CmpInst>(*OI) ||
- isa<ShuffleVectorInst>(*OI) ||
- isa<ExtractElementInst>(*OI) ||
- isa<InsertElementInst>(*OI) ||
- isa<SelectInst>(*OI) ||
- isa<CastInst>(*OI) ||
- isa<GetElementPtrInst>(*OI)) {
- sVarargs.push_back(find_leader(availableOut[*PI],
- VN.lookup(*OI)));
- } else {
- sVarargs.push_back(*OI);
- }
- }
- }
-
- Value* newVal = 0;
- if (BinaryOperator* BO = dyn_cast<BinaryOperator>(U))
- newVal = BinaryOperator::Create(BO->getOpcode(), s1, s2,
- BO->getName()+".gvnpre",
- (*PI)->getTerminator());
- else if (CmpInst* C = dyn_cast<CmpInst>(U))
- newVal = CmpInst::Create(C->getOpcode(), C->getPredicate(), s1, s2,
- C->getName()+".gvnpre",
- (*PI)->getTerminator());
- else if (ShuffleVectorInst* S = dyn_cast<ShuffleVectorInst>(U))
- newVal = new ShuffleVectorInst(s1, s2, s3, S->getName()+".gvnpre",
- (*PI)->getTerminator());
- else if (InsertElementInst* S = dyn_cast<InsertElementInst>(U))
- newVal = InsertElementInst::Create(s1, s2, s3, S->getName()+".gvnpre",
- (*PI)->getTerminator());
- else if (ExtractElementInst* S = dyn_cast<ExtractElementInst>(U))
- newVal = new ExtractElementInst(s1, s2, S->getName()+".gvnpre",
- (*PI)->getTerminator());
- else if (SelectInst* S = dyn_cast<SelectInst>(U))
- newVal = SelectInst::Create(s1, s2, s3, S->getName()+".gvnpre",
- (*PI)->getTerminator());
- else if (CastInst* C = dyn_cast<CastInst>(U))
- newVal = CastInst::Create(C->getOpcode(), s1, C->getType(),
- C->getName()+".gvnpre",
- (*PI)->getTerminator());
- else if (GetElementPtrInst* G = dyn_cast<GetElementPtrInst>(U))
- newVal = GetElementPtrInst::Create(s1, sVarargs.begin(), sVarargs.end(),
- G->getName()+".gvnpre",
- (*PI)->getTerminator());
-
- VN.add(newVal, VN.lookup(U));
-
- ValueNumberedSet& predAvail = availableOut[*PI];
- val_replace(predAvail, newVal);
- val_replace(new_sets[*PI], newVal);
- predAvail.set(VN.lookup(newVal));
-
- DenseMap<BasicBlock*, Value*>::iterator av = avail.find(*PI);
- if (av != avail.end())
- avail.erase(av);
- avail.insert(std::make_pair(*PI, newVal));
-
- ++NumInsertedVals;
- }
- }
-
- PHINode* p = 0;
-
- for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; ++PI) {
- if (p == 0)
- p = PHINode::Create(avail[*PI]->getType(), "gvnpre-join", BB->begin());
-
- p->addIncoming(avail[*PI], *PI);
- }
-
- VN.add(p, VN.lookup(e));
- val_replace(availableOut[BB], p);
- availableOut[BB].set(VN.lookup(e));
- generatedPhis[BB].insert(p);
- generatedPhis[BB].set(VN.lookup(e));
- new_sets[BB].insert(p);
- new_sets[BB].set(VN.lookup(e));
-
- ++NumInsertedPhis;
-}
-
-/// insertion_mergepoint - When walking the dom tree, check at each merge
-/// block for the possibility of a partial redundancy. If present, eliminate it
-unsigned GVNPRE::insertion_mergepoint(SmallVector<Value*, 8>& workList,
- df_iterator<DomTreeNode*>& D,
- std::map<BasicBlock*, ValueNumberedSet >& new_sets) {
- bool changed_function = false;
- bool new_stuff = false;
-
- BasicBlock* BB = D->getBlock();
- for (unsigned i = 0; i < workList.size(); ++i) {
- Value* e = workList[i];
-
- if (isa<BinaryOperator>(e) || isa<CmpInst>(e) ||
- isa<ExtractElementInst>(e) || isa<InsertElementInst>(e) ||
- isa<ShuffleVectorInst>(e) || isa<SelectInst>(e) || isa<CastInst>(e) ||
- isa<GetElementPtrInst>(e)) {
- if (availableOut[D->getIDom()->getBlock()].test(VN.lookup(e)))
- continue;
-
- DenseMap<BasicBlock*, Value*> avail;
- bool by_some = false;
- bool all_same = true;
- Value * first_s = 0;
-
- for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE;
- ++PI) {
- Value *e2 = phi_translate(e, *PI, BB);
- Value *e3 = find_leader(availableOut[*PI], VN.lookup(e2));
-
- if (e3 == 0) {
- DenseMap<BasicBlock*, Value*>::iterator av = avail.find(*PI);
- if (av != avail.end())
- avail.erase(av);
- avail.insert(std::make_pair(*PI, e2));
- all_same = false;
- } else {
- DenseMap<BasicBlock*, Value*>::iterator av = avail.find(*PI);
- if (av != avail.end())
- avail.erase(av);
- avail.insert(std::make_pair(*PI, e3));
-
- by_some = true;
- if (first_s == 0)
- first_s = e3;
- else if (first_s != e3)
- all_same = false;
- }
- }
-
- if (by_some && !all_same &&
- !generatedPhis[BB].test(VN.lookup(e))) {
- insertion_pre(e, BB, avail, new_sets);
-
- changed_function = true;
- new_stuff = true;
- }
- }
- }
-
- unsigned retval = 0;
- if (changed_function)
- retval += 1;
- if (new_stuff)
- retval += 2;
-
- return retval;
-}
-
-/// insert - Phase 2 of the main algorithm. Walk the dominator tree looking for
-/// merge points. When one is found, check for a partial redundancy. If one is
-/// present, eliminate it. Repeat this walk until no changes are made.
-bool GVNPRE::insertion(Function& F) {
- bool changed_function = false;
-
- DominatorTree &DT = getAnalysis<DominatorTree>();
-
- std::map<BasicBlock*, ValueNumberedSet> new_sets;
- bool new_stuff = true;
- while (new_stuff) {
- new_stuff = false;
- for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()),
- E = df_end(DT.getRootNode()); DI != E; ++DI) {
- BasicBlock* BB = DI->getBlock();
-
- if (BB == 0)
- continue;
-
- ValueNumberedSet& availOut = availableOut[BB];
- ValueNumberedSet& anticIn = anticipatedIn[BB];
-
- // Replace leaders with leaders inherited from dominator
- if (DI->getIDom() != 0) {
- ValueNumberedSet& dom_set = new_sets[DI->getIDom()->getBlock()];
- for (ValueNumberedSet::iterator I = dom_set.begin(),
- E = dom_set.end(); I != E; ++I) {
- val_replace(new_sets[BB], *I);
- val_replace(availOut, *I);
- }
- }
-
- // If there is more than one predecessor...
- if (pred_begin(BB) != pred_end(BB) && ++pred_begin(BB) != pred_end(BB)) {
- SmallVector<Value*, 8> workList;
- workList.reserve(anticIn.size());
- topo_sort(anticIn, workList);
-
- unsigned result = insertion_mergepoint(workList, DI, new_sets);
- if (result & 1)
- changed_function = true;
- if (result & 2)
- new_stuff = true;
- }
- }
- }
-
- return changed_function;
-}
-
-// GVNPRE::runOnFunction - This is the main transformation entry point for a
-// function.
-//
-bool GVNPRE::runOnFunction(Function &F) {
- // Clean out global sets from any previous functions
- VN.clear();
- createdExpressions.clear();
- availableOut.clear();
- anticipatedIn.clear();
- generatedPhis.clear();
-
- bool changed_function = false;
-
- // Phase 1: BuildSets
- // This phase calculates the AVAIL_OUT and ANTIC_IN sets
- buildsets(F);
-
- // Phase 2: Insert
- // This phase inserts values to make partially redundant values
- // fully redundant
- changed_function |= insertion(F);
-
- // Phase 3: Eliminate
- // This phase performs trivial full redundancy elimination
- changed_function |= elimination();
-
- // Phase 4: Cleanup
- // This phase cleans up values that were created solely
- // as leaders for expressions
- cleanup();
-
- return changed_function;
-}
diff --git a/lib/Transforms/Scalar/PredicateSimplifier.cpp b/lib/Transforms/Scalar/PredicateSimplifier.cpp
deleted file mode 100644
index a3cb751..0000000
--- a/lib/Transforms/Scalar/PredicateSimplifier.cpp
+++ /dev/null
@@ -1,2721 +0,0 @@
-//===-- PredicateSimplifier.cpp - Path Sensitive Simplifier ---------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Path-sensitive optimizer. In a branch where x == y, replace uses of
-// x with y. Permits further optimization, such as the elimination of
-// the unreachable call:
-//
-// void test(int *p, int *q)
-// {
-// if (p != q)
-// return;
-//
-// if (*p != *q)
-// foo(); // unreachable
-// }
-//
-//===----------------------------------------------------------------------===//
-//
-// The InequalityGraph focusses on four properties; equals, not equals,
-// less-than and less-than-or-equals-to. The greater-than forms are also held
-// just to allow walking from a lesser node to a greater one. These properties
-// are stored in a lattice; LE can become LT or EQ, NE can become LT or GT.
-//
-// These relationships define a graph between values of the same type. Each
-// Value is stored in a map table that retrieves the associated Node. This
-// is how EQ relationships are stored; the map contains pointers from equal
-// Value to the same node. The node contains a most canonical Value* form
-// and the list of known relationships with other nodes.
-//
-// If two nodes are known to be inequal, then they will contain pointers to
-// each other with an "NE" relationship. If node getNode(%x) is less than
-// getNode(%y), then the %x node will contain <%y, GT> and %y will contain
-// <%x, LT>. This allows us to tie nodes together into a graph like this:
-//
-// %a < %b < %c < %d
-//
-// with four nodes representing the properties. The InequalityGraph provides
-// querying with "isRelatedBy" and mutators "addEquality" and "addInequality".
-// To find a relationship, we start with one of the nodes any binary search
-// through its list to find where the relationships with the second node start.
-// Then we iterate through those to find the first relationship that dominates
-// our context node.
-//
-// To create these properties, we wait until a branch or switch instruction
-// implies that a particular value is true (or false). The VRPSolver is
-// responsible for analyzing the variable and seeing what new inferences
-// can be made from each property. For example:
-//
-// %P = icmp ne i32* %ptr, null
-// %a = and i1 %P, %Q
-// br i1 %a label %cond_true, label %cond_false
-//
-// For the true branch, the VRPSolver will start with %a EQ true and look at
-// the definition of %a and find that it can infer that %P and %Q are both
-// true. From %P being true, it can infer that %ptr NE null. For the false
-// branch it can't infer anything from the "and" instruction.
-//
-// Besides branches, we can also infer properties from instruction that may
-// have undefined behaviour in certain cases. For example, the dividend of
-// a division may never be zero. After the division instruction, we may assume
-// that the dividend is not equal to zero.
-//
-//===----------------------------------------------------------------------===//
-//
-// The ValueRanges class stores the known integer bounds of a Value. When we
-// encounter i8 %a u< %b, the ValueRanges stores that %a = [1, 255] and
-// %b = [0, 254].
-//
-// It never stores an empty range, because that means that the code is
-// unreachable. It never stores a single-element range since that's an equality
-// relationship and better stored in the InequalityGraph, nor an empty range
-// since that is better stored in UnreachableBlocks.
-//
-//===----------------------------------------------------------------------===//
-
-#define DEBUG_TYPE "predsimplify"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Instructions.h"
-#include "llvm/Pass.h"
-#include "llvm/ADT/DepthFirstIterator.h"
-#include "llvm/ADT/SetOperations.h"
-#include "llvm/ADT/SetVector.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Analysis/Dominators.h"
-#include "llvm/Assembly/Writer.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/ConstantRange.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/InstVisitor.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Transforms/Utils/Local.h"
-#include <algorithm>
-#include <deque>
-#include <stack>
-using namespace llvm;
-
-STATISTIC(NumVarsReplaced, "Number of argument substitutions");
-STATISTIC(NumInstruction , "Number of instructions removed");
-STATISTIC(NumSimple , "Number of simple replacements");
-STATISTIC(NumBlocks , "Number of blocks marked unreachable");
-STATISTIC(NumSnuggle , "Number of comparisons snuggled");
-
-static const ConstantRange empty(1, false);
-
-namespace {
- class DomTreeDFS {
- public:
- class Node {
- friend class DomTreeDFS;
- public:
- typedef std::vector<Node *>::iterator iterator;
- typedef std::vector<Node *>::const_iterator const_iterator;
-
- unsigned getDFSNumIn() const { return DFSin; }
- unsigned getDFSNumOut() const { return DFSout; }
-
- BasicBlock *getBlock() const { return BB; }
-
- iterator begin() { return Children.begin(); }
- iterator end() { return Children.end(); }
-
- const_iterator begin() const { return Children.begin(); }
- const_iterator end() const { return Children.end(); }
-
- bool dominates(const Node *N) const {
- return DFSin <= N->DFSin && DFSout >= N->DFSout;
- }
-
- bool DominatedBy(const Node *N) const {
- return N->dominates(this);
- }
-
- /// Sorts by the number of descendants. With this, you can iterate
- /// through a sorted list and the first matching entry is the most
- /// specific match for your basic block. The order provided is stable;
- /// DomTreeDFS::Nodes with the same number of descendants are sorted by
- /// DFS in number.
- bool operator<(const Node &N) const {
- unsigned spread = DFSout - DFSin;
- unsigned N_spread = N.DFSout - N.DFSin;
- if (spread == N_spread) return DFSin < N.DFSin;
- return spread < N_spread;
- }
- bool operator>(const Node &N) const { return N < *this; }
-
- private:
- unsigned DFSin, DFSout;
- BasicBlock *BB;
-
- std::vector<Node *> Children;
- };
-
- // XXX: this may be slow. Instead of using "new" for each node, consider
- // putting them in a vector to keep them contiguous.
- explicit DomTreeDFS(DominatorTree *DT) {
- std::stack<std::pair<Node *, DomTreeNode *> > S;
-
- Entry = new Node;
- Entry->BB = DT->getRootNode()->getBlock();
- S.push(std::make_pair(Entry, DT->getRootNode()));
-
- NodeMap[Entry->BB] = Entry;
-
- while (!S.empty()) {
- std::pair<Node *, DomTreeNode *> &Pair = S.top();
- Node *N = Pair.first;
- DomTreeNode *DTNode = Pair.second;
- S.pop();
-
- for (DomTreeNode::iterator I = DTNode->begin(), E = DTNode->end();
- I != E; ++I) {
- Node *NewNode = new Node;
- NewNode->BB = (*I)->getBlock();
- N->Children.push_back(NewNode);
- S.push(std::make_pair(NewNode, *I));
-
- NodeMap[NewNode->BB] = NewNode;
- }
- }
-
- renumber();
-
-#ifndef NDEBUG
- DEBUG(dump());
-#endif
- }
-
-#ifndef NDEBUG
- virtual
-#endif
- ~DomTreeDFS() {
- std::stack<Node *> S;
-
- S.push(Entry);
- while (!S.empty()) {
- Node *N = S.top(); S.pop();
-
- for (Node::iterator I = N->begin(), E = N->end(); I != E; ++I)
- S.push(*I);
-
- delete N;
- }
- }
-
- /// getRootNode - This returns the entry node for the CFG of the function.
- Node *getRootNode() const { return Entry; }
-
- /// getNodeForBlock - return the node for the specified basic block.
- Node *getNodeForBlock(BasicBlock *BB) const {
- if (!NodeMap.count(BB)) return 0;
- return const_cast<DomTreeDFS*>(this)->NodeMap[BB];
- }
-
- /// dominates - returns true if the basic block for I1 dominates that of
- /// the basic block for I2. If the instructions belong to the same basic
- /// block, the instruction first instruction sequentially in the block is
- /// considered dominating.
- bool dominates(Instruction *I1, Instruction *I2) {
- BasicBlock *BB1 = I1->getParent(),
- *BB2 = I2->getParent();
- if (BB1 == BB2) {
- if (isa<TerminatorInst>(I1)) return false;
- if (isa<TerminatorInst>(I2)) return true;
- if ( isa<PHINode>(I1) && !isa<PHINode>(I2)) return true;
- if (!isa<PHINode>(I1) && isa<PHINode>(I2)) return false;
-
- for (BasicBlock::const_iterator I = BB2->begin(), E = BB2->end();
- I != E; ++I) {
- if (&*I == I1) return true;
- else if (&*I == I2) return false;
- }
- assert(!"Instructions not found in parent BasicBlock?");
- } else {
- Node *Node1 = getNodeForBlock(BB1),
- *Node2 = getNodeForBlock(BB2);
- return Node1 && Node2 && Node1->dominates(Node2);
- }
- return false; // Not reached
- }
-
- private:
- /// renumber - calculates the depth first search numberings and applies
- /// them onto the nodes.
- void renumber() {
- std::stack<std::pair<Node *, Node::iterator> > S;
- unsigned n = 0;
-
- Entry->DFSin = ++n;
- S.push(std::make_pair(Entry, Entry->begin()));
-
- while (!S.empty()) {
- std::pair<Node *, Node::iterator> &Pair = S.top();
- Node *N = Pair.first;
- Node::iterator &I = Pair.second;
-
- if (I == N->end()) {
- N->DFSout = ++n;
- S.pop();
- } else {
- Node *Next = *I++;
- Next->DFSin = ++n;
- S.push(std::make_pair(Next, Next->begin()));
- }
- }
- }
-
-#ifndef NDEBUG
- virtual void dump() const {
- dump(*cerr.stream());
- }
-
- void dump(std::ostream &os) const {
- os << "Predicate simplifier DomTreeDFS: \n";
- dump(Entry, 0, os);
- os << "\n\n";
- }
-
- void dump(Node *N, int depth, std::ostream &os) const {
- ++depth;
- for (int i = 0; i < depth; ++i) { os << " "; }
- os << "[" << depth << "] ";
-
- os << N->getBlock()->getName() << " (" << N->getDFSNumIn()
- << ", " << N->getDFSNumOut() << ")\n";
-
- for (Node::iterator I = N->begin(), E = N->end(); I != E; ++I)
- dump(*I, depth, os);
- }
-#endif
-
- Node *Entry;
- std::map<BasicBlock *, Node *> NodeMap;
- };
-
- // SLT SGT ULT UGT EQ
- // 0 1 0 1 0 -- GT 10
- // 0 1 0 1 1 -- GE 11
- // 0 1 1 0 0 -- SGTULT 12
- // 0 1 1 0 1 -- SGEULE 13
- // 0 1 1 1 0 -- SGT 14
- // 0 1 1 1 1 -- SGE 15
- // 1 0 0 1 0 -- SLTUGT 18
- // 1 0 0 1 1 -- SLEUGE 19
- // 1 0 1 0 0 -- LT 20
- // 1 0 1 0 1 -- LE 21
- // 1 0 1 1 0 -- SLT 22
- // 1 0 1 1 1 -- SLE 23
- // 1 1 0 1 0 -- UGT 26
- // 1 1 0 1 1 -- UGE 27
- // 1 1 1 0 0 -- ULT 28
- // 1 1 1 0 1 -- ULE 29
- // 1 1 1 1 0 -- NE 30
- enum LatticeBits {
- EQ_BIT = 1, UGT_BIT = 2, ULT_BIT = 4, SGT_BIT = 8, SLT_BIT = 16
- };
- enum LatticeVal {
- GT = SGT_BIT | UGT_BIT,
- GE = GT | EQ_BIT,
- LT = SLT_BIT | ULT_BIT,
- LE = LT | EQ_BIT,
- NE = SLT_BIT | SGT_BIT | ULT_BIT | UGT_BIT,
- SGTULT = SGT_BIT | ULT_BIT,
- SGEULE = SGTULT | EQ_BIT,
- SLTUGT = SLT_BIT | UGT_BIT,
- SLEUGE = SLTUGT | EQ_BIT,
- ULT = SLT_BIT | SGT_BIT | ULT_BIT,
- UGT = SLT_BIT | SGT_BIT | UGT_BIT,
- SLT = SLT_BIT | ULT_BIT | UGT_BIT,
- SGT = SGT_BIT | ULT_BIT | UGT_BIT,
- SLE = SLT | EQ_BIT,
- SGE = SGT | EQ_BIT,
- ULE = ULT | EQ_BIT,
- UGE = UGT | EQ_BIT
- };
-
-#ifndef NDEBUG
- /// validPredicate - determines whether a given value is actually a lattice
- /// value. Only used in assertions or debugging.
- static bool validPredicate(LatticeVal LV) {
- switch (LV) {
- case GT: case GE: case LT: case LE: case NE:
- case SGTULT: case SGT: case SGEULE:
- case SLTUGT: case SLT: case SLEUGE:
- case ULT: case UGT:
- case SLE: case SGE: case ULE: case UGE:
- return true;
- default:
- return false;
- }
- }
-#endif
-
- /// reversePredicate - reverse the direction of the inequality
- static LatticeVal reversePredicate(LatticeVal LV) {
- unsigned reverse = LV ^ (SLT_BIT|SGT_BIT|ULT_BIT|UGT_BIT); //preserve EQ_BIT
-
- if ((reverse & (SLT_BIT|SGT_BIT)) == 0)
- reverse |= (SLT_BIT|SGT_BIT);
-
- if ((reverse & (ULT_BIT|UGT_BIT)) == 0)
- reverse |= (ULT_BIT|UGT_BIT);
-
- LatticeVal Rev = static_cast<LatticeVal>(reverse);
- assert(validPredicate(Rev) && "Failed reversing predicate.");
- return Rev;
- }
-
- /// ValueNumbering stores the scope-specific value numbers for a given Value.
- class VISIBILITY_HIDDEN ValueNumbering {
-
- /// VNPair is a tuple of {Value, index number, DomTreeDFS::Node}. It
- /// includes the comparison operators necessary to allow you to store it
- /// in a sorted vector.
- class VISIBILITY_HIDDEN VNPair {
- public:
- Value *V;
- unsigned index;
- DomTreeDFS::Node *Subtree;
-
- VNPair(Value *V, unsigned index, DomTreeDFS::Node *Subtree)
- : V(V), index(index), Subtree(Subtree) {}
-
- bool operator==(const VNPair &RHS) const {
- return V == RHS.V && Subtree == RHS.Subtree;
- }
-
- bool operator<(const VNPair &RHS) const {
- if (V != RHS.V) return V < RHS.V;
- return *Subtree < *RHS.Subtree;
- }
-
- bool operator<(Value *RHS) const {
- return V < RHS;
- }
-
- bool operator>(Value *RHS) const {
- return V > RHS;
- }
-
- friend bool operator<(Value *RHS, const VNPair &pair) {
- return pair.operator>(RHS);
- }
- };
-
- typedef std::vector<VNPair> VNMapType;
- VNMapType VNMap;
-
- /// The canonical choice for value number at index.
- std::vector<Value *> Values;
-
- DomTreeDFS *DTDFS;
-
- public:
-#ifndef NDEBUG
- virtual ~ValueNumbering() {}
- virtual void dump() {
- dump(*cerr.stream());
- }
-
- void dump(std::ostream &os) {
- for (unsigned i = 1; i <= Values.size(); ++i) {
- os << i << " = ";
- WriteAsOperand(os, Values[i-1]);
- os << " {";
- for (unsigned j = 0; j < VNMap.size(); ++j) {
- if (VNMap[j].index == i) {
- WriteAsOperand(os, VNMap[j].V);
- os << " (" << VNMap[j].Subtree->getDFSNumIn() << ") ";
- }
- }
- os << "}\n";
- }
- }
-#endif
-
- /// compare - returns true if V1 is a better canonical value than V2.
- bool compare(Value *V1, Value *V2) const {
- if (isa<Constant>(V1))
- return !isa<Constant>(V2);
- else if (isa<Constant>(V2))
- return false;
- else if (isa<Argument>(V1))
- return !isa<Argument>(V2);
- else if (isa<Argument>(V2))
- return false;
-
- Instruction *I1 = dyn_cast<Instruction>(V1);
- Instruction *I2 = dyn_cast<Instruction>(V2);
-
- if (!I1 || !I2)
- return V1->getNumUses() < V2->getNumUses();
-
- return DTDFS->dominates(I1, I2);
- }
-
- ValueNumbering(DomTreeDFS *DTDFS) : DTDFS(DTDFS) {}
-
- /// valueNumber - finds the value number for V under the Subtree. If
- /// there is no value number, returns zero.
- unsigned valueNumber(Value *V, DomTreeDFS::Node *Subtree) {
- if (!(isa<Constant>(V) || isa<Argument>(V) || isa<Instruction>(V))
- || V->getType() == Type::VoidTy) return 0;
-
- VNMapType::iterator E = VNMap.end();
- VNPair pair(V, 0, Subtree);
- VNMapType::iterator I = std::lower_bound(VNMap.begin(), E, pair);
- while (I != E && I->V == V) {
- if (I->Subtree->dominates(Subtree))
- return I->index;
- ++I;
- }
- return 0;
- }
-
- /// getOrInsertVN - always returns a value number, creating it if necessary.
- unsigned getOrInsertVN(Value *V, DomTreeDFS::Node *Subtree) {
- if (unsigned n = valueNumber(V, Subtree))
- return n;
- else
- return newVN(V);
- }
-
- /// newVN - creates a new value number. Value V must not already have a
- /// value number assigned.
- unsigned newVN(Value *V) {
- assert((isa<Constant>(V) || isa<Argument>(V) || isa<Instruction>(V)) &&
- "Bad Value for value numbering.");
- assert(V->getType() != Type::VoidTy && "Won't value number a void value");
-
- Values.push_back(V);
-
- VNPair pair = VNPair(V, Values.size(), DTDFS->getRootNode());
- VNMapType::iterator I = std::lower_bound(VNMap.begin(), VNMap.end(), pair);
- assert((I == VNMap.end() || value(I->index) != V) &&
- "Attempt to create a duplicate value number.");
- VNMap.insert(I, pair);
-
- return Values.size();
- }
-
- /// value - returns the Value associated with a value number.
- Value *value(unsigned index) const {
- assert(index != 0 && "Zero index is reserved for not found.");
- assert(index <= Values.size() && "Index out of range.");
- return Values[index-1];
- }
-
- /// canonicalize - return a Value that is equal to V under Subtree.
- Value *canonicalize(Value *V, DomTreeDFS::Node *Subtree) {
- if (isa<Constant>(V)) return V;
-
- if (unsigned n = valueNumber(V, Subtree))
- return value(n);
- else
- return V;
- }
-
- /// addEquality - adds that value V belongs to the set of equivalent
- /// values defined by value number n under Subtree.
- void addEquality(unsigned n, Value *V, DomTreeDFS::Node *Subtree) {
- assert(canonicalize(value(n), Subtree) == value(n) &&
- "Node's 'canonical' choice isn't best within this subtree.");
-
- // Suppose that we are given "%x -> node #1 (%y)". The problem is that
- // we may already have "%z -> node #2 (%x)" somewhere above us in the
- // graph. We need to find those edges and add "%z -> node #1 (%y)"
- // to keep the lookups canonical.
-
- std::vector<Value *> ToRepoint(1, V);
-
- if (unsigned Conflict = valueNumber(V, Subtree)) {
- for (VNMapType::iterator I = VNMap.begin(), E = VNMap.end();
- I != E; ++I) {
- if (I->index == Conflict && I->Subtree->dominates(Subtree))
- ToRepoint.push_back(I->V);
- }
- }
-
- for (std::vector<Value *>::iterator VI = ToRepoint.begin(),
- VE = ToRepoint.end(); VI != VE; ++VI) {
- Value *V = *VI;
-
- VNPair pair(V, n, Subtree);
- VNMapType::iterator B = VNMap.begin(), E = VNMap.end();
- VNMapType::iterator I = std::lower_bound(B, E, pair);
- if (I != E && I->V == V && I->Subtree == Subtree)
- I->index = n; // Update best choice
- else
- VNMap.insert(I, pair); // New Value
-
- // XXX: we currently don't have to worry about updating values with
- // more specific Subtrees, but we will need to for PHI node support.
-
-#ifndef NDEBUG
- Value *V_n = value(n);
- if (isa<Constant>(V) && isa<Constant>(V_n)) {
- assert(V == V_n && "Constant equals different constant?");
- }
-#endif
- }
- }
-
- /// remove - removes all references to value V.
- void remove(Value *V) {
- VNMapType::iterator B = VNMap.begin(), E = VNMap.end();
- VNPair pair(V, 0, DTDFS->getRootNode());
- VNMapType::iterator J = std::upper_bound(B, E, pair);
- VNMapType::iterator I = J;
-
- while (I != B && (I == E || I->V == V)) --I;
-
- VNMap.erase(I, J);
- }
- };
-
- /// The InequalityGraph stores the relationships between values.
- /// Each Value in the graph is assigned to a Node. Nodes are pointer
- /// comparable for equality. The caller is expected to maintain the logical
- /// consistency of the system.
- ///
- /// The InequalityGraph class may invalidate Node*s after any mutator call.
- /// @brief The InequalityGraph stores the relationships between values.
- class VISIBILITY_HIDDEN InequalityGraph {
- ValueNumbering &VN;
- DomTreeDFS::Node *TreeRoot;
-
- InequalityGraph(); // DO NOT IMPLEMENT
- InequalityGraph(InequalityGraph &); // DO NOT IMPLEMENT
- public:
- InequalityGraph(ValueNumbering &VN, DomTreeDFS::Node *TreeRoot)
- : VN(VN), TreeRoot(TreeRoot) {}
-
- class Node;
-
- /// An Edge is contained inside a Node making one end of the edge implicit
- /// and contains a pointer to the other end. The edge contains a lattice
- /// value specifying the relationship and an DomTreeDFS::Node specifying
- /// the root in the dominator tree to which this edge applies.
- class VISIBILITY_HIDDEN Edge {
- public:
- Edge(unsigned T, LatticeVal V, DomTreeDFS::Node *ST)
- : To(T), LV(V), Subtree(ST) {}
-
- unsigned To;
- LatticeVal LV;
- DomTreeDFS::Node *Subtree;
-
- bool operator<(const Edge &edge) const {
- if (To != edge.To) return To < edge.To;
- return *Subtree < *edge.Subtree;
- }
-
- bool operator<(unsigned to) const {
- return To < to;
- }
-
- bool operator>(unsigned to) const {
- return To > to;
- }
-
- friend bool operator<(unsigned to, const Edge &edge) {
- return edge.operator>(to);
- }
- };
-
- /// A single node in the InequalityGraph. This stores the canonical Value
- /// for the node, as well as the relationships with the neighbours.
- ///
- /// @brief A single node in the InequalityGraph.
- class VISIBILITY_HIDDEN Node {
- friend class InequalityGraph;
-
- typedef SmallVector<Edge, 4> RelationsType;
- RelationsType Relations;
-
- // TODO: can this idea improve performance?
- //friend class std::vector<Node>;
- //Node(Node &N) { RelationsType.swap(N.RelationsType); }
-
- public:
- typedef RelationsType::iterator iterator;
- typedef RelationsType::const_iterator const_iterator;
-
-#ifndef NDEBUG
- virtual ~Node() {}
- virtual void dump() const {
- dump(*cerr.stream());
- }
- private:
- void dump(std::ostream &os) const {
- static const std::string names[32] =
- { "000000", "000001", "000002", "000003", "000004", "000005",
- "000006", "000007", "000008", "000009", " >", " >=",
- " s>u<", "s>=u<=", " s>", " s>=", "000016", "000017",
- " s<u>", "s<=u>=", " <", " <=", " s<", " s<=",
- "000024", "000025", " u>", " u>=", " u<", " u<=",
- " !=", "000031" };
- for (Node::const_iterator NI = begin(), NE = end(); NI != NE; ++NI) {
- os << names[NI->LV] << " " << NI->To
- << " (" << NI->Subtree->getDFSNumIn() << "), ";
- }
- }
- public:
-#endif
-
- iterator begin() { return Relations.begin(); }
- iterator end() { return Relations.end(); }
- const_iterator begin() const { return Relations.begin(); }
- const_iterator end() const { return Relations.end(); }
-
- iterator find(unsigned n, DomTreeDFS::Node *Subtree) {
- iterator E = end();
- for (iterator I = std::lower_bound(begin(), E, n);
- I != E && I->To == n; ++I) {
- if (Subtree->DominatedBy(I->Subtree))
- return I;
- }
- return E;
- }
-
- const_iterator find(unsigned n, DomTreeDFS::Node *Subtree) const {
- const_iterator E = end();
- for (const_iterator I = std::lower_bound(begin(), E, n);
- I != E && I->To == n; ++I) {
- if (Subtree->DominatedBy(I->Subtree))
- return I;
- }
- return E;
- }
-
- /// update - updates the lattice value for a given node, creating a new
- /// entry if one doesn't exist. The new lattice value must not be
- /// inconsistent with any previously existing value.
- void update(unsigned n, LatticeVal R, DomTreeDFS::Node *Subtree) {
- assert(validPredicate(R) && "Invalid predicate.");
-
- Edge edge(n, R, Subtree);
- iterator B = begin(), E = end();
- iterator I = std::lower_bound(B, E, edge);
-
- iterator J = I;
- while (J != E && J->To == n) {
- if (Subtree->DominatedBy(J->Subtree))
- break;
- ++J;
- }
-
- if (J != E && J->To == n) {
- edge.LV = static_cast<LatticeVal>(J->LV & R);
- assert(validPredicate(edge.LV) && "Invalid union of lattice values.");
-
- if (edge.LV == J->LV)
- return; // This update adds nothing new.
- }
-
- if (I != B) {
- // We also have to tighten any edge beneath our update.
- for (iterator K = I - 1; K->To == n; --K) {
- if (K->Subtree->DominatedBy(Subtree)) {
- LatticeVal LV = static_cast<LatticeVal>(K->LV & edge.LV);
- assert(validPredicate(LV) && "Invalid union of lattice values");
- K->LV = LV;
- }
- if (K == B) break;
- }
- }
-
- // Insert new edge at Subtree if it isn't already there.
- if (I == E || I->To != n || Subtree != I->Subtree)
- Relations.insert(I, edge);
- }
- };
-
- private:
-
- std::vector<Node> Nodes;
-
- public:
- /// node - returns the node object at a given value number. The pointer
- /// returned may be invalidated on the next call to node().
- Node *node(unsigned index) {
- assert(VN.value(index)); // This triggers the necessary checks.
- if (Nodes.size() < index) Nodes.resize(index);
- return &Nodes[index-1];
- }
-
- /// isRelatedBy - true iff n1 op n2
- bool isRelatedBy(unsigned n1, unsigned n2, DomTreeDFS::Node *Subtree,
- LatticeVal LV) {
- if (n1 == n2) return LV & EQ_BIT;
-
- Node *N1 = node(n1);
- Node::iterator I = N1->find(n2, Subtree), E = N1->end();
- if (I != E) return (I->LV & LV) == I->LV;
-
- return false;
- }
-
- // The add* methods assume that your input is logically valid and may
- // assertion-fail or infinitely loop if you attempt a contradiction.
-
- /// addInequality - Sets n1 op n2.
- /// It is also an error to call this on an inequality that is already true.
- void addInequality(unsigned n1, unsigned n2, DomTreeDFS::Node *Subtree,
- LatticeVal LV1) {
- assert(n1 != n2 && "A node can't be inequal to itself.");
-
- if (LV1 != NE)
- assert(!isRelatedBy(n1, n2, Subtree, reversePredicate(LV1)) &&
- "Contradictory inequality.");
-
- // Suppose we're adding %n1 < %n2. Find all the %a < %n1 and
- // add %a < %n2 too. This keeps the graph fully connected.
- if (LV1 != NE) {
- // Break up the relationship into signed and unsigned comparison parts.
- // If the signed parts of %a op1 %n1 match that of %n1 op2 %n2, and
- // op1 and op2 aren't NE, then add %a op3 %n2. The new relationship
- // should have the EQ_BIT iff it's set for both op1 and op2.
-
- unsigned LV1_s = LV1 & (SLT_BIT|SGT_BIT);
- unsigned LV1_u = LV1 & (ULT_BIT|UGT_BIT);
-
- for (Node::iterator I = node(n1)->begin(), E = node(n1)->end(); I != E; ++I) {
- if (I->LV != NE && I->To != n2) {
-
- DomTreeDFS::Node *Local_Subtree = NULL;
- if (Subtree->DominatedBy(I->Subtree))
- Local_Subtree = Subtree;
- else if (I->Subtree->DominatedBy(Subtree))
- Local_Subtree = I->Subtree;
-
- if (Local_Subtree) {
- unsigned new_relationship = 0;
- LatticeVal ILV = reversePredicate(I->LV);
- unsigned ILV_s = ILV & (SLT_BIT|SGT_BIT);
- unsigned ILV_u = ILV & (ULT_BIT|UGT_BIT);
-
- if (LV1_s != (SLT_BIT|SGT_BIT) && ILV_s == LV1_s)
- new_relationship |= ILV_s;
- if (LV1_u != (ULT_BIT|UGT_BIT) && ILV_u == LV1_u)
- new_relationship |= ILV_u;
-
- if (new_relationship) {
- if ((new_relationship & (SLT_BIT|SGT_BIT)) == 0)
- new_relationship |= (SLT_BIT|SGT_BIT);
- if ((new_relationship & (ULT_BIT|UGT_BIT)) == 0)
- new_relationship |= (ULT_BIT|UGT_BIT);
- if ((LV1 & EQ_BIT) && (ILV & EQ_BIT))
- new_relationship |= EQ_BIT;
-
- LatticeVal NewLV = static_cast<LatticeVal>(new_relationship);
-
- node(I->To)->update(n2, NewLV, Local_Subtree);
- node(n2)->update(I->To, reversePredicate(NewLV), Local_Subtree);
- }
- }
- }
- }
-
- for (Node::iterator I = node(n2)->begin(), E = node(n2)->end(); I != E; ++I) {
- if (I->LV != NE && I->To != n1) {
- DomTreeDFS::Node *Local_Subtree = NULL;
- if (Subtree->DominatedBy(I->Subtree))
- Local_Subtree = Subtree;
- else if (I->Subtree->DominatedBy(Subtree))
- Local_Subtree = I->Subtree;
-
- if (Local_Subtree) {
- unsigned new_relationship = 0;
- unsigned ILV_s = I->LV & (SLT_BIT|SGT_BIT);
- unsigned ILV_u = I->LV & (ULT_BIT|UGT_BIT);
-
- if (LV1_s != (SLT_BIT|SGT_BIT) && ILV_s == LV1_s)
- new_relationship |= ILV_s;
-
- if (LV1_u != (ULT_BIT|UGT_BIT) && ILV_u == LV1_u)
- new_relationship |= ILV_u;
-
- if (new_relationship) {
- if ((new_relationship & (SLT_BIT|SGT_BIT)) == 0)
- new_relationship |= (SLT_BIT|SGT_BIT);
- if ((new_relationship & (ULT_BIT|UGT_BIT)) == 0)
- new_relationship |= (ULT_BIT|UGT_BIT);
- if ((LV1 & EQ_BIT) && (I->LV & EQ_BIT))
- new_relationship |= EQ_BIT;
-
- LatticeVal NewLV = static_cast<LatticeVal>(new_relationship);
-
- node(n1)->update(I->To, NewLV, Local_Subtree);
- node(I->To)->update(n1, reversePredicate(NewLV), Local_Subtree);
- }
- }
- }
- }
- }
-
- node(n1)->update(n2, LV1, Subtree);
- node(n2)->update(n1, reversePredicate(LV1), Subtree);
- }
-
- /// remove - removes a node from the graph by removing all references to
- /// and from it.
- void remove(unsigned n) {
- Node *N = node(n);
- for (Node::iterator NI = N->begin(), NE = N->end(); NI != NE; ++NI) {
- Node::iterator Iter = node(NI->To)->find(n, TreeRoot);
- do {
- node(NI->To)->Relations.erase(Iter);
- Iter = node(NI->To)->find(n, TreeRoot);
- } while (Iter != node(NI->To)->end());
- }
- N->Relations.clear();
- }
-
-#ifndef NDEBUG
- virtual ~InequalityGraph() {}
- virtual void dump() {
- dump(*cerr.stream());
- }
-
- void dump(std::ostream &os) {
- for (unsigned i = 1; i <= Nodes.size(); ++i) {
- os << i << " = {";
- node(i)->dump(os);
- os << "}\n";
- }
- }
-#endif
- };
-
- class VRPSolver;
-
- /// ValueRanges tracks the known integer ranges and anti-ranges of the nodes
- /// in the InequalityGraph.
- class VISIBILITY_HIDDEN ValueRanges {
- ValueNumbering &VN;
- TargetData *TD;
-
- class VISIBILITY_HIDDEN ScopedRange {
- typedef std::vector<std::pair<DomTreeDFS::Node *, ConstantRange> >
- RangeListType;
- RangeListType RangeList;
-
- static bool swo(const std::pair<DomTreeDFS::Node *, ConstantRange> &LHS,
- const std::pair<DomTreeDFS::Node *, ConstantRange> &RHS) {
- return *LHS.first < *RHS.first;
- }
-
- public:
-#ifndef NDEBUG
- virtual ~ScopedRange() {}
- virtual void dump() const {
- dump(*cerr.stream());
- }
-
- void dump(std::ostream &os) const {
- os << "{";
- for (const_iterator I = begin(), E = end(); I != E; ++I) {
- os << &I->second << " (" << I->first->getDFSNumIn() << "), ";
- }
- os << "}";
- }
-#endif
-
- typedef RangeListType::iterator iterator;
- typedef RangeListType::const_iterator const_iterator;
-
- iterator begin() { return RangeList.begin(); }
- iterator end() { return RangeList.end(); }
- const_iterator begin() const { return RangeList.begin(); }
- const_iterator end() const { return RangeList.end(); }
-
- iterator find(DomTreeDFS::Node *Subtree) {
- iterator E = end();
- iterator I = std::lower_bound(begin(), E,
- std::make_pair(Subtree, empty), swo);
-
- while (I != E && !I->first->dominates(Subtree)) ++I;
- return I;
- }
-
- const_iterator find(DomTreeDFS::Node *Subtree) const {
- const_iterator E = end();
- const_iterator I = std::lower_bound(begin(), E,
- std::make_pair(Subtree, empty), swo);
-
- while (I != E && !I->first->dominates(Subtree)) ++I;
- return I;
- }
-
- void update(const ConstantRange &CR, DomTreeDFS::Node *Subtree) {
- assert(!CR.isEmptySet() && "Empty ConstantRange.");
- assert(!CR.isSingleElement() && "Refusing to store single element.");
-
- iterator E = end();
- iterator I =
- std::lower_bound(begin(), E, std::make_pair(Subtree, empty), swo);
-
- if (I != end() && I->first == Subtree) {
- ConstantRange CR2 = I->second.maximalIntersectWith(CR);
- assert(!CR2.isEmptySet() && !CR2.isSingleElement() &&
- "Invalid union of ranges.");
- I->second = CR2;
- } else
- RangeList.insert(I, std::make_pair(Subtree, CR));
- }
- };
-
- std::vector<ScopedRange> Ranges;
-
- void update(unsigned n, const ConstantRange &CR, DomTreeDFS::Node *Subtree){
- if (CR.isFullSet()) return;
- if (Ranges.size() < n) Ranges.resize(n);
- Ranges[n-1].update(CR, Subtree);
- }
-
- /// create - Creates a ConstantRange that matches the given LatticeVal
- /// relation with a given integer.
- ConstantRange create(LatticeVal LV, const ConstantRange &CR) {
- assert(!CR.isEmptySet() && "Can't deal with empty set.");
-
- if (LV == NE)
- return makeConstantRange(ICmpInst::ICMP_NE, CR);
-
- unsigned LV_s = LV & (SGT_BIT|SLT_BIT);
- unsigned LV_u = LV & (UGT_BIT|ULT_BIT);
- bool hasEQ = LV & EQ_BIT;
-
- ConstantRange Range(CR.getBitWidth());
-
- if (LV_s == SGT_BIT) {
- Range = Range.maximalIntersectWith(makeConstantRange(
- hasEQ ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_SGT, CR));
- } else if (LV_s == SLT_BIT) {
- Range = Range.maximalIntersectWith(makeConstantRange(
- hasEQ ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_SLT, CR));
- }
-
- if (LV_u == UGT_BIT) {
- Range = Range.maximalIntersectWith(makeConstantRange(
- hasEQ ? ICmpInst::ICMP_UGE : ICmpInst::ICMP_UGT, CR));
- } else if (LV_u == ULT_BIT) {
- Range = Range.maximalIntersectWith(makeConstantRange(
- hasEQ ? ICmpInst::ICMP_ULE : ICmpInst::ICMP_ULT, CR));
- }
-
- return Range;
- }
-
- /// makeConstantRange - Creates a ConstantRange representing the set of all
- /// value that match the ICmpInst::Predicate with any of the values in CR.
- ConstantRange makeConstantRange(ICmpInst::Predicate ICmpOpcode,
- const ConstantRange &CR) {
- uint32_t W = CR.getBitWidth();
- switch (ICmpOpcode) {
- default: assert(!"Invalid ICmp opcode to makeConstantRange()");
- case ICmpInst::ICMP_EQ:
- return ConstantRange(CR.getLower(), CR.getUpper());
- case ICmpInst::ICMP_NE:
- if (CR.isSingleElement())
- return ConstantRange(CR.getUpper(), CR.getLower());
- return ConstantRange(W);
- case ICmpInst::ICMP_ULT:
- return ConstantRange(APInt::getMinValue(W), CR.getUnsignedMax());
- case ICmpInst::ICMP_SLT:
- return ConstantRange(APInt::getSignedMinValue(W), CR.getSignedMax());
- case ICmpInst::ICMP_ULE: {
- APInt UMax(CR.getUnsignedMax());
- if (UMax.isMaxValue())
- return ConstantRange(W);
- return ConstantRange(APInt::getMinValue(W), UMax + 1);
- }
- case ICmpInst::ICMP_SLE: {
- APInt SMax(CR.getSignedMax());
- if (SMax.isMaxSignedValue() || (SMax+1).isMaxSignedValue())
- return ConstantRange(W);
- return ConstantRange(APInt::getSignedMinValue(W), SMax + 1);
- }
- case ICmpInst::ICMP_UGT:
- return ConstantRange(CR.getUnsignedMin() + 1, APInt::getNullValue(W));
- case ICmpInst::ICMP_SGT:
- return ConstantRange(CR.getSignedMin() + 1,
- APInt::getSignedMinValue(W));
- case ICmpInst::ICMP_UGE: {
- APInt UMin(CR.getUnsignedMin());
- if (UMin.isMinValue())
- return ConstantRange(W);
- return ConstantRange(UMin, APInt::getNullValue(W));
- }
- case ICmpInst::ICMP_SGE: {
- APInt SMin(CR.getSignedMin());
- if (SMin.isMinSignedValue())
- return ConstantRange(W);
- return ConstantRange(SMin, APInt::getSignedMinValue(W));
- }
- }
- }
-
-#ifndef NDEBUG
- bool isCanonical(Value *V, DomTreeDFS::Node *Subtree) {
- return V == VN.canonicalize(V, Subtree);
- }
-#endif
-
- public:
-
- ValueRanges(ValueNumbering &VN, TargetData *TD) : VN(VN), TD(TD) {}
-
-#ifndef NDEBUG
- virtual ~ValueRanges() {}
-
- virtual void dump() const {
- dump(*cerr.stream());
- }
-
- void dump(std::ostream &os) const {
- for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
- os << (i+1) << " = ";
- Ranges[i].dump(os);
- os << "\n";
- }
- }
-#endif
-
- /// range - looks up the ConstantRange associated with a value number.
- ConstantRange range(unsigned n, DomTreeDFS::Node *Subtree) {
- assert(VN.value(n)); // performs range checks
-
- if (n <= Ranges.size()) {
- ScopedRange::iterator I = Ranges[n-1].find(Subtree);
- if (I != Ranges[n-1].end()) return I->second;
- }
-
- Value *V = VN.value(n);
- ConstantRange CR = range(V);
- return CR;
- }
-
- /// range - determine a range from a Value without performing any lookups.
- ConstantRange range(Value *V) const {
- if (ConstantInt *C = dyn_cast<ConstantInt>(V))
- return ConstantRange(C->getValue());
- else if (isa<ConstantPointerNull>(V))
- return ConstantRange(APInt::getNullValue(typeToWidth(V->getType())));
- else
- return ConstantRange(typeToWidth(V->getType()));
- }
-
- // typeToWidth - returns the number of bits necessary to store a value of
- // this type, or zero if unknown.
- uint32_t typeToWidth(const Type *Ty) const {
- if (TD)
- return TD->getTypeSizeInBits(Ty);
- else
- return Ty->getPrimitiveSizeInBits();
- }
-
- static bool isRelatedBy(const ConstantRange &CR1, const ConstantRange &CR2,
- LatticeVal LV) {
- switch (LV) {
- default: assert(!"Impossible lattice value!");
- case NE:
- return CR1.maximalIntersectWith(CR2).isEmptySet();
- case ULT:
- return CR1.getUnsignedMax().ult(CR2.getUnsignedMin());
- case ULE:
- return CR1.getUnsignedMax().ule(CR2.getUnsignedMin());
- case UGT:
- return CR1.getUnsignedMin().ugt(CR2.getUnsignedMax());
- case UGE:
- return CR1.getUnsignedMin().uge(CR2.getUnsignedMax());
- case SLT:
- return CR1.getSignedMax().slt(CR2.getSignedMin());
- case SLE:
- return CR1.getSignedMax().sle(CR2.getSignedMin());
- case SGT:
- return CR1.getSignedMin().sgt(CR2.getSignedMax());
- case SGE:
- return CR1.getSignedMin().sge(CR2.getSignedMax());
- case LT:
- return CR1.getUnsignedMax().ult(CR2.getUnsignedMin()) &&
- CR1.getSignedMax().slt(CR2.getUnsignedMin());
- case LE:
- return CR1.getUnsignedMax().ule(CR2.getUnsignedMin()) &&
- CR1.getSignedMax().sle(CR2.getUnsignedMin());
- case GT:
- return CR1.getUnsignedMin().ugt(CR2.getUnsignedMax()) &&
- CR1.getSignedMin().sgt(CR2.getSignedMax());
- case GE:
- return CR1.getUnsignedMin().uge(CR2.getUnsignedMax()) &&
- CR1.getSignedMin().sge(CR2.getSignedMax());
- case SLTUGT:
- return CR1.getSignedMax().slt(CR2.getSignedMin()) &&
- CR1.getUnsignedMin().ugt(CR2.getUnsignedMax());
- case SLEUGE:
- return CR1.getSignedMax().sle(CR2.getSignedMin()) &&
- CR1.getUnsignedMin().uge(CR2.getUnsignedMax());
- case SGTULT:
- return CR1.getSignedMin().sgt(CR2.getSignedMax()) &&
- CR1.getUnsignedMax().ult(CR2.getUnsignedMin());
- case SGEULE:
- return CR1.getSignedMin().sge(CR2.getSignedMax()) &&
- CR1.getUnsignedMax().ule(CR2.getUnsignedMin());
- }
- }
-
- bool isRelatedBy(unsigned n1, unsigned n2, DomTreeDFS::Node *Subtree,
- LatticeVal LV) {
- ConstantRange CR1 = range(n1, Subtree);
- ConstantRange CR2 = range(n2, Subtree);
-
- // True iff all values in CR1 are LV to all values in CR2.
- return isRelatedBy(CR1, CR2, LV);
- }
-
- void addToWorklist(Value *V, Constant *C, ICmpInst::Predicate Pred,
- VRPSolver *VRP);
- void markBlock(VRPSolver *VRP);
-
- void mergeInto(Value **I, unsigned n, unsigned New,
- DomTreeDFS::Node *Subtree, VRPSolver *VRP) {
- ConstantRange CR_New = range(New, Subtree);
- ConstantRange Merged = CR_New;
-
- for (; n != 0; ++I, --n) {
- unsigned i = VN.valueNumber(*I, Subtree);
- ConstantRange CR_Kill = i ? range(i, Subtree) : range(*I);
- if (CR_Kill.isFullSet()) continue;
- Merged = Merged.maximalIntersectWith(CR_Kill);
- }
-
- if (Merged.isFullSet() || Merged == CR_New) return;
-
- applyRange(New, Merged, Subtree, VRP);
- }
-
- void applyRange(unsigned n, const ConstantRange &CR,
- DomTreeDFS::Node *Subtree, VRPSolver *VRP) {
- ConstantRange Merged = CR.maximalIntersectWith(range(n, Subtree));
- if (Merged.isEmptySet()) {
- markBlock(VRP);
- return;
- }
-
- if (const APInt *I = Merged.getSingleElement()) {
- Value *V = VN.value(n); // XXX: redesign worklist.
- const Type *Ty = V->getType();
- if (Ty->isInteger()) {
- addToWorklist(V, ConstantInt::get(*I), ICmpInst::ICMP_EQ, VRP);
- return;
- } else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
- assert(*I == 0 && "Pointer is null but not zero?");
- addToWorklist(V, ConstantPointerNull::get(PTy),
- ICmpInst::ICMP_EQ, VRP);
- return;
- }
- }
-
- update(n, Merged, Subtree);
- }
-
- void addNotEquals(unsigned n1, unsigned n2, DomTreeDFS::Node *Subtree,
- VRPSolver *VRP) {
- ConstantRange CR1 = range(n1, Subtree);
- ConstantRange CR2 = range(n2, Subtree);
-
- uint32_t W = CR1.getBitWidth();
-
- if (const APInt *I = CR1.getSingleElement()) {
- if (CR2.isFullSet()) {
- ConstantRange NewCR2(CR1.getUpper(), CR1.getLower());
- applyRange(n2, NewCR2, Subtree, VRP);
- } else if (*I == CR2.getLower()) {
- APInt NewLower(CR2.getLower() + 1),
- NewUpper(CR2.getUpper());
- if (NewLower == NewUpper)
- NewLower = NewUpper = APInt::getMinValue(W);
-
- ConstantRange NewCR2(NewLower, NewUpper);
- applyRange(n2, NewCR2, Subtree, VRP);
- } else if (*I == CR2.getUpper() - 1) {
- APInt NewLower(CR2.getLower()),
- NewUpper(CR2.getUpper() - 1);
- if (NewLower == NewUpper)
- NewLower = NewUpper = APInt::getMinValue(W);
-
- ConstantRange NewCR2(NewLower, NewUpper);
- applyRange(n2, NewCR2, Subtree, VRP);
- }
- }
-
- if (const APInt *I = CR2.getSingleElement()) {
- if (CR1.isFullSet()) {
- ConstantRange NewCR1(CR2.getUpper(), CR2.getLower());
- applyRange(n1, NewCR1, Subtree, VRP);
- } else if (*I == CR1.getLower()) {
- APInt NewLower(CR1.getLower() + 1),
- NewUpper(CR1.getUpper());
- if (NewLower == NewUpper)
- NewLower = NewUpper = APInt::getMinValue(W);
-
- ConstantRange NewCR1(NewLower, NewUpper);
- applyRange(n1, NewCR1, Subtree, VRP);
- } else if (*I == CR1.getUpper() - 1) {
- APInt NewLower(CR1.getLower()),
- NewUpper(CR1.getUpper() - 1);
- if (NewLower == NewUpper)
- NewLower = NewUpper = APInt::getMinValue(W);
-
- ConstantRange NewCR1(NewLower, NewUpper);
- applyRange(n1, NewCR1, Subtree, VRP);
- }
- }
- }
-
- void addInequality(unsigned n1, unsigned n2, DomTreeDFS::Node *Subtree,
- LatticeVal LV, VRPSolver *VRP) {
- assert(!isRelatedBy(n1, n2, Subtree, LV) && "Asked to do useless work.");
-
- if (LV == NE) {
- addNotEquals(n1, n2, Subtree, VRP);
- return;
- }
-
- ConstantRange CR1 = range(n1, Subtree);
- ConstantRange CR2 = range(n2, Subtree);
-
- if (!CR1.isSingleElement()) {
- ConstantRange NewCR1 = CR1.maximalIntersectWith(create(LV, CR2));
- if (NewCR1 != CR1)
- applyRange(n1, NewCR1, Subtree, VRP);
- }
-
- if (!CR2.isSingleElement()) {
- ConstantRange NewCR2 = CR2.maximalIntersectWith(
- create(reversePredicate(LV), CR1));
- if (NewCR2 != CR2)
- applyRange(n2, NewCR2, Subtree, VRP);
- }
- }
- };
-
- /// UnreachableBlocks keeps tracks of blocks that are for one reason or
- /// another discovered to be unreachable. This is used to cull the graph when
- /// analyzing instructions, and to mark blocks with the "unreachable"
- /// terminator instruction after the function has executed.
- class VISIBILITY_HIDDEN UnreachableBlocks {
- private:
- std::vector<BasicBlock *> DeadBlocks;
-
- public:
- /// mark - mark a block as dead
- void mark(BasicBlock *BB) {
- std::vector<BasicBlock *>::iterator E = DeadBlocks.end();
- std::vector<BasicBlock *>::iterator I =
- std::lower_bound(DeadBlocks.begin(), E, BB);
-
- if (I == E || *I != BB) DeadBlocks.insert(I, BB);
- }
-
- /// isDead - returns whether a block is known to be dead already
- bool isDead(BasicBlock *BB) {
- std::vector<BasicBlock *>::iterator E = DeadBlocks.end();
- std::vector<BasicBlock *>::iterator I =
- std::lower_bound(DeadBlocks.begin(), E, BB);
-
- return I != E && *I == BB;
- }
-
- /// kill - replace the dead blocks' terminator with an UnreachableInst.
- bool kill() {
- bool modified = false;
- for (std::vector<BasicBlock *>::iterator I = DeadBlocks.begin(),
- E = DeadBlocks.end(); I != E; ++I) {
- BasicBlock *BB = *I;
-
- DOUT << "unreachable block: " << BB->getName() << "\n";
-
- for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB);
- SI != SE; ++SI) {
- BasicBlock *Succ = *SI;
- Succ->removePredecessor(BB);
- }
-
- TerminatorInst *TI = BB->getTerminator();
- TI->replaceAllUsesWith(UndefValue::get(TI->getType()));
- TI->eraseFromParent();
- new UnreachableInst(BB);
- ++NumBlocks;
- modified = true;
- }
- DeadBlocks.clear();
- return modified;
- }
- };
-
- /// VRPSolver keeps track of how changes to one variable affect other
- /// variables, and forwards changes along to the InequalityGraph. It
- /// also maintains the correct choice for "canonical" in the IG.
- /// @brief VRPSolver calculates inferences from a new relationship.
- class VISIBILITY_HIDDEN VRPSolver {
- private:
- friend class ValueRanges;
-
- struct Operation {
- Value *LHS, *RHS;
- ICmpInst::Predicate Op;
-
- BasicBlock *ContextBB; // XXX use a DomTreeDFS::Node instead
- Instruction *ContextInst;
- };
- std::deque<Operation> WorkList;
-
- ValueNumbering &VN;
- InequalityGraph &IG;
- UnreachableBlocks &UB;
- ValueRanges &VR;
- DomTreeDFS *DTDFS;
- DomTreeDFS::Node *Top;
- BasicBlock *TopBB;
- Instruction *TopInst;
- bool &modified;
-
- typedef InequalityGraph::Node Node;
-
- // below - true if the Instruction is dominated by the current context
- // block or instruction
- bool below(Instruction *I) {
- BasicBlock *BB = I->getParent();
- if (TopInst && TopInst->getParent() == BB) {
- if (isa<TerminatorInst>(TopInst)) return false;
- if (isa<TerminatorInst>(I)) return true;
- if ( isa<PHINode>(TopInst) && !isa<PHINode>(I)) return true;
- if (!isa<PHINode>(TopInst) && isa<PHINode>(I)) return false;
-
- for (BasicBlock::const_iterator Iter = BB->begin(), E = BB->end();
- Iter != E; ++Iter) {
- if (&*Iter == TopInst) return true;
- else if (&*Iter == I) return false;
- }
- assert(!"Instructions not found in parent BasicBlock?");
- } else {
- DomTreeDFS::Node *Node = DTDFS->getNodeForBlock(BB);
- if (!Node) return false;
- return Top->dominates(Node);
- }
- return false; // Not reached
- }
-
- // aboveOrBelow - true if the Instruction either dominates or is dominated
- // by the current context block or instruction
- bool aboveOrBelow(Instruction *I) {
- BasicBlock *BB = I->getParent();
- DomTreeDFS::Node *Node = DTDFS->getNodeForBlock(BB);
- if (!Node) return false;
-
- return Top == Node || Top->dominates(Node) || Node->dominates(Top);
- }
-
- bool makeEqual(Value *V1, Value *V2) {
- DOUT << "makeEqual(" << *V1 << ", " << *V2 << ")\n";
- DOUT << "context is ";
- if (TopInst) DOUT << "I: " << *TopInst << "\n";
- else DOUT << "BB: " << TopBB->getName()
- << "(" << Top->getDFSNumIn() << ")\n";
-
- assert(V1->getType() == V2->getType() &&
- "Can't make two values with different types equal.");
-
- if (V1 == V2) return true;
-
- if (isa<Constant>(V1) && isa<Constant>(V2))
- return false;
-
- unsigned n1 = VN.valueNumber(V1, Top), n2 = VN.valueNumber(V2, Top);
-
- if (n1 && n2) {
- if (n1 == n2) return true;
- if (IG.isRelatedBy(n1, n2, Top, NE)) return false;
- }
-
- if (n1) assert(V1 == VN.value(n1) && "Value isn't canonical.");
- if (n2) assert(V2 == VN.value(n2) && "Value isn't canonical.");
-
- assert(!VN.compare(V2, V1) && "Please order parameters to makeEqual.");
-
- assert(!isa<Constant>(V2) && "Tried to remove a constant.");
-
- SetVector<unsigned> Remove;
- if (n2) Remove.insert(n2);
-
- if (n1 && n2) {
- // Suppose we're being told that %x == %y, and %x <= %z and %y >= %z.
- // We can't just merge %x and %y because the relationship with %z would
- // be EQ and that's invalid. What we're doing is looking for any nodes
- // %z such that %x <= %z and %y >= %z, and vice versa.
-
- Node::iterator end = IG.node(n2)->end();
-
- // Find the intersection between N1 and N2 which is dominated by
- // Top. If we find %x where N1 <= %x <= N2 (or >=) then add %x to
- // Remove.
- for (Node::iterator I = IG.node(n1)->begin(), E = IG.node(n1)->end();
- I != E; ++I) {
- if (!(I->LV & EQ_BIT) || !Top->DominatedBy(I->Subtree)) continue;
-
- unsigned ILV_s = I->LV & (SLT_BIT|SGT_BIT);
- unsigned ILV_u = I->LV & (ULT_BIT|UGT_BIT);
- Node::iterator NI = IG.node(n2)->find(I->To, Top);
- if (NI != end) {
- LatticeVal NILV = reversePredicate(NI->LV);
- unsigned NILV_s = NILV & (SLT_BIT|SGT_BIT);
- unsigned NILV_u = NILV & (ULT_BIT|UGT_BIT);
-
- if ((ILV_s != (SLT_BIT|SGT_BIT) && ILV_s == NILV_s) ||
- (ILV_u != (ULT_BIT|UGT_BIT) && ILV_u == NILV_u))
- Remove.insert(I->To);
- }
- }
-
- // See if one of the nodes about to be removed is actually a better
- // canonical choice than n1.
- unsigned orig_n1 = n1;
- SetVector<unsigned>::iterator DontRemove = Remove.end();
- for (SetVector<unsigned>::iterator I = Remove.begin()+1 /* skip n2 */,
- E = Remove.end(); I != E; ++I) {
- unsigned n = *I;
- Value *V = VN.value(n);
- if (VN.compare(V, V1)) {
- V1 = V;
- n1 = n;
- DontRemove = I;
- }
- }
- if (DontRemove != Remove.end()) {
- unsigned n = *DontRemove;
- Remove.remove(n);
- Remove.insert(orig_n1);
- }
- }
-
- // We'd like to allow makeEqual on two values to perform a simple
- // substitution without creating nodes in the IG whenever possible.
- //
- // The first iteration through this loop operates on V2 before going
- // through the Remove list and operating on those too. If all of the
- // iterations performed simple replacements then we exit early.
- bool mergeIGNode = false;
- unsigned i = 0;
- for (Value *R = V2; i == 0 || i < Remove.size(); ++i) {
- if (i) R = VN.value(Remove[i]); // skip n2.
-
- // Try to replace the whole instruction. If we can, we're done.
- Instruction *I2 = dyn_cast<Instruction>(R);
- if (I2 && below(I2)) {
- std::vector<Instruction *> ToNotify;
- for (Value::use_iterator UI = I2->use_begin(), UE = I2->use_end();
- UI != UE;) {
- Use &TheUse = UI.getUse();
- ++UI;
- Instruction *I = cast<Instruction>(TheUse.getUser());
- ToNotify.push_back(I);
- }
-
- DOUT << "Simply removing " << *I2
- << ", replacing with " << *V1 << "\n";
- I2->replaceAllUsesWith(V1);
- // leave it dead; it'll get erased later.
- ++NumInstruction;
- modified = true;
-
- for (std::vector<Instruction *>::iterator II = ToNotify.begin(),
- IE = ToNotify.end(); II != IE; ++II) {
- opsToDef(*II);
- }
-
- continue;
- }
-
- // Otherwise, replace all dominated uses.
- for (Value::use_iterator UI = R->use_begin(), UE = R->use_end();
- UI != UE;) {
- Use &TheUse = UI.getUse();
- ++UI;
- if (Instruction *I = dyn_cast<Instruction>(TheUse.getUser())) {
- if (below(I)) {
- TheUse.set(V1);
- modified = true;
- ++NumVarsReplaced;
- opsToDef(I);
- }
- }
- }
-
- // If that killed the instruction, stop here.
- if (I2 && isInstructionTriviallyDead(I2)) {
- DOUT << "Killed all uses of " << *I2
- << ", replacing with " << *V1 << "\n";
- continue;
- }
-
- // If we make it to here, then we will need to create a node for N1.
- // Otherwise, we can skip out early!
- mergeIGNode = true;
- }
-
- if (!isa<Constant>(V1)) {
- if (Remove.empty()) {
- VR.mergeInto(&V2, 1, VN.getOrInsertVN(V1, Top), Top, this);
- } else {
- std::vector<Value*> RemoveVals;
- RemoveVals.reserve(Remove.size());
-
- for (SetVector<unsigned>::iterator I = Remove.begin(),
- E = Remove.end(); I != E; ++I) {
- Value *V = VN.value(*I);
- if (!V->use_empty())
- RemoveVals.push_back(V);
- }
- VR.mergeInto(&RemoveVals[0], RemoveVals.size(),
- VN.getOrInsertVN(V1, Top), Top, this);
- }
- }
-
- if (mergeIGNode) {
- // Create N1.
- if (!n1) n1 = VN.getOrInsertVN(V1, Top);
- IG.node(n1); // Ensure that IG.Nodes won't get resized
-
- // Migrate relationships from removed nodes to N1.
- for (SetVector<unsigned>::iterator I = Remove.begin(), E = Remove.end();
- I != E; ++I) {
- unsigned n = *I;
- for (Node::iterator NI = IG.node(n)->begin(), NE = IG.node(n)->end();
- NI != NE; ++NI) {
- if (NI->Subtree->DominatedBy(Top)) {
- if (NI->To == n1) {
- assert((NI->LV & EQ_BIT) && "Node inequal to itself.");
- continue;
- }
- if (Remove.count(NI->To))
- continue;
-
- IG.node(NI->To)->update(n1, reversePredicate(NI->LV), Top);
- IG.node(n1)->update(NI->To, NI->LV, Top);
- }
- }
- }
-
- // Point V2 (and all items in Remove) to N1.
- if (!n2)
- VN.addEquality(n1, V2, Top);
- else {
- for (SetVector<unsigned>::iterator I = Remove.begin(),
- E = Remove.end(); I != E; ++I) {
- VN.addEquality(n1, VN.value(*I), Top);
- }
- }
-
- // If !Remove.empty() then V2 = Remove[0]->getValue().
- // Even when Remove is empty, we still want to process V2.
- i = 0;
- for (Value *R = V2; i == 0 || i < Remove.size(); ++i) {
- if (i) R = VN.value(Remove[i]); // skip n2.
-
- if (Instruction *I2 = dyn_cast<Instruction>(R)) {
- if (aboveOrBelow(I2))
- defToOps(I2);
- }
- for (Value::use_iterator UI = V2->use_begin(), UE = V2->use_end();
- UI != UE;) {
- Use &TheUse = UI.getUse();
- ++UI;
- if (Instruction *I = dyn_cast<Instruction>(TheUse.getUser())) {
- if (aboveOrBelow(I))
- opsToDef(I);
- }
- }
- }
- }
-
- // re-opsToDef all dominated users of V1.
- if (Instruction *I = dyn_cast<Instruction>(V1)) {
- for (Value::use_iterator UI = I->use_begin(), UE = I->use_end();
- UI != UE;) {
- Use &TheUse = UI.getUse();
- ++UI;
- Value *V = TheUse.getUser();
- if (!V->use_empty()) {
- Instruction *Inst = cast<Instruction>(V);
- if (aboveOrBelow(Inst))
- opsToDef(Inst);
- }
- }
- }
-
- return true;
- }
-
- /// cmpInstToLattice - converts an CmpInst::Predicate to lattice value
- /// Requires that the lattice value be valid; does not accept ICMP_EQ.
- static LatticeVal cmpInstToLattice(ICmpInst::Predicate Pred) {
- switch (Pred) {
- case ICmpInst::ICMP_EQ:
- assert(!"No matching lattice value.");
- return static_cast<LatticeVal>(EQ_BIT);
- default:
- assert(!"Invalid 'icmp' predicate.");
- case ICmpInst::ICMP_NE:
- return NE;
- case ICmpInst::ICMP_UGT:
- return UGT;
- case ICmpInst::ICMP_UGE:
- return UGE;
- case ICmpInst::ICMP_ULT:
- return ULT;
- case ICmpInst::ICMP_ULE:
- return ULE;
- case ICmpInst::ICMP_SGT:
- return SGT;
- case ICmpInst::ICMP_SGE:
- return SGE;
- case ICmpInst::ICMP_SLT:
- return SLT;
- case ICmpInst::ICMP_SLE:
- return SLE;
- }
- }
-
- public:
- VRPSolver(ValueNumbering &VN, InequalityGraph &IG, UnreachableBlocks &UB,
- ValueRanges &VR, DomTreeDFS *DTDFS, bool &modified,
- BasicBlock *TopBB)
- : VN(VN),
- IG(IG),
- UB(UB),
- VR(VR),
- DTDFS(DTDFS),
- Top(DTDFS->getNodeForBlock(TopBB)),
- TopBB(TopBB),
- TopInst(NULL),
- modified(modified)
- {
- assert(Top && "VRPSolver created for unreachable basic block.");
- }
-
- VRPSolver(ValueNumbering &VN, InequalityGraph &IG, UnreachableBlocks &UB,
- ValueRanges &VR, DomTreeDFS *DTDFS, bool &modified,
- Instruction *TopInst)
- : VN(VN),
- IG(IG),
- UB(UB),
- VR(VR),
- DTDFS(DTDFS),
- Top(DTDFS->getNodeForBlock(TopInst->getParent())),
- TopBB(TopInst->getParent()),
- TopInst(TopInst),
- modified(modified)
- {
- assert(Top && "VRPSolver created for unreachable basic block.");
- assert(Top->getBlock() == TopInst->getParent() && "Context mismatch.");
- }
-
- bool isRelatedBy(Value *V1, Value *V2, ICmpInst::Predicate Pred) const {
- if (Constant *C1 = dyn_cast<Constant>(V1))
- if (Constant *C2 = dyn_cast<Constant>(V2))
- return ConstantExpr::getCompare(Pred, C1, C2) ==
- ConstantInt::getTrue();
-
- unsigned n1 = VN.valueNumber(V1, Top);
- unsigned n2 = VN.valueNumber(V2, Top);
-
- if (n1 && n2) {
- if (n1 == n2) return Pred == ICmpInst::ICMP_EQ ||
- Pred == ICmpInst::ICMP_ULE ||
- Pred == ICmpInst::ICMP_UGE ||
- Pred == ICmpInst::ICMP_SLE ||
- Pred == ICmpInst::ICMP_SGE;
- if (Pred == ICmpInst::ICMP_EQ) return false;
- if (IG.isRelatedBy(n1, n2, Top, cmpInstToLattice(Pred))) return true;
- if (VR.isRelatedBy(n1, n2, Top, cmpInstToLattice(Pred))) return true;
- }
-
- if ((n1 && !n2 && isa<Constant>(V2)) ||
- (n2 && !n1 && isa<Constant>(V1))) {
- ConstantRange CR1 = n1 ? VR.range(n1, Top) : VR.range(V1);
- ConstantRange CR2 = n2 ? VR.range(n2, Top) : VR.range(V2);
-
- if (Pred == ICmpInst::ICMP_EQ)
- return CR1.isSingleElement() &&
- CR1.getSingleElement() == CR2.getSingleElement();
-
- return VR.isRelatedBy(CR1, CR2, cmpInstToLattice(Pred));
- }
- if (Pred == ICmpInst::ICMP_EQ) return V1 == V2;
- return false;
- }
-
- /// add - adds a new property to the work queue
- void add(Value *V1, Value *V2, ICmpInst::Predicate Pred,
- Instruction *I = NULL) {
- DOUT << "adding " << *V1 << " " << Pred << " " << *V2;
- if (I) DOUT << " context: " << *I;
- else DOUT << " default context (" << Top->getDFSNumIn() << ")";
- DOUT << "\n";
-
- assert(V1->getType() == V2->getType() &&
- "Can't relate two values with different types.");
-
- WorkList.push_back(Operation());
- Operation &O = WorkList.back();
- O.LHS = V1, O.RHS = V2, O.Op = Pred, O.ContextInst = I;
- O.ContextBB = I ? I->getParent() : TopBB;
- }
-
- /// defToOps - Given an instruction definition that we've learned something
- /// new about, find any new relationships between its operands.
- void defToOps(Instruction *I) {
- Instruction *NewContext = below(I) ? I : TopInst;
- Value *Canonical = VN.canonicalize(I, Top);
-
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(I)) {
- const Type *Ty = BO->getType();
- assert(!Ty->isFPOrFPVector() && "Float in work queue!");
-
- Value *Op0 = VN.canonicalize(BO->getOperand(0), Top);
- Value *Op1 = VN.canonicalize(BO->getOperand(1), Top);
-
- // TODO: "and i32 -1, %x" EQ %y then %x EQ %y.
-
- switch (BO->getOpcode()) {
- case Instruction::And: {
- // "and i32 %a, %b" EQ -1 then %a EQ -1 and %b EQ -1
- ConstantInt *CI = ConstantInt::getAllOnesValue(Ty);
- if (Canonical == CI) {
- add(CI, Op0, ICmpInst::ICMP_EQ, NewContext);
- add(CI, Op1, ICmpInst::ICMP_EQ, NewContext);
- }
- } break;
- case Instruction::Or: {
- // "or i32 %a, %b" EQ 0 then %a EQ 0 and %b EQ 0
- Constant *Zero = Constant::getNullValue(Ty);
- if (Canonical == Zero) {
- add(Zero, Op0, ICmpInst::ICMP_EQ, NewContext);
- add(Zero, Op1, ICmpInst::ICMP_EQ, NewContext);
- }
- } break;
- case Instruction::Xor: {
- // "xor i32 %c, %a" EQ %b then %a EQ %c ^ %b
- // "xor i32 %c, %a" EQ %c then %a EQ 0
- // "xor i32 %c, %a" NE %c then %a NE 0
- // Repeat the above, with order of operands reversed.
- Value *LHS = Op0;
- Value *RHS = Op1;
- if (!isa<Constant>(LHS)) std::swap(LHS, RHS);
-
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Canonical)) {
- if (ConstantInt *Arg = dyn_cast<ConstantInt>(LHS)) {
- add(RHS, ConstantInt::get(CI->getValue() ^ Arg->getValue()),
- ICmpInst::ICMP_EQ, NewContext);
- }
- }
- if (Canonical == LHS) {
- if (isa<ConstantInt>(Canonical))
- add(RHS, Constant::getNullValue(Ty), ICmpInst::ICMP_EQ,
- NewContext);
- } else if (isRelatedBy(LHS, Canonical, ICmpInst::ICMP_NE)) {
- add(RHS, Constant::getNullValue(Ty), ICmpInst::ICMP_NE,
- NewContext);
- }
- } break;
- default:
- break;
- }
- } else if (ICmpInst *IC = dyn_cast<ICmpInst>(I)) {
- // "icmp ult i32 %a, %y" EQ true then %a u< y
- // etc.
-
- if (Canonical == ConstantInt::getTrue()) {
- add(IC->getOperand(0), IC->getOperand(1), IC->getPredicate(),
- NewContext);
- } else if (Canonical == ConstantInt::getFalse()) {
- add(IC->getOperand(0), IC->getOperand(1),
- ICmpInst::getInversePredicate(IC->getPredicate()), NewContext);
- }
- } else if (SelectInst *SI = dyn_cast<SelectInst>(I)) {
- if (I->getType()->isFPOrFPVector()) return;
-
- // Given: "%a = select i1 %x, i32 %b, i32 %c"
- // %a EQ %b and %b NE %c then %x EQ true
- // %a EQ %c and %b NE %c then %x EQ false
-
- Value *True = SI->getTrueValue();
- Value *False = SI->getFalseValue();
- if (isRelatedBy(True, False, ICmpInst::ICMP_NE)) {
- if (Canonical == VN.canonicalize(True, Top) ||
- isRelatedBy(Canonical, False, ICmpInst::ICMP_NE))
- add(SI->getCondition(), ConstantInt::getTrue(),
- ICmpInst::ICMP_EQ, NewContext);
- else if (Canonical == VN.canonicalize(False, Top) ||
- isRelatedBy(Canonical, True, ICmpInst::ICMP_NE))
- add(SI->getCondition(), ConstantInt::getFalse(),
- ICmpInst::ICMP_EQ, NewContext);
- }
- } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
- for (GetElementPtrInst::op_iterator OI = GEPI->idx_begin(),
- OE = GEPI->idx_end(); OI != OE; ++OI) {
- ConstantInt *Op = dyn_cast<ConstantInt>(VN.canonicalize(*OI, Top));
- if (!Op || !Op->isZero()) return;
- }
- // TODO: The GEPI indices are all zero. Copy from definition to operand,
- // jumping the type plane as needed.
- if (isRelatedBy(GEPI, Constant::getNullValue(GEPI->getType()),
- ICmpInst::ICMP_NE)) {
- Value *Ptr = GEPI->getPointerOperand();
- add(Ptr, Constant::getNullValue(Ptr->getType()), ICmpInst::ICMP_NE,
- NewContext);
- }
- } else if (CastInst *CI = dyn_cast<CastInst>(I)) {
- const Type *SrcTy = CI->getSrcTy();
-
- unsigned ci = VN.getOrInsertVN(CI, Top);
- uint32_t W = VR.typeToWidth(SrcTy);
- if (!W) return;
- ConstantRange CR = VR.range(ci, Top);
-
- if (CR.isFullSet()) return;
-
- switch (CI->getOpcode()) {
- default: break;
- case Instruction::ZExt:
- case Instruction::SExt:
- VR.applyRange(VN.getOrInsertVN(CI->getOperand(0), Top),
- CR.truncate(W), Top, this);
- break;
- case Instruction::BitCast:
- VR.applyRange(VN.getOrInsertVN(CI->getOperand(0), Top),
- CR, Top, this);
- break;
- }
- }
- }
-
- /// opsToDef - A new relationship was discovered involving one of this
- /// instruction's operands. Find any new relationship involving the
- /// definition, or another operand.
- void opsToDef(Instruction *I) {
- Instruction *NewContext = below(I) ? I : TopInst;
-
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(I)) {
- Value *Op0 = VN.canonicalize(BO->getOperand(0), Top);
- Value *Op1 = VN.canonicalize(BO->getOperand(1), Top);
-
- if (ConstantInt *CI0 = dyn_cast<ConstantInt>(Op0))
- if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Op1)) {
- add(BO, ConstantExpr::get(BO->getOpcode(), CI0, CI1),
- ICmpInst::ICMP_EQ, NewContext);
- return;
- }
-
- // "%y = and i1 true, %x" then %x EQ %y
- // "%y = or i1 false, %x" then %x EQ %y
- // "%x = add i32 %y, 0" then %x EQ %y
- // "%x = mul i32 %y, 0" then %x EQ 0
-
- Instruction::BinaryOps Opcode = BO->getOpcode();
- const Type *Ty = BO->getType();
- assert(!Ty->isFPOrFPVector() && "Float in work queue!");
-
- Constant *Zero = Constant::getNullValue(Ty);
- Constant *One = ConstantInt::get(Ty, 1);
- ConstantInt *AllOnes = ConstantInt::getAllOnesValue(Ty);
-
- switch (Opcode) {
- default: break;
- case Instruction::LShr:
- case Instruction::AShr:
- case Instruction::Shl:
- if (Op1 == Zero) {
- add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
- return;
- }
- break;
- case Instruction::Sub:
- if (Op1 == Zero) {
- add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
- return;
- }
- if (ConstantInt *CI0 = dyn_cast<ConstantInt>(Op0)) {
- unsigned n_ci0 = VN.getOrInsertVN(Op1, Top);
- ConstantRange CR = VR.range(n_ci0, Top);
- if (!CR.isFullSet()) {
- CR.subtract(CI0->getValue());
- unsigned n_bo = VN.getOrInsertVN(BO, Top);
- VR.applyRange(n_bo, CR, Top, this);
- return;
- }
- }
- if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Op1)) {
- unsigned n_ci1 = VN.getOrInsertVN(Op0, Top);
- ConstantRange CR = VR.range(n_ci1, Top);
- if (!CR.isFullSet()) {
- CR.subtract(CI1->getValue());
- unsigned n_bo = VN.getOrInsertVN(BO, Top);
- VR.applyRange(n_bo, CR, Top, this);
- return;
- }
- }
- break;
- case Instruction::Or:
- if (Op0 == AllOnes || Op1 == AllOnes) {
- add(BO, AllOnes, ICmpInst::ICMP_EQ, NewContext);
- return;
- }
- if (Op0 == Zero) {
- add(BO, Op1, ICmpInst::ICMP_EQ, NewContext);
- return;
- } else if (Op1 == Zero) {
- add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
- return;
- }
- break;
- case Instruction::Add:
- if (ConstantInt *CI0 = dyn_cast<ConstantInt>(Op0)) {
- unsigned n_ci0 = VN.getOrInsertVN(Op1, Top);
- ConstantRange CR = VR.range(n_ci0, Top);
- if (!CR.isFullSet()) {
- CR.subtract(-CI0->getValue());
- unsigned n_bo = VN.getOrInsertVN(BO, Top);
- VR.applyRange(n_bo, CR, Top, this);
- return;
- }
- }
- if (ConstantInt *CI1 = dyn_cast<ConstantInt>(Op1)) {
- unsigned n_ci1 = VN.getOrInsertVN(Op0, Top);
- ConstantRange CR = VR.range(n_ci1, Top);
- if (!CR.isFullSet()) {
- CR.subtract(-CI1->getValue());
- unsigned n_bo = VN.getOrInsertVN(BO, Top);
- VR.applyRange(n_bo, CR, Top, this);
- return;
- }
- }
- // fall-through
- case Instruction::Xor:
- if (Op0 == Zero) {
- add(BO, Op1, ICmpInst::ICMP_EQ, NewContext);
- return;
- } else if (Op1 == Zero) {
- add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
- return;
- }
- break;
- case Instruction::And:
- if (Op0 == AllOnes) {
- add(BO, Op1, ICmpInst::ICMP_EQ, NewContext);
- return;
- } else if (Op1 == AllOnes) {
- add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
- return;
- }
- if (Op0 == Zero || Op1 == Zero) {
- add(BO, Zero, ICmpInst::ICMP_EQ, NewContext);
- return;
- }
- break;
- case Instruction::Mul:
- if (Op0 == Zero || Op1 == Zero) {
- add(BO, Zero, ICmpInst::ICMP_EQ, NewContext);
- return;
- }
- if (Op0 == One) {
- add(BO, Op1, ICmpInst::ICMP_EQ, NewContext);
- return;
- } else if (Op1 == One) {
- add(BO, Op0, ICmpInst::ICMP_EQ, NewContext);
- return;
- }
- break;
- }
-
- // "%x = add i32 %y, %z" and %x EQ %y then %z EQ 0
- // "%x = add i32 %y, %z" and %x EQ %z then %y EQ 0
- // "%x = shl i32 %y, %z" and %x EQ %y and %y NE 0 then %z EQ 0
- // "%x = udiv i32 %y, %z" and %x EQ %y and %y NE 0 then %z EQ 1
-
- Value *Known = Op0, *Unknown = Op1,
- *TheBO = VN.canonicalize(BO, Top);
- if (Known != TheBO) std::swap(Known, Unknown);
- if (Known == TheBO) {
- switch (Opcode) {
- default: break;
- case Instruction::LShr:
- case Instruction::AShr:
- case Instruction::Shl:
- if (!isRelatedBy(Known, Zero, ICmpInst::ICMP_NE)) break;
- // otherwise, fall-through.
- case Instruction::Sub:
- if (Unknown == Op0) break;
- // otherwise, fall-through.
- case Instruction::Xor:
- case Instruction::Add:
- add(Unknown, Zero, ICmpInst::ICMP_EQ, NewContext);
- break;
- case Instruction::UDiv:
- case Instruction::SDiv:
- if (Unknown == Op1) break;
- if (isRelatedBy(Known, Zero, ICmpInst::ICMP_NE))
- add(Unknown, One, ICmpInst::ICMP_EQ, NewContext);
- break;
- }
- }
-
- // TODO: "%a = add i32 %b, 1" and %b > %z then %a >= %z.
-
- } else if (ICmpInst *IC = dyn_cast<ICmpInst>(I)) {
- // "%a = icmp ult i32 %b, %c" and %b u< %c then %a EQ true
- // "%a = icmp ult i32 %b, %c" and %b u>= %c then %a EQ false
- // etc.
-
- Value *Op0 = VN.canonicalize(IC->getOperand(0), Top);
- Value *Op1 = VN.canonicalize(IC->getOperand(1), Top);
-
- ICmpInst::Predicate Pred = IC->getPredicate();
- if (isRelatedBy(Op0, Op1, Pred))
- add(IC, ConstantInt::getTrue(), ICmpInst::ICMP_EQ, NewContext);
- else if (isRelatedBy(Op0, Op1, ICmpInst::getInversePredicate(Pred)))
- add(IC, ConstantInt::getFalse(), ICmpInst::ICMP_EQ, NewContext);
-
- } else if (SelectInst *SI = dyn_cast<SelectInst>(I)) {
- if (I->getType()->isFPOrFPVector()) return;
-
- // Given: "%a = select i1 %x, i32 %b, i32 %c"
- // %x EQ true then %a EQ %b
- // %x EQ false then %a EQ %c
- // %b EQ %c then %a EQ %b
-
- Value *Canonical = VN.canonicalize(SI->getCondition(), Top);
- if (Canonical == ConstantInt::getTrue()) {
- add(SI, SI->getTrueValue(), ICmpInst::ICMP_EQ, NewContext);
- } else if (Canonical == ConstantInt::getFalse()) {
- add(SI, SI->getFalseValue(), ICmpInst::ICMP_EQ, NewContext);
- } else if (VN.canonicalize(SI->getTrueValue(), Top) ==
- VN.canonicalize(SI->getFalseValue(), Top)) {
- add(SI, SI->getTrueValue(), ICmpInst::ICMP_EQ, NewContext);
- }
- } else if (CastInst *CI = dyn_cast<CastInst>(I)) {
- const Type *DestTy = CI->getDestTy();
- if (DestTy->isFPOrFPVector()) return;
-
- Value *Op = VN.canonicalize(CI->getOperand(0), Top);
- Instruction::CastOps Opcode = CI->getOpcode();
-
- if (Constant *C = dyn_cast<Constant>(Op)) {
- add(CI, ConstantExpr::getCast(Opcode, C, DestTy),
- ICmpInst::ICMP_EQ, NewContext);
- }
-
- uint32_t W = VR.typeToWidth(DestTy);
- unsigned ci = VN.getOrInsertVN(CI, Top);
- ConstantRange CR = VR.range(VN.getOrInsertVN(Op, Top), Top);
-
- if (!CR.isFullSet()) {
- switch (Opcode) {
- default: break;
- case Instruction::ZExt:
- VR.applyRange(ci, CR.zeroExtend(W), Top, this);
- break;
- case Instruction::SExt:
- VR.applyRange(ci, CR.signExtend(W), Top, this);
- break;
- case Instruction::Trunc: {
- ConstantRange Result = CR.truncate(W);
- if (!Result.isFullSet())
- VR.applyRange(ci, Result, Top, this);
- } break;
- case Instruction::BitCast:
- VR.applyRange(ci, CR, Top, this);
- break;
- // TODO: other casts?
- }
- }
- } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
- for (GetElementPtrInst::op_iterator OI = GEPI->idx_begin(),
- OE = GEPI->idx_end(); OI != OE; ++OI) {
- ConstantInt *Op = dyn_cast<ConstantInt>(VN.canonicalize(*OI, Top));
- if (!Op || !Op->isZero()) return;
- }
- // TODO: The GEPI indices are all zero. Copy from operand to definition,
- // jumping the type plane as needed.
- Value *Ptr = GEPI->getPointerOperand();
- if (isRelatedBy(Ptr, Constant::getNullValue(Ptr->getType()),
- ICmpInst::ICMP_NE)) {
- add(GEPI, Constant::getNullValue(GEPI->getType()), ICmpInst::ICMP_NE,
- NewContext);
- }
- }
- }
-
- /// solve - process the work queue
- void solve() {
- //DOUT << "WorkList entry, size: " << WorkList.size() << "\n";
- while (!WorkList.empty()) {
- //DOUT << "WorkList size: " << WorkList.size() << "\n";
-
- Operation &O = WorkList.front();
- TopInst = O.ContextInst;
- TopBB = O.ContextBB;
- Top = DTDFS->getNodeForBlock(TopBB); // XXX move this into Context
-
- O.LHS = VN.canonicalize(O.LHS, Top);
- O.RHS = VN.canonicalize(O.RHS, Top);
-
- assert(O.LHS == VN.canonicalize(O.LHS, Top) && "Canonicalize isn't.");
- assert(O.RHS == VN.canonicalize(O.RHS, Top) && "Canonicalize isn't.");
-
- DOUT << "solving " << *O.LHS << " " << O.Op << " " << *O.RHS;
- if (O.ContextInst) DOUT << " context inst: " << *O.ContextInst;
- else DOUT << " context block: " << O.ContextBB->getName();
- DOUT << "\n";
-
- DEBUG(VN.dump());
- DEBUG(IG.dump());
- DEBUG(VR.dump());
-
- // If they're both Constant, skip it. Check for contradiction and mark
- // the BB as unreachable if so.
- if (Constant *CI_L = dyn_cast<Constant>(O.LHS)) {
- if (Constant *CI_R = dyn_cast<Constant>(O.RHS)) {
- if (ConstantExpr::getCompare(O.Op, CI_L, CI_R) ==
- ConstantInt::getFalse())
- UB.mark(TopBB);
-
- WorkList.pop_front();
- continue;
- }
- }
-
- if (VN.compare(O.LHS, O.RHS)) {
- std::swap(O.LHS, O.RHS);
- O.Op = ICmpInst::getSwappedPredicate(O.Op);
- }
-
- if (O.Op == ICmpInst::ICMP_EQ) {
- if (!makeEqual(O.RHS, O.LHS))
- UB.mark(TopBB);
- } else {
- LatticeVal LV = cmpInstToLattice(O.Op);
-
- if ((LV & EQ_BIT) &&
- isRelatedBy(O.LHS, O.RHS, ICmpInst::getSwappedPredicate(O.Op))) {
- if (!makeEqual(O.RHS, O.LHS))
- UB.mark(TopBB);
- } else {
- if (isRelatedBy(O.LHS, O.RHS, ICmpInst::getInversePredicate(O.Op))){
- UB.mark(TopBB);
- WorkList.pop_front();
- continue;
- }
-
- unsigned n1 = VN.getOrInsertVN(O.LHS, Top);
- unsigned n2 = VN.getOrInsertVN(O.RHS, Top);
-
- if (n1 == n2) {
- if (O.Op != ICmpInst::ICMP_UGE && O.Op != ICmpInst::ICMP_ULE &&
- O.Op != ICmpInst::ICMP_SGE && O.Op != ICmpInst::ICMP_SLE)
- UB.mark(TopBB);
-
- WorkList.pop_front();
- continue;
- }
-
- if (VR.isRelatedBy(n1, n2, Top, LV) ||
- IG.isRelatedBy(n1, n2, Top, LV)) {
- WorkList.pop_front();
- continue;
- }
-
- VR.addInequality(n1, n2, Top, LV, this);
- if ((!isa<ConstantInt>(O.RHS) && !isa<ConstantInt>(O.LHS)) ||
- LV == NE)
- IG.addInequality(n1, n2, Top, LV);
-
- if (Instruction *I1 = dyn_cast<Instruction>(O.LHS)) {
- if (aboveOrBelow(I1))
- defToOps(I1);
- }
- if (isa<Instruction>(O.LHS) || isa<Argument>(O.LHS)) {
- for (Value::use_iterator UI = O.LHS->use_begin(),
- UE = O.LHS->use_end(); UI != UE;) {
- Use &TheUse = UI.getUse();
- ++UI;
- Instruction *I = cast<Instruction>(TheUse.getUser());
- if (aboveOrBelow(I))
- opsToDef(I);
- }
- }
- if (Instruction *I2 = dyn_cast<Instruction>(O.RHS)) {
- if (aboveOrBelow(I2))
- defToOps(I2);
- }
- if (isa<Instruction>(O.RHS) || isa<Argument>(O.RHS)) {
- for (Value::use_iterator UI = O.RHS->use_begin(),
- UE = O.RHS->use_end(); UI != UE;) {
- Use &TheUse = UI.getUse();
- ++UI;
- Instruction *I = cast<Instruction>(TheUse.getUser());
- if (aboveOrBelow(I))
- opsToDef(I);
- }
- }
- }
- }
- WorkList.pop_front();
- }
- }
- };
-
- void ValueRanges::addToWorklist(Value *V, Constant *C,
- ICmpInst::Predicate Pred, VRPSolver *VRP) {
- VRP->add(V, C, Pred, VRP->TopInst);
- }
-
- void ValueRanges::markBlock(VRPSolver *VRP) {
- VRP->UB.mark(VRP->TopBB);
- }
-
- /// PredicateSimplifier - This class is a simplifier that replaces
- /// one equivalent variable with another. It also tracks what
- /// can't be equal and will solve setcc instructions when possible.
- /// @brief Root of the predicate simplifier optimization.
- class VISIBILITY_HIDDEN PredicateSimplifier : public FunctionPass {
- DomTreeDFS *DTDFS;
- bool modified;
- ValueNumbering *VN;
- InequalityGraph *IG;
- UnreachableBlocks UB;
- ValueRanges *VR;
-
- std::vector<DomTreeDFS::Node *> WorkList;
-
- public:
- static char ID; // Pass identification, replacement for typeid
- PredicateSimplifier() : FunctionPass(&ID) {}
-
- bool runOnFunction(Function &F);
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequiredID(BreakCriticalEdgesID);
- AU.addRequired<DominatorTree>();
- AU.addRequired<TargetData>();
- AU.addPreserved<TargetData>();
- }
-
- private:
- /// Forwards - Adds new properties to VRPSolver and uses them to
- /// simplify instructions. Because new properties sometimes apply to
- /// a transition from one BasicBlock to another, this will use the
- /// PredicateSimplifier::proceedToSuccessor(s) interface to enter the
- /// basic block.
- /// @brief Performs abstract execution of the program.
- class VISIBILITY_HIDDEN Forwards : public InstVisitor<Forwards> {
- friend class InstVisitor<Forwards>;
- PredicateSimplifier *PS;
- DomTreeDFS::Node *DTNode;
-
- public:
- ValueNumbering &VN;
- InequalityGraph &IG;
- UnreachableBlocks &UB;
- ValueRanges &VR;
-
- Forwards(PredicateSimplifier *PS, DomTreeDFS::Node *DTNode)
- : PS(PS), DTNode(DTNode), VN(*PS->VN), IG(*PS->IG), UB(PS->UB),
- VR(*PS->VR) {}
-
- void visitTerminatorInst(TerminatorInst &TI);
- void visitBranchInst(BranchInst &BI);
- void visitSwitchInst(SwitchInst &SI);
-
- void visitAllocaInst(AllocaInst &AI);
- void visitLoadInst(LoadInst &LI);
- void visitStoreInst(StoreInst &SI);
-
- void visitSExtInst(SExtInst &SI);
- void visitZExtInst(ZExtInst &ZI);
-
- void visitBinaryOperator(BinaryOperator &BO);
- void visitICmpInst(ICmpInst &IC);
- };
-
- // Used by terminator instructions to proceed from the current basic
- // block to the next. Verifies that "current" dominates "next",
- // then calls visitBasicBlock.
- void proceedToSuccessors(DomTreeDFS::Node *Current) {
- for (DomTreeDFS::Node::iterator I = Current->begin(),
- E = Current->end(); I != E; ++I) {
- WorkList.push_back(*I);
- }
- }
-
- void proceedToSuccessor(DomTreeDFS::Node *Next) {
- WorkList.push_back(Next);
- }
-
- // Visits each instruction in the basic block.
- void visitBasicBlock(DomTreeDFS::Node *Node) {
- BasicBlock *BB = Node->getBlock();
- DOUT << "Entering Basic Block: " << BB->getName()
- << " (" << Node->getDFSNumIn() << ")\n";
- for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;) {
- visitInstruction(I++, Node);
- }
- }
-
- // Tries to simplify each Instruction and add new properties.
- void visitInstruction(Instruction *I, DomTreeDFS::Node *DT) {
- DOUT << "Considering instruction " << *I << "\n";
- DEBUG(VN->dump());
- DEBUG(IG->dump());
- DEBUG(VR->dump());
-
- // Sometimes instructions are killed in earlier analysis.
- if (isInstructionTriviallyDead(I)) {
- ++NumSimple;
- modified = true;
- if (unsigned n = VN->valueNumber(I, DTDFS->getRootNode()))
- if (VN->value(n) == I) IG->remove(n);
- VN->remove(I);
- I->eraseFromParent();
- return;
- }
-
-#ifndef NDEBUG
- // Try to replace the whole instruction.
- Value *V = VN->canonicalize(I, DT);
- assert(V == I && "Late instruction canonicalization.");
- if (V != I) {
- modified = true;
- ++NumInstruction;
- DOUT << "Removing " << *I << ", replacing with " << *V << "\n";
- if (unsigned n = VN->valueNumber(I, DTDFS->getRootNode()))
- if (VN->value(n) == I) IG->remove(n);
- VN->remove(I);
- I->replaceAllUsesWith(V);
- I->eraseFromParent();
- return;
- }
-
- // Try to substitute operands.
- for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
- Value *Oper = I->getOperand(i);
- Value *V = VN->canonicalize(Oper, DT);
- assert(V == Oper && "Late operand canonicalization.");
- if (V != Oper) {
- modified = true;
- ++NumVarsReplaced;
- DOUT << "Resolving " << *I;
- I->setOperand(i, V);
- DOUT << " into " << *I;
- }
- }
-#endif
-
- std::string name = I->getParent()->getName();
- DOUT << "push (%" << name << ")\n";
- Forwards visit(this, DT);
- visit.visit(*I);
- DOUT << "pop (%" << name << ")\n";
- }
- };
-
- bool PredicateSimplifier::runOnFunction(Function &F) {
- DominatorTree *DT = &getAnalysis<DominatorTree>();
- DTDFS = new DomTreeDFS(DT);
- TargetData *TD = &getAnalysis<TargetData>();
-
- DOUT << "Entering Function: " << F.getName() << "\n";
-
- modified = false;
- DomTreeDFS::Node *Root = DTDFS->getRootNode();
- VN = new ValueNumbering(DTDFS);
- IG = new InequalityGraph(*VN, Root);
- VR = new ValueRanges(*VN, TD);
- WorkList.push_back(Root);
-
- do {
- DomTreeDFS::Node *DTNode = WorkList.back();
- WorkList.pop_back();
- if (!UB.isDead(DTNode->getBlock())) visitBasicBlock(DTNode);
- } while (!WorkList.empty());
-
- delete DTDFS;
- delete VR;
- delete IG;
- delete VN;
-
- modified |= UB.kill();
-
- return modified;
- }
-
- void PredicateSimplifier::Forwards::visitTerminatorInst(TerminatorInst &TI) {
- PS->proceedToSuccessors(DTNode);
- }
-
- void PredicateSimplifier::Forwards::visitBranchInst(BranchInst &BI) {
- if (BI.isUnconditional()) {
- PS->proceedToSuccessors(DTNode);
- return;
- }
-
- Value *Condition = BI.getCondition();
- BasicBlock *TrueDest = BI.getSuccessor(0);
- BasicBlock *FalseDest = BI.getSuccessor(1);
-
- if (isa<Constant>(Condition) || TrueDest == FalseDest) {
- PS->proceedToSuccessors(DTNode);
- return;
- }
-
- for (DomTreeDFS::Node::iterator I = DTNode->begin(), E = DTNode->end();
- I != E; ++I) {
- BasicBlock *Dest = (*I)->getBlock();
- DOUT << "Branch thinking about %" << Dest->getName()
- << "(" << PS->DTDFS->getNodeForBlock(Dest)->getDFSNumIn() << ")\n";
-
- if (Dest == TrueDest) {
- DOUT << "(" << DTNode->getBlock()->getName() << ") true set:\n";
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, Dest);
- VRP.add(ConstantInt::getTrue(), Condition, ICmpInst::ICMP_EQ);
- VRP.solve();
- DEBUG(VN.dump());
- DEBUG(IG.dump());
- DEBUG(VR.dump());
- } else if (Dest == FalseDest) {
- DOUT << "(" << DTNode->getBlock()->getName() << ") false set:\n";
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, Dest);
- VRP.add(ConstantInt::getFalse(), Condition, ICmpInst::ICMP_EQ);
- VRP.solve();
- DEBUG(VN.dump());
- DEBUG(IG.dump());
- DEBUG(VR.dump());
- }
-
- PS->proceedToSuccessor(*I);
- }
- }
-
- void PredicateSimplifier::Forwards::visitSwitchInst(SwitchInst &SI) {
- Value *Condition = SI.getCondition();
-
- // Set the EQProperty in each of the cases BBs, and the NEProperties
- // in the default BB.
-
- for (DomTreeDFS::Node::iterator I = DTNode->begin(), E = DTNode->end();
- I != E; ++I) {
- BasicBlock *BB = (*I)->getBlock();
- DOUT << "Switch thinking about BB %" << BB->getName()
- << "(" << PS->DTDFS->getNodeForBlock(BB)->getDFSNumIn() << ")\n";
-
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, BB);
- if (BB == SI.getDefaultDest()) {
- for (unsigned i = 1, e = SI.getNumCases(); i < e; ++i)
- if (SI.getSuccessor(i) != BB)
- VRP.add(Condition, SI.getCaseValue(i), ICmpInst::ICMP_NE);
- VRP.solve();
- } else if (ConstantInt *CI = SI.findCaseDest(BB)) {
- VRP.add(Condition, CI, ICmpInst::ICMP_EQ);
- VRP.solve();
- }
- PS->proceedToSuccessor(*I);
- }
- }
-
- void PredicateSimplifier::Forwards::visitAllocaInst(AllocaInst &AI) {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &AI);
- VRP.add(Constant::getNullValue(AI.getType()), &AI, ICmpInst::ICMP_NE);
- VRP.solve();
- }
-
- void PredicateSimplifier::Forwards::visitLoadInst(LoadInst &LI) {
- Value *Ptr = LI.getPointerOperand();
- // avoid "load i8* null" -> null NE null.
- if (isa<Constant>(Ptr)) return;
-
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &LI);
- VRP.add(Constant::getNullValue(Ptr->getType()), Ptr, ICmpInst::ICMP_NE);
- VRP.solve();
- }
-
- void PredicateSimplifier::Forwards::visitStoreInst(StoreInst &SI) {
- Value *Ptr = SI.getPointerOperand();
- if (isa<Constant>(Ptr)) return;
-
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &SI);
- VRP.add(Constant::getNullValue(Ptr->getType()), Ptr, ICmpInst::ICMP_NE);
- VRP.solve();
- }
-
- void PredicateSimplifier::Forwards::visitSExtInst(SExtInst &SI) {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &SI);
- uint32_t SrcBitWidth = cast<IntegerType>(SI.getSrcTy())->getBitWidth();
- uint32_t DstBitWidth = cast<IntegerType>(SI.getDestTy())->getBitWidth();
- APInt Min(APInt::getHighBitsSet(DstBitWidth, DstBitWidth-SrcBitWidth+1));
- APInt Max(APInt::getLowBitsSet(DstBitWidth, SrcBitWidth-1));
- VRP.add(ConstantInt::get(Min), &SI, ICmpInst::ICMP_SLE);
- VRP.add(ConstantInt::get(Max), &SI, ICmpInst::ICMP_SGE);
- VRP.solve();
- }
-
- void PredicateSimplifier::Forwards::visitZExtInst(ZExtInst &ZI) {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &ZI);
- uint32_t SrcBitWidth = cast<IntegerType>(ZI.getSrcTy())->getBitWidth();
- uint32_t DstBitWidth = cast<IntegerType>(ZI.getDestTy())->getBitWidth();
- APInt Max(APInt::getLowBitsSet(DstBitWidth, SrcBitWidth));
- VRP.add(ConstantInt::get(Max), &ZI, ICmpInst::ICMP_UGE);
- VRP.solve();
- }
-
- void PredicateSimplifier::Forwards::visitBinaryOperator(BinaryOperator &BO) {
- Instruction::BinaryOps ops = BO.getOpcode();
-
- switch (ops) {
- default: break;
- case Instruction::URem:
- case Instruction::SRem:
- case Instruction::UDiv:
- case Instruction::SDiv: {
- Value *Divisor = BO.getOperand(1);
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO);
- VRP.add(Constant::getNullValue(Divisor->getType()), Divisor,
- ICmpInst::ICMP_NE);
- VRP.solve();
- break;
- }
- }
-
- switch (ops) {
- default: break;
- case Instruction::Shl: {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO);
- VRP.add(&BO, BO.getOperand(0), ICmpInst::ICMP_UGE);
- VRP.solve();
- } break;
- case Instruction::AShr: {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO);
- VRP.add(&BO, BO.getOperand(0), ICmpInst::ICMP_SLE);
- VRP.solve();
- } break;
- case Instruction::LShr:
- case Instruction::UDiv: {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO);
- VRP.add(&BO, BO.getOperand(0), ICmpInst::ICMP_ULE);
- VRP.solve();
- } break;
- case Instruction::URem: {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO);
- VRP.add(&BO, BO.getOperand(1), ICmpInst::ICMP_ULE);
- VRP.solve();
- } break;
- case Instruction::And: {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO);
- VRP.add(&BO, BO.getOperand(0), ICmpInst::ICMP_ULE);
- VRP.add(&BO, BO.getOperand(1), ICmpInst::ICMP_ULE);
- VRP.solve();
- } break;
- case Instruction::Or: {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &BO);
- VRP.add(&BO, BO.getOperand(0), ICmpInst::ICMP_UGE);
- VRP.add(&BO, BO.getOperand(1), ICmpInst::ICMP_UGE);
- VRP.solve();
- } break;
- }
- }
-
- void PredicateSimplifier::Forwards::visitICmpInst(ICmpInst &IC) {
- // If possible, squeeze the ICmp predicate into something simpler.
- // Eg., if x = [0, 4) and we're being asked icmp uge %x, 3 then change
- // the predicate to eq.
-
- // XXX: once we do full PHI handling, modifying the instruction in the
- // Forwards visitor will cause missed optimizations.
-
- ICmpInst::Predicate Pred = IC.getPredicate();
-
- switch (Pred) {
- default: break;
- case ICmpInst::ICMP_ULE: Pred = ICmpInst::ICMP_ULT; break;
- case ICmpInst::ICMP_UGE: Pred = ICmpInst::ICMP_UGT; break;
- case ICmpInst::ICMP_SLE: Pred = ICmpInst::ICMP_SLT; break;
- case ICmpInst::ICMP_SGE: Pred = ICmpInst::ICMP_SGT; break;
- }
- if (Pred != IC.getPredicate()) {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &IC);
- if (VRP.isRelatedBy(IC.getOperand(1), IC.getOperand(0),
- ICmpInst::ICMP_NE)) {
- ++NumSnuggle;
- PS->modified = true;
- IC.setPredicate(Pred);
- }
- }
-
- Pred = IC.getPredicate();
-
- if (ConstantInt *Op1 = dyn_cast<ConstantInt>(IC.getOperand(1))) {
- ConstantInt *NextVal = 0;
- switch (Pred) {
- default: break;
- case ICmpInst::ICMP_SLT:
- case ICmpInst::ICMP_ULT:
- if (Op1->getValue() != 0)
- NextVal = ConstantInt::get(Op1->getValue()-1);
- break;
- case ICmpInst::ICMP_SGT:
- case ICmpInst::ICMP_UGT:
- if (!Op1->getValue().isAllOnesValue())
- NextVal = ConstantInt::get(Op1->getValue()+1);
- break;
- }
-
- if (NextVal) {
- VRPSolver VRP(VN, IG, UB, VR, PS->DTDFS, PS->modified, &IC);
- if (VRP.isRelatedBy(IC.getOperand(0), NextVal,
- ICmpInst::getInversePredicate(Pred))) {
- ICmpInst *NewIC = new ICmpInst(ICmpInst::ICMP_EQ, IC.getOperand(0),
- NextVal, "", &IC);
- NewIC->takeName(&IC);
- IC.replaceAllUsesWith(NewIC);
-
- // XXX: prove this isn't necessary
- if (unsigned n = VN.valueNumber(&IC, PS->DTDFS->getRootNode()))
- if (VN.value(n) == &IC) IG.remove(n);
- VN.remove(&IC);
-
- IC.eraseFromParent();
- ++NumSnuggle;
- PS->modified = true;
- }
- }
- }
- }
-}
-
-char PredicateSimplifier::ID = 0;
-static RegisterPass<PredicateSimplifier>
-X("predsimplify", "Predicate Simplifier");
-
-FunctionPass *llvm::createPredicateSimplifierPass() {
- return new PredicateSimplifier();
-}
diff --git a/lib/Transforms/Utils/CloneTrace.cpp b/lib/Transforms/Utils/CloneTrace.cpp
deleted file mode 100644
index 0711139..0000000
--- a/lib/Transforms/Utils/CloneTrace.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-//===- CloneTrace.cpp - Clone a trace -------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements the CloneTrace interface, which is used when writing
-// runtime optimizations. It takes a vector of basic blocks clones the basic
-// blocks, removes internal phi nodes, adds it to the same function as the
-// original (although there is no jump to it) and returns the new vector of
-// basic blocks.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Analysis/Trace.h"
-#include "llvm/Transforms/Utils/Cloning.h"
-#include "llvm/Instructions.h"
-#include "llvm/Function.h"
-#include "llvm/Transforms/Utils/ValueMapper.h"
-using namespace llvm;
-
-//Clones the trace (a vector of basic blocks)
-std::vector<BasicBlock *>
-llvm::CloneTrace(const std::vector<BasicBlock*> &origTrace) {
- std::vector<BasicBlock *> clonedTrace;
- DenseMap<const Value*, Value*> ValueMap;
-
- //First, loop over all the Basic Blocks in the trace and copy
- //them using CloneBasicBlock. Also fix the phi nodes during
- //this loop. To fix the phi nodes, we delete incoming branches
- //that are not in the trace.
- for (std::vector<BasicBlock *>::const_iterator T = origTrace.begin(),
- End = origTrace.end(); T != End; ++T) {
-
- //Clone Basic Block
- BasicBlock *clonedBlock =
- CloneBasicBlock(*T, ValueMap, ".tr", (*T)->getParent());
-
- //Add it to our new trace
- clonedTrace.push_back(clonedBlock);
-
- //Add this new mapping to our Value Map
- ValueMap[*T] = clonedBlock;
-
- //Loop over the phi instructions and delete operands
- //that are from blocks not in the trace
- //only do this if we are NOT the first block
- if (T != origTrace.begin()) {
- for (BasicBlock::iterator I = clonedBlock->begin();
- isa<PHINode>(I); ++I) {
- PHINode *PN = cast<PHINode>(I);
- //get incoming value for the previous BB
- Value *V = PN->getIncomingValueForBlock(*(T-1));
- assert(V && "No incoming value from a BasicBlock in our trace!");
-
- //remap our phi node to point to incoming value
- ValueMap[*&I] = V;
-
- //remove phi node
- clonedBlock->getInstList().erase(PN);
- }
- }
- }
-
- //Second loop to do the remapping
- for (std::vector<BasicBlock *>::const_iterator BB = clonedTrace.begin(),
- BE = clonedTrace.end(); BB != BE; ++BB) {
- for (BasicBlock::iterator I = (*BB)->begin(); I != (*BB)->end(); ++I) {
- //Loop over all the operands of the instruction
- for (unsigned op=0, E = I->getNumOperands(); op != E; ++op) {
- const Value *Op = I->getOperand(op);
-
- //Get it out of the value map
- Value *V = ValueMap[Op];
-
- //If not in the value map, then its outside our trace so ignore
- if (V != 0)
- I->setOperand(op,V);
- }
- }
- }
-
- //return new vector of basic blocks
- return clonedTrace;
-}
-
-/// CloneTraceInto - Clone T into NewFunc. Original<->clone mapping is
-/// saved in ValueMap.
-///
-void llvm::CloneTraceInto(Function *NewFunc, Trace &T,
- DenseMap<const Value*, Value*> &ValueMap,
- const char *NameSuffix) {
- assert(NameSuffix && "NameSuffix cannot be null!");
-
- // Loop over all of the basic blocks in the trace, cloning them as
- // appropriate.
- //
- for (Trace::const_iterator BI = T.begin(), BE = T.end(); BI != BE; ++BI) {
- const BasicBlock *BB = *BI;
-
- // Create a new basic block and copy instructions into it!
- BasicBlock *CBB = CloneBasicBlock(BB, ValueMap, NameSuffix, NewFunc);
- ValueMap[BB] = CBB; // Add basic block mapping.
- }
-
- // Loop over all of the instructions in the new function, fixing up operand
- // references as we go. This uses ValueMap to do all the hard work.
- //
- for (Function::iterator BB =
- cast<BasicBlock>(ValueMap[T.getEntryBasicBlock()]),
- BE = NewFunc->end(); BB != BE; ++BB)
- // Loop over all instructions, fixing each one as we find it...
- for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II)
- RemapInstruction(II, ValueMap);
-}
-
diff --git a/lib/Transforms/Utils/InlineCost.cpp b/lib/Transforms/Utils/InlineCost.cpp
deleted file mode 100644
index 87aff01..0000000
--- a/lib/Transforms/Utils/InlineCost.cpp
+++ /dev/null
@@ -1,315 +0,0 @@
-//===- InlineCost.cpp - Cost analysis for inliner -------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements inline cost analysis.
-//
-//===----------------------------------------------------------------------===//
-
-
-#include "llvm/Transforms/Utils/InlineCost.h"
-#include "llvm/Support/CallSite.h"
-#include "llvm/CallingConv.h"
-#include "llvm/IntrinsicInst.h"
-
-using namespace llvm;
-
-// CountCodeReductionForConstant - Figure out an approximation for how many
-// instructions will be constant folded if the specified value is constant.
-//
-unsigned InlineCostAnalyzer::FunctionInfo::
- CountCodeReductionForConstant(Value *V) {
- unsigned Reduction = 0;
- for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI)
- if (isa<BranchInst>(*UI))
- Reduction += 40; // Eliminating a conditional branch is a big win
- else if (SwitchInst *SI = dyn_cast<SwitchInst>(*UI))
- // Eliminating a switch is a big win, proportional to the number of edges
- // deleted.
- Reduction += (SI->getNumSuccessors()-1) * 40;
- else if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
- // Turning an indirect call into a direct call is a BIG win
- Reduction += CI->getCalledValue() == V ? 500 : 0;
- } else if (InvokeInst *II = dyn_cast<InvokeInst>(*UI)) {
- // Turning an indirect call into a direct call is a BIG win
- Reduction += II->getCalledValue() == V ? 500 : 0;
- } else {
- // Figure out if this instruction will be removed due to simple constant
- // propagation.
- Instruction &Inst = cast<Instruction>(**UI);
- bool AllOperandsConstant = true;
- for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i)
- if (!isa<Constant>(Inst.getOperand(i)) && Inst.getOperand(i) != V) {
- AllOperandsConstant = false;
- break;
- }
-
- if (AllOperandsConstant) {
- // We will get to remove this instruction...
- Reduction += 7;
-
- // And any other instructions that use it which become constants
- // themselves.
- Reduction += CountCodeReductionForConstant(&Inst);
- }
- }
-
- return Reduction;
-}
-
-// CountCodeReductionForAlloca - Figure out an approximation of how much smaller
-// the function will be if it is inlined into a context where an argument
-// becomes an alloca.
-//
-unsigned InlineCostAnalyzer::FunctionInfo::
- CountCodeReductionForAlloca(Value *V) {
- if (!isa<PointerType>(V->getType())) return 0; // Not a pointer
- unsigned Reduction = 0;
- for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
- Instruction *I = cast<Instruction>(*UI);
- if (isa<LoadInst>(I) || isa<StoreInst>(I))
- Reduction += 10;
- else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
- // If the GEP has variable indices, we won't be able to do much with it.
- if (!GEP->hasAllConstantIndices())
- Reduction += CountCodeReductionForAlloca(GEP)+15;
- } else {
- // If there is some other strange instruction, we're not going to be able
- // to do much if we inline this.
- return 0;
- }
- }
-
- return Reduction;
-}
-
-/// analyzeFunction - Fill in the current structure with information gleaned
-/// from the specified function.
-void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) {
- unsigned NumInsts = 0, NumBlocks = 0, NumVectorInsts = 0;
-
- // Look at the size of the callee. Each basic block counts as 20 units, and
- // each instruction counts as 5.
- for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
- for (BasicBlock::const_iterator II = BB->begin(), E = BB->end();
- II != E; ++II) {
- if (isa<PHINode>(II)) continue; // PHI nodes don't count.
-
- // Special handling for calls.
- if (isa<CallInst>(II) || isa<InvokeInst>(II)) {
- if (isa<DbgInfoIntrinsic>(II))
- continue; // Debug intrinsics don't count as size.
-
- CallSite CS = CallSite::get(const_cast<Instruction*>(&*II));
-
- // If this function contains a call to setjmp or _setjmp, never inline
- // it. This is a hack because we depend on the user marking their local
- // variables as volatile if they are live across a setjmp call, and they
- // probably won't do this in callers.
- if (Function *F = CS.getCalledFunction())
- if (F->isDeclaration() &&
- (F->isName("setjmp") || F->isName("_setjmp"))) {
- NeverInline = true;
- return;
- }
-
- // Calls often compile into many machine instructions. Bump up their
- // cost to reflect this.
- if (!isa<IntrinsicInst>(II))
- NumInsts += 5;
- }
-
- if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
- if (!AI->isStaticAlloca())
- this->usesDynamicAlloca = true;
- }
-
- if (isa<ExtractElementInst>(II) || isa<VectorType>(II->getType()))
- ++NumVectorInsts;
-
- // Noop casts, including ptr <-> int, don't count.
- if (const CastInst *CI = dyn_cast<CastInst>(II)) {
- if (CI->isLosslessCast() || isa<IntToPtrInst>(CI) ||
- isa<PtrToIntInst>(CI))
- continue;
- } else if (const GetElementPtrInst *GEPI =
- dyn_cast<GetElementPtrInst>(II)) {
- // If a GEP has all constant indices, it will probably be folded with
- // a load/store.
- if (GEPI->hasAllConstantIndices())
- continue;
- }
-
- ++NumInsts;
- }
-
- ++NumBlocks;
- }
-
- this->NumBlocks = NumBlocks;
- this->NumInsts = NumInsts;
- this->NumVectorInsts = NumVectorInsts;
-
- // Check out all of the arguments to the function, figuring out how much
- // code can be eliminated if one of the arguments is a constant.
- for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
- ArgumentWeights.push_back(ArgInfo(CountCodeReductionForConstant(I),
- CountCodeReductionForAlloca(I)));
-}
-
-
-
-// getInlineCost - The heuristic used to determine if we should inline the
-// function call or not.
-//
-InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
- SmallPtrSet<const Function *, 16> &NeverInline) {
- Instruction *TheCall = CS.getInstruction();
- Function *Callee = CS.getCalledFunction();
- Function *Caller = TheCall->getParent()->getParent();
-
- // Don't inline functions which can be redefined at link-time to mean
- // something else.
- if (Callee->mayBeOverridden() ||
- // Don't inline functions marked noinline.
- Callee->hasFnAttr(Attribute::NoInline) || NeverInline.count(Callee))
- return llvm::InlineCost::getNever();
-
- // InlineCost - This value measures how good of an inline candidate this call
- // site is to inline. A lower inline cost make is more likely for the call to
- // be inlined. This value may go negative.
- //
- int InlineCost = 0;
-
- // If there is only one call of the function, and it has internal linkage,
- // make it almost guaranteed to be inlined.
- //
- if ((Callee->hasLocalLinkage() || Callee->hasAvailableExternallyLinkage()) &&
- Callee->hasOneUse())
- InlineCost -= 15000;
-
- // If this function uses the coldcc calling convention, prefer not to inline
- // it.
- if (Callee->getCallingConv() == CallingConv::Cold)
- InlineCost += 2000;
-
- // If the instruction after the call, or if the normal destination of the
- // invoke is an unreachable instruction, the function is noreturn. As such,
- // there is little point in inlining this.
- if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
- if (isa<UnreachableInst>(II->getNormalDest()->begin()))
- InlineCost += 10000;
- } else if (isa<UnreachableInst>(++BasicBlock::iterator(TheCall)))
- InlineCost += 10000;
-
- // Get information about the callee...
- FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];
-
- // If we haven't calculated this information yet, do so now.
- if (CalleeFI.NumBlocks == 0)
- CalleeFI.analyzeFunction(Callee);
-
- // If we should never inline this, return a huge cost.
- if (CalleeFI.NeverInline)
- return InlineCost::getNever();
-
- // FIXME: It would be nice to kill off CalleeFI.NeverInline. Then we
- // could move this up and avoid computing the FunctionInfo for
- // things we are going to just return always inline for. This
- // requires handling setjmp somewhere else, however.
- if (!Callee->isDeclaration() && Callee->hasFnAttr(Attribute::AlwaysInline))
- return InlineCost::getAlways();
-
- if (CalleeFI.usesDynamicAlloca) {
- // Get infomation about the caller...
- FunctionInfo &CallerFI = CachedFunctionInfo[Caller];
-
- // If we haven't calculated this information yet, do so now.
- if (CallerFI.NumBlocks == 0)
- CallerFI.analyzeFunction(Caller);
-
- // Don't inline a callee with dynamic alloca into a caller without them.
- // Functions containing dynamic alloca's are inefficient in various ways;
- // don't create more inefficiency.
- if (!CallerFI.usesDynamicAlloca)
- return InlineCost::getNever();
- }
-
- // Add to the inline quality for properties that make the call valuable to
- // inline. This includes factors that indicate that the result of inlining
- // the function will be optimizable. Currently this just looks at arguments
- // passed into the function.
- //
- unsigned ArgNo = 0;
- for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
- I != E; ++I, ++ArgNo) {
- // Each argument passed in has a cost at both the caller and the callee
- // sides. This favors functions that take many arguments over functions
- // that take few arguments.
- InlineCost -= 20;
-
- // If this is a function being passed in, it is very likely that we will be
- // able to turn an indirect function call into a direct function call.
- if (isa<Function>(I))
- InlineCost -= 100;
-
- // If an alloca is passed in, inlining this function is likely to allow
- // significant future optimization possibilities (like scalar promotion, and
- // scalarization), so encourage the inlining of the function.
- //
- else if (isa<AllocaInst>(I)) {
- if (ArgNo < CalleeFI.ArgumentWeights.size())
- InlineCost -= CalleeFI.ArgumentWeights[ArgNo].AllocaWeight;
-
- // If this is a constant being passed into the function, use the argument
- // weights calculated for the callee to determine how much will be folded
- // away with this information.
- } else if (isa<Constant>(I)) {
- if (ArgNo < CalleeFI.ArgumentWeights.size())
- InlineCost -= CalleeFI.ArgumentWeights[ArgNo].ConstantWeight;
- }
- }
-
- // Now that we have considered all of the factors that make the call site more
- // likely to be inlined, look at factors that make us not want to inline it.
-
- // Don't inline into something too big, which would make it bigger.
- //
- InlineCost += Caller->size()/15;
-
- // Look at the size of the callee. Each instruction counts as 5.
- InlineCost += CalleeFI.NumInsts*5;
-
- return llvm::InlineCost::get(InlineCost);
-}
-
-// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a
-// higher threshold to determine if the function call should be inlined.
-float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) {
- Function *Callee = CS.getCalledFunction();
-
- // Get information about the callee...
- FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];
-
- // If we haven't calculated this information yet, do so now.
- if (CalleeFI.NumBlocks == 0)
- CalleeFI.analyzeFunction(Callee);
-
- float Factor = 1.0f;
- // Single BB functions are often written to be inlined.
- if (CalleeFI.NumBlocks == 1)
- Factor += 0.5f;
-
- // Be more aggressive if the function contains a good chunk (if it mades up
- // at least 10% of the instructions) of vector instructions.
- if (CalleeFI.NumVectorInsts > CalleeFI.NumInsts/2)
- Factor += 2.0f;
- else if (CalleeFI.NumVectorInsts > CalleeFI.NumInsts/10)
- Factor += 1.5f;
- return Factor;
-}
OpenPOWER on IntegriCloud