mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-30 21:29:28 +00:00
- Some clients which used DOUT have moved to DEBUG. We are deprecating the "magic" DOUT behavior which avoided calling printing functions when the statement was disabled. In addition to being unnecessary magic, it had the downside of leaving code in -Asserts builds, and of hiding potentially unnecessary computations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77019 91177308-0d34-0410-b5e6-96231b3b80d8
1357 lines
51 KiB
C++
1357 lines
51 KiB
C++
//===-- SelectionDAGISel.cpp - Implement the SelectionDAGISel 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 SelectionDAGISel class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "isel"
|
|
#include "ScheduleDAGSDNodes.h"
|
|
#include "SelectionDAGBuild.h"
|
|
#include "llvm/CodeGen/SelectionDAGISel.h"
|
|
#include "llvm/Analysis/AliasAnalysis.h"
|
|
#include "llvm/Constants.h"
|
|
#include "llvm/CallingConv.h"
|
|
#include "llvm/DerivedTypes.h"
|
|
#include "llvm/Function.h"
|
|
#include "llvm/GlobalVariable.h"
|
|
#include "llvm/InlineAsm.h"
|
|
#include "llvm/Instructions.h"
|
|
#include "llvm/Intrinsics.h"
|
|
#include "llvm/IntrinsicInst.h"
|
|
#include "llvm/CodeGen/FastISel.h"
|
|
#include "llvm/CodeGen/GCStrategy.h"
|
|
#include "llvm/CodeGen/GCMetadata.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
|
|
#include "llvm/CodeGen/SchedulerRegistry.h"
|
|
#include "llvm/CodeGen/SelectionDAG.h"
|
|
#include "llvm/CodeGen/DwarfWriter.h"
|
|
#include "llvm/Target/TargetRegisterInfo.h"
|
|
#include "llvm/Target/TargetData.h"
|
|
#include "llvm/Target/TargetFrameInfo.h"
|
|
#include "llvm/Target/TargetInstrInfo.h"
|
|
#include "llvm/Target/TargetLowering.h"
|
|
#include "llvm/Target/TargetMachine.h"
|
|
#include "llvm/Target/TargetOptions.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/MathExtras.h"
|
|
#include "llvm/Support/Timer.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <algorithm>
|
|
using namespace llvm;
|
|
|
|
static cl::opt<bool>
|
|
DisableLegalizeTypes("disable-legalize-types", cl::Hidden);
|
|
static cl::opt<bool>
|
|
EnableFastISelVerbose("fast-isel-verbose", cl::Hidden,
|
|
cl::desc("Enable verbose messages in the \"fast\" "
|
|
"instruction selector"));
|
|
static cl::opt<bool>
|
|
EnableFastISelAbort("fast-isel-abort", cl::Hidden,
|
|
cl::desc("Enable abort calls when \"fast\" instruction fails"));
|
|
static cl::opt<bool>
|
|
SchedLiveInCopies("schedule-livein-copies",
|
|
cl::desc("Schedule copies of livein registers"),
|
|
cl::init(false));
|
|
|
|
#ifndef NDEBUG
|
|
static cl::opt<bool>
|
|
ViewDAGCombine1("view-dag-combine1-dags", cl::Hidden,
|
|
cl::desc("Pop up a window to show dags before the first "
|
|
"dag combine pass"));
|
|
static cl::opt<bool>
|
|
ViewLegalizeTypesDAGs("view-legalize-types-dags", cl::Hidden,
|
|
cl::desc("Pop up a window to show dags before legalize types"));
|
|
static cl::opt<bool>
|
|
ViewLegalizeDAGs("view-legalize-dags", cl::Hidden,
|
|
cl::desc("Pop up a window to show dags before legalize"));
|
|
static cl::opt<bool>
|
|
ViewDAGCombine2("view-dag-combine2-dags", cl::Hidden,
|
|
cl::desc("Pop up a window to show dags before the second "
|
|
"dag combine pass"));
|
|
static cl::opt<bool>
|
|
ViewDAGCombineLT("view-dag-combine-lt-dags", cl::Hidden,
|
|
cl::desc("Pop up a window to show dags before the post legalize types"
|
|
" dag combine pass"));
|
|
static cl::opt<bool>
|
|
ViewISelDAGs("view-isel-dags", cl::Hidden,
|
|
cl::desc("Pop up a window to show isel dags as they are selected"));
|
|
static cl::opt<bool>
|
|
ViewSchedDAGs("view-sched-dags", cl::Hidden,
|
|
cl::desc("Pop up a window to show sched dags as they are processed"));
|
|
static cl::opt<bool>
|
|
ViewSUnitDAGs("view-sunit-dags", cl::Hidden,
|
|
cl::desc("Pop up a window to show SUnit dags after they are processed"));
|
|
#else
|
|
static const bool ViewDAGCombine1 = false,
|
|
ViewLegalizeTypesDAGs = false, ViewLegalizeDAGs = false,
|
|
ViewDAGCombine2 = false,
|
|
ViewDAGCombineLT = false,
|
|
ViewISelDAGs = false, ViewSchedDAGs = false,
|
|
ViewSUnitDAGs = false;
|
|
#endif
|
|
|
|
//===---------------------------------------------------------------------===//
|
|
///
|
|
/// RegisterScheduler class - Track the registration of instruction schedulers.
|
|
///
|
|
//===---------------------------------------------------------------------===//
|
|
MachinePassRegistry RegisterScheduler::Registry;
|
|
|
|
//===---------------------------------------------------------------------===//
|
|
///
|
|
/// ISHeuristic command line option for instruction schedulers.
|
|
///
|
|
//===---------------------------------------------------------------------===//
|
|
static cl::opt<RegisterScheduler::FunctionPassCtor, false,
|
|
RegisterPassParser<RegisterScheduler> >
|
|
ISHeuristic("pre-RA-sched",
|
|
cl::init(&createDefaultScheduler),
|
|
cl::desc("Instruction schedulers available (before register"
|
|
" allocation):"));
|
|
|
|
static RegisterScheduler
|
|
defaultListDAGScheduler("default", "Best scheduler for the target",
|
|
createDefaultScheduler);
|
|
|
|
namespace llvm {
|
|
//===--------------------------------------------------------------------===//
|
|
/// createDefaultScheduler - This creates an instruction scheduler appropriate
|
|
/// for the target.
|
|
ScheduleDAGSDNodes* createDefaultScheduler(SelectionDAGISel *IS,
|
|
CodeGenOpt::Level OptLevel) {
|
|
const TargetLowering &TLI = IS->getTargetLowering();
|
|
|
|
if (OptLevel == CodeGenOpt::None)
|
|
return createFastDAGScheduler(IS, OptLevel);
|
|
if (TLI.getSchedulingPreference() == TargetLowering::SchedulingForLatency)
|
|
return createTDListDAGScheduler(IS, OptLevel);
|
|
assert(TLI.getSchedulingPreference() ==
|
|
TargetLowering::SchedulingForRegPressure && "Unknown sched type!");
|
|
return createBURRListDAGScheduler(IS, OptLevel);
|
|
}
|
|
}
|
|
|
|
// EmitInstrWithCustomInserter - This method should be implemented by targets
|
|
// that mark instructions with the 'usesCustomDAGSchedInserter' flag. These
|
|
// instructions are special in various ways, which require special support to
|
|
// insert. The specified MachineInstr is created but not inserted into any
|
|
// basic blocks, and the scheduler passes ownership of it to this method.
|
|
MachineBasicBlock *TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
|
MachineBasicBlock *MBB) const {
|
|
#ifndef NDEBUG
|
|
cerr << "If a target marks an instruction with "
|
|
"'usesCustomDAGSchedInserter', it must implement "
|
|
"TargetLowering::EmitInstrWithCustomInserter!";
|
|
#endif
|
|
llvm_unreachable(0);
|
|
return 0;
|
|
}
|
|
|
|
/// EmitLiveInCopy - Emit a copy for a live in physical register. If the
|
|
/// physical register has only a single copy use, then coalesced the copy
|
|
/// if possible.
|
|
static void EmitLiveInCopy(MachineBasicBlock *MBB,
|
|
MachineBasicBlock::iterator &InsertPos,
|
|
unsigned VirtReg, unsigned PhysReg,
|
|
const TargetRegisterClass *RC,
|
|
DenseMap<MachineInstr*, unsigned> &CopyRegMap,
|
|
const MachineRegisterInfo &MRI,
|
|
const TargetRegisterInfo &TRI,
|
|
const TargetInstrInfo &TII) {
|
|
unsigned NumUses = 0;
|
|
MachineInstr *UseMI = NULL;
|
|
for (MachineRegisterInfo::use_iterator UI = MRI.use_begin(VirtReg),
|
|
UE = MRI.use_end(); UI != UE; ++UI) {
|
|
UseMI = &*UI;
|
|
if (++NumUses > 1)
|
|
break;
|
|
}
|
|
|
|
// If the number of uses is not one, or the use is not a move instruction,
|
|
// don't coalesce. Also, only coalesce away a virtual register to virtual
|
|
// register copy.
|
|
bool Coalesced = false;
|
|
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
|
|
if (NumUses == 1 &&
|
|
TII.isMoveInstr(*UseMI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
|
|
TargetRegisterInfo::isVirtualRegister(DstReg)) {
|
|
VirtReg = DstReg;
|
|
Coalesced = true;
|
|
}
|
|
|
|
// Now find an ideal location to insert the copy.
|
|
MachineBasicBlock::iterator Pos = InsertPos;
|
|
while (Pos != MBB->begin()) {
|
|
MachineInstr *PrevMI = prior(Pos);
|
|
DenseMap<MachineInstr*, unsigned>::iterator RI = CopyRegMap.find(PrevMI);
|
|
// copyRegToReg might emit multiple instructions to do a copy.
|
|
unsigned CopyDstReg = (RI == CopyRegMap.end()) ? 0 : RI->second;
|
|
if (CopyDstReg && !TRI.regsOverlap(CopyDstReg, PhysReg))
|
|
// This is what the BB looks like right now:
|
|
// r1024 = mov r0
|
|
// ...
|
|
// r1 = mov r1024
|
|
//
|
|
// We want to insert "r1025 = mov r1". Inserting this copy below the
|
|
// move to r1024 makes it impossible for that move to be coalesced.
|
|
//
|
|
// r1025 = mov r1
|
|
// r1024 = mov r0
|
|
// ...
|
|
// r1 = mov 1024
|
|
// r2 = mov 1025
|
|
break; // Woot! Found a good location.
|
|
--Pos;
|
|
}
|
|
|
|
bool Emitted = TII.copyRegToReg(*MBB, Pos, VirtReg, PhysReg, RC, RC);
|
|
assert(Emitted && "Unable to issue a live-in copy instruction!\n");
|
|
(void) Emitted;
|
|
|
|
CopyRegMap.insert(std::make_pair(prior(Pos), VirtReg));
|
|
if (Coalesced) {
|
|
if (&*InsertPos == UseMI) ++InsertPos;
|
|
MBB->erase(UseMI);
|
|
}
|
|
}
|
|
|
|
/// EmitLiveInCopies - If this is the first basic block in the function,
|
|
/// and if it has live ins that need to be copied into vregs, emit the
|
|
/// copies into the block.
|
|
static void EmitLiveInCopies(MachineBasicBlock *EntryMBB,
|
|
const MachineRegisterInfo &MRI,
|
|
const TargetRegisterInfo &TRI,
|
|
const TargetInstrInfo &TII) {
|
|
if (SchedLiveInCopies) {
|
|
// Emit the copies at a heuristically-determined location in the block.
|
|
DenseMap<MachineInstr*, unsigned> CopyRegMap;
|
|
MachineBasicBlock::iterator InsertPos = EntryMBB->begin();
|
|
for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(),
|
|
E = MRI.livein_end(); LI != E; ++LI)
|
|
if (LI->second) {
|
|
const TargetRegisterClass *RC = MRI.getRegClass(LI->second);
|
|
EmitLiveInCopy(EntryMBB, InsertPos, LI->second, LI->first,
|
|
RC, CopyRegMap, MRI, TRI, TII);
|
|
}
|
|
} else {
|
|
// Emit the copies into the top of the block.
|
|
for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(),
|
|
E = MRI.livein_end(); LI != E; ++LI)
|
|
if (LI->second) {
|
|
const TargetRegisterClass *RC = MRI.getRegClass(LI->second);
|
|
bool Emitted = TII.copyRegToReg(*EntryMBB, EntryMBB->begin(),
|
|
LI->second, LI->first, RC, RC);
|
|
assert(Emitted && "Unable to issue a live-in copy instruction!\n");
|
|
(void) Emitted;
|
|
}
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// SelectionDAGISel code
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
SelectionDAGISel::SelectionDAGISel(TargetMachine &tm, CodeGenOpt::Level OL) :
|
|
FunctionPass(&ID), TM(tm), TLI(*tm.getTargetLowering()),
|
|
FuncInfo(new FunctionLoweringInfo(TLI)),
|
|
CurDAG(new SelectionDAG(TLI, *FuncInfo)),
|
|
SDL(new SelectionDAGLowering(*CurDAG, TLI, *FuncInfo, OL)),
|
|
GFI(),
|
|
OptLevel(OL),
|
|
DAGSize(0)
|
|
{}
|
|
|
|
SelectionDAGISel::~SelectionDAGISel() {
|
|
delete SDL;
|
|
delete CurDAG;
|
|
delete FuncInfo;
|
|
}
|
|
|
|
unsigned SelectionDAGISel::MakeReg(MVT VT) {
|
|
return RegInfo->createVirtualRegister(TLI.getRegClassFor(VT));
|
|
}
|
|
|
|
void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
AU.addRequired<AliasAnalysis>();
|
|
AU.addRequired<GCModuleInfo>();
|
|
AU.addRequired<DwarfWriter>();
|
|
AU.setPreservesAll();
|
|
}
|
|
|
|
bool SelectionDAGISel::runOnFunction(Function &Fn) {
|
|
// Do some sanity-checking on the command-line options.
|
|
assert((!EnableFastISelVerbose || EnableFastISel) &&
|
|
"-fast-isel-verbose requires -fast-isel");
|
|
assert((!EnableFastISelAbort || EnableFastISel) &&
|
|
"-fast-isel-abort requires -fast-isel");
|
|
|
|
// Do not codegen any 'available_externally' functions at all, they have
|
|
// definitions outside the translation unit.
|
|
if (Fn.hasAvailableExternallyLinkage())
|
|
return false;
|
|
|
|
|
|
// Get alias analysis for load/store combining.
|
|
AA = &getAnalysis<AliasAnalysis>();
|
|
|
|
TargetMachine &TM = TLI.getTargetMachine();
|
|
MF = &MachineFunction::construct(&Fn, TM);
|
|
const TargetInstrInfo &TII = *TM.getInstrInfo();
|
|
const TargetRegisterInfo &TRI = *TM.getRegisterInfo();
|
|
|
|
if (MF->getFunction()->hasGC())
|
|
GFI = &getAnalysis<GCModuleInfo>().getFunctionInfo(*MF->getFunction());
|
|
else
|
|
GFI = 0;
|
|
RegInfo = &MF->getRegInfo();
|
|
DEBUG(errs() << "\n\n\n=== " << Fn.getName() << "\n");
|
|
|
|
MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>();
|
|
DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>();
|
|
CurDAG->init(*MF, MMI, DW);
|
|
FuncInfo->set(Fn, *MF, *CurDAG, EnableFastISel);
|
|
SDL->init(GFI, *AA);
|
|
|
|
for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
|
|
if (InvokeInst *Invoke = dyn_cast<InvokeInst>(I->getTerminator()))
|
|
// Mark landing pad.
|
|
FuncInfo->MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
|
|
|
|
SelectAllBasicBlocks(Fn, *MF, MMI, DW, TII);
|
|
|
|
// If the first basic block in the function has live ins that need to be
|
|
// copied into vregs, emit the copies into the top of the block before
|
|
// emitting the code for the block.
|
|
EmitLiveInCopies(MF->begin(), *RegInfo, TRI, TII);
|
|
|
|
// Add function live-ins to entry block live-in set.
|
|
for (MachineRegisterInfo::livein_iterator I = RegInfo->livein_begin(),
|
|
E = RegInfo->livein_end(); I != E; ++I)
|
|
MF->begin()->addLiveIn(I->first);
|
|
|
|
#ifndef NDEBUG
|
|
assert(FuncInfo->CatchInfoFound.size() == FuncInfo->CatchInfoLost.size() &&
|
|
"Not all catch info was assigned to a landing pad!");
|
|
#endif
|
|
|
|
FuncInfo->clear();
|
|
|
|
return true;
|
|
}
|
|
|
|
static void copyCatchInfo(BasicBlock *SrcBB, BasicBlock *DestBB,
|
|
MachineModuleInfo *MMI, FunctionLoweringInfo &FLI) {
|
|
for (BasicBlock::iterator I = SrcBB->begin(), E = --SrcBB->end(); I != E; ++I)
|
|
if (EHSelectorInst *EHSel = dyn_cast<EHSelectorInst>(I)) {
|
|
// Apply the catch info to DestBB.
|
|
AddCatchInfo(*EHSel, MMI, FLI.MBBMap[DestBB]);
|
|
#ifndef NDEBUG
|
|
if (!FLI.MBBMap[SrcBB]->isLandingPad())
|
|
FLI.CatchInfoFound.insert(EHSel);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/// IsFixedFrameObjectWithPosOffset - Check if object is a fixed frame object and
|
|
/// whether object offset >= 0.
|
|
static bool
|
|
IsFixedFrameObjectWithPosOffset(MachineFrameInfo *MFI, SDValue Op) {
|
|
if (!isa<FrameIndexSDNode>(Op)) return false;
|
|
|
|
FrameIndexSDNode * FrameIdxNode = dyn_cast<FrameIndexSDNode>(Op);
|
|
int FrameIdx = FrameIdxNode->getIndex();
|
|
return MFI->isFixedObjectIndex(FrameIdx) &&
|
|
MFI->getObjectOffset(FrameIdx) >= 0;
|
|
}
|
|
|
|
/// IsPossiblyOverwrittenArgumentOfTailCall - Check if the operand could
|
|
/// possibly be overwritten when lowering the outgoing arguments in a tail
|
|
/// call. Currently the implementation of this call is very conservative and
|
|
/// assumes all arguments sourcing from FORMAL_ARGUMENTS or a CopyFromReg with
|
|
/// virtual registers would be overwritten by direct lowering.
|
|
static bool IsPossiblyOverwrittenArgumentOfTailCall(SDValue Op,
|
|
MachineFrameInfo *MFI) {
|
|
RegisterSDNode * OpReg = NULL;
|
|
if (Op.getOpcode() == ISD::FORMAL_ARGUMENTS ||
|
|
(Op.getOpcode()== ISD::CopyFromReg &&
|
|
(OpReg = dyn_cast<RegisterSDNode>(Op.getOperand(1))) &&
|
|
(OpReg->getReg() >= TargetRegisterInfo::FirstVirtualRegister)) ||
|
|
(Op.getOpcode() == ISD::LOAD &&
|
|
IsFixedFrameObjectWithPosOffset(MFI, Op.getOperand(1))) ||
|
|
(Op.getOpcode() == ISD::MERGE_VALUES &&
|
|
Op.getOperand(Op.getResNo()).getOpcode() == ISD::LOAD &&
|
|
IsFixedFrameObjectWithPosOffset(MFI, Op.getOperand(Op.getResNo()).
|
|
getOperand(1))))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/// CheckDAGForTailCallsAndFixThem - This Function looks for CALL nodes in the
|
|
/// DAG and fixes their tailcall attribute operand.
|
|
static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG,
|
|
const TargetLowering& TLI) {
|
|
SDNode * Ret = NULL;
|
|
SDValue Terminator = DAG.getRoot();
|
|
|
|
// Find RET node.
|
|
if (Terminator.getOpcode() == ISD::RET) {
|
|
Ret = Terminator.getNode();
|
|
}
|
|
|
|
// Fix tail call attribute of CALL nodes.
|
|
for (SelectionDAG::allnodes_iterator BE = DAG.allnodes_begin(),
|
|
BI = DAG.allnodes_end(); BI != BE; ) {
|
|
--BI;
|
|
if (CallSDNode *TheCall = dyn_cast<CallSDNode>(BI)) {
|
|
SDValue OpRet(Ret, 0);
|
|
SDValue OpCall(BI, 0);
|
|
bool isMarkedTailCall = TheCall->isTailCall();
|
|
// If CALL node has tail call attribute set to true and the call is not
|
|
// eligible (no RET or the target rejects) the attribute is fixed to
|
|
// false. The TargetLowering::IsEligibleForTailCallOptimization function
|
|
// must correctly identify tail call optimizable calls.
|
|
if (!isMarkedTailCall) continue;
|
|
if (Ret==NULL ||
|
|
!TLI.IsEligibleForTailCallOptimization(TheCall, OpRet, DAG)) {
|
|
// Not eligible. Mark CALL node as non tail call. Note that we
|
|
// can modify the call node in place since calls are not CSE'd.
|
|
TheCall->setNotTailCall();
|
|
} else {
|
|
// Look for tail call clobbered arguments. Emit a series of
|
|
// copyto/copyfrom virtual register nodes to protect them.
|
|
SmallVector<SDValue, 32> Ops;
|
|
SDValue Chain = TheCall->getChain(), InFlag;
|
|
Ops.push_back(Chain);
|
|
Ops.push_back(TheCall->getCallee());
|
|
for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) {
|
|
SDValue Arg = TheCall->getArg(i);
|
|
bool isByVal = TheCall->getArgFlags(i).isByVal();
|
|
MachineFunction &MF = DAG.getMachineFunction();
|
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
if (!isByVal &&
|
|
IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)) {
|
|
MVT VT = Arg.getValueType();
|
|
unsigned VReg = MF.getRegInfo().
|
|
createVirtualRegister(TLI.getRegClassFor(VT));
|
|
Chain = DAG.getCopyToReg(Chain, Arg.getDebugLoc(),
|
|
VReg, Arg, InFlag);
|
|
InFlag = Chain.getValue(1);
|
|
Arg = DAG.getCopyFromReg(Chain, Arg.getDebugLoc(),
|
|
VReg, VT, InFlag);
|
|
Chain = Arg.getValue(1);
|
|
InFlag = Arg.getValue(2);
|
|
}
|
|
Ops.push_back(Arg);
|
|
Ops.push_back(TheCall->getArgFlagsVal(i));
|
|
}
|
|
// Link in chain of CopyTo/CopyFromReg.
|
|
Ops[0] = Chain;
|
|
DAG.UpdateNodeOperands(OpCall, Ops.begin(), Ops.size());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SelectionDAGISel::SelectBasicBlock(BasicBlock *LLVMBB,
|
|
BasicBlock::iterator Begin,
|
|
BasicBlock::iterator End) {
|
|
SDL->setCurrentBasicBlock(BB);
|
|
|
|
// Lower all of the non-terminator instructions.
|
|
for (BasicBlock::iterator I = Begin; I != End; ++I)
|
|
if (!isa<TerminatorInst>(I))
|
|
SDL->visit(*I);
|
|
|
|
// Ensure that all instructions which are used outside of their defining
|
|
// blocks are available as virtual registers. Invoke is handled elsewhere.
|
|
for (BasicBlock::iterator I = Begin; I != End; ++I)
|
|
if (!isa<PHINode>(I) && !isa<InvokeInst>(I))
|
|
SDL->CopyToExportRegsIfNeeded(I);
|
|
|
|
// Handle PHI nodes in successor blocks.
|
|
if (End == LLVMBB->end()) {
|
|
HandlePHINodesInSuccessorBlocks(LLVMBB);
|
|
|
|
// Lower the terminator after the copies are emitted.
|
|
SDL->visit(*LLVMBB->getTerminator());
|
|
}
|
|
|
|
// Make sure the root of the DAG is up-to-date.
|
|
CurDAG->setRoot(SDL->getControlRoot());
|
|
|
|
// Check whether calls in this block are real tail calls. Fix up CALL nodes
|
|
// with correct tailcall attribute so that the target can rely on the tailcall
|
|
// attribute indicating whether the call is really eligible for tail call
|
|
// optimization.
|
|
if (PerformTailCallOpt)
|
|
CheckDAGForTailCallsAndFixThem(*CurDAG, TLI);
|
|
|
|
// Final step, emit the lowered DAG as machine code.
|
|
CodeGenAndEmitDAG();
|
|
SDL->clear();
|
|
}
|
|
|
|
void SelectionDAGISel::ComputeLiveOutVRegInfo() {
|
|
SmallPtrSet<SDNode*, 128> VisitedNodes;
|
|
SmallVector<SDNode*, 128> Worklist;
|
|
|
|
Worklist.push_back(CurDAG->getRoot().getNode());
|
|
|
|
APInt Mask;
|
|
APInt KnownZero;
|
|
APInt KnownOne;
|
|
|
|
while (!Worklist.empty()) {
|
|
SDNode *N = Worklist.back();
|
|
Worklist.pop_back();
|
|
|
|
// If we've already seen this node, ignore it.
|
|
if (!VisitedNodes.insert(N))
|
|
continue;
|
|
|
|
// Otherwise, add all chain operands to the worklist.
|
|
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
|
|
if (N->getOperand(i).getValueType() == MVT::Other)
|
|
Worklist.push_back(N->getOperand(i).getNode());
|
|
|
|
// If this is a CopyToReg with a vreg dest, process it.
|
|
if (N->getOpcode() != ISD::CopyToReg)
|
|
continue;
|
|
|
|
unsigned DestReg = cast<RegisterSDNode>(N->getOperand(1))->getReg();
|
|
if (!TargetRegisterInfo::isVirtualRegister(DestReg))
|
|
continue;
|
|
|
|
// Ignore non-scalar or non-integer values.
|
|
SDValue Src = N->getOperand(2);
|
|
MVT SrcVT = Src.getValueType();
|
|
if (!SrcVT.isInteger() || SrcVT.isVector())
|
|
continue;
|
|
|
|
unsigned NumSignBits = CurDAG->ComputeNumSignBits(Src);
|
|
Mask = APInt::getAllOnesValue(SrcVT.getSizeInBits());
|
|
CurDAG->ComputeMaskedBits(Src, Mask, KnownZero, KnownOne);
|
|
|
|
// Only install this information if it tells us something.
|
|
if (NumSignBits != 1 || KnownZero != 0 || KnownOne != 0) {
|
|
DestReg -= TargetRegisterInfo::FirstVirtualRegister;
|
|
FunctionLoweringInfo &FLI = CurDAG->getFunctionLoweringInfo();
|
|
if (DestReg >= FLI.LiveOutRegInfo.size())
|
|
FLI.LiveOutRegInfo.resize(DestReg+1);
|
|
FunctionLoweringInfo::LiveOutInfo &LOI = FLI.LiveOutRegInfo[DestReg];
|
|
LOI.NumSignBits = NumSignBits;
|
|
LOI.KnownOne = KnownOne;
|
|
LOI.KnownZero = KnownZero;
|
|
}
|
|
}
|
|
}
|
|
|
|
void SelectionDAGISel::CodeGenAndEmitDAG() {
|
|
std::string GroupName;
|
|
if (TimePassesIsEnabled)
|
|
GroupName = "Instruction Selection and Scheduling";
|
|
std::string BlockName;
|
|
if (ViewDAGCombine1 || ViewLegalizeTypesDAGs || ViewLegalizeDAGs ||
|
|
ViewDAGCombine2 || ViewDAGCombineLT || ViewISelDAGs || ViewSchedDAGs ||
|
|
ViewSUnitDAGs)
|
|
BlockName = CurDAG->getMachineFunction().getFunction()->getNameStr() + ":" +
|
|
BB->getBasicBlock()->getNameStr();
|
|
|
|
DOUT << "Initial selection DAG:\n";
|
|
DEBUG(CurDAG->dump());
|
|
|
|
if (ViewDAGCombine1) CurDAG->viewGraph("dag-combine1 input for " + BlockName);
|
|
|
|
// Run the DAG combiner in pre-legalize mode.
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("DAG Combining 1", GroupName);
|
|
CurDAG->Combine(Unrestricted, *AA, OptLevel);
|
|
} else {
|
|
CurDAG->Combine(Unrestricted, *AA, OptLevel);
|
|
}
|
|
|
|
DOUT << "Optimized lowered selection DAG:\n";
|
|
DEBUG(CurDAG->dump());
|
|
|
|
// Second step, hack on the DAG until it only uses operations and types that
|
|
// the target supports.
|
|
if (!DisableLegalizeTypes) {
|
|
if (ViewLegalizeTypesDAGs) CurDAG->viewGraph("legalize-types input for " +
|
|
BlockName);
|
|
|
|
bool Changed;
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("Type Legalization", GroupName);
|
|
Changed = CurDAG->LegalizeTypes();
|
|
} else {
|
|
Changed = CurDAG->LegalizeTypes();
|
|
}
|
|
|
|
DOUT << "Type-legalized selection DAG:\n";
|
|
DEBUG(CurDAG->dump());
|
|
|
|
if (Changed) {
|
|
if (ViewDAGCombineLT)
|
|
CurDAG->viewGraph("dag-combine-lt input for " + BlockName);
|
|
|
|
// Run the DAG combiner in post-type-legalize mode.
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("DAG Combining after legalize types", GroupName);
|
|
CurDAG->Combine(NoIllegalTypes, *AA, OptLevel);
|
|
} else {
|
|
CurDAG->Combine(NoIllegalTypes, *AA, OptLevel);
|
|
}
|
|
|
|
DOUT << "Optimized type-legalized selection DAG:\n";
|
|
DEBUG(CurDAG->dump());
|
|
}
|
|
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("Vector Legalization", GroupName);
|
|
Changed = CurDAG->LegalizeVectors();
|
|
} else {
|
|
Changed = CurDAG->LegalizeVectors();
|
|
}
|
|
|
|
if (Changed) {
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("Type Legalization 2", GroupName);
|
|
Changed = CurDAG->LegalizeTypes();
|
|
} else {
|
|
Changed = CurDAG->LegalizeTypes();
|
|
}
|
|
|
|
if (ViewDAGCombineLT)
|
|
CurDAG->viewGraph("dag-combine-lv input for " + BlockName);
|
|
|
|
// Run the DAG combiner in post-type-legalize mode.
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("DAG Combining after legalize vectors", GroupName);
|
|
CurDAG->Combine(NoIllegalOperations, *AA, OptLevel);
|
|
} else {
|
|
CurDAG->Combine(NoIllegalOperations, *AA, OptLevel);
|
|
}
|
|
|
|
DOUT << "Optimized vector-legalized selection DAG:\n";
|
|
DEBUG(CurDAG->dump());
|
|
}
|
|
}
|
|
|
|
if (ViewLegalizeDAGs) CurDAG->viewGraph("legalize input for " + BlockName);
|
|
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("DAG Legalization", GroupName);
|
|
CurDAG->Legalize(DisableLegalizeTypes, OptLevel);
|
|
} else {
|
|
CurDAG->Legalize(DisableLegalizeTypes, OptLevel);
|
|
}
|
|
|
|
DOUT << "Legalized selection DAG:\n";
|
|
DEBUG(CurDAG->dump());
|
|
|
|
if (ViewDAGCombine2) CurDAG->viewGraph("dag-combine2 input for " + BlockName);
|
|
|
|
// Run the DAG combiner in post-legalize mode.
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("DAG Combining 2", GroupName);
|
|
CurDAG->Combine(NoIllegalOperations, *AA, OptLevel);
|
|
} else {
|
|
CurDAG->Combine(NoIllegalOperations, *AA, OptLevel);
|
|
}
|
|
|
|
DOUT << "Optimized legalized selection DAG:\n";
|
|
DEBUG(CurDAG->dump());
|
|
|
|
if (ViewISelDAGs) CurDAG->viewGraph("isel input for " + BlockName);
|
|
|
|
if (OptLevel != CodeGenOpt::None)
|
|
ComputeLiveOutVRegInfo();
|
|
|
|
// Third, instruction select all of the operations to machine code, adding the
|
|
// code to the MachineBasicBlock.
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("Instruction Selection", GroupName);
|
|
InstructionSelect();
|
|
} else {
|
|
InstructionSelect();
|
|
}
|
|
|
|
DOUT << "Selected selection DAG:\n";
|
|
DEBUG(CurDAG->dump());
|
|
|
|
if (ViewSchedDAGs) CurDAG->viewGraph("scheduler input for " + BlockName);
|
|
|
|
// Schedule machine code.
|
|
ScheduleDAGSDNodes *Scheduler = CreateScheduler();
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("Instruction Scheduling", GroupName);
|
|
Scheduler->Run(CurDAG, BB, BB->end());
|
|
} else {
|
|
Scheduler->Run(CurDAG, BB, BB->end());
|
|
}
|
|
|
|
if (ViewSUnitDAGs) Scheduler->viewGraph();
|
|
|
|
// Emit machine code to BB. This can change 'BB' to the last block being
|
|
// inserted into.
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("Instruction Creation", GroupName);
|
|
BB = Scheduler->EmitSchedule();
|
|
} else {
|
|
BB = Scheduler->EmitSchedule();
|
|
}
|
|
|
|
// Free the scheduler state.
|
|
if (TimePassesIsEnabled) {
|
|
NamedRegionTimer T("Instruction Scheduling Cleanup", GroupName);
|
|
delete Scheduler;
|
|
} else {
|
|
delete Scheduler;
|
|
}
|
|
|
|
DOUT << "Selected machine code:\n";
|
|
DEBUG(BB->dump());
|
|
}
|
|
|
|
void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn,
|
|
MachineFunction &MF,
|
|
MachineModuleInfo *MMI,
|
|
DwarfWriter *DW,
|
|
const TargetInstrInfo &TII) {
|
|
// Initialize the Fast-ISel state, if needed.
|
|
FastISel *FastIS = 0;
|
|
if (EnableFastISel)
|
|
FastIS = TLI.createFastISel(MF, MMI, DW,
|
|
FuncInfo->ValueMap,
|
|
FuncInfo->MBBMap,
|
|
FuncInfo->StaticAllocaMap
|
|
#ifndef NDEBUG
|
|
, FuncInfo->CatchInfoLost
|
|
#endif
|
|
);
|
|
|
|
// Iterate over all basic blocks in the function.
|
|
for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
|
|
BasicBlock *LLVMBB = &*I;
|
|
BB = FuncInfo->MBBMap[LLVMBB];
|
|
|
|
BasicBlock::iterator const Begin = LLVMBB->begin();
|
|
BasicBlock::iterator const End = LLVMBB->end();
|
|
BasicBlock::iterator BI = Begin;
|
|
|
|
// Lower any arguments needed in this block if this is the entry block.
|
|
bool SuppressFastISel = false;
|
|
if (LLVMBB == &Fn.getEntryBlock()) {
|
|
LowerArguments(LLVMBB);
|
|
|
|
// If any of the arguments has the byval attribute, forgo
|
|
// fast-isel in the entry block.
|
|
if (FastIS) {
|
|
unsigned j = 1;
|
|
for (Function::arg_iterator I = Fn.arg_begin(), E = Fn.arg_end();
|
|
I != E; ++I, ++j)
|
|
if (Fn.paramHasAttr(j, Attribute::ByVal)) {
|
|
if (EnableFastISelVerbose || EnableFastISelAbort)
|
|
cerr << "FastISel skips entry block due to byval argument\n";
|
|
SuppressFastISel = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (MMI && BB->isLandingPad()) {
|
|
// Add a label to mark the beginning of the landing pad. Deletion of the
|
|
// landing pad can thus be detected via the MachineModuleInfo.
|
|
unsigned LabelID = MMI->addLandingPad(BB);
|
|
|
|
const TargetInstrDesc &II = TII.get(TargetInstrInfo::EH_LABEL);
|
|
BuildMI(BB, SDL->getCurDebugLoc(), II).addImm(LabelID);
|
|
|
|
// Mark exception register as live in.
|
|
unsigned Reg = TLI.getExceptionAddressRegister();
|
|
if (Reg) BB->addLiveIn(Reg);
|
|
|
|
// Mark exception selector register as live in.
|
|
Reg = TLI.getExceptionSelectorRegister();
|
|
if (Reg) BB->addLiveIn(Reg);
|
|
|
|
// FIXME: Hack around an exception handling flaw (PR1508): the personality
|
|
// function and list of typeids logically belong to the invoke (or, if you
|
|
// like, the basic block containing the invoke), and need to be associated
|
|
// with it in the dwarf exception handling tables. Currently however the
|
|
// information is provided by an intrinsic (eh.selector) that can be moved
|
|
// to unexpected places by the optimizers: if the unwind edge is critical,
|
|
// then breaking it can result in the intrinsics being in the successor of
|
|
// the landing pad, not the landing pad itself. This results in exceptions
|
|
// not being caught because no typeids are associated with the invoke.
|
|
// This may not be the only way things can go wrong, but it is the only way
|
|
// we try to work around for the moment.
|
|
BranchInst *Br = dyn_cast<BranchInst>(LLVMBB->getTerminator());
|
|
|
|
if (Br && Br->isUnconditional()) { // Critical edge?
|
|
BasicBlock::iterator I, E;
|
|
for (I = LLVMBB->begin(), E = --LLVMBB->end(); I != E; ++I)
|
|
if (isa<EHSelectorInst>(I))
|
|
break;
|
|
|
|
if (I == E)
|
|
// No catch info found - try to extract some from the successor.
|
|
copyCatchInfo(Br->getSuccessor(0), LLVMBB, MMI, *FuncInfo);
|
|
}
|
|
}
|
|
|
|
// Before doing SelectionDAG ISel, see if FastISel has been requested.
|
|
if (FastIS && !SuppressFastISel) {
|
|
// Emit code for any incoming arguments. This must happen before
|
|
// beginning FastISel on the entry block.
|
|
if (LLVMBB == &Fn.getEntryBlock()) {
|
|
CurDAG->setRoot(SDL->getControlRoot());
|
|
CodeGenAndEmitDAG();
|
|
SDL->clear();
|
|
}
|
|
FastIS->startNewBlock(BB);
|
|
// Do FastISel on as many instructions as possible.
|
|
for (; BI != End; ++BI) {
|
|
// Just before the terminator instruction, insert instructions to
|
|
// feed PHI nodes in successor blocks.
|
|
if (isa<TerminatorInst>(BI))
|
|
if (!HandlePHINodesInSuccessorBlocksFast(LLVMBB, FastIS)) {
|
|
if (EnableFastISelVerbose || EnableFastISelAbort) {
|
|
cerr << "FastISel miss: ";
|
|
BI->dump();
|
|
}
|
|
assert(!EnableFastISelAbort &&
|
|
"FastISel didn't handle a PHI in a successor");
|
|
break;
|
|
}
|
|
|
|
// First try normal tablegen-generated "fast" selection.
|
|
if (FastIS->SelectInstruction(BI))
|
|
continue;
|
|
|
|
// Next, try calling the target to attempt to handle the instruction.
|
|
if (FastIS->TargetSelectInstruction(BI))
|
|
continue;
|
|
|
|
// Then handle certain instructions as single-LLVM-Instruction blocks.
|
|
if (isa<CallInst>(BI)) {
|
|
if (EnableFastISelVerbose || EnableFastISelAbort) {
|
|
cerr << "FastISel missed call: ";
|
|
BI->dump();
|
|
}
|
|
|
|
if (BI->getType() != Type::VoidTy) {
|
|
unsigned &R = FuncInfo->ValueMap[BI];
|
|
if (!R)
|
|
R = FuncInfo->CreateRegForValue(BI);
|
|
}
|
|
|
|
SDL->setCurDebugLoc(FastIS->getCurDebugLoc());
|
|
SelectBasicBlock(LLVMBB, BI, next(BI));
|
|
// If the instruction was codegen'd with multiple blocks,
|
|
// inform the FastISel object where to resume inserting.
|
|
FastIS->setCurrentBlock(BB);
|
|
continue;
|
|
}
|
|
|
|
// Otherwise, give up on FastISel for the rest of the block.
|
|
// For now, be a little lenient about non-branch terminators.
|
|
if (!isa<TerminatorInst>(BI) || isa<BranchInst>(BI)) {
|
|
if (EnableFastISelVerbose || EnableFastISelAbort) {
|
|
cerr << "FastISel miss: ";
|
|
BI->dump();
|
|
}
|
|
if (EnableFastISelAbort)
|
|
// The "fast" selector couldn't handle something and bailed.
|
|
// For the purpose of debugging, just abort.
|
|
llvm_unreachable("FastISel didn't select the entire block");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Run SelectionDAG instruction selection on the remainder of the block
|
|
// not handled by FastISel. If FastISel is not run, this is the entire
|
|
// block.
|
|
if (BI != End) {
|
|
// If FastISel is run and it has known DebugLoc then use it.
|
|
if (FastIS && !FastIS->getCurDebugLoc().isUnknown())
|
|
SDL->setCurDebugLoc(FastIS->getCurDebugLoc());
|
|
SelectBasicBlock(LLVMBB, BI, End);
|
|
}
|
|
|
|
FinishBasicBlock();
|
|
}
|
|
|
|
delete FastIS;
|
|
}
|
|
|
|
void
|
|
SelectionDAGISel::FinishBasicBlock() {
|
|
|
|
DOUT << "Target-post-processed machine code:\n";
|
|
DEBUG(BB->dump());
|
|
|
|
DOUT << "Total amount of phi nodes to update: "
|
|
<< SDL->PHINodesToUpdate.size() << "\n";
|
|
DEBUG(for (unsigned i = 0, e = SDL->PHINodesToUpdate.size(); i != e; ++i)
|
|
DOUT << "Node " << i << " : (" << SDL->PHINodesToUpdate[i].first
|
|
<< ", " << SDL->PHINodesToUpdate[i].second << ")\n";);
|
|
|
|
// Next, now that we know what the last MBB the LLVM BB expanded is, update
|
|
// PHI nodes in successors.
|
|
if (SDL->SwitchCases.empty() &&
|
|
SDL->JTCases.empty() &&
|
|
SDL->BitTestCases.empty()) {
|
|
for (unsigned i = 0, e = SDL->PHINodesToUpdate.size(); i != e; ++i) {
|
|
MachineInstr *PHI = SDL->PHINodesToUpdate[i].first;
|
|
assert(PHI->getOpcode() == TargetInstrInfo::PHI &&
|
|
"This is not a machine PHI node that we are updating!");
|
|
PHI->addOperand(MachineOperand::CreateReg(SDL->PHINodesToUpdate[i].second,
|
|
false));
|
|
PHI->addOperand(MachineOperand::CreateMBB(BB));
|
|
}
|
|
SDL->PHINodesToUpdate.clear();
|
|
return;
|
|
}
|
|
|
|
for (unsigned i = 0, e = SDL->BitTestCases.size(); i != e; ++i) {
|
|
// Lower header first, if it wasn't already lowered
|
|
if (!SDL->BitTestCases[i].Emitted) {
|
|
// Set the current basic block to the mbb we wish to insert the code into
|
|
BB = SDL->BitTestCases[i].Parent;
|
|
SDL->setCurrentBasicBlock(BB);
|
|
// Emit the code
|
|
SDL->visitBitTestHeader(SDL->BitTestCases[i]);
|
|
CurDAG->setRoot(SDL->getRoot());
|
|
CodeGenAndEmitDAG();
|
|
SDL->clear();
|
|
}
|
|
|
|
for (unsigned j = 0, ej = SDL->BitTestCases[i].Cases.size(); j != ej; ++j) {
|
|
// Set the current basic block to the mbb we wish to insert the code into
|
|
BB = SDL->BitTestCases[i].Cases[j].ThisBB;
|
|
SDL->setCurrentBasicBlock(BB);
|
|
// Emit the code
|
|
if (j+1 != ej)
|
|
SDL->visitBitTestCase(SDL->BitTestCases[i].Cases[j+1].ThisBB,
|
|
SDL->BitTestCases[i].Reg,
|
|
SDL->BitTestCases[i].Cases[j]);
|
|
else
|
|
SDL->visitBitTestCase(SDL->BitTestCases[i].Default,
|
|
SDL->BitTestCases[i].Reg,
|
|
SDL->BitTestCases[i].Cases[j]);
|
|
|
|
|
|
CurDAG->setRoot(SDL->getRoot());
|
|
CodeGenAndEmitDAG();
|
|
SDL->clear();
|
|
}
|
|
|
|
// Update PHI Nodes
|
|
for (unsigned pi = 0, pe = SDL->PHINodesToUpdate.size(); pi != pe; ++pi) {
|
|
MachineInstr *PHI = SDL->PHINodesToUpdate[pi].first;
|
|
MachineBasicBlock *PHIBB = PHI->getParent();
|
|
assert(PHI->getOpcode() == TargetInstrInfo::PHI &&
|
|
"This is not a machine PHI node that we are updating!");
|
|
// This is "default" BB. We have two jumps to it. From "header" BB and
|
|
// from last "case" BB.
|
|
if (PHIBB == SDL->BitTestCases[i].Default) {
|
|
PHI->addOperand(MachineOperand::CreateReg(SDL->PHINodesToUpdate[pi].second,
|
|
false));
|
|
PHI->addOperand(MachineOperand::CreateMBB(SDL->BitTestCases[i].Parent));
|
|
PHI->addOperand(MachineOperand::CreateReg(SDL->PHINodesToUpdate[pi].second,
|
|
false));
|
|
PHI->addOperand(MachineOperand::CreateMBB(SDL->BitTestCases[i].Cases.
|
|
back().ThisBB));
|
|
}
|
|
// One of "cases" BB.
|
|
for (unsigned j = 0, ej = SDL->BitTestCases[i].Cases.size();
|
|
j != ej; ++j) {
|
|
MachineBasicBlock* cBB = SDL->BitTestCases[i].Cases[j].ThisBB;
|
|
if (cBB->succ_end() !=
|
|
std::find(cBB->succ_begin(),cBB->succ_end(), PHIBB)) {
|
|
PHI->addOperand(MachineOperand::CreateReg(SDL->PHINodesToUpdate[pi].second,
|
|
false));
|
|
PHI->addOperand(MachineOperand::CreateMBB(cBB));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
SDL->BitTestCases.clear();
|
|
|
|
// If the JumpTable record is filled in, then we need to emit a jump table.
|
|
// Updating the PHI nodes is tricky in this case, since we need to determine
|
|
// whether the PHI is a successor of the range check MBB or the jump table MBB
|
|
for (unsigned i = 0, e = SDL->JTCases.size(); i != e; ++i) {
|
|
// Lower header first, if it wasn't already lowered
|
|
if (!SDL->JTCases[i].first.Emitted) {
|
|
// Set the current basic block to the mbb we wish to insert the code into
|
|
BB = SDL->JTCases[i].first.HeaderBB;
|
|
SDL->setCurrentBasicBlock(BB);
|
|
// Emit the code
|
|
SDL->visitJumpTableHeader(SDL->JTCases[i].second, SDL->JTCases[i].first);
|
|
CurDAG->setRoot(SDL->getRoot());
|
|
CodeGenAndEmitDAG();
|
|
SDL->clear();
|
|
}
|
|
|
|
// Set the current basic block to the mbb we wish to insert the code into
|
|
BB = SDL->JTCases[i].second.MBB;
|
|
SDL->setCurrentBasicBlock(BB);
|
|
// Emit the code
|
|
SDL->visitJumpTable(SDL->JTCases[i].second);
|
|
CurDAG->setRoot(SDL->getRoot());
|
|
CodeGenAndEmitDAG();
|
|
SDL->clear();
|
|
|
|
// Update PHI Nodes
|
|
for (unsigned pi = 0, pe = SDL->PHINodesToUpdate.size(); pi != pe; ++pi) {
|
|
MachineInstr *PHI = SDL->PHINodesToUpdate[pi].first;
|
|
MachineBasicBlock *PHIBB = PHI->getParent();
|
|
assert(PHI->getOpcode() == TargetInstrInfo::PHI &&
|
|
"This is not a machine PHI node that we are updating!");
|
|
// "default" BB. We can go there only from header BB.
|
|
if (PHIBB == SDL->JTCases[i].second.Default) {
|
|
PHI->addOperand(MachineOperand::CreateReg(SDL->PHINodesToUpdate[pi].second,
|
|
false));
|
|
PHI->addOperand(MachineOperand::CreateMBB(SDL->JTCases[i].first.HeaderBB));
|
|
}
|
|
// JT BB. Just iterate over successors here
|
|
if (BB->succ_end() != std::find(BB->succ_begin(),BB->succ_end(), PHIBB)) {
|
|
PHI->addOperand(MachineOperand::CreateReg(SDL->PHINodesToUpdate[pi].second,
|
|
false));
|
|
PHI->addOperand(MachineOperand::CreateMBB(BB));
|
|
}
|
|
}
|
|
}
|
|
SDL->JTCases.clear();
|
|
|
|
// If the switch block involved a branch to one of the actual successors, we
|
|
// need to update PHI nodes in that block.
|
|
for (unsigned i = 0, e = SDL->PHINodesToUpdate.size(); i != e; ++i) {
|
|
MachineInstr *PHI = SDL->PHINodesToUpdate[i].first;
|
|
assert(PHI->getOpcode() == TargetInstrInfo::PHI &&
|
|
"This is not a machine PHI node that we are updating!");
|
|
if (BB->isSuccessor(PHI->getParent())) {
|
|
PHI->addOperand(MachineOperand::CreateReg(SDL->PHINodesToUpdate[i].second,
|
|
false));
|
|
PHI->addOperand(MachineOperand::CreateMBB(BB));
|
|
}
|
|
}
|
|
|
|
// If we generated any switch lowering information, build and codegen any
|
|
// additional DAGs necessary.
|
|
for (unsigned i = 0, e = SDL->SwitchCases.size(); i != e; ++i) {
|
|
// Set the current basic block to the mbb we wish to insert the code into
|
|
BB = SDL->SwitchCases[i].ThisBB;
|
|
SDL->setCurrentBasicBlock(BB);
|
|
|
|
// Emit the code
|
|
SDL->visitSwitchCase(SDL->SwitchCases[i]);
|
|
CurDAG->setRoot(SDL->getRoot());
|
|
CodeGenAndEmitDAG();
|
|
SDL->clear();
|
|
|
|
// Handle any PHI nodes in successors of this chunk, as if we were coming
|
|
// from the original BB before switch expansion. Note that PHI nodes can
|
|
// occur multiple times in PHINodesToUpdate. We have to be very careful to
|
|
// handle them the right number of times.
|
|
while ((BB = SDL->SwitchCases[i].TrueBB)) { // Handle LHS and RHS.
|
|
for (MachineBasicBlock::iterator Phi = BB->begin();
|
|
Phi != BB->end() && Phi->getOpcode() == TargetInstrInfo::PHI; ++Phi){
|
|
// This value for this PHI node is recorded in PHINodesToUpdate, get it.
|
|
for (unsigned pn = 0; ; ++pn) {
|
|
assert(pn != SDL->PHINodesToUpdate.size() &&
|
|
"Didn't find PHI entry!");
|
|
if (SDL->PHINodesToUpdate[pn].first == Phi) {
|
|
Phi->addOperand(MachineOperand::CreateReg(SDL->PHINodesToUpdate[pn].
|
|
second, false));
|
|
Phi->addOperand(MachineOperand::CreateMBB(SDL->SwitchCases[i].ThisBB));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Don't process RHS if same block as LHS.
|
|
if (BB == SDL->SwitchCases[i].FalseBB)
|
|
SDL->SwitchCases[i].FalseBB = 0;
|
|
|
|
// If we haven't handled the RHS, do so now. Otherwise, we're done.
|
|
SDL->SwitchCases[i].TrueBB = SDL->SwitchCases[i].FalseBB;
|
|
SDL->SwitchCases[i].FalseBB = 0;
|
|
}
|
|
assert(SDL->SwitchCases[i].TrueBB == 0 && SDL->SwitchCases[i].FalseBB == 0);
|
|
}
|
|
SDL->SwitchCases.clear();
|
|
|
|
SDL->PHINodesToUpdate.clear();
|
|
}
|
|
|
|
|
|
/// Create the scheduler. If a specific scheduler was specified
|
|
/// via the SchedulerRegistry, use it, otherwise select the
|
|
/// one preferred by the target.
|
|
///
|
|
ScheduleDAGSDNodes *SelectionDAGISel::CreateScheduler() {
|
|
RegisterScheduler::FunctionPassCtor Ctor = RegisterScheduler::getDefault();
|
|
|
|
if (!Ctor) {
|
|
Ctor = ISHeuristic;
|
|
RegisterScheduler::setDefault(Ctor);
|
|
}
|
|
|
|
return Ctor(this, OptLevel);
|
|
}
|
|
|
|
ScheduleHazardRecognizer *SelectionDAGISel::CreateTargetHazardRecognizer() {
|
|
return new ScheduleHazardRecognizer();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Helper functions used by the generated instruction selector.
|
|
//===----------------------------------------------------------------------===//
|
|
// Calls to these methods are generated by tblgen.
|
|
|
|
/// CheckAndMask - The isel is trying to match something like (and X, 255). If
|
|
/// the dag combiner simplified the 255, we still want to match. RHS is the
|
|
/// actual value in the DAG on the RHS of an AND, and DesiredMaskS is the value
|
|
/// specified in the .td file (e.g. 255).
|
|
bool SelectionDAGISel::CheckAndMask(SDValue LHS, ConstantSDNode *RHS,
|
|
int64_t DesiredMaskS) const {
|
|
const APInt &ActualMask = RHS->getAPIntValue();
|
|
const APInt &DesiredMask = APInt(LHS.getValueSizeInBits(), DesiredMaskS);
|
|
|
|
// If the actual mask exactly matches, success!
|
|
if (ActualMask == DesiredMask)
|
|
return true;
|
|
|
|
// If the actual AND mask is allowing unallowed bits, this doesn't match.
|
|
if (ActualMask.intersects(~DesiredMask))
|
|
return false;
|
|
|
|
// Otherwise, the DAG Combiner may have proven that the value coming in is
|
|
// either already zero or is not demanded. Check for known zero input bits.
|
|
APInt NeededMask = DesiredMask & ~ActualMask;
|
|
if (CurDAG->MaskedValueIsZero(LHS, NeededMask))
|
|
return true;
|
|
|
|
// TODO: check to see if missing bits are just not demanded.
|
|
|
|
// Otherwise, this pattern doesn't match.
|
|
return false;
|
|
}
|
|
|
|
/// CheckOrMask - The isel is trying to match something like (or X, 255). If
|
|
/// the dag combiner simplified the 255, we still want to match. RHS is the
|
|
/// actual value in the DAG on the RHS of an OR, and DesiredMaskS is the value
|
|
/// specified in the .td file (e.g. 255).
|
|
bool SelectionDAGISel::CheckOrMask(SDValue LHS, ConstantSDNode *RHS,
|
|
int64_t DesiredMaskS) const {
|
|
const APInt &ActualMask = RHS->getAPIntValue();
|
|
const APInt &DesiredMask = APInt(LHS.getValueSizeInBits(), DesiredMaskS);
|
|
|
|
// If the actual mask exactly matches, success!
|
|
if (ActualMask == DesiredMask)
|
|
return true;
|
|
|
|
// If the actual AND mask is allowing unallowed bits, this doesn't match.
|
|
if (ActualMask.intersects(~DesiredMask))
|
|
return false;
|
|
|
|
// Otherwise, the DAG Combiner may have proven that the value coming in is
|
|
// either already zero or is not demanded. Check for known zero input bits.
|
|
APInt NeededMask = DesiredMask & ~ActualMask;
|
|
|
|
APInt KnownZero, KnownOne;
|
|
CurDAG->ComputeMaskedBits(LHS, NeededMask, KnownZero, KnownOne);
|
|
|
|
// If all the missing bits in the or are already known to be set, match!
|
|
if ((NeededMask & KnownOne) == NeededMask)
|
|
return true;
|
|
|
|
// TODO: check to see if missing bits are just not demanded.
|
|
|
|
// Otherwise, this pattern doesn't match.
|
|
return false;
|
|
}
|
|
|
|
|
|
/// SelectInlineAsmMemoryOperands - Calls to this are automatically generated
|
|
/// by tblgen. Others should not call it.
|
|
void SelectionDAGISel::
|
|
SelectInlineAsmMemoryOperands(std::vector<SDValue> &Ops) {
|
|
std::vector<SDValue> InOps;
|
|
std::swap(InOps, Ops);
|
|
|
|
Ops.push_back(InOps[0]); // input chain.
|
|
Ops.push_back(InOps[1]); // input asm string.
|
|
|
|
unsigned i = 2, e = InOps.size();
|
|
if (InOps[e-1].getValueType() == MVT::Flag)
|
|
--e; // Don't process a flag operand if it is here.
|
|
|
|
while (i != e) {
|
|
unsigned Flags = cast<ConstantSDNode>(InOps[i])->getZExtValue();
|
|
if ((Flags & 7) != 4 /*MEM*/) {
|
|
// Just skip over this operand, copying the operands verbatim.
|
|
Ops.insert(Ops.end(), InOps.begin()+i,
|
|
InOps.begin()+i+InlineAsm::getNumOperandRegisters(Flags) + 1);
|
|
i += InlineAsm::getNumOperandRegisters(Flags) + 1;
|
|
} else {
|
|
assert(InlineAsm::getNumOperandRegisters(Flags) == 1 &&
|
|
"Memory operand with multiple values?");
|
|
// Otherwise, this is a memory operand. Ask the target to select it.
|
|
std::vector<SDValue> SelOps;
|
|
if (SelectInlineAsmMemoryOperand(InOps[i+1], 'm', SelOps)) {
|
|
llvm_report_error("Could not match memory address. Inline asm"
|
|
" failure!");
|
|
}
|
|
|
|
// Add this to the output node.
|
|
MVT IntPtrTy = CurDAG->getTargetLoweringInfo().getPointerTy();
|
|
Ops.push_back(CurDAG->getTargetConstant(4/*MEM*/ | (SelOps.size()<< 3),
|
|
IntPtrTy));
|
|
Ops.insert(Ops.end(), SelOps.begin(), SelOps.end());
|
|
i += 2;
|
|
}
|
|
}
|
|
|
|
// Add the flag input back if present.
|
|
if (e != InOps.size())
|
|
Ops.push_back(InOps.back());
|
|
}
|
|
|
|
/// findFlagUse - Return use of MVT::Flag value produced by the specified
|
|
/// SDNode.
|
|
///
|
|
static SDNode *findFlagUse(SDNode *N) {
|
|
unsigned FlagResNo = N->getNumValues()-1;
|
|
for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
|
|
SDUse &Use = I.getUse();
|
|
if (Use.getResNo() == FlagResNo)
|
|
return Use.getUser();
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/// findNonImmUse - Return true if "Use" is a non-immediate use of "Def".
|
|
/// This function recursively traverses up the operand chain, ignoring
|
|
/// certain nodes.
|
|
static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse,
|
|
SDNode *Root,
|
|
SmallPtrSet<SDNode*, 16> &Visited) {
|
|
if (Use->getNodeId() < Def->getNodeId() ||
|
|
!Visited.insert(Use))
|
|
return false;
|
|
|
|
for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) {
|
|
SDNode *N = Use->getOperand(i).getNode();
|
|
if (N == Def) {
|
|
if (Use == ImmedUse || Use == Root)
|
|
continue; // We are not looking for immediate use.
|
|
assert(N != Root);
|
|
return true;
|
|
}
|
|
|
|
// Traverse up the operand chain.
|
|
if (findNonImmUse(N, Def, ImmedUse, Root, Visited))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// isNonImmUse - Start searching from Root up the DAG to check is Def can
|
|
/// be reached. Return true if that's the case. However, ignore direct uses
|
|
/// by ImmedUse (which would be U in the example illustrated in
|
|
/// IsLegalAndProfitableToFold) and by Root (which can happen in the store
|
|
/// case).
|
|
/// FIXME: to be really generic, we should allow direct use by any node
|
|
/// that is being folded. But realisticly since we only fold loads which
|
|
/// have one non-chain use, we only need to watch out for load/op/store
|
|
/// and load/op/cmp case where the root (store / cmp) may reach the load via
|
|
/// its chain operand.
|
|
static inline bool isNonImmUse(SDNode *Root, SDNode *Def, SDNode *ImmedUse) {
|
|
SmallPtrSet<SDNode*, 16> Visited;
|
|
return findNonImmUse(Root, Def, ImmedUse, Root, Visited);
|
|
}
|
|
|
|
/// IsLegalAndProfitableToFold - Returns true if the specific operand node N of
|
|
/// U can be folded during instruction selection that starts at Root and
|
|
/// folding N is profitable.
|
|
bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U,
|
|
SDNode *Root) const {
|
|
if (OptLevel == CodeGenOpt::None) return false;
|
|
|
|
// If Root use can somehow reach N through a path that that doesn't contain
|
|
// U then folding N would create a cycle. e.g. In the following
|
|
// diagram, Root can reach N through X. If N is folded into into Root, then
|
|
// X is both a predecessor and a successor of U.
|
|
//
|
|
// [N*] //
|
|
// ^ ^ //
|
|
// / \ //
|
|
// [U*] [X]? //
|
|
// ^ ^ //
|
|
// \ / //
|
|
// \ / //
|
|
// [Root*] //
|
|
//
|
|
// * indicates nodes to be folded together.
|
|
//
|
|
// If Root produces a flag, then it gets (even more) interesting. Since it
|
|
// will be "glued" together with its flag use in the scheduler, we need to
|
|
// check if it might reach N.
|
|
//
|
|
// [N*] //
|
|
// ^ ^ //
|
|
// / \ //
|
|
// [U*] [X]? //
|
|
// ^ ^ //
|
|
// \ \ //
|
|
// \ | //
|
|
// [Root*] | //
|
|
// ^ | //
|
|
// f | //
|
|
// | / //
|
|
// [Y] / //
|
|
// ^ / //
|
|
// f / //
|
|
// | / //
|
|
// [FU] //
|
|
//
|
|
// If FU (flag use) indirectly reaches N (the load), and Root folds N
|
|
// (call it Fold), then X is a predecessor of FU and a successor of
|
|
// Fold. But since Fold and FU are flagged together, this will create
|
|
// a cycle in the scheduling graph.
|
|
|
|
MVT VT = Root->getValueType(Root->getNumValues()-1);
|
|
while (VT == MVT::Flag) {
|
|
SDNode *FU = findFlagUse(Root);
|
|
if (FU == NULL)
|
|
break;
|
|
Root = FU;
|
|
VT = Root->getValueType(Root->getNumValues()-1);
|
|
}
|
|
|
|
return !isNonImmUse(Root, N, U);
|
|
}
|
|
|
|
|
|
char SelectionDAGISel::ID = 0;
|