From 1adacceba9c9ee0f16e54388e56c9a249b296f75 Mon Sep 17 00:00:00 2001 From: rdivacky Date: Thu, 15 Oct 2009 16:26:17 +0000 Subject: Delete all stale files. --- lib/Analysis/LoopVR.cpp | 291 --- lib/CodeGen/LazyLiveness.cpp | 167 -- lib/CodeGen/PBQP.cpp | 1395 ---------- lib/CodeGen/PBQP.h | 284 -- lib/CodeGen/RegAllocBigBlock.cpp | 892 ------- lib/CodeGen/RegAllocSimple.cpp | 257 -- .../SelectionDAG/ScheduleDAGSDNodesEmit.cpp | 671 ----- lib/Debugger/CMakeLists.txt | 10 - lib/Debugger/Debugger.cpp | 231 -- lib/Debugger/Makefile | 16 - lib/Debugger/ProgramInfo.cpp | 375 --- lib/Debugger/README.txt | 7 - lib/Debugger/RuntimeInfo.cpp | 69 - lib/Debugger/SourceFile.cpp | 82 - lib/Debugger/SourceLanguage-CFamily.cpp | 28 - lib/Debugger/SourceLanguage-CPlusPlus.cpp | 27 - lib/Debugger/SourceLanguage-Unknown.cpp | 138 - lib/Debugger/SourceLanguage.cpp | 54 - lib/Support/Annotation.cpp | 130 - lib/Support/Streams.cpp | 30 - lib/System/LICENSE.TXT | 6 - lib/Target/ARM/ARMTargetAsmInfo.cpp | 254 -- lib/Target/ARM/ARMTargetAsmInfo.h | 63 - lib/Target/Alpha/AlphaTargetAsmInfo.cpp | 31 - lib/Target/Alpha/AlphaTargetAsmInfo.h | 32 - lib/Target/CellSPU/SPUTargetAsmInfo.cpp | 73 - lib/Target/CellSPU/SPUTargetAsmInfo.h | 51 - lib/Target/DarwinTargetAsmInfo.cpp | 216 -- lib/Target/ELFTargetAsmInfo.cpp | 227 -- lib/Target/IA64/AsmPrinter/CMakeLists.txt | 9 - lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp | 389 --- lib/Target/IA64/AsmPrinter/Makefile | 17 - lib/Target/IA64/CMakeLists.txt | 22 - lib/Target/IA64/IA64.h | 57 - lib/Target/IA64/IA64.td | 39 - lib/Target/IA64/IA64Bundling.cpp | 118 - lib/Target/IA64/IA64ISelDAGToDAG.cpp | 575 ----- lib/Target/IA64/IA64ISelLowering.cpp | 632 ----- lib/Target/IA64/IA64ISelLowering.h | 78 - lib/Target/IA64/IA64InstrBuilder.h | 40 - lib/Target/IA64/IA64InstrFormats.td | 80 - lib/Target/IA64/IA64InstrInfo.cpp | 193 -- lib/Target/IA64/IA64InstrInfo.h | 70 - lib/Target/IA64/IA64InstrInfo.td | 751 ------ lib/Target/IA64/IA64MachineFunctionInfo.h | 34 - lib/Target/IA64/IA64RegisterInfo.cpp | 319 --- lib/Target/IA64/IA64RegisterInfo.h | 63 - lib/Target/IA64/IA64RegisterInfo.td | 509 ---- lib/Target/IA64/IA64Subtarget.cpp | 18 - lib/Target/IA64/IA64Subtarget.h | 28 - lib/Target/IA64/IA64TargetAsmInfo.cpp | 44 - lib/Target/IA64/IA64TargetAsmInfo.h | 33 - lib/Target/IA64/IA64TargetMachine.cpp | 97 - lib/Target/IA64/IA64TargetMachine.h | 75 - lib/Target/IA64/Makefile | 20 - lib/Target/IA64/README | 48 - lib/Target/MSP430/MSP430AsmPrinter.cpp | 262 -- lib/Target/MSP430/MSP430TargetAsmInfo.cpp | 22 - lib/Target/MSP430/MSP430TargetAsmInfo.h | 31 - lib/Target/Mips/MipsTargetAsmInfo.cpp | 98 - lib/Target/Mips/MipsTargetAsmInfo.h | 51 - lib/Target/PIC16/PIC16AsmPrinter.cpp | 442 ---- lib/Target/PIC16/PIC16AsmPrinter.h | 70 - lib/Target/PIC16/PIC16TargetAsmInfo.cpp | 264 -- lib/Target/PIC16/PIC16TargetAsmInfo.h | 83 - lib/Target/PowerPC/PPCTargetAsmInfo.cpp | 121 - lib/Target/PowerPC/PPCTargetAsmInfo.h | 62 - lib/Target/Sparc/SparcTargetAsmInfo.cpp | 50 - lib/Target/Sparc/SparcTargetAsmInfo.h | 33 - lib/Target/TargetAsmInfo.cpp | 456 ---- lib/Target/TargetMachineRegistry.cpp | 78 - lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp | 1108 -------- lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h | 226 -- lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp | 633 ----- lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h | 162 -- lib/Target/X86/X86TargetAsmInfo.cpp | 429 --- lib/Target/X86/X86TargetAsmInfo.h | 75 - lib/Target/XCore/XCoreAsmPrinter.cpp | 438 ---- lib/Target/XCore/XCoreTargetAsmInfo.cpp | 202 -- lib/Target/XCore/XCoreTargetAsmInfo.h | 45 - lib/Transforms/Scalar/GVNPRE.cpp | 1892 -------------- lib/Transforms/Scalar/PredicateSimplifier.cpp | 2721 -------------------- lib/Transforms/Utils/CloneTrace.cpp | 119 - lib/Transforms/Utils/InlineCost.cpp | 315 --- 84 files changed, 20953 deletions(-) delete mode 100644 lib/Analysis/LoopVR.cpp delete mode 100644 lib/CodeGen/LazyLiveness.cpp delete mode 100644 lib/CodeGen/PBQP.cpp delete mode 100644 lib/CodeGen/PBQP.h delete mode 100644 lib/CodeGen/RegAllocBigBlock.cpp delete mode 100644 lib/CodeGen/RegAllocSimple.cpp delete mode 100644 lib/CodeGen/SelectionDAG/ScheduleDAGSDNodesEmit.cpp delete mode 100644 lib/Debugger/CMakeLists.txt delete mode 100644 lib/Debugger/Debugger.cpp delete mode 100644 lib/Debugger/Makefile delete mode 100644 lib/Debugger/ProgramInfo.cpp delete mode 100644 lib/Debugger/README.txt delete mode 100644 lib/Debugger/RuntimeInfo.cpp delete mode 100644 lib/Debugger/SourceFile.cpp delete mode 100644 lib/Debugger/SourceLanguage-CFamily.cpp delete mode 100644 lib/Debugger/SourceLanguage-CPlusPlus.cpp delete mode 100644 lib/Debugger/SourceLanguage-Unknown.cpp delete mode 100644 lib/Debugger/SourceLanguage.cpp delete mode 100644 lib/Support/Annotation.cpp delete mode 100644 lib/Support/Streams.cpp delete mode 100644 lib/System/LICENSE.TXT delete mode 100644 lib/Target/ARM/ARMTargetAsmInfo.cpp delete mode 100644 lib/Target/ARM/ARMTargetAsmInfo.h delete mode 100644 lib/Target/Alpha/AlphaTargetAsmInfo.cpp delete mode 100644 lib/Target/Alpha/AlphaTargetAsmInfo.h delete mode 100644 lib/Target/CellSPU/SPUTargetAsmInfo.cpp delete mode 100644 lib/Target/CellSPU/SPUTargetAsmInfo.h delete mode 100644 lib/Target/DarwinTargetAsmInfo.cpp delete mode 100644 lib/Target/ELFTargetAsmInfo.cpp delete mode 100644 lib/Target/IA64/AsmPrinter/CMakeLists.txt delete mode 100644 lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp delete mode 100644 lib/Target/IA64/AsmPrinter/Makefile delete mode 100644 lib/Target/IA64/CMakeLists.txt delete mode 100644 lib/Target/IA64/IA64.h delete mode 100644 lib/Target/IA64/IA64.td delete mode 100644 lib/Target/IA64/IA64Bundling.cpp delete mode 100644 lib/Target/IA64/IA64ISelDAGToDAG.cpp delete mode 100644 lib/Target/IA64/IA64ISelLowering.cpp delete mode 100644 lib/Target/IA64/IA64ISelLowering.h delete mode 100644 lib/Target/IA64/IA64InstrBuilder.h delete mode 100644 lib/Target/IA64/IA64InstrFormats.td delete mode 100644 lib/Target/IA64/IA64InstrInfo.cpp delete mode 100644 lib/Target/IA64/IA64InstrInfo.h delete mode 100644 lib/Target/IA64/IA64InstrInfo.td delete mode 100644 lib/Target/IA64/IA64MachineFunctionInfo.h delete mode 100644 lib/Target/IA64/IA64RegisterInfo.cpp delete mode 100644 lib/Target/IA64/IA64RegisterInfo.h delete mode 100644 lib/Target/IA64/IA64RegisterInfo.td delete mode 100644 lib/Target/IA64/IA64Subtarget.cpp delete mode 100644 lib/Target/IA64/IA64Subtarget.h delete mode 100644 lib/Target/IA64/IA64TargetAsmInfo.cpp delete mode 100644 lib/Target/IA64/IA64TargetAsmInfo.h delete mode 100644 lib/Target/IA64/IA64TargetMachine.cpp delete mode 100644 lib/Target/IA64/IA64TargetMachine.h delete mode 100644 lib/Target/IA64/Makefile delete mode 100644 lib/Target/IA64/README delete mode 100644 lib/Target/MSP430/MSP430AsmPrinter.cpp delete mode 100644 lib/Target/MSP430/MSP430TargetAsmInfo.cpp delete mode 100644 lib/Target/MSP430/MSP430TargetAsmInfo.h delete mode 100644 lib/Target/Mips/MipsTargetAsmInfo.cpp delete mode 100644 lib/Target/Mips/MipsTargetAsmInfo.h delete mode 100644 lib/Target/PIC16/PIC16AsmPrinter.cpp delete mode 100644 lib/Target/PIC16/PIC16AsmPrinter.h delete mode 100644 lib/Target/PIC16/PIC16TargetAsmInfo.cpp delete mode 100644 lib/Target/PIC16/PIC16TargetAsmInfo.h delete mode 100644 lib/Target/PowerPC/PPCTargetAsmInfo.cpp delete mode 100644 lib/Target/PowerPC/PPCTargetAsmInfo.h delete mode 100644 lib/Target/Sparc/SparcTargetAsmInfo.cpp delete mode 100644 lib/Target/Sparc/SparcTargetAsmInfo.h delete mode 100644 lib/Target/TargetAsmInfo.cpp delete mode 100644 lib/Target/TargetMachineRegistry.cpp delete mode 100644 lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp delete mode 100644 lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h delete mode 100644 lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp delete mode 100644 lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h delete mode 100644 lib/Target/X86/X86TargetAsmInfo.cpp delete mode 100644 lib/Target/X86/X86TargetAsmInfo.h delete mode 100644 lib/Target/XCore/XCoreAsmPrinter.cpp delete mode 100644 lib/Target/XCore/XCoreTargetAsmInfo.cpp delete mode 100644 lib/Target/XCore/XCoreTargetAsmInfo.h delete mode 100644 lib/Transforms/Scalar/GVNPRE.cpp delete mode 100644 lib/Transforms/Scalar/PredicateSimplifier.cpp delete mode 100644 lib/Transforms/Utils/CloneTrace.cpp delete mode 100644 lib/Transforms/Utils/InlineCost.cpp (limited to 'lib') 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 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(T)) - return ConstantRange(cast(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(S)) - return ConstantRange(C->getValue()->getValue()); - - ConstantRange FullSet(cast(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(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(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(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(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(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(S)) { - T = SE.getTruncateOrZeroExtend(T, ZExt->getOperand()->getType()); - ConstantRange X = getRange(ZExt->getOperand(), T, SE); - return X.zeroExtend(cast(ZExt->getType())->getBitWidth()); - } - - if (const SCEVSignExtendExpr *SExt = dyn_cast(S)) { - T = SE.getTruncateOrZeroExtend(T, SExt->getOperand()->getType()); - ConstantRange X = getRange(SExt->getOperand(), T, SE); - return X.signExtend(cast(SExt->getType())->getBitWidth()); - } - - if (const SCEVTruncateExpr *Trunc = dyn_cast(S)) { - T = SE.getTruncateOrZeroExtend(T, Trunc->getOperand()->getType()); - ConstantRange X = getRange(Trunc->getOperand(), T, SE); - if (X.isFullSet()) return FullSet; - return X.truncate(cast(Trunc->getType())->getBitWidth()); - } - - if (const SCEVAddRecExpr *AddRec = dyn_cast(S)) { - const SCEVConstant *Trip = dyn_cast(T); - if (!Trip) return FullSet; - - if (AddRec->isAffine()) { - const SCEV* StartHandle = AddRec->getStart(); - const SCEV* StepHandle = AddRec->getOperand(1); - - const SCEVConstant *Step = dyn_cast(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(StartHandle); - const SCEVConstant *End = dyn_cast(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::const_iterator I = Map.begin(), - E = Map.end(); I != E; ++I) { - OS << *I->first << ": " << *I->second << '\n'; - } -} - -void LoopVR::releaseMemory() { - for (std::map::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(V)) - return ConstantRange(CI->getValue()); - - Instruction *I = dyn_cast(V); - if (!I) - return ConstantRange(cast(V->getType())->getBitWidth(), false); - - LoopInfo &LI = getAnalysis(); - - Loop *L = LI.getLoopFor(I->getParent()); - if (!L || L->isLoopInvariant(I)) - return ConstantRange(cast(V->getType())->getBitWidth(), false); - - ScalarEvolution &SE = getAnalysis(); - - const SCEV* S = SE.getSCEV(I); - if (isa(S) || isa(S)) - return ConstantRange(cast(V->getType())->getBitWidth(), false); - - return ConstantRange(getRange(S, L, SE)); -} - -ConstantRange LoopVR::get(Value *V) { - std::map::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::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::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 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(); - - // Step 0: Compute preorder numbering for all MBBs. - unsigned num = 0; - for (df_iterator 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 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 >::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 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 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(); - - MachineBasicBlock* DefMBB = MRI->def_begin(vreg)->getParent(); - unsigned def = preorder[DefMBB]; - unsigned max_dom = 0; - for (df_iterator 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 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 -#include -#include - -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::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;usolution[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;unum_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;unum_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 num_nodes); - assert (v >= 0 && v 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 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::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 -#include -#include - -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()); - 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()); - 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()); - 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(), 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(), 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 -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 VRegTimes; - - /// VRegReadTable - maps VRegs in a BB to the set of times they are read - /// - DenseMap VRegReadTable; - - /// VRegReadIdx - keeps track of the "current time" in terms of - /// positions in VRegReadTable - DenseMap VRegReadIdx; - - /// StackSlotForVirtReg - Maps virtual regs to the frame index where these - /// values are spilled. - IndexedMap StackSlotForVirtReg; - - /// Virt2PhysRegMap - This map contains entries for each virtual register - /// that is currently available in a physical register. - IndexedMap 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 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 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 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::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 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 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 -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 StackSlotForVirtReg; - - // RegsUsed - Keep track of what registers are currently in use. This is a - // bitset. - std::vector 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 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::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 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 &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(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(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 &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(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 &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::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 &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 &VRBaseMap) { - if (Op.isMachineOpcode()) { - AddRegisterOperand(MI, Op, IIOpNum, II, VRBaseMap); - } else if (ConstantSDNode *C = dyn_cast(Op)) { - MI->addOperand(MachineOperand::CreateImm(C->getZExtValue())); - } else if (ConstantFPSDNode *F = dyn_cast(Op)) { - const ConstantFP *CFP = F->getConstantFPValue(); - MI->addOperand(MachineOperand::CreateFPImm(CFP)); - } else if (RegisterSDNode *R = dyn_cast(Op)) { - MI->addOperand(MachineOperand::CreateReg(R->getReg(), false)); - } else if (GlobalAddressSDNode *TGA = dyn_cast(Op)) { - MI->addOperand(MachineOperand::CreateGA(TGA->getGlobal(), TGA->getOffset(), - TGA->getTargetFlags())); - } else if (BasicBlockSDNode *BBNode = dyn_cast(Op)) { - MI->addOperand(MachineOperand::CreateMBB(BBNode->getBasicBlock())); - } else if (FrameIndexSDNode *FI = dyn_cast(Op)) { - MI->addOperand(MachineOperand::CreateFI(FI->getIndex())); - } else if (JumpTableSDNode *JT = dyn_cast(Op)) { - MI->addOperand(MachineOperand::CreateJTI(JT->getIndex(), - JT->getTargetFlags())); - } else if (ConstantPoolSDNode *CP = dyn_cast(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(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 &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(User->getOperand(1))->getReg(); - if (TargetRegisterInfo::isVirtualRegister(DestReg)) { - VRBase = DestReg; - break; - } - } - } - - if (Opc == TargetInstrInfo::EXTRACT_SUBREG) { - unsigned SubIdx = cast(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(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(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 &VRBaseMap) { - unsigned VReg = getVR(Node->getOperand(0), VRBaseMap); - const TargetRegisterClass *SrcRC = MRI.getRegClass(VReg); - - unsigned DstRCIdx = cast(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 &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(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(SrcVal)) - SrcReg = R->getReg(); - else - SrcReg = getVR(SrcVal, VRBaseMap); - - unsigned DestReg = cast(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(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(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(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(Node->getOperand(i))->getReg(); - MI->addOperand(MachineOperand::CreateReg(Reg, true)); - } - break; - case 6: // Def of earlyclobber register. - for (; NumVals; --NumVals, ++i) { - unsigned Reg = cast(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 VRBaseMap; - DenseMap 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 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 -#include -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 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 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 &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 &Found) { - for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { - if (GlobalVariable *GV = dyn_cast(*I)) - Found.push_back(GV); - else if (Constant *C = dyn_cast(*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(*UI)->getOpcode() == Instruction::PHI) { - // Infinite loops == bad, ignore PHI nodes. - ShouldRecurse = false; - } else if (const CallInst *CI = dyn_cast(*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(CI)) { - unsigned CurLineNo = SPI->getLine(); - unsigned CurColNo = SPI->getColumn(); - const GlobalVariable *CurDesc = 0; - const Value *Op = SPI->getContext(); - - if ((CurDesc = dyn_cast(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(Desc->getInitializer())) - if (CS->getNumOperands() > 4) { - if (ConstantInt *CUI = dyn_cast(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(Desc->getInitializer())) - if (CS->getNumOperands() > 2) { - // Entry #1 is the file descriptor. - if (const GlobalVariable *GV = - dyn_cast(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(*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::iterator - I = SourceFiles.begin(), E = SourceFiles.end(); I != E; ++I) - delete I->second; - for (std::map::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(Desc->getInitializer())) - if (CS->getNumOperands() > 2) - if (ConstantInt *CUI = dyn_cast(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 & -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 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::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(Desc->getInitializer())) - if (CS->getNumOperands() > 0) - if (const GlobalVariable *GV = - dyn_cast(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 & -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 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 -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 -#include -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 FunctionMap; - public: - SLUCache(ProgramInfo &pi); - - typedef std::multimap::const_iterator - fm_iterator; - - std::pair - 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 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 -#include -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 IDMapType; -static volatile sys::cas_flag IDCounter = 0; // Unique ID counter - -// Static member to ensure initialiation on demand. -static ManagedStatic IDMap; -static ManagedStatic > AnnotationsLock; - -// On demand annotation creation support... -typedef Annotation *(*AnnFactory)(AnnotationID, const Annotable *, void *); -typedef std::map > FactMapType; - -static ManagedStatic TheFactMap; -static FactMapType &getFactMap() { - return *TheFactMap; -} - -static void eraseFromFactMap(unsigned ID) { - sys::SmartScopedWriter 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 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 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 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 to each file just to get I/O. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/Streams.h" -#include -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 -#include -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(TM) { - Subtarget = &TM.getSubtarget(); - - 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(TM) { - Subtarget = &TM.getSubtarget(); - - 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 -unsigned ARMTargetAsmInfo::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 -unsigned ARMTargetAsmInfo::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 -unsigned ARMTargetAsmInfo::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 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); 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 - 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 ARMGenericTargetAsmInfo; - - EXTERN_TEMPLATE_INSTANTIATION(class ARMTargetAsmInfo); - - struct ARMDarwinTargetAsmInfo : public ARMTargetAsmInfo { - explicit ARMDarwinTargetAsmInfo(const ARMBaseTargetMachine &TM); - }; - - struct ARMELFTargetAsmInfo : public ARMTargetAsmInfo { - 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(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); 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 - struct SPUTargetAsmInfo : public BaseTAI { - explicit SPUTargetAsmInfo(const SPUTargetMachine &TM): - BaseTAI(TM) { - /* (unused today) - * const SPUSubtarget *Subtarget = &TM.getSubtarget(); */ - - 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 { - 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(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(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(GV))); - case SectionKind::RODataMergeConst: - return (isWeak ? - ConstDataCoalSection: - MergeableConstSection(cast(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(GV)->getInitializer(); - const Type *Ty = cast(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(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(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(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(GV)->getInitializer(); - const Type *Ty = cast(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 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), r1;; we now -// emit movl rX = @gprel(CPIgetOperand(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(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 << ""; 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(C) || isa(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::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::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 -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 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 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(N->getOperand(1))) { - CallOpcode = IA64::BRCALL_IPREL_GA; - CallOperand = CurDAG->getTargetGlobalAddress(GASD->getGlobal(), MVT::i64); - } else if (isa(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 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(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(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(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(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(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(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(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(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(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 &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 -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()->outRegsUsed= - std::max(outRegsUsed, MF.getInfo()->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 Stores; - std::vector Converts; - std::vector 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(Callee)) { - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i64); - } -*/ - - std::vector NodeTys; - std::vector 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 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(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(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 &ArgValues, - DebugLoc dl); - - /// LowerCallTo - This hook lowers an abstract call to a function into an - /// actual call. - virtual std::pair - 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 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 opcode, bits<6> qpReg, dag OOL, dag IOL, string asmstr> : - InstIA64 { - - let Inst{5-0} = qpReg; -} - -class AForm_DAG opcode, bits<6> qpReg, dag OOL, dag IOL, string asmstr, - list pattern> : - InstIA64 { - - let Pattern = pattern; - let Inst{5-0} = qpReg; -} - -let isBranch = 1, isTerminator = 1 in -class BForm opcode, bits<6> x6, bits<3> btype, dag OOL, dag IOL, string asmstr> : - InstIA64 { - - let Inst{32-27} = x6; - let Inst{8-6} = btype; -} - -class MForm opcode, bits<6> x6, dag OOL, dag IOL, string asmstr> : - InstIA64 { - 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 opcode, bits<26> rest, dag OOL, dag IOL, string asmstr> : - InstIA64 { - let Inst{25-0} = rest; -} - -// Pseudo instructions. -class PseudoInstIA64 : InstIA64<0, OOL, IOL, nm> { -} - -class PseudoInstIA64_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 a - // move instruction -} - -unsigned -IA64InstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB, - MachineBasicBlock *FBB, - const SmallVectorImpl &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 &Addr, - const TargetRegisterClass *RC, - SmallVectorImpl &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 &Addr, - const TargetRegisterClass *RC, - SmallVectorImpl &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 &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 &Addr, - const TargetRegisterClass *RC, - SmallVectorImpl &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 &Addr, - const TargetRegisterClass *RC, - SmallVectorImpl &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; -def u6imm : Operand; -def s8imm : Operand { - let PrintMethod = "printS8ImmOperand"; -} -def s14imm : Operand { - let PrintMethod = "printS14ImmOperand"; -} -def s22imm : Operand { - let PrintMethod = "printS22ImmOperand"; -} -def u64imm : Operand { - let PrintMethod = "printU64ImmOperand"; -} -def s64imm : Operand { - let PrintMethod = "printS64ImmOperand"; -} - -let PrintMethod = "printGlobalOperand" in - def globaladdress : Operand; - -// the asmprinter needs to know about calls -let PrintMethod = "printCallOperand" in - def calltarget : Operand; - -/* 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, ' and the adjcallstackdown instruction into 'add SP, - // ' - 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()->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 : Register { - let Namespace = "IA64"; -} - -// GR - One of 128 32-bit general registers -class GR num, string n> : IA64Register { - field bits<7> Num = num; -} - -// FP - One of 128 82-bit floating-point registers -class FP num, string n> : IA64Register { - field bits<7> Num = num; -} - -// PR - One of 64 1-bit predicate registers -class PR num, string n> : IA64Register { - 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()->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()->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 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(&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(); - - 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(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(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_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"<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 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 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 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 IDATASections = PTAI->IDATASections; - for (unsigned i = 0; i < IDATASections.size(); i++) { - O << "\n"; - SwitchToSection(IDATASections[i]->S_); - std::vector 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 BSSSections = PTAI->BSSSections; - for (unsigned i = 0; i < BSSSections.size(); i++) { - O << "\n"; - SwitchToSection(BSSSections[i]->S_); - std::vector 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 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 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 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 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 -#include - -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 (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 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(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 -#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 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 BSSSections; - mutable std::vector IDATASections; - mutable std::vector 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 getBSSSections() const { - return BSSSections; - } - std::vector getIDATASections() const { - return IDATASections; - } - std::vector 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(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(); - if (Subtarget->getDarwinVers() > 9) - return PrivateGlobalPrefix; - else - return ""; -} - -PPCLinuxTargetAsmInfo::PPCLinuxTargetAsmInfo(const PPCTargetMachine &TM) : - PPCTargetAsmInfo(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); 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 - struct PPCTargetAsmInfo : public BaseTAI { - explicit PPCTargetAsmInfo(const PPCTargetMachine &TM): - BaseTAI(TM) { - const PPCSubtarget *Subtarget = &TM.getSubtarget(); - 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 PPCGenericTargetAsmInfo; - - EXTERN_TEMPLATE_INSTANTIATION(class PPCTargetAsmInfo); - - struct PPCDarwinTargetAsmInfo : public PPCTargetAsmInfo { - explicit PPCDarwinTargetAsmInfo(const PPCTargetMachine &TM); - virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason, - bool Global) const; - virtual const char *getEHGlobalPrefix() const; - }; - - struct PPCLinuxTargetAsmInfo : public PPCTargetAsmInfo { - 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 -#include -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(C); - // Check, if initializer is a null-terminated string - if (CVA && CVA->isCString()) - return true; - - // Another possibility: [1 x i8] zeroinitializer - if (isa(C)) { - if (const ArrayType *Ty = dyn_cast(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(GV)) - return SectionKind::Text; - - const GlobalVariable* GVar = dyn_cast(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 -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 > UsableTargets; - for (Registry::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 > UsableTargets; - for (Registry::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 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(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(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(); - - // 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(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(C) || isa(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 &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(); - 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(); - } - AU.addRequired(); - 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 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(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(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(); - - 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 << ""; 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(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 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(TM) { - const X86Subtarget* Subtarget = &TM.getSubtarget(); - 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(); - if (Subtarget->getDarwinVers() > 9) - return PrivateGlobalPrefix; - else - return ""; -} - -X86ELFTargetAsmInfo::X86ELFTargetAsmInfo(const X86TargetMachine &TM): - X86TargetAsmInfo(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().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().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().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 -bool X86TargetAsmInfo::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(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 -bool X86TargetAsmInfo::ExpandInlineAsm(CallInst *CI) const { - InlineAsm *IA = cast(CI->getCalledValue()); - std::vector Constraints = IA->ParseConstraints(); - - std::string AsmStr = IA->getAsmString(); - - // TODO: should remove alternatives from the asmstring: "foo {a|b}" -> "foo a" - std::vector 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 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); 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 - struct X86TargetAsmInfo : public BaseTAI { - explicit X86TargetAsmInfo(const X86TargetMachine &TM): - BaseTAI(TM) { - const X86Subtarget *Subtarget = &TM.getSubtarget(); - - BaseTAI::AsmTransCBE = x86_asm_table; - BaseTAI::AssemblerDialect = Subtarget->getAsmFlavor(); - } - - virtual bool ExpandInlineAsm(CallInst *CI) const; - - private: - bool LowerToBSwap(CallInst *CI) const; - }; - - typedef X86TargetAsmInfo X86GenericTargetAsmInfo; - - EXTERN_TEMPLATE_INSTANTIATION(class X86TargetAsmInfo); - - struct X86DarwinTargetAsmInfo : public X86TargetAsmInfo { - explicit X86DarwinTargetAsmInfo(const X86TargetMachine &TM); - virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason, - bool Global) const; - virtual const char *getEHGlobalPrefix() const; - }; - - struct X86ELFTargetAsmInfo : public X86TargetAsmInfo { - 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 -#include -using namespace llvm; - -STATISTIC(EmittedInsts, "Number of machine instrs printed"); - -static cl::opt 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 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(); - AU.addRequired(); - } - }; -} // 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( - cast(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(); - - 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(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 -#include -#include -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 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 valueNumbering; - DenseMap 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 { - 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::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::iterator VI = valueNumbering.find(V); - if (VI != valueNumbering.end()) - return VI->second; - - - if (BinaryOperator* BO = dyn_cast(V)) { - Expression e = create_expression(BO); - - DenseMap::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(V)) { - Expression e = create_expression(C); - - DenseMap::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(V)) { - Expression e = create_expression(U); - - DenseMap::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(V)) { - Expression e = create_expression(U); - - DenseMap::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(V)) { - Expression e = create_expression(U); - - DenseMap::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(V)) { - Expression e = create_expression(U); - - DenseMap::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(V)) { - Expression e = create_expression(U); - - DenseMap::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(V)) { - Expression e = create_expression(U); - - DenseMap::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::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::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 contents; - BitVector numbers; - public: - ValueNumberedSet() { numbers.resize(1); } - ValueNumberedSet(const ValueNumberedSet& other) { - numbers = other.numbers; - contents = other.contents; - } - - typedef SmallPtrSet::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 createdExpressions; - - DenseMap availableOut; - DenseMap anticipatedIn; - DenseMap generatedPhis; - - // This transformation requires dominator postdominator info - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); - AU.addRequiredID(BreakCriticalEdgesID); - AU.addRequired(); - AU.addRequired(); - } - - // 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& 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& currTemps); - bool buildsets_anticout(BasicBlock* BB, - ValueNumberedSet& anticOut, - SmallPtrSet& visited); - unsigned buildsets_anticin(BasicBlock* BB, - ValueNumberedSet& anticOut, - ValueNumberedSet& currExps, - SmallPtrSet& currTemps, - SmallPtrSet& visited); - void buildsets(Function& F) ; - - void insertion_pre(Value* e, BasicBlock* BB, - DenseMap& avail, - std::map& new_set); - unsigned insertion_mergepoint(SmallVector& workList, - df_iterator& D, - std::map& 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 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(V)) { - Value* newOp1 = 0; - if (isa(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(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(V) || isa(V) || - isa(V)) { - User* U = cast(V); - - Value* newOp1 = 0; - if (isa(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(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(U)) - newVal = BinaryOperator::Create(BO->getOpcode(), - newOp1, newOp2, - BO->getName()+".expr"); - else if (CmpInst* C = dyn_cast(U)) - newVal = CmpInst::Create(C->getOpcode(), - C->getPredicate(), - newOp1, newOp2, - C->getName()+".expr"); - else if (ExtractElementInst* E = dyn_cast(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(V) || isa(V) || - isa(V)) { - User* U = cast(V); - - Value* newOp1 = 0; - if (isa(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(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(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(U)) - newVal = new ShuffleVectorInst(newOp1, newOp2, newOp3, - S->getName() + ".expr"); - else if (InsertElementInst* I = dyn_cast(U)) - newVal = InsertElementInst::Create(newOp1, newOp2, newOp3, - I->getName() + ".expr"); - else if (SelectInst* I = dyn_cast(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(V)) { - Value* newOp1 = 0; - if (isa(U->getPointerOperand())) - newOp1 = phi_translate(U->getPointerOperand(), pred, succ); - else - newOp1 = U->getPointerOperand(); - - if (newOp1 == 0) - return 0; - - bool changed_idx = false; - SmallVector newIdx; - for (GetElementPtrInst::op_iterator I = U->idx_begin(), E = U->idx_end(); - I != E; ++I) - if (isa(*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(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(V)) { - for (PHINode::op_iterator I = p->op_begin(), E = p->op_end(); I != E; ++I) - if (isa(*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 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(v)) { - bool lhsValid = !isa(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(v) || isa(v) || - isa(v)) { - User* U = cast(v); - - bool lhsValid = !isa(U->getOperand(0)); - lhsValid |= set.test(VN.lookup(U->getOperand(0))); - if (lhsValid) - lhsValid = !dependsOnInvoke(U->getOperand(0)); - - bool rhsValid = !isa(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(v) || isa(v) || - isa(v)) { - User* U = cast(v); - - bool lhsValid = !isa(U->getOperand(0)); - lhsValid |= set.test(VN.lookup(U->getOperand(0))); - if (lhsValid) - lhsValid = !dependsOnInvoke(U->getOperand(0)); - - bool rhsValid = !isa(U->getOperand(1)); - rhsValid |= set.test(VN.lookup(U->getOperand(1))); - if (rhsValid) - rhsValid = !dependsOnInvoke(U->getOperand(1)); - - bool thirdValid = !isa(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(v)) { - bool ptrValid = !isa(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(*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& vec) { - SmallPtrSet visited; - SmallVector 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(e)) { - Value* l = find_leader(set, VN.lookup(U->getOperand(0))); - - if (l != 0 && isa(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(e) || isa(e) || - isa(e)) { - User* U = cast(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(l) && - visited.count(l) == 0) - stack.push_back(l); - else if (r != 0 && isa(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(e) || isa(e) || - isa(e)) { - User* U = cast(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(l) && - visited.count(l) == 0) - stack.push_back(l); - else if (r != 0 && isa(r) && - visited.count(r) == 0) - stack.push_back(r); - else if (m != 0 && isa(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(e)) { - Value* p = find_leader(set, VN.lookup(U->getPointerOperand())); - - if (p != 0 && isa(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(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, 8> replace; - SmallVector erase; - - DominatorTree& DT = getAnalysis(); - - for (df_iterator 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(BI) || isa(BI) || - isa(BI) || isa(BI) || - isa(BI) || isa(BI) || - isa(BI) || isa(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(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 rep = replace.back(); - replace.pop_back(); - rep.first->replaceAllUsesWith(rep.second); - changed_function = true; - } - - for (SmallVector::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& currTemps) { - // Handle PHI nodes - if (PHINode* p = dyn_cast(I)) { - unsigned num = VN.lookup_or_add(p); - - currPhis.insert(p); - currPhis.set(num); - - // Handle unary ops - } else if (CastInst* U = dyn_cast(I)) { - Value* leftValue = U->getOperand(0); - - unsigned num = VN.lookup_or_add(U); - - if (isa(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(I) || isa(I) || - isa(I)) { - User* U = cast(I); - Value* leftValue = U->getOperand(0); - Value* rightValue = U->getOperand(1); - - unsigned num = VN.lookup_or_add(U); - - if (isa(leftValue)) - if (!currExps.test(VN.lookup(leftValue))) { - currExps.insert(leftValue); - currExps.set(VN.lookup(leftValue)); - } - - if (isa(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(I) || isa(I) || - isa(I)) { - User* U = cast(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(leftValue)) - if (!currExps.test(VN.lookup(leftValue))) { - currExps.insert(leftValue); - currExps.set(VN.lookup(leftValue)); - } - if (isa(rightValue)) - if (!currExps.test(VN.lookup(rightValue))) { - currExps.insert(rightValue); - currExps.set(VN.lookup(rightValue)); - } - if (isa(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(I)) { - Value* ptrValue = U->getPointerOperand(); - - VN.lookup_or_add(U); - - unsigned num = VN.lookup_or_add(U); - - if (isa(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(*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& 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 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::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& currTemps, - SmallPtrSet& 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::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 generatedExpressions; - DenseMap > generatedTemporaries; - - DominatorTree &DT = getAnalysis(); - - // Phase 1, Part 1: calculate AVAIL_OUT - - // Top-down walk of the dominator tree - for (df_iterator 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& 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 visited; - SmallPtrSet 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 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& avail, - std::map& 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(e2); - - Value* s1 = 0; - if (isa(U->getOperand(0)) || - isa(U->getOperand(0)) || - isa(U->getOperand(0)) || - isa(U->getOperand(0)) || - isa(U->getOperand(0)) || - isa(U->getOperand(0)) || - isa(U->getOperand(0)) || - isa(U->getOperand(0))) - s1 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(0))); - else - s1 = U->getOperand(0); - - Value* s2 = 0; - - if (isa(U) || - isa(U) || - isa(U) || - isa(U) || - isa(U) || - isa(U)) { - if (isa(U->getOperand(1)) || - isa(U->getOperand(1)) || - isa(U->getOperand(1)) || - isa(U->getOperand(1)) || - isa(U->getOperand(1)) || - isa(U->getOperand(1)) || - isa(U->getOperand(1)) || - isa(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(U) || - isa(U) || - isa(U)) { - if (isa(U->getOperand(2)) || - isa(U->getOperand(2)) || - isa(U->getOperand(2)) || - isa(U->getOperand(2)) || - isa(U->getOperand(2)) || - isa(U->getOperand(2)) || - isa(U->getOperand(2)) || - isa(U->getOperand(2))) { - s3 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(2))); - } else { - s3 = U->getOperand(2); - } - } - - // Vararg operators - SmallVector sVarargs; - if (GetElementPtrInst* G = dyn_cast(U)) { - for (GetElementPtrInst::op_iterator OI = G->idx_begin(), - OE = G->idx_end(); OI != OE; ++OI) { - if (isa(*OI) || - isa(*OI) || - isa(*OI) || - isa(*OI) || - isa(*OI) || - isa(*OI) || - isa(*OI) || - isa(*OI)) { - sVarargs.push_back(find_leader(availableOut[*PI], - VN.lookup(*OI))); - } else { - sVarargs.push_back(*OI); - } - } - } - - Value* newVal = 0; - if (BinaryOperator* BO = dyn_cast(U)) - newVal = BinaryOperator::Create(BO->getOpcode(), s1, s2, - BO->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (CmpInst* C = dyn_cast(U)) - newVal = CmpInst::Create(C->getOpcode(), C->getPredicate(), s1, s2, - C->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (ShuffleVectorInst* S = dyn_cast(U)) - newVal = new ShuffleVectorInst(s1, s2, s3, S->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (InsertElementInst* S = dyn_cast(U)) - newVal = InsertElementInst::Create(s1, s2, s3, S->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (ExtractElementInst* S = dyn_cast(U)) - newVal = new ExtractElementInst(s1, s2, S->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (SelectInst* S = dyn_cast(U)) - newVal = SelectInst::Create(s1, s2, s3, S->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (CastInst* C = dyn_cast(U)) - newVal = CastInst::Create(C->getOpcode(), s1, C->getType(), - C->getName()+".gvnpre", - (*PI)->getTerminator()); - else if (GetElementPtrInst* G = dyn_cast(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::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& workList, - df_iterator& D, - std::map& 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(e) || isa(e) || - isa(e) || isa(e) || - isa(e) || isa(e) || isa(e) || - isa(e)) { - if (availableOut[D->getIDom()->getBlock()].test(VN.lookup(e))) - continue; - - DenseMap 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::iterator av = avail.find(*PI); - if (av != avail.end()) - avail.erase(av); - avail.insert(std::make_pair(*PI, e2)); - all_same = false; - } else { - DenseMap::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(); - - std::map new_sets; - bool new_stuff = true; - while (new_stuff) { - new_stuff = false; - for (df_iterator 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 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 -#include -#include -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::iterator iterator; - typedef std::vector::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 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 > 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 &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 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(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(I1)) return false; - if (isa(I2)) return true; - if ( isa(I1) && !isa(I2)) return true; - if (!isa(I1) && isa(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 > S; - unsigned n = 0; - - Entry->DFSin = ++n; - S.push(std::make_pair(Entry, Entry->begin())); - - while (!S.empty()) { - std::pair &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 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(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 VNMapType; - VNMapType VNMap; - - /// The canonical choice for value number at index. - std::vector 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(V1)) - return !isa(V2); - else if (isa(V2)) - return false; - else if (isa(V1)) - return !isa(V2); - else if (isa(V2)) - return false; - - Instruction *I1 = dyn_cast(V1); - Instruction *I2 = dyn_cast(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(V) || isa(V) || isa(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(V) || isa(V) || isa(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(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 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::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(V) && isa(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 RelationsType; - RelationsType Relations; - - // TODO: can this idea improve performance? - //friend class std::vector; - //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", "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(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(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 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(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(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 > - RangeListType; - RangeListType RangeList; - - static bool swo(const std::pair &LHS, - const std::pair &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 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(V)) - return ConstantRange(C->getValue()); - else if (isa(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(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 DeadBlocks; - - public: - /// mark - mark a block as dead - void mark(BasicBlock *BB) { - std::vector::iterator E = DeadBlocks.end(); - std::vector::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::iterator E = DeadBlocks.end(); - std::vector::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::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 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(TopInst)) return false; - if (isa(I)) return true; - if ( isa(TopInst) && !isa(I)) return true; - if (!isa(TopInst) && isa(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(V1) && isa(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(V2) && "Tried to remove a constant."); - - SetVector 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::iterator DontRemove = Remove.end(); - for (SetVector::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(R); - if (I2 && below(I2)) { - std::vector ToNotify; - for (Value::use_iterator UI = I2->use_begin(), UE = I2->use_end(); - UI != UE;) { - Use &TheUse = UI.getUse(); - ++UI; - Instruction *I = cast(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::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(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(V1)) { - if (Remove.empty()) { - VR.mergeInto(&V2, 1, VN.getOrInsertVN(V1, Top), Top, this); - } else { - std::vector RemoveVals; - RemoveVals.reserve(Remove.size()); - - for (SetVector::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::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::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(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(TheUse.getUser())) { - if (aboveOrBelow(I)) - opsToDef(I); - } - } - } - } - - // re-opsToDef all dominated users of V1. - if (Instruction *I = dyn_cast(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(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(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(V1)) - if (Constant *C2 = dyn_cast(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(V2)) || - (n2 && !n1 && isa(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(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(LHS)) std::swap(LHS, RHS); - - if (ConstantInt *CI = dyn_cast(Canonical)) { - if (ConstantInt *Arg = dyn_cast(LHS)) { - add(RHS, ConstantInt::get(CI->getValue() ^ Arg->getValue()), - ICmpInst::ICMP_EQ, NewContext); - } - } - if (Canonical == LHS) { - if (isa(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(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(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(I)) { - for (GetElementPtrInst::op_iterator OI = GEPI->idx_begin(), - OE = GEPI->idx_end(); OI != OE; ++OI) { - ConstantInt *Op = dyn_cast(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(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(I)) { - Value *Op0 = VN.canonicalize(BO->getOperand(0), Top); - Value *Op1 = VN.canonicalize(BO->getOperand(1), Top); - - if (ConstantInt *CI0 = dyn_cast(Op0)) - if (ConstantInt *CI1 = dyn_cast(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(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(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(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(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(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(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(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(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(I)) { - for (GetElementPtrInst::op_iterator OI = GEPI->idx_begin(), - OE = GEPI->idx_end(); OI != OE; ++OI) { - ConstantInt *Op = dyn_cast(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(O.LHS)) { - if (Constant *CI_R = dyn_cast(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(O.RHS) && !isa(O.LHS)) || - LV == NE) - IG.addInequality(n1, n2, Top, LV); - - if (Instruction *I1 = dyn_cast(O.LHS)) { - if (aboveOrBelow(I1)) - defToOps(I1); - } - if (isa(O.LHS) || isa(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(TheUse.getUser()); - if (aboveOrBelow(I)) - opsToDef(I); - } - } - if (Instruction *I2 = dyn_cast(O.RHS)) { - if (aboveOrBelow(I2)) - defToOps(I2); - } - if (isa(O.RHS) || isa(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(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 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(); - AU.addRequired(); - AU.addPreserved(); - } - - 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 { - friend class InstVisitor; - 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(); - DTDFS = new DomTreeDFS(DT); - TargetData *TD = &getAnalysis(); - - 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(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(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(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(SI.getSrcTy())->getBitWidth(); - uint32_t DstBitWidth = cast(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(ZI.getSrcTy())->getBitWidth(); - uint32_t DstBitWidth = cast(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(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 -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 -llvm::CloneTrace(const std::vector &origTrace) { - std::vector clonedTrace; - DenseMap 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::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(I); ++I) { - PHINode *PN = cast(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::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 &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(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(*UI)) - Reduction += 40; // Eliminating a conditional branch is a big win - else if (SwitchInst *SI = dyn_cast(*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(*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(*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(**UI); - bool AllOperandsConstant = true; - for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) - if (!isa(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(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(*UI); - if (isa(I) || isa(I)) - Reduction += 10; - else if (GetElementPtrInst *GEP = dyn_cast(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(II)) continue; // PHI nodes don't count. - - // Special handling for calls. - if (isa(II) || isa(II)) { - if (isa(II)) - continue; // Debug intrinsics don't count as size. - - CallSite CS = CallSite::get(const_cast(&*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(II)) - NumInsts += 5; - } - - if (const AllocaInst *AI = dyn_cast(II)) { - if (!AI->isStaticAlloca()) - this->usesDynamicAlloca = true; - } - - if (isa(II) || isa(II->getType())) - ++NumVectorInsts; - - // Noop casts, including ptr <-> int, don't count. - if (const CastInst *CI = dyn_cast(II)) { - if (CI->isLosslessCast() || isa(CI) || - isa(CI)) - continue; - } else if (const GetElementPtrInst *GEPI = - dyn_cast(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 &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(TheCall)) { - if (isa(II->getNormalDest()->begin())) - InlineCost += 10000; - } else if (isa(++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(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(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(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; -} -- cgit v1.1