You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
33
external/llvm/lib/Target/ARC/ARC.h
vendored
33
external/llvm/lib/Target/ARC/ARC.h
vendored
@ -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
|
25
external/llvm/lib/Target/ARC/ARC.td
vendored
25
external/llvm/lib/Target/ARC/ARC.td
vendored
@ -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;
|
||||
}
|
83
external/llvm/lib/Target/ARC/ARCAsmPrinter.cpp
vendored
83
external/llvm/lib/Target/ARC/ARCAsmPrinter.cpp
vendored
@ -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());
|
||||
}
|
183
external/llvm/lib/Target/ARC/ARCBranchFinalize.cpp
vendored
183
external/llvm/lib/Target/ARC/ARCBranchFinalize.cpp
vendored
@ -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();
|
||||
}
|
41
external/llvm/lib/Target/ARC/ARCCallingConv.td
vendored
41
external/llvm/lib/Target/ARC/ARCCallingConv.td
vendored
@ -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)>;
|
103
external/llvm/lib/Target/ARC/ARCExpandPseudos.cpp
vendored
103
external/llvm/lib/Target/ARC/ARCExpandPseudos.cpp
vendored
@ -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();
|
||||
}
|
471
external/llvm/lib/Target/ARC/ARCFrameLowering.cpp
vendored
471
external/llvm/lib/Target/ARC/ARCFrameLowering.cpp
vendored
@ -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;
|
||||
}
|
78
external/llvm/lib/Target/ARC/ARCFrameLowering.h
vendored
78
external/llvm/lib/Target/ARC/ARCFrameLowering.h
vendored
@ -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
|
182
external/llvm/lib/Target/ARC/ARCISelDAGToDAG.cpp
vendored
182
external/llvm/lib/Target/ARC/ARCISelDAGToDAG.cpp
vendored
@ -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);
|
||||
}
|
767
external/llvm/lib/Target/ARC/ARCISelLowering.cpp
vendored
767
external/llvm/lib/Target/ARC/ARCISelLowering.cpp
vendored
File diff suppressed because it is too large
Load Diff
121
external/llvm/lib/Target/ARC/ARCISelLowering.h
vendored
121
external/llvm/lib/Target/ARC/ARCISelLowering.h
vendored
@ -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
|
891
external/llvm/lib/Target/ARC/ARCInstrFormats.td
vendored
891
external/llvm/lib/Target/ARC/ARCInstrFormats.td
vendored
File diff suppressed because it is too large
Load Diff
394
external/llvm/lib/Target/ARC/ARCInstrInfo.cpp
vendored
394
external/llvm/lib/Target/ARC/ARCInstrInfo.cpp
vendored
@ -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();
|
||||
}
|
94
external/llvm/lib/Target/ARC/ARCInstrInfo.h
vendored
94
external/llvm/lib/Target/ARC/ARCInstrInfo.h
vendored
@ -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
|
874
external/llvm/lib/Target/ARC/ARCInstrInfo.td
vendored
874
external/llvm/lib/Target/ARC/ARCInstrInfo.td
vendored
File diff suppressed because it is too large
Load Diff
115
external/llvm/lib/Target/ARC/ARCMCInstLower.cpp
vendored
115
external/llvm/lib/Target/ARC/ARCMCInstLower.cpp
vendored
@ -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);
|
||||
}
|
||||
}
|
44
external/llvm/lib/Target/ARC/ARCMCInstLower.h
vendored
44
external/llvm/lib/Target/ARC/ARCMCInstLower.h
vendored
@ -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
|
@ -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() {}
|
@ -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
|
232
external/llvm/lib/Target/ARC/ARCRegisterInfo.cpp
vendored
232
external/llvm/lib/Target/ARC/ARCRegisterInfo.cpp
vendored
@ -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
Reference in New Issue
Block a user