Imported Upstream version 5.18.0.167

Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-20 08:25:10 +00:00
parent e19d552987
commit b084638f15
28489 changed files with 184 additions and 3866856 deletions

View File

@ -1,33 +0,0 @@
//===- ARC.h - Top-level interface for ARC 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 LLVM
// ARC back-end.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_ARC_ARC_H
#define LLVM_LIB_TARGET_ARC_ARC_H
#include "MCTargetDesc/ARCMCTargetDesc.h"
#include "llvm/Target/TargetMachine.h"
namespace llvm {
class FunctionPass;
class ARCTargetMachine;
FunctionPass *createARCISelDag(ARCTargetMachine &TM,
CodeGenOpt::Level OptLevel);
FunctionPass *createARCExpandPseudosPass();
FunctionPass *createARCBranchFinalizePass();
} // end namespace llvm
#endif // LLVM_LIB_TARGET_ARC_ARC_H

View File

@ -1,25 +0,0 @@
//===- ARC.td - Describe the ARC Target Machine ------------*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
include "llvm/Target/Target.td"
include "ARCRegisterInfo.td"
include "ARCInstrInfo.td"
include "ARCCallingConv.td"
def ARCInstrInfo : InstrInfo;
class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, NoItineraries, Features>;
def : Proc<"generic", []>;
def ARC : Target {
let InstructionSet = ARCInstrInfo;
}

View File

@ -1,83 +0,0 @@
//===- ARCAsmPrinter.cpp - ARC LLVM assembly writer -------------*- 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 a printer that converts from our internal representation
// of machine-dependent LLVM code to GNU format ARC assembly language.
//
//===----------------------------------------------------------------------===//
#include "ARC.h"
#include "ARCInstrInfo.h"
#include "ARCMCInstLower.h"
#include "ARCSubtarget.h"
#include "ARCTargetMachine.h"
#include "ARCTargetStreamer.h"
#include "InstPrinter/ARCInstPrinter.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;
#define DEBUG_TYPE "asm-printer"
namespace {
class ARCAsmPrinter : public AsmPrinter {
ARCMCInstLower MCInstLowering;
ARCTargetStreamer &getTargetStreamer();
public:
explicit ARCAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
: AsmPrinter(TM, std::move(Streamer)),
MCInstLowering(&OutContext, *this) {}
StringRef getPassName() const override { return "ARC Assembly Printer"; }
void EmitInstruction(const MachineInstr *MI) override;
};
} // end anonymous namespace
ARCTargetStreamer &ARCAsmPrinter::getTargetStreamer() {
return static_cast<ARCTargetStreamer &>(*OutStreamer->getTargetStreamer());
}
void ARCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
SmallString<128> Str;
raw_svector_ostream O(Str);
switch (MI->getOpcode()) {
case ARC::DBG_VALUE:
llvm_unreachable("Should be handled target independently");
break;
}
MCInst TmpInst;
MCInstLowering.Lower(MI, TmpInst);
EmitToStreamer(*OutStreamer, TmpInst);
}
// Force static initialization.
extern "C" void LLVMInitializeARCAsmPrinter() {
RegisterAsmPrinter<ARCAsmPrinter> X(getTheARCTarget());
}

View File

@ -1,183 +0,0 @@
//===- ARCBranchFinalize.cpp - ARC conditional branches ---------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass takes existing conditional branches and expands them into longer
// range conditional branches.
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "arc-branch-finalize"
#include "ARCInstrInfo.h"
#include "ARCTargetMachine.h"
#include "MCTargetDesc/ARCInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/Support/Debug.h"
#include <vector>
using namespace llvm;
namespace llvm {
void initializeARCBranchFinalizePass(PassRegistry &Registry);
FunctionPass *createARCBranchFinalizePass();
} // end namespace llvm
namespace {
class ARCBranchFinalize : public MachineFunctionPass {
public:
static char ID;
ARCBranchFinalize() : MachineFunctionPass(ID) {
initializeARCBranchFinalizePass(*PassRegistry::getPassRegistry());
}
StringRef getPassName() const override {
return "ARC Branch Finalization Pass";
}
bool runOnMachineFunction(MachineFunction &MF) override;
void replaceWithBRcc(MachineInstr *MI) const;
void replaceWithCmpBcc(MachineInstr *MI) const;
private:
const ARCInstrInfo *TII{nullptr};
};
char ARCBranchFinalize::ID = 0;
} // end anonymous namespace
INITIALIZE_PASS_BEGIN(ARCBranchFinalize, "arc-branch-finalize",
"ARC finalize branches", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
INITIALIZE_PASS_END(ARCBranchFinalize, "arc-branch-finalize",
"ARC finalize branches", false, false)
// BRcc has 6 supported condition codes, which differ from the 16
// condition codes supported in the predicated instructions:
// EQ -- 000
// NE -- 001
// LT -- 010
// GE -- 011
// LO -- 100
// HS -- 101
static unsigned getCCForBRcc(unsigned CC) {
switch (CC) {
case ARCCC::EQ:
return 0;
case ARCCC::NE:
return 1;
case ARCCC::LT:
return 2;
case ARCCC::GE:
return 3;
case ARCCC::LO:
return 4;
case ARCCC::HS:
return 5;
default:
return -1U;
}
}
static bool isBRccPseudo(MachineInstr *MI) {
return !(MI->getOpcode() != ARC::BRcc_rr_p &&
MI->getOpcode() != ARC::BRcc_ru6_p);
}
static unsigned getBRccForPseudo(MachineInstr *MI) {
assert(isBRccPseudo(MI) && "Can't get BRcc for wrong instruction.");
if (MI->getOpcode() == ARC::BRcc_rr_p)
return ARC::BRcc_rr;
return ARC::BRcc_ru6;
}
static unsigned getCmpForPseudo(MachineInstr *MI) {
assert(isBRccPseudo(MI) && "Can't get BRcc for wrong instruction.");
if (MI->getOpcode() == ARC::BRcc_rr_p)
return ARC::CMP_rr;
return ARC::CMP_ru6;
}
void ARCBranchFinalize::replaceWithBRcc(MachineInstr *MI) const {
DEBUG(dbgs() << "Replacing pseudo branch with BRcc\n");
unsigned CC = getCCForBRcc(MI->getOperand(3).getImm());
if (CC != -1U) {
BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
TII->get(getBRccForPseudo(MI)))
.addMBB(MI->getOperand(0).getMBB())
.addReg(MI->getOperand(1).getReg())
.add(MI->getOperand(2))
.addImm(getCCForBRcc(MI->getOperand(3).getImm()));
MI->eraseFromParent();
} else {
replaceWithCmpBcc(MI);
}
}
void ARCBranchFinalize::replaceWithCmpBcc(MachineInstr *MI) const {
DEBUG(dbgs() << "Branch: " << *MI << "\n");
DEBUG(dbgs() << "Replacing pseudo branch with Cmp + Bcc\n");
BuildMI(*MI->getParent(), MI, MI->getDebugLoc(),
TII->get(getCmpForPseudo(MI)))
.addReg(MI->getOperand(1).getReg())
.add(MI->getOperand(2));
BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(ARC::Bcc))
.addMBB(MI->getOperand(0).getMBB())
.addImm(MI->getOperand(3).getImm());
MI->eraseFromParent();
}
bool ARCBranchFinalize::runOnMachineFunction(MachineFunction &MF) {
DEBUG(dbgs() << "Running ARC Branch Finalize on "
<< MF.getName() << "\n");
std::vector<MachineInstr *> Branches;
bool Changed = false;
unsigned MaxSize = 0;
TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
std::map<MachineBasicBlock *, unsigned> BlockToPCMap;
std::vector<std::pair<MachineInstr *, unsigned>> BranchToPCList;
unsigned PC = 0;
for (auto &MBB : MF) {
BlockToPCMap.insert(std::make_pair(&MBB, PC));
for (auto &MI : MBB) {
unsigned Size = TII->getInstSizeInBytes(MI);
if (Size > 8 || Size == 0) {
DEBUG(dbgs() << "Unknown (or size 0) size for: " << MI << "\n");
} else {
MaxSize += Size;
}
if (MI.isBranch()) {
Branches.push_back(&MI);
BranchToPCList.emplace_back(&MI, PC);
}
PC += Size;
}
}
for (auto P : BranchToPCList) {
if (isBRccPseudo(P.first))
isInt<9>(MaxSize) ? replaceWithBRcc(P.first) : replaceWithCmpBcc(P.first);
}
DEBUG(dbgs() << "Estimated function size for " << MF.getName()
<< ": " << MaxSize << "\n");
return Changed;
}
FunctionPass *llvm::createARCBranchFinalizePass() {
return new ARCBranchFinalize();
}

View File

@ -1,41 +0,0 @@
//===- ARCCallingConv.td - Calling Conventions for ARC -----*- tablegen -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This describes the calling conventions for ARC architecture.
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// ARC Return Value Calling Convention
//===----------------------------------------------------------------------===//
def RetCC_ARC : CallingConv<[
// i32 are returned in registers R0, R1, R2, R3
CCIfType<[i32, i64], CCAssignToReg<[R0, R1, R2, R3]>>,
// Integer values get stored in stack slots that are 4 bytes in
// size and 4-byte aligned.
CCIfType<[i64], CCAssignToStack<8, 4>>,
CCIfType<[i32], CCAssignToStack<4, 4>>
]>;
//===----------------------------------------------------------------------===//
// ARC Argument Calling Conventions
//===----------------------------------------------------------------------===//
def CC_ARC : CallingConv<[
// Promote i8/i16 arguments to i32.
CCIfType<[i8, i16], CCPromoteToType<i32>>,
// The first 8 integer arguments are passed in integer registers.
CCIfType<[i32, i64], CCAssignToReg<[R0, R1, R2, R3, R4, R5, R6, R7]>>,
// Integer values get stored in stack slots that are 4 bytes in
// size and 4-byte aligned.
CCIfType<[i64], CCAssignToStack<8, 4>>,
CCIfType<[i32], CCAssignToStack<4, 4>>
]>;
def CSR_ARC : CalleeSavedRegs<(add (sequence "R%u", 13, 25), GP, FP)>;

View File

@ -1,103 +0,0 @@
//===- ARCExpandPseudosPass - ARC expand pseudo loads -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass expands stores with large offsets into an appropriate sequence.
//===----------------------------------------------------------------------===//
#include "ARC.h"
#include "ARCInstrInfo.h"
#include "ARCRegisterInfo.h"
#include "ARCSubtarget.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
using namespace llvm;
#define DEBUG_TYPE "arc-expand-pseudos"
namespace {
class ARCExpandPseudos : public MachineFunctionPass {
public:
static char ID;
ARCExpandPseudos() : MachineFunctionPass(ID) {}
bool runOnMachineFunction(MachineFunction &Fn) override;
StringRef getPassName() const override { return "ARC Expand Pseudos"; }
private:
void ExpandStore(MachineFunction &, MachineBasicBlock::iterator);
const ARCInstrInfo *TII;
};
char ARCExpandPseudos::ID = 0;
} // end anonymous namespace
static unsigned getMappedOp(unsigned PseudoOp) {
switch (PseudoOp) {
case ARC::ST_FAR:
return ARC::ST_rs9;
case ARC::STH_FAR:
return ARC::STH_rs9;
case ARC::STB_FAR:
return ARC::STB_rs9;
default:
llvm_unreachable("Unhandled pseudo op.");
}
}
void ARCExpandPseudos::ExpandStore(MachineFunction &MF,
MachineBasicBlock::iterator SII) {
MachineInstr &SI = *SII;
unsigned AddrReg = MF.getRegInfo().createVirtualRegister(&ARC::GPR32RegClass);
unsigned AddOpc =
isUInt<6>(SI.getOperand(2).getImm()) ? ARC::ADD_rru6 : ARC::ADD_rrlimm;
BuildMI(*SI.getParent(), SI, SI.getDebugLoc(), TII->get(AddOpc), AddrReg)
.addReg(SI.getOperand(1).getReg())
.addImm(SI.getOperand(2).getImm());
BuildMI(*SI.getParent(), SI, SI.getDebugLoc(),
TII->get(getMappedOp(SI.getOpcode())))
.addReg(SI.getOperand(0).getReg())
.addReg(AddrReg)
.addImm(0);
SI.eraseFromParent();
}
bool ARCExpandPseudos::runOnMachineFunction(MachineFunction &MF) {
const ARCSubtarget *STI = &MF.getSubtarget<ARCSubtarget>();
TII = STI->getInstrInfo();
bool ExpandedStore = false;
for (auto &MBB : MF) {
MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
while (MBBI != E) {
MachineBasicBlock::iterator NMBBI = std::next(MBBI);
switch (MBBI->getOpcode()) {
case ARC::ST_FAR:
case ARC::STH_FAR:
case ARC::STB_FAR:
ExpandStore(MF, MBBI);
ExpandedStore = true;
break;
default:
break;
}
MBBI = NMBBI;
}
}
return ExpandedStore;
}
FunctionPass *llvm::createARCExpandPseudosPass() {
return new ARCExpandPseudos();
}

View File

@ -1,471 +0,0 @@
//===- ARCFrameLowering.cpp - ARC Frame 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 ARC implementation of the TargetFrameLowering class.
//
//===----------------------------------------------------------------------===//
#include "ARCFrameLowering.h"
#include "ARCMachineFunctionInfo.h"
#include "ARCSubtarget.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/Debug.h"
#define DEBUG_TYPE "arc-frame-lowering"
using namespace llvm;
static cl::opt<bool>
UseSaveRestoreFunclet("arc-save-restore-funclet", cl::Hidden,
cl::desc("Use arc callee save/restore functions"),
cl::init(true));
static const char *store_funclet_name[] = {
"__st_r13_to_r15", "__st_r13_to_r16", "__st_r13_to_r17", "__st_r13_to_r18",
"__st_r13_to_r19", "__st_r13_to_r20", "__st_r13_to_r21", "__st_r13_to_r22",
"__st_r13_to_r23", "__st_r13_to_r24", "__st_r13_to_r25",
};
static const char *load_funclet_name[] = {
"__ld_r13_to_r15", "__ld_r13_to_r16", "__ld_r13_to_r17", "__ld_r13_to_r18",
"__ld_r13_to_r19", "__ld_r13_to_r20", "__ld_r13_to_r21", "__ld_r13_to_r22",
"__ld_r13_to_r23", "__ld_r13_to_r24", "__ld_r13_to_r25",
};
static void generateStackAdjustment(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
const ARCInstrInfo &TII, DebugLoc dl,
int Amount, int StackPtr) {
unsigned AdjOp;
if (!Amount)
return;
bool Positive;
unsigned AbsAmount;
if (Amount < 0) {
AbsAmount = -Amount;
Positive = false;
} else {
AbsAmount = Amount;
Positive = true;
}
DEBUG(dbgs() << "Internal: adjust stack by: " << Amount << "," << AbsAmount
<< "\n");
assert((AbsAmount % 4 == 0) && "Stack adjustments must be 4-byte aligned.");
if (isUInt<6>(AbsAmount))
AdjOp = Positive ? ARC::ADD_rru6 : ARC::SUB_rru6;
else
AdjOp = Positive ? ARC::ADD_rrlimm : ARC::SUB_rrlimm;
BuildMI(MBB, MBBI, dl, TII.get(AdjOp), StackPtr)
.addReg(StackPtr)
.addImm(AbsAmount);
}
static unsigned
determineLastCalleeSave(const std::vector<CalleeSavedInfo> &CSI) {
unsigned Last = 0;
for (auto Reg : CSI) {
assert(Reg.getReg() >= ARC::R13 && Reg.getReg() <= ARC::R25 &&
"Unexpected callee saved reg.");
if (Reg.getReg() > Last)
Last = Reg.getReg();
}
return Last;
}
void ARCFrameLowering::determineCalleeSaves(MachineFunction &MF,
BitVector &SavedRegs,
RegScavenger *RS) const {
DEBUG(dbgs() << "Determine Callee Saves: " << MF.getName()
<< "\n");
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
SavedRegs.set(ARC::BLINK);
}
void ARCFrameLowering::adjustStackToMatchRecords(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
bool Allocate) const {
MachineFunction &MF = *MBB.getParent();
int ScalarAlloc = MF.getFrameInfo().getStackSize();
if (Allocate) {
// Allocate by adjusting by the negative of what the record holder tracked
// it tracked a positive offset in a downward growing stack.
ScalarAlloc = -ScalarAlloc;
}
generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), DebugLoc(),
ScalarAlloc, ARC::SP);
}
/// Insert prolog code into the function.
/// For ARC, this inserts a call to a function that puts required callee saved
/// registers onto the stack, when enough callee saved registers are required.
void ARCFrameLowering::emitPrologue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
DEBUG(dbgs() << "Emit Prologue: " << MF.getName() << "\n");
auto *AFI = MF.getInfo<ARCFunctionInfo>();
MachineModuleInfo &MMI = MF.getMMI();
MCContext &Context = MMI.getContext();
const MCRegisterInfo *MRI = Context.getRegisterInfo();
const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
MachineBasicBlock::iterator MBBI = MBB.begin();
// Debug location must be unknown since the first debug location is used
// to determine the end of the prologue.
DebugLoc dl;
MachineFrameInfo &MFI = MF.getFrameInfo();
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
unsigned Last = determineLastCalleeSave(CSI);
unsigned StackSlotsUsedByFunclet = 0;
bool SavedBlink = false;
unsigned AlreadyAdjusted = 0;
if (MF.getFunction().isVarArg()) {
// Add in the varargs area here first.
DEBUG(dbgs() << "Varargs\n");
unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());
BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
.addReg(ARC::SP)
.addReg(ARC::SP)
.addImm(VarArgsBytes);
}
if (hasFP(MF)) {
DEBUG(dbgs() << "Saving FP\n");
BuildMI(MBB, MBBI, dl, TII->get(ARC::ST_AW_rs9))
.addReg(ARC::SP, RegState::Define)
.addReg(ARC::FP)
.addReg(ARC::SP)
.addImm(-4);
AlreadyAdjusted += 4;
}
if (UseSaveRestoreFunclet && Last > ARC::R14) {
DEBUG(dbgs() << "Creating store funclet.\n");
// BL to __save_r13_to_<TRI->getRegAsmName()>
StackSlotsUsedByFunclet = Last - ARC::R12;
BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
BuildMI(MBB, MBBI, dl, TII->get(ARC::SUB_rru6))
.addReg(ARC::SP)
.addReg(ARC::SP)
.addImm(4 * StackSlotsUsedByFunclet);
BuildMI(MBB, MBBI, dl, TII->get(ARC::BL))
.addExternalSymbol(store_funclet_name[Last - ARC::R15])
.addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);
AlreadyAdjusted += 4 * (StackSlotsUsedByFunclet + 1);
SavedBlink = true;
}
// If we haven't saved BLINK, but we need to...do that now.
if (MFI.hasCalls() && !SavedBlink) {
DEBUG(dbgs() << "Creating save blink.\n");
BuildMI(MBB, MBBI, dl, TII->get(ARC::PUSH_S_BLINK));
AlreadyAdjusted += 4;
}
if (AFI->MaxCallStackReq > 0)
MFI.setStackSize(MFI.getStackSize() + AFI->MaxCallStackReq);
// We have already saved some of the stack...
DEBUG(dbgs() << "Adjusting stack by: "
<< (MFI.getStackSize() - AlreadyAdjusted) << "\n");
generateStackAdjustment(MBB, MBBI, *ST.getInstrInfo(), dl,
-(MFI.getStackSize() - AlreadyAdjusted), ARC::SP);
if (hasFP(MF)) {
DEBUG(dbgs() << "Setting FP from SP.\n");
BuildMI(MBB, MBBI, dl,
TII->get(isUInt<6>(MFI.getStackSize()) ? ARC::ADD_rru6
: ARC::ADD_rrlimm),
ARC::FP)
.addReg(ARC::SP)
.addImm(MFI.getStackSize());
}
// Emit CFI records:
// .cfi_def_cfa_offset StackSize
// .cfi_offset fp, -StackSize
// .cfi_offset blink, -StackSize+4
unsigned CFIIndex = MF.addFrameInst(
MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize()));
BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlags(MachineInstr::FrameSetup);
int CurOffset = -4;
if (hasFP(MF)) {
CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
nullptr, MRI->getDwarfRegNum(ARC::FP, true), CurOffset));
BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlags(MachineInstr::FrameSetup);
CurOffset -= 4;
}
if (MFI.hasCalls()) {
CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
nullptr, MRI->getDwarfRegNum(ARC::BLINK, true), CurOffset));
BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlags(MachineInstr::FrameSetup);
}
// CFI for the rest of the registers.
for (const auto &Entry : CSI) {
unsigned Reg = Entry.getReg();
int FI = Entry.getFrameIdx();
// Skip BLINK and FP.
if ((hasFP(MF) && Reg == ARC::FP) || (MFI.hasCalls() && Reg == ARC::BLINK))
continue;
CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset(
nullptr, MRI->getDwarfRegNum(Reg, true), MFI.getObjectOffset(FI)));
BuildMI(MBB, MBBI, dl, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex)
.setMIFlags(MachineInstr::FrameSetup);
}
}
/// Insert epilog code into the function.
/// For ARC, this inserts a call to a function that restores callee saved
/// registers onto the stack, when enough callee saved registers are required.
void ARCFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
DEBUG(dbgs() << "Emit Epilogue: " << MF.getName() << "\n");
auto *AFI = MF.getInfo<ARCFunctionInfo>();
const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
MachineFrameInfo &MFI = MF.getFrameInfo();
uint64_t StackSize = MF.getFrameInfo().getStackSize();
bool SavedBlink = false;
unsigned AmountAboveFunclet = 0;
// If we have variable sized frame objects, then we have to move
// the stack pointer to a known spot (fp - StackSize).
// Then, replace the frame pointer by (new) [sp,StackSize-4].
// Then, move the stack pointer the rest of the way (sp = sp + StackSize).
if (hasFP(MF)) {
BuildMI(MBB, MBBI, DebugLoc(), TII->get(ARC::SUB_rru6), ARC::SP)
.addReg(ARC::FP)
.addImm(StackSize);
AmountAboveFunclet += 4;
}
// Now, move the stack pointer to the bottom of the save area for the funclet.
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
unsigned Last = determineLastCalleeSave(CSI);
unsigned StackSlotsUsedByFunclet = 0;
// Now, restore the callee save registers.
if (UseSaveRestoreFunclet && Last > ARC::R14) {
// BL to __ld_r13_to_<TRI->getRegAsmName()>
StackSlotsUsedByFunclet = Last - ARC::R12;
AmountAboveFunclet += 4 * (StackSlotsUsedByFunclet + 1);
SavedBlink = true;
}
if (MFI.hasCalls() && !SavedBlink) {
AmountAboveFunclet += 4;
SavedBlink = true;
}
// Move the stack pointer up to the point of the funclet.
if (StackSize - AmountAboveFunclet) {
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
.addReg(ARC::SP)
.addReg(ARC::SP)
.addImm(StackSize - AmountAboveFunclet);
}
if (StackSlotsUsedByFunclet) {
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::BL))
.addExternalSymbol(load_funclet_name[Last - ARC::R15])
.addReg(ARC::BLINK, RegState::Implicit | RegState::Kill);
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
.addReg(ARC::SP)
.addReg(ARC::SP)
.addImm(4 * (StackSlotsUsedByFunclet));
}
// Now, pop blink if necessary.
if (SavedBlink) {
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::POP_S_BLINK));
}
// Now, pop fp if necessary.
if (hasFP(MF)) {
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::LD_AB_rs9))
.addReg(ARC::SP, RegState::Define)
.addReg(ARC::FP, RegState::Define)
.addReg(ARC::SP)
.addImm(4);
}
// Relieve the varargs area if necessary.
if (MF.getFunction().isVarArg()) {
// Add in the varargs area here first.
DEBUG(dbgs() << "Varargs\n");
unsigned VarArgsBytes = MFI.getObjectSize(AFI->getVarArgsFrameIndex());
BuildMI(MBB, MBBI, MBB.findDebugLoc(MBBI), TII->get(ARC::ADD_rru6))
.addReg(ARC::SP)
.addReg(ARC::SP)
.addImm(VarArgsBytes);
}
}
static std::vector<CalleeSavedInfo>::iterator
getSavedReg(std::vector<CalleeSavedInfo> &V, unsigned reg) {
for (auto I = V.begin(), E = V.end(); I != E; ++I) {
if (reg == I->getReg())
return I;
}
return V.end();
}
bool ARCFrameLowering::assignCalleeSavedSpillSlots(
MachineFunction &MF, const TargetRegisterInfo *TRI,
std::vector<CalleeSavedInfo> &CSI) const {
// Use this opportunity to assign the spill slots for all of the potential
// callee save registers (blink, fp, r13->r25) that we care about the
// placement for. We can calculate all of that data here.
int CurOffset = -4;
unsigned Last = determineLastCalleeSave(CSI);
MachineFrameInfo &MFI = MF.getFrameInfo();
if (hasFP(MF)) {
// Create a fixed slot at for FP
int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for FP at "
<< CurOffset << "\n");
(void)StackObj;
CurOffset -= 4;
}
if (MFI.hasCalls() || (UseSaveRestoreFunclet && Last > ARC::R14)) {
// Create a fixed slot for BLINK.
int StackObj = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
DEBUG(dbgs() << "Creating fixed object (" << StackObj << ") for BLINK at "
<< CurOffset << "\n");
(void)StackObj;
CurOffset -= 4;
}
// Create slots for last down to r13.
for (unsigned Which = Last; Which > ARC::R12; Which--) {
auto RegI = getSavedReg(CSI, Which);
if (RegI == CSI.end() || RegI->getFrameIdx() == 0) {
// Always create the stack slot. If for some reason the register isn't in
// the save list, then don't worry about it.
int FI = MFI.CreateFixedSpillStackObject(4, CurOffset, true);
if (RegI != CSI.end())
RegI->setFrameIdx(FI);
} else
MFI.setObjectOffset(RegI->getFrameIdx(), CurOffset);
CurOffset -= 4;
}
for (auto &I : CSI) {
if (I.getReg() > ARC::R12)
continue;
if (I.getFrameIdx() == 0) {
I.setFrameIdx(MFI.CreateFixedSpillStackObject(4, CurOffset, true));
DEBUG(dbgs() << "Creating fixed object (" << I.getFrameIdx()
<< ") for other register at " << CurOffset << "\n");
} else {
MFI.setObjectOffset(I.getFrameIdx(), CurOffset);
DEBUG(dbgs() << "Updating fixed object (" << I.getFrameIdx()
<< ") for other register at " << CurOffset << "\n");
}
CurOffset -= 4;
}
return true;
}
bool ARCFrameLowering::spillCalleeSavedRegisters(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
DEBUG(dbgs() << "Spill callee saved registers: "
<< MBB.getParent()->getName() << "\n");
// There are routines for saving at least 3 registers (r13 to r15, etc.)
unsigned Last = determineLastCalleeSave(CSI);
if (UseSaveRestoreFunclet && Last > ARC::R14) {
// Use setObjectOffset for these registers.
// Needs to be in or before processFunctionBeforeFrameFinalized.
// Or, do assignCalleeSaveSpillSlots?
// Will be handled in prolog.
return true;
}
return false;
}
bool ARCFrameLowering::restoreCalleeSavedRegisters(
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const {
DEBUG(dbgs() << "Restore callee saved registers: "
<< MBB.getParent()->getName() << "\n");
// There are routines for saving at least 3 registers (r13 to r15, etc.)
unsigned Last = determineLastCalleeSave(CSI);
if (UseSaveRestoreFunclet && Last > ARC::R14) {
// Will be handled in epilog.
return true;
}
return false;
}
// Adjust local variables that are 4-bytes or larger to 4-byte boundary
void ARCFrameLowering::processFunctionBeforeFrameFinalized(
MachineFunction &MF, RegScavenger *RS) const {
const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
DEBUG(dbgs() << "Process function before frame finalized: "
<< MF.getName() << "\n");
MachineFrameInfo &MFI = MF.getFrameInfo();
DEBUG(dbgs() << "Current stack size: " << MFI.getStackSize() << "\n");
const TargetRegisterClass *RC = &ARC::GPR32RegClass;
if (MFI.hasStackObjects()) {
int RegScavFI = MFI.CreateStackObject(
RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false);
RS->addScavengingFrameIndex(RegScavFI);
DEBUG(dbgs() << "Created scavenging index RegScavFI=" << RegScavFI << "\n");
}
}
static void emitRegUpdate(MachineBasicBlock &MBB,
MachineBasicBlock::iterator &MBBI, DebugLoc dl,
unsigned Reg, int NumBytes, bool IsAdd,
const ARCInstrInfo *TII) {
unsigned Opc = IsAdd ? ARC::ADD_rru6 : ARC::SUB_rru6;
BuildMI(MBB, MBBI, dl, TII->get(Opc), Reg)
.addReg(Reg, RegState::Kill)
.addImm(NumBytes);
}
MachineBasicBlock::iterator ARCFrameLowering::eliminateCallFramePseudoInstr(
MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
DEBUG(dbgs() << "EmitCallFramePseudo: " << MF.getName() << "\n");
const ARCInstrInfo *TII = MF.getSubtarget<ARCSubtarget>().getInstrInfo();
MachineInstr &Old = *I;
DebugLoc dl = Old.getDebugLoc();
unsigned Amt = Old.getOperand(0).getImm();
auto *AFI = MF.getInfo<ARCFunctionInfo>();
if (!hasFP(MF)) {
if (Amt > AFI->MaxCallStackReq && Old.getOpcode() == ARC::ADJCALLSTACKDOWN)
AFI->MaxCallStackReq = Amt;
} else {
if (Amt != 0) {
assert((Old.getOpcode() == ARC::ADJCALLSTACKDOWN ||
Old.getOpcode() == ARC::ADJCALLSTACKUP) &&
"Unknown Frame Pseudo.");
bool IsAdd = (Old.getOpcode() == ARC::ADJCALLSTACKUP);
emitRegUpdate(MBB, I, dl, ARC::SP, Amt, IsAdd, TII);
}
}
return MBB.erase(I);
}
bool ARCFrameLowering::hasFP(const MachineFunction &MF) const {
const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
bool HasFP = MF.getTarget().Options.DisableFramePointerElim(MF) ||
MF.getFrameInfo().hasVarSizedObjects() ||
MF.getFrameInfo().isFrameAddressTaken() ||
RegInfo->needsStackRealignment(MF);
return HasFP;
}

View File

@ -1,78 +0,0 @@
//===- ARCFrameLowering.h - Define frame lowering for ARC -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class implements the ARC specific frame lowering.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_ARC_ARCFRAMELOWERING_H
#define LLVM_LIB_TARGET_ARC_ARCFRAMELOWERING_H
#include "ARC.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
namespace llvm {
class MachineFunction;
class ARCSubtarget;
class ARCInstrInfo;
class ARCFrameLowering : public TargetFrameLowering {
public:
ARCFrameLowering(const ARCSubtarget &st)
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0), ST(st) {
}
/// Insert Prologue into the function.
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
/// Insert Epilogue into the function.
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
/// Add explicit callee save registers.
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
RegScavenger *RS) const override;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const override;
bool
restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const override;
void processFunctionBeforeFrameFinalized(MachineFunction &MF,
RegScavenger *RS) const override;
bool hasFP(const MachineFunction &MF) const override;
MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const override;
bool assignCalleeSavedSpillSlots(
llvm::MachineFunction &, const llvm::TargetRegisterInfo *,
std::vector<llvm::CalleeSavedInfo> &) const override;
private:
void adjustStackToMatchRecords(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
bool allocate) const;
const ARCSubtarget &ST;
};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_ARC_ARCFRAMELOWERING_H

View File

@ -1,182 +0,0 @@
//===- ARCISelDAGToDAG.cpp - ARC dag to dag inst selector -------*- 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 an instruction selector for the ARC target.
//
//===----------------------------------------------------------------------===//
#include "ARC.h"
#include "ARCTargetMachine.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
/// ARCDAGToDAGISel - ARC specific code to select ARC machine
/// instructions for SelectionDAG operations.
namespace {
class ARCDAGToDAGISel : public SelectionDAGISel {
public:
ARCDAGToDAGISel(ARCTargetMachine &TM, CodeGenOpt::Level OptLevel)
: SelectionDAGISel(TM, OptLevel) {}
void Select(SDNode *N) override;
// Complex Pattern Selectors.
bool SelectFrameADDR_ri(SDValue Addr, SDValue &Base, SDValue &Offset);
bool SelectAddrModeS9(SDValue Addr, SDValue &Base, SDValue &Offset);
bool SelectAddrModeImm(SDValue Addr, SDValue &Base, SDValue &Offset);
bool SelectAddrModeFar(SDValue Addr, SDValue &Base, SDValue &Offset);
bool SelectCMOVPred(SDValue N, SDValue &Pred, SDValue &Reg) {
const ConstantSDNode *CN = cast<ConstantSDNode>(N);
Pred = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(N), MVT::i32);
Reg = CurDAG->getRegister(ARC::STATUS32, MVT::i32);
return true;
}
StringRef getPassName() const override {
return "ARC DAG->DAG Pattern Instruction Selection";
}
// Include the pieces autogenerated from the target description.
#include "ARCGenDAGISel.inc"
};
} // end anonymous namespace
/// This pass converts a legalized DAG into a ARC-specific DAG, ready for
/// instruction scheduling.
FunctionPass *llvm::createARCISelDag(ARCTargetMachine &TM,
CodeGenOpt::Level OptLevel) {
return new ARCDAGToDAGISel(TM, OptLevel);
}
bool ARCDAGToDAGISel::SelectAddrModeImm(SDValue Addr, SDValue &Base,
SDValue &Offset) {
if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
Base = Addr.getOperand(0);
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
return true;
}
return false;
}
bool ARCDAGToDAGISel::SelectAddrModeS9(SDValue Addr, SDValue &Base,
SDValue &Offset) {
if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
return false;
}
if (Addr.getOpcode() != ISD::ADD && Addr.getOpcode() != ISD::SUB &&
!CurDAG->isBaseWithConstantOffset(Addr)) {
if (Addr.getOpcode() == ISD::FrameIndex) {
// Match frame index.
int FI = cast<FrameIndexSDNode>(Addr)->getIndex();
Base = CurDAG->getTargetFrameIndex(
FI, TLI->getPointerTy(CurDAG->getDataLayout()));
} else {
Base = Addr;
}
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
return true;
}
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
int32_t RHSC = RHS->getSExtValue();
if (Addr.getOpcode() == ISD::SUB)
RHSC = -RHSC;
// Do we need more than 9 bits to encode?
if (!isInt<9>(RHSC))
return false;
Base = Addr.getOperand(0);
if (Base.getOpcode() == ISD::FrameIndex) {
int FI = cast<FrameIndexSDNode>(Base)->getIndex();
Base = CurDAG->getTargetFrameIndex(
FI, TLI->getPointerTy(CurDAG->getDataLayout()));
}
Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);
return true;
}
Base = Addr;
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
return true;
}
bool ARCDAGToDAGISel::SelectAddrModeFar(SDValue Addr, SDValue &Base,
SDValue &Offset) {
if (SelectAddrModeS9(Addr, Base, Offset))
return false;
if (Addr.getOpcode() == ARCISD::GAWRAPPER) {
return false;
}
if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
int32_t RHSC = RHS->getSExtValue();
if (Addr.getOpcode() == ISD::SUB)
RHSC = -RHSC;
Base = Addr.getOperand(0);
Offset = CurDAG->getTargetConstant(RHSC, SDLoc(Addr), MVT::i32);
return true;
}
return false;
}
// Is this a legal frame index addressing expression.
bool ARCDAGToDAGISel::SelectFrameADDR_ri(SDValue Addr, SDValue &Base,
SDValue &Offset) {
FrameIndexSDNode *FIN = nullptr;
if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), MVT::i32);
return true;
}
if (Addr.getOpcode() == ISD::ADD) {
ConstantSDNode *CN = nullptr;
if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&
(CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&
(CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
// Constant positive word offset from frame index
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
Offset =
CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Addr), MVT::i32);
return true;
}
}
return false;
}
void ARCDAGToDAGISel::Select(SDNode *N) {
switch (N->getOpcode()) {
case ISD::Constant: {
uint64_t CVal = cast<ConstantSDNode>(N)->getZExtValue();
ReplaceNode(N, CurDAG->getMachineNode(
isInt<12>(CVal) ? ARC::MOV_rs12 : ARC::MOV_rlimm,
SDLoc(N), MVT::i32,
CurDAG->getTargetConstant(CVal, SDLoc(N), MVT::i32)));
return;
}
}
SelectCode(N);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,121 +0,0 @@
//===- ARCISelLowering.h - ARC 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 ARC uses to lower LLVM code into a
// selection DAG.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_ARC_ARCISELLOWERING_H
#define LLVM_LIB_TARGET_ARC_ARCISELLOWERING_H
#include "ARC.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/TargetLowering.h"
namespace llvm {
// Forward delcarations
class ARCSubtarget;
class ARCTargetMachine;
namespace ARCISD {
enum NodeType : unsigned {
// Start the numbering where the builtin ops and target ops leave off.
FIRST_NUMBER = ISD::BUILTIN_OP_END,
// Branch and link (call)
BL,
// Jump and link (indirect call)
JL,
// CMP
CMP,
// CMOV
CMOV,
// BRcc
BRcc,
// Global Address Wrapper
GAWRAPPER,
// return, (j_s [blink])
RET
};
} // end namespace ARCISD
//===--------------------------------------------------------------------===//
// TargetLowering Implementation
//===--------------------------------------------------------------------===//
class ARCTargetLowering : public TargetLowering {
public:
explicit ARCTargetLowering(const TargetMachine &TM,
const ARCSubtarget &Subtarget);
/// Provide custom lowering hooks for some operations.
SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
/// This method returns the name of a target specific DAG node.
const char *getTargetNodeName(unsigned Opcode) const override;
/// Return true if the addressing mode represented by AM is legal for this
/// target, for a load/store of the specified type.
bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
unsigned AS,
Instruction *I = nullptr) const override;
private:
const TargetMachine &TM;
const ARCSubtarget &Subtarget;
// Lower Operand helpers
SDValue LowerCallArguments(SDValue Chain, CallingConv::ID CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
SDLoc dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const;
// Lower Operand specifics
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
const SDLoc &dl, SelectionDAG &DAG,
SmallVectorImpl<SDValue> &InVals) const override;
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
SmallVectorImpl<SDValue> &InVals) const override;
SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
SelectionDAG &DAG) const override;
bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &ArgsFlags,
LLVMContext &Context) const override;
bool mayBeEmittedAsTailCall(const CallInst *CI) const override;
};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_ARC_ARCISELLOWERING_H

File diff suppressed because it is too large Load Diff

View File

@ -1,394 +0,0 @@
//===- ARCInstrInfo.cpp - ARC 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 ARC implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#include "ARCInstrInfo.h"
#include "ARC.h"
#include "ARCMachineFunctionInfo.h"
#include "ARCSubtarget.h"
#include "MCTargetDesc/ARCInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
#define GET_INSTRINFO_CTOR_DTOR
#include "ARCGenInstrInfo.inc"
#define DEBUG_TYPE "arc-inst-info"
// Pin the vtable to this file.
void ARCInstrInfo::anchor() {}
ARCInstrInfo::ARCInstrInfo()
: ARCGenInstrInfo(ARC::ADJCALLSTACKDOWN, ARC::ADJCALLSTACKUP), RI() {}
static bool isZeroImm(const MachineOperand &Op) {
return Op.isImm() && Op.getImm() == 0;
}
static bool isLoad(int Opcode) {
return Opcode == ARC::LD_rs9 || Opcode == ARC::LDH_rs9 ||
Opcode == ARC::LDB_rs9;
}
static bool isStore(int Opcode) {
return Opcode == ARC::ST_rs9 || Opcode == ARC::STH_rs9 ||
Opcode == ARC::STB_rs9;
}
/// If the specified machine instruction is a direct
/// load from a stack slot, return the virtual or physical register number of
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
unsigned ARCInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
int Opcode = MI.getOpcode();
if (isLoad(Opcode)) {
if ((MI.getOperand(1).isFI()) && // is a stack slot
(MI.getOperand(2).isImm()) && // the imm is zero
(isZeroImm(MI.getOperand(2)))) {
FrameIndex = MI.getOperand(1).getIndex();
return MI.getOperand(0).getReg();
}
}
return 0;
}
/// If the specified machine instruction is a direct
/// store to a stack slot, return the virtual or physical register number of
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
unsigned ARCInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
int Opcode = MI.getOpcode();
if (isStore(Opcode)) {
if ((MI.getOperand(1).isFI()) && // is a stack slot
(MI.getOperand(2).isImm()) && // the imm is zero
(isZeroImm(MI.getOperand(2)))) {
FrameIndex = MI.getOperand(1).getIndex();
return MI.getOperand(0).getReg();
}
}
return 0;
}
/// Return the inverse of passed condition, i.e. turning COND_E to COND_NE.
static ARCCC::CondCode GetOppositeBranchCondition(ARCCC::CondCode CC) {
switch (CC) {
default:
llvm_unreachable("Illegal condition code!");
case ARCCC::EQ:
return ARCCC::NE;
case ARCCC::NE:
return ARCCC::EQ;
case ARCCC::LO:
return ARCCC::HS;
case ARCCC::HS:
return ARCCC::LO;
case ARCCC::GT:
return ARCCC::LE;
case ARCCC::GE:
return ARCCC::LT;
case ARCCC::LT:
return ARCCC::GE;
case ARCCC::LE:
return ARCCC::GT;
case ARCCC::HI:
return ARCCC::LS;
case ARCCC::LS:
return ARCCC::HI;
case ARCCC::NZ:
return ARCCC::Z;
case ARCCC::Z:
return ARCCC::NZ;
}
}
static bool isUncondBranchOpcode(int Opc) { return Opc == ARC::BR; }
static bool isCondBranchOpcode(int Opc) {
return Opc == ARC::BRcc_rr_p || Opc == ARC::BRcc_ru6_p;
}
static bool isJumpOpcode(int Opc) { return Opc == ARC::J; }
/// Analyze the branching code at the end of MBB, returning
/// true if it cannot be understood (e.g. it's a switch dispatch or isn't
/// implemented for a target). Upon success, this returns false and returns
/// with the following information in various cases:
///
/// 1. If this block ends with no branches (it just falls through to its succ)
/// just return false, leaving TBB/FBB null.
/// 2. If this block ends with only an unconditional branch, it sets TBB to be
/// the destination block.
/// 3. If this block ends with a conditional branch and it falls through to a
/// successor block, it sets TBB to be the branch destination block and a
/// list of operands that evaluate the condition. These operands can be
/// passed to other TargetInstrInfo methods to create new branches.
/// 4. If this block ends with a conditional branch followed by an
/// unconditional branch, it returns the 'true' destination in TBB, the
/// 'false' destination in FBB, and a list of operands that evaluate the
/// condition. These operands can be passed to other TargetInstrInfo
/// methods to create new branches.
///
/// Note that RemoveBranch and InsertBranch must be implemented to support
/// cases where this method returns success.
///
/// If AllowModify is true, then this routine is allowed to modify the basic
/// block (e.g. delete instructions after the unconditional branch).
bool ARCInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
bool AllowModify) const {
TBB = FBB = nullptr;
MachineBasicBlock::iterator I = MBB.end();
if (I == MBB.begin())
return false;
--I;
while (isPredicated(*I) || I->isTerminator() || I->isDebugValue()) {
// Flag to be raised on unanalyzeable instructions. This is useful in cases
// where we want to clean up on the end of the basic block before we bail
// out.
bool CantAnalyze = false;
// Skip over DEBUG values and predicated nonterminators.
while (I->isDebugValue() || !I->isTerminator()) {
if (I == MBB.begin())
return false;
--I;
}
if (isJumpOpcode(I->getOpcode())) {
// Indirect branches and jump tables can't be analyzed, but we still want
// to clean up any instructions at the tail of the basic block.
CantAnalyze = true;
} else if (isUncondBranchOpcode(I->getOpcode())) {
TBB = I->getOperand(0).getMBB();
} else if (isCondBranchOpcode(I->getOpcode())) {
// Bail out if we encounter multiple conditional branches.
if (!Cond.empty())
return true;
assert(!FBB && "FBB should have been null.");
FBB = TBB;
TBB = I->getOperand(0).getMBB();
Cond.push_back(I->getOperand(1));
Cond.push_back(I->getOperand(2));
Cond.push_back(I->getOperand(3));
} else if (I->isReturn()) {
// Returns can't be analyzed, but we should run cleanup.
CantAnalyze = !isPredicated(*I);
} else {
// We encountered other unrecognized terminator. Bail out immediately.
return true;
}
// Cleanup code - to be run for unpredicated unconditional branches and
// returns.
if (!isPredicated(*I) && (isUncondBranchOpcode(I->getOpcode()) ||
isJumpOpcode(I->getOpcode()) || I->isReturn())) {
// Forget any previous condition branch information - it no longer
// applies.
Cond.clear();
FBB = nullptr;
// If we can modify the function, delete everything below this
// unconditional branch.
if (AllowModify) {
MachineBasicBlock::iterator DI = std::next(I);
while (DI != MBB.end()) {
MachineInstr &InstToDelete = *DI;
++DI;
InstToDelete.eraseFromParent();
}
}
}
if (CantAnalyze)
return true;
if (I == MBB.begin())
return false;
--I;
}
// We made it past the terminators without bailing out - we must have
// analyzed this branch successfully.
return false;
}
unsigned ARCInstrInfo::removeBranch(MachineBasicBlock &MBB,
int *BytesRemoved) const {
assert(!BytesRemoved && "Code size not handled");
MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
if (I == MBB.end())
return 0;
if (!isUncondBranchOpcode(I->getOpcode()) &&
!isCondBranchOpcode(I->getOpcode()))
return 0;
// Remove the branch.
I->eraseFromParent();
I = MBB.end();
if (I == MBB.begin())
return 1;
--I;
if (!isCondBranchOpcode(I->getOpcode()))
return 1;
// Remove the branch.
I->eraseFromParent();
return 2;
}
void ARCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
const DebugLoc &dl, unsigned DestReg,
unsigned SrcReg, bool KillSrc) const {
assert(ARC::GPR32RegClass.contains(SrcReg) &&
"Only GPR32 src copy supported.");
assert(ARC::GPR32RegClass.contains(DestReg) &&
"Only GPR32 dest copy supported.");
BuildMI(MBB, I, dl, get(ARC::MOV_rr), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc));
}
void ARCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned SrcReg, bool isKill,
int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
DebugLoc dl = MBB.findDebugLoc(I);
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
unsigned Align = MFI.getObjectAlignment(FrameIndex);
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FrameIndex),
MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex), Align);
assert(MMO && "Couldn't get MachineMemOperand for store to stack.");
assert(TRI->getSpillSize(*RC) == 4 &&
"Only support 4-byte stores to stack now.");
assert(ARC::GPR32RegClass.hasSubClassEq(RC) &&
"Only support GPR32 stores to stack now.");
DEBUG(dbgs() << "Created store reg=" << printReg(SrcReg, TRI)
<< " to FrameIndex=" << FrameIndex << "\n");
BuildMI(MBB, I, dl, get(ARC::ST_rs9))
.addReg(SrcReg, getKillRegState(isKill))
.addFrameIndex(FrameIndex)
.addImm(0)
.addMemOperand(MMO);
}
void ARCInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned DestReg, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
DebugLoc dl = MBB.findDebugLoc(I);
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
unsigned Align = MFI.getObjectAlignment(FrameIndex);
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FrameIndex),
MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex), Align);
assert(MMO && "Couldn't get MachineMemOperand for store to stack.");
assert(TRI->getSpillSize(*RC) == 4 &&
"Only support 4-byte loads from stack now.");
assert(ARC::GPR32RegClass.hasSubClassEq(RC) &&
"Only support GPR32 stores to stack now.");
DEBUG(dbgs() << "Created load reg=" << printReg(DestReg, TRI)
<< " from FrameIndex=" << FrameIndex << "\n");
BuildMI(MBB, I, dl, get(ARC::LD_rs9))
.addReg(DestReg, RegState::Define)
.addFrameIndex(FrameIndex)
.addImm(0)
.addMemOperand(MMO);
}
/// Return the inverse opcode of the specified Branch instruction.
bool ARCInstrInfo::reverseBranchCondition(
SmallVectorImpl<MachineOperand> &Cond) const {
assert((Cond.size() == 3) && "Invalid ARC branch condition!");
Cond[2].setImm(GetOppositeBranchCondition((ARCCC::CondCode)Cond[2].getImm()));
return false;
}
MachineBasicBlock::iterator
ARCInstrInfo::loadImmediate(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, unsigned Reg,
uint64_t Value) const {
DebugLoc dl = MBB.findDebugLoc(MI);
if (isInt<12>(Value)) {
return BuildMI(MBB, MI, dl, get(ARC::MOV_rs12), Reg)
.addImm(Value)
.getInstr();
}
llvm_unreachable("Need Arc long immediate instructions.");
}
unsigned ARCInstrInfo::insertBranch(MachineBasicBlock &MBB,
MachineBasicBlock *TBB,
MachineBasicBlock *FBB,
ArrayRef<MachineOperand> Cond,
const DebugLoc &dl, int *BytesAdded) const {
assert(!BytesAdded && "Code size not handled.");
// Shouldn't be a fall through.
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
assert((Cond.size() == 3 || Cond.size() == 0) &&
"ARC branch conditions have two components!");
if (Cond.empty()) {
BuildMI(&MBB, dl, get(ARC::BR)).addMBB(TBB);
return 1;
}
int BccOpc = Cond[1].isImm() ? ARC::BRcc_ru6_p : ARC::BRcc_rr_p;
MachineInstrBuilder MIB = BuildMI(&MBB, dl, get(BccOpc));
MIB.addMBB(TBB);
for (unsigned i = 0; i < 3; i++) {
MIB.add(Cond[i]);
}
// One-way conditional branch.
if (!FBB) {
return 1;
}
// Two-way conditional branch.
BuildMI(&MBB, dl, get(ARC::BR)).addMBB(FBB);
return 2;
}
unsigned ARCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
if (MI.getOpcode() == TargetOpcode::INLINEASM) {
const MachineFunction *MF = MI.getParent()->getParent();
const char *AsmStr = MI.getOperand(0).getSymbolName();
return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
}
return MI.getDesc().getSize();
}

View File

@ -1,94 +0,0 @@
//===- ARCInstrInfo.h - ARC 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 ARC implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_ARC_ARCINSTRINFO_H
#define LLVM_LIB_TARGET_ARC_ARCINSTRINFO_H
#include "ARCRegisterInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#define GET_INSTRINFO_HEADER
#include "ARCGenInstrInfo.inc"
namespace llvm {
class ARCSubtarget;
class ARCInstrInfo : public ARCGenInstrInfo {
const ARCRegisterInfo RI;
virtual void anchor();
public:
ARCInstrInfo();
const ARCRegisterInfo &getRegisterInfo() const { return RI; }
/// If the specified machine instruction is a direct
/// load from a stack slot, return the virtual or physical register number of
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
unsigned isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
/// If the specified machine instruction is a direct
/// store to a stack slot, return the virtual or physical register number of
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
unsigned isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
bool AllowModify) const override;
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
const DebugLoc &dl,
int *BytesAdded = nullptr) const override;
unsigned removeBranch(MachineBasicBlock &MBB,
int *BytesRemoved = nullptr) const override;
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
const DebugLoc &dl, unsigned DestReg, unsigned SrcReg,
bool KillSrc) const override;
void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, unsigned SrcReg,
bool isKill, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const override;
void loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI, unsigned DestReg,
int FrameIndex, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const override;
bool
reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
// Emit code before MBBI to load immediate value into physical register Reg.
// Returns an iterator to the new instruction.
MachineBasicBlock::iterator loadImmediate(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
unsigned Reg, uint64_t Value) const;
};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_ARC_ARCINSTRINFO_H

File diff suppressed because it is too large Load Diff

View File

@ -1,115 +0,0 @@
//===- ARCMCInstLower.cpp - ARC MachineInstr to MCInst ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file contains code to lower ARC MachineInstrs to their
/// corresponding MCInst records.
///
//===----------------------------------------------------------------------===//
#include "ARCMCInstLower.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
using namespace llvm;
ARCMCInstLower::ARCMCInstLower(MCContext *C, AsmPrinter &AsmPrinter)
: Ctx(C), Printer(AsmPrinter) {}
MCOperand ARCMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
MachineOperandType MOTy,
unsigned Offset) const {
MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
const MCSymbol *Symbol;
switch (MOTy) {
case MachineOperand::MO_MachineBasicBlock:
Symbol = MO.getMBB()->getSymbol();
break;
case MachineOperand::MO_GlobalAddress:
Symbol = Printer.getSymbol(MO.getGlobal());
Offset += MO.getOffset();
break;
case MachineOperand::MO_BlockAddress:
Symbol = Printer.GetBlockAddressSymbol(MO.getBlockAddress());
Offset += MO.getOffset();
break;
case MachineOperand::MO_ExternalSymbol:
Symbol = Printer.GetExternalSymbolSymbol(MO.getSymbolName());
Offset += MO.getOffset();
break;
case MachineOperand::MO_JumpTableIndex:
Symbol = Printer.GetJTISymbol(MO.getIndex());
break;
case MachineOperand::MO_ConstantPoolIndex:
Symbol = Printer.GetCPISymbol(MO.getIndex());
Offset += MO.getOffset();
break;
default:
llvm_unreachable("<unknown operand type>");
}
assert(Symbol && "Symbol creation failed.\n");
const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
if (!Offset)
return MCOperand::createExpr(MCSym);
// Assume offset is never negative.
assert(Offset > 0);
const MCConstantExpr *OffsetExpr = MCConstantExpr::create(Offset, *Ctx);
const MCBinaryExpr *Add = MCBinaryExpr::createAdd(MCSym, OffsetExpr, *Ctx);
return MCOperand::createExpr(Add);
}
MCOperand ARCMCInstLower::LowerOperand(const MachineOperand &MO,
unsigned Offset) const {
MachineOperandType MOTy = MO.getType();
switch (MOTy) {
default:
llvm_unreachable("unknown operand type");
case MachineOperand::MO_Register:
// Ignore all implicit register operands.
if (MO.isImplicit())
break;
return MCOperand::createReg(MO.getReg());
case MachineOperand::MO_Immediate:
return MCOperand::createImm(MO.getImm() + Offset);
case MachineOperand::MO_MachineBasicBlock:
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_ExternalSymbol:
case MachineOperand::MO_JumpTableIndex:
case MachineOperand::MO_ConstantPoolIndex:
case MachineOperand::MO_BlockAddress:
return LowerSymbolOperand(MO, MOTy, Offset);
case MachineOperand::MO_RegisterMask:
break;
}
return {};
}
void ARCMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
OutMI.setOpcode(MI->getOpcode());
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
MCOperand MCOp = LowerOperand(MO);
if (MCOp.isValid())
OutMI.addOperand(MCOp);
}
}

View File

@ -1,44 +0,0 @@
//===- ARCMCInstLower.h - Lower MachineInstr to MCInst ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_ARC_ARCMCINSTLOWER_H
#define LLVM_LIB_TARGET_ARC_ARCMCINSTLOWER_H
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
class MCContext;
class MCInst;
class MCOperand;
class MachineInstr;
class MachineFunction;
class Mangler;
class AsmPrinter;
/// \brief This class is used to lower an MachineInstr into an MCInst.
class LLVM_LIBRARY_VISIBILITY ARCMCInstLower {
using MachineOperandType = MachineOperand::MachineOperandType;
MCContext *Ctx;
AsmPrinter &Printer;
public:
ARCMCInstLower(MCContext *C, AsmPrinter &asmprinter);
void Lower(const MachineInstr *MI, MCInst &OutMI) const;
MCOperand LowerOperand(const MachineOperand &MO, unsigned offset = 0) const;
private:
MCOperand LowerSymbolOperand(const MachineOperand &MO,
MachineOperandType MOTy, unsigned Offset) const;
};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_ARC_ARCMCINSTLOWER_H

View File

@ -1,14 +0,0 @@
//===- ARCMachineFunctionInfo.cpp - ARC machine func info -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ARCMachineFunctionInfo.h"
using namespace llvm;
void ARCFunctionInfo::anchor() {}

View File

@ -1,64 +0,0 @@
//===- ARCMachineFunctionInfo.h - ARC machine function info -----*- 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 ARC-specific per-machine-function information.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_TARGET_ARC_ARCMACHINEFUNCTIONINFO_H
#define LLVM_LIB_TARGET_ARC_ARCMACHINEFUNCTIONINFO_H
#include "llvm/CodeGen/MachineFunction.h"
#include <vector>
namespace llvm {
/// ARCFunctionInfo - This class is derived from MachineFunction private
/// ARC target-specific information for each MachineFunction.
class ARCFunctionInfo : public MachineFunctionInfo {
virtual void anchor();
bool ReturnStackOffsetSet;
int VarArgsFrameIndex;
unsigned VarArgFrameBytes;
unsigned ReturnStackOffset;
public:
ARCFunctionInfo()
: ReturnStackOffsetSet(false), VarArgsFrameIndex(0), VarArgFrameBytes(0),
ReturnStackOffset(-1U), MaxCallStackReq(0) {}
explicit ARCFunctionInfo(MachineFunction &MF)
: ReturnStackOffsetSet(false), VarArgsFrameIndex(0), VarArgFrameBytes(0),
ReturnStackOffset(-1U), MaxCallStackReq(0) {
// Functions are 4-byte (2**2) aligned.
MF.setAlignment(2);
}
~ARCFunctionInfo() {}
void setVarArgsFrameIndex(int off) { VarArgsFrameIndex = off; }
int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
void setReturnStackOffset(unsigned value) {
assert(!ReturnStackOffsetSet && "Return stack offset set twice");
ReturnStackOffset = value;
ReturnStackOffsetSet = true;
}
unsigned getReturnStackOffset() const {
assert(ReturnStackOffsetSet && "Return stack offset not set");
return ReturnStackOffset;
}
unsigned MaxCallStackReq;
};
} // end namespace llvm
#endif // LLVM_LIB_TARGET_ARC_ARCMACHINEFUNCTIONINFO_H

View File

@ -1,232 +0,0 @@
//===- ARCRegisterInfo.cpp - ARC 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 ARC implementation of the MRegisterInfo class.
//
//===----------------------------------------------------------------------===//
#include "ARCRegisterInfo.h"
#include "ARC.h"
#include "ARCInstrInfo.h"
#include "ARCMachineFunctionInfo.h"
#include "ARCSubtarget.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/Debug.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
#define DEBUG_TYPE "arc-reg-info"
#define GET_REGINFO_TARGET_DESC
#include "ARCGenRegisterInfo.inc"
static void ReplaceFrameIndex(MachineBasicBlock::iterator II,
const ARCInstrInfo &TII, unsigned Reg,
unsigned FrameReg, int Offset, int StackSize,
int ObjSize, RegScavenger *RS, int SPAdj) {
assert(RS && "Need register scavenger.");
MachineInstr &MI = *II;
MachineBasicBlock &MBB = *MI.getParent();
DebugLoc dl = MI.getDebugLoc();
unsigned BaseReg = FrameReg;
unsigned KillState = 0;
if (MI.getOpcode() == ARC::LD_rs9 && (Offset >= 256 || Offset < -256)) {
// Loads can always be reached with LD_rlimm.
BuildMI(MBB, II, dl, TII.get(ARC::LD_rlimm), Reg)
.addReg(BaseReg)
.addImm(Offset)
.addMemOperand(*MI.memoperands_begin());
MBB.erase(II);
return;
}
if (MI.getOpcode() != ARC::GETFI && (Offset >= 256 || Offset < -256)) {
// We need to use a scratch register to reach the far-away frame indexes.
BaseReg = RS->FindUnusedReg(&ARC::GPR32RegClass);
if (!BaseReg) {
// We can be sure that the scavenged-register slot is within the range
// of the load offset.
const TargetRegisterInfo *TRI =
MBB.getParent()->getSubtarget().getRegisterInfo();
BaseReg = RS->scavengeRegister(&ARC::GPR32RegClass, II, SPAdj);
assert(BaseReg && "Register scavenging failed.");
DEBUG(dbgs() << "Scavenged register " << printReg(BaseReg, TRI)
<< " for FrameReg=" << printReg(FrameReg, TRI)
<< "+Offset=" << Offset << "\n");
(void)TRI;
RS->setRegUsed(BaseReg);
}
unsigned AddOpc = isUInt<6>(Offset) ? ARC::ADD_rru6 : ARC::ADD_rrlimm;
BuildMI(MBB, II, dl, TII.get(AddOpc))
.addReg(BaseReg, RegState::Define)
.addReg(FrameReg)
.addImm(Offset);
Offset = 0;
KillState = RegState::Kill;
}
switch (MI.getOpcode()) {
case ARC::LD_rs9:
assert((Offset % 4 == 0) && "LD needs 4 byte alignment.");
case ARC::LDH_rs9:
case ARC::LDH_X_rs9:
assert((Offset % 2 == 0) && "LDH needs 2 byte alignment.");
case ARC::LDB_rs9:
case ARC::LDB_X_rs9:
DEBUG(dbgs() << "Building LDFI\n");
BuildMI(MBB, II, dl, TII.get(MI.getOpcode()), Reg)
.addReg(BaseReg, KillState)
.addImm(Offset)
.addMemOperand(*MI.memoperands_begin());
break;
case ARC::ST_rs9:
assert((Offset % 4 == 0) && "ST needs 4 byte alignment.");
case ARC::STH_rs9:
assert((Offset % 2 == 0) && "STH needs 2 byte alignment.");
case ARC::STB_rs9:
DEBUG(dbgs() << "Building STFI\n");
BuildMI(MBB, II, dl, TII.get(MI.getOpcode()))
.addReg(Reg, getKillRegState(MI.getOperand(0).isKill()))
.addReg(BaseReg, KillState)
.addImm(Offset)
.addMemOperand(*MI.memoperands_begin());
break;
case ARC::GETFI:
DEBUG(dbgs() << "Building GETFI\n");
BuildMI(MBB, II, dl,
TII.get(isUInt<6>(Offset) ? ARC::ADD_rru6 : ARC::ADD_rrlimm))
.addReg(Reg, RegState::Define)
.addReg(FrameReg)
.addImm(Offset);
break;
default:
llvm_unreachable("Unhandled opcode.");
}
// Erase old instruction.
MBB.erase(II);
}
ARCRegisterInfo::ARCRegisterInfo() : ARCGenRegisterInfo(ARC::BLINK) {}
bool ARCRegisterInfo::needsFrameMoves(const MachineFunction &MF) {
return MF.getMMI().hasDebugInfo() || MF.getFunction().needsUnwindTableEntry();
}
const MCPhysReg *
ARCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
return CSR_ARC_SaveList;
}
BitVector ARCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
Reserved.set(ARC::ILINK);
Reserved.set(ARC::SP);
Reserved.set(ARC::GP);
Reserved.set(ARC::R25);
Reserved.set(ARC::BLINK);
Reserved.set(ARC::FP);
return Reserved;
}
bool ARCRegisterInfo::requiresRegisterScavenging(
const MachineFunction &MF) const {
return true;
}
bool ARCRegisterInfo::trackLivenessAfterRegAlloc(
const MachineFunction &MF) const {
return true;
}
bool ARCRegisterInfo::useFPForScavengingIndex(const MachineFunction &MF) const {
return true;
}
void ARCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
MachineInstr &MI = *II;
MachineOperand &FrameOp = MI.getOperand(FIOperandNum);
int FrameIndex = FrameOp.getIndex();
MachineFunction &MF = *MI.getParent()->getParent();
const ARCInstrInfo &TII = *MF.getSubtarget<ARCSubtarget>().getInstrInfo();
const ARCFrameLowering *TFI = getFrameLowering(MF);
int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex);
int ObjSize = MF.getFrameInfo().getObjectSize(FrameIndex);
int StackSize = MF.getFrameInfo().getStackSize();
int LocalFrameSize = MF.getFrameInfo().getLocalFrameSize();
DEBUG(dbgs() << "\nFunction : " << MF.getName() << "\n");
DEBUG(dbgs() << "<--------->\n");
DEBUG(dbgs() << MI << "\n");
DEBUG(dbgs() << "FrameIndex : " << FrameIndex << "\n");
DEBUG(dbgs() << "ObjSize : " << ObjSize << "\n");
DEBUG(dbgs() << "FrameOffset : " << Offset << "\n");
DEBUG(dbgs() << "StackSize : " << StackSize << "\n");
DEBUG(dbgs() << "LocalFrameSize : " << LocalFrameSize << "\n");
(void)LocalFrameSize;
// Special handling of DBG_VALUE instructions.
if (MI.isDebugValue()) {
unsigned FrameReg = getFrameRegister(MF);
MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false /*isDef*/);
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
return;
}
// fold constant into offset.
Offset += MI.getOperand(FIOperandNum + 1).getImm();
// TODO: assert based on the load type:
// ldb needs no alignment,
// ldh needs 2 byte alignment
// ld needs 4 byte alignment
DEBUG(dbgs() << "Offset : " << Offset << "\n"
<< "<--------->\n");
unsigned Reg = MI.getOperand(0).getReg();
assert(ARC::GPR32RegClass.contains(Reg) && "Unexpected register operand");
if (!TFI->hasFP(MF)) {
Offset = StackSize + Offset;
if (FrameIndex >= 0)
assert((Offset >= 0 && Offset < StackSize) && "SP Offset not in bounds.");
} else {
if (FrameIndex >= 0) {
assert((Offset < 0 && -Offset <= StackSize) &&
"FP Offset not in bounds.");
}
}
ReplaceFrameIndex(II, TII, Reg, getFrameRegister(MF), Offset, StackSize,
ObjSize, RS, SPAdj);
}
unsigned ARCRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
const ARCFrameLowering *TFI = getFrameLowering(MF);
return TFI->hasFP(MF) ? ARC::FP : ARC::SP;
}
const uint32_t *
ARCRegisterInfo::getCallPreservedMask(const MachineFunction &MF,
CallingConv::ID CC) const {
return CSR_ARC_RegMask;
}

Some files were not shown because too many files have changed in this diff Show More