mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
Currently, codegen may spent some time in SDISel passes even if an entire
function is successfully handled by fast-isel. That's because function arguments are *always* handled by SDISel. Introduce FastLowerArguments to allow each target to provide hook to handle formal argument lowering. As a proof-of-concept, add ARMFastIsel::FastLowerArguments to handle functions with 4 or fewer scalar integer (i8, i16, or i32) arguments. It completely eliminates the need for SDISel for trivial functions. rdar://13163905 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174855 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5f352cc6e4
commit
092e5e7566
@ -90,6 +90,11 @@ public:
|
||||
|
||||
/// getCurDebugLoc() - Return current debug location information.
|
||||
DebugLoc getCurDebugLoc() const { return DL; }
|
||||
|
||||
/// LowerArguments - Do "fast" instruction selection for function arguments
|
||||
/// and append machine instructions to the current block. Return true if
|
||||
/// it is successful.
|
||||
bool LowerArguments();
|
||||
|
||||
/// SelectInstruction - Do "fast" instruction selection for the given
|
||||
/// LLVM IR instruction, and append generated machine instructions to
|
||||
@ -160,6 +165,11 @@ protected:
|
||||
///
|
||||
virtual bool
|
||||
TargetSelectInstruction(const Instruction *I) = 0;
|
||||
|
||||
/// FastLowerArguments - This method is called by target-independent code to
|
||||
/// do target specific argument lowering. It returns true if it was
|
||||
/// successful.
|
||||
virtual bool FastLowerArguments();
|
||||
|
||||
/// FastEmit_r - This method is called by target-independent code
|
||||
/// to request that an instruction with the given type and opcode
|
||||
|
@ -87,6 +87,27 @@ void FastISel::startNewBlock() {
|
||||
LastLocalValue = EmitStartPt;
|
||||
}
|
||||
|
||||
bool FastISel::LowerArguments() {
|
||||
if (!FuncInfo.CanLowerReturn)
|
||||
// Fallback to SDISel argument lowering code to deal with sret pointer
|
||||
// parameter.
|
||||
return false;
|
||||
|
||||
if (!FastLowerArguments())
|
||||
return false;
|
||||
|
||||
// Enter non-dead arguments into ValueMap for uses in non-entry BBs.
|
||||
for (Function::const_arg_iterator I = FuncInfo.Fn->arg_begin(),
|
||||
E = FuncInfo.Fn->arg_end(); I != E; ++I) {
|
||||
if (!I->use_empty()) {
|
||||
DenseMap<const Value *, unsigned>::iterator VI = LocalValueMap.find(I);
|
||||
assert(VI != LocalValueMap.end() && "Missed an argument?");
|
||||
FuncInfo.ValueMap[I] = VI->second;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FastISel::flushLocalValueMap() {
|
||||
LocalValueMap.clear();
|
||||
LastLocalValue = EmitStartPt;
|
||||
@ -836,7 +857,8 @@ FastISel::SelectInstruction(const Instruction *I) {
|
||||
void
|
||||
FastISel::FastEmitBranch(MachineBasicBlock *MSucc, DebugLoc DL) {
|
||||
|
||||
if (FuncInfo.MBB->getBasicBlock()->size() > 1 && FuncInfo.MBB->isLayoutSuccessor(MSucc)) {
|
||||
if (FuncInfo.MBB->getBasicBlock()->size() > 1 &&
|
||||
FuncInfo.MBB->isLayoutSuccessor(MSucc)) {
|
||||
// For more accurate line information if this is the only instruction
|
||||
// in the block then emit it, otherwise we have the unconditional
|
||||
// fall-through case, which needs no instructions.
|
||||
@ -1067,6 +1089,10 @@ FastISel::FastISel(FunctionLoweringInfo &funcInfo,
|
||||
|
||||
FastISel::~FastISel() {}
|
||||
|
||||
bool FastISel::FastLowerArguments() {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned FastISel::FastEmit_(MVT, MVT,
|
||||
unsigned) {
|
||||
return 0;
|
||||
|
@ -1032,10 +1032,6 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
||||
if (FuncInfo->MBB->isLandingPad())
|
||||
PrepareEHLandingPad();
|
||||
|
||||
// Lower any arguments needed in this block if this is the entry block.
|
||||
if (LLVMBB == &Fn.getEntryBlock())
|
||||
LowerArguments(LLVMBB);
|
||||
|
||||
// Before doing SelectionDAG ISel, see if FastISel has been requested.
|
||||
if (FastIS) {
|
||||
FastIS->startNewBlock();
|
||||
@ -1043,9 +1039,15 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
||||
// Emit code for any incoming arguments. This must happen before
|
||||
// beginning FastISel on the entry block.
|
||||
if (LLVMBB == &Fn.getEntryBlock()) {
|
||||
CurDAG->setRoot(SDB->getControlRoot());
|
||||
SDB->clear();
|
||||
CodeGenAndEmitDAG();
|
||||
// Lower any arguments needed in this block if this is the entry block.
|
||||
if (!FastIS->LowerArguments()) {
|
||||
// Call target indepedent SDISel argument lowering code if the target
|
||||
// specific routine is not successful.
|
||||
LowerArguments(LLVMBB);
|
||||
CurDAG->setRoot(SDB->getControlRoot());
|
||||
SDB->clear();
|
||||
CodeGenAndEmitDAG();
|
||||
}
|
||||
|
||||
// If we inserted any instructions at the beginning, make a note of
|
||||
// where they are, so we can be sure to emit subsequent instructions
|
||||
@ -1156,6 +1158,10 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
||||
}
|
||||
|
||||
FastIS->recomputeInsertPt();
|
||||
} else {
|
||||
// Lower any arguments needed in this block if this is the entry block.
|
||||
if (LLVMBB == &Fn.getEntryBlock())
|
||||
LowerArguments(LLVMBB);
|
||||
}
|
||||
|
||||
if (Begin != BI)
|
||||
|
@ -146,6 +146,7 @@ class ARMFastISel : public FastISel {
|
||||
virtual unsigned TargetMaterializeAlloca(const AllocaInst *AI);
|
||||
virtual bool TryToFoldLoad(MachineInstr *MI, unsigned OpNo,
|
||||
const LoadInst *LI);
|
||||
virtual bool FastLowerArguments();
|
||||
private:
|
||||
#include "ARMGenFastISel.inc"
|
||||
|
||||
@ -2884,6 +2885,79 @@ unsigned ARMFastISel::ARMLowerPICELF(const GlobalValue *GV,
|
||||
return DestReg2;
|
||||
}
|
||||
|
||||
bool ARMFastISel::FastLowerArguments() {
|
||||
if (!FuncInfo.CanLowerReturn)
|
||||
return false;
|
||||
|
||||
const Function *F = FuncInfo.Fn;
|
||||
if (F->isVarArg())
|
||||
return false;
|
||||
|
||||
CallingConv::ID CC = F->getCallingConv();
|
||||
switch (CC) {
|
||||
default:
|
||||
return false;
|
||||
case CallingConv::Fast:
|
||||
case CallingConv::C:
|
||||
case CallingConv::ARM_AAPCS_VFP:
|
||||
case CallingConv::ARM_AAPCS:
|
||||
case CallingConv::ARM_APCS:
|
||||
break;
|
||||
}
|
||||
|
||||
// Only handle simple cases. i.e. Up to 4 i8/i16/i32 scalar arguments
|
||||
// which are passed in r0 - r3.
|
||||
unsigned Idx = 1;
|
||||
for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
|
||||
I != E; ++I, ++Idx) {
|
||||
if (Idx > 4)
|
||||
return false;
|
||||
|
||||
if (F->getAttributes().hasAttribute(Idx, Attribute::InReg) ||
|
||||
F->getAttributes().hasAttribute(Idx, Attribute::StructRet) ||
|
||||
F->getAttributes().hasAttribute(Idx, Attribute::ByVal))
|
||||
return false;
|
||||
|
||||
Type *ArgTy = I->getType();
|
||||
if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy())
|
||||
return false;
|
||||
|
||||
EVT ArgVT = TLI.getValueType(ArgTy);
|
||||
switch (ArgVT.getSimpleVT().SimpleTy) {
|
||||
case MVT::i8:
|
||||
case MVT::i16:
|
||||
case MVT::i32:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const uint16_t GPRArgRegs[] = {
|
||||
ARM::R0, ARM::R1, ARM::R2, ARM::R3
|
||||
};
|
||||
|
||||
const TargetRegisterClass *RC = TLI.getRegClassFor(MVT::i32);
|
||||
Idx = 0;
|
||||
for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
|
||||
I != E; ++I, ++Idx) {
|
||||
if (I->use_empty())
|
||||
continue;
|
||||
unsigned SrcReg = GPRArgRegs[Idx];
|
||||
unsigned DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
|
||||
// FIXME: Unfortunately it's necessary to emit a copy from the livein copy.
|
||||
// Without this, EmitLiveInCopies may eliminate the livein if its only
|
||||
// use is a bitcast (which isn't turned into an instruction).
|
||||
unsigned ResultReg = createResultReg(RC);
|
||||
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY),
|
||||
ResultReg).addReg(DstReg, getKillRegState(true));
|
||||
UpdateValueMap(I, ResultReg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo,
|
||||
const TargetLibraryInfo *libInfo) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user