[llvm] r311667 - [ARC] Add ARC backend.
Pete Couperus via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 24 08:40:33 PDT 2017
Author: petecoup
Date: Thu Aug 24 08:40:33 2017
New Revision: 311667
URL: http://llvm.org/viewvc/llvm-project?rev=311667&view=rev
Log:
[ARC] Add ARC backend.
Add the ARC backend as an experimental target to lib/Target.
Reviewed at: https://reviews.llvm.org/D36331
Added:
llvm/trunk/lib/Target/ARC/
llvm/trunk/lib/Target/ARC/ARC.h
llvm/trunk/lib/Target/ARC/ARC.td
llvm/trunk/lib/Target/ARC/ARCAsmPrinter.cpp
llvm/trunk/lib/Target/ARC/ARCBranchFinalize.cpp
llvm/trunk/lib/Target/ARC/ARCCallingConv.td
llvm/trunk/lib/Target/ARC/ARCExpandPseudos.cpp
llvm/trunk/lib/Target/ARC/ARCFrameLowering.cpp
llvm/trunk/lib/Target/ARC/ARCFrameLowering.h
llvm/trunk/lib/Target/ARC/ARCISelDAGToDAG.cpp
llvm/trunk/lib/Target/ARC/ARCISelLowering.cpp
llvm/trunk/lib/Target/ARC/ARCISelLowering.h
llvm/trunk/lib/Target/ARC/ARCInstrFormats.td
llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp
llvm/trunk/lib/Target/ARC/ARCInstrInfo.h
llvm/trunk/lib/Target/ARC/ARCInstrInfo.td
llvm/trunk/lib/Target/ARC/ARCMCInstLower.cpp
llvm/trunk/lib/Target/ARC/ARCMCInstLower.h
llvm/trunk/lib/Target/ARC/ARCMachineFunctionInfo.cpp
llvm/trunk/lib/Target/ARC/ARCMachineFunctionInfo.h
llvm/trunk/lib/Target/ARC/ARCRegisterInfo.cpp
llvm/trunk/lib/Target/ARC/ARCRegisterInfo.h
llvm/trunk/lib/Target/ARC/ARCRegisterInfo.td
llvm/trunk/lib/Target/ARC/ARCSubtarget.cpp
llvm/trunk/lib/Target/ARC/ARCSubtarget.h
llvm/trunk/lib/Target/ARC/ARCTargetMachine.cpp
llvm/trunk/lib/Target/ARC/ARCTargetMachine.h
llvm/trunk/lib/Target/ARC/ARCTargetStreamer.h
llvm/trunk/lib/Target/ARC/ARCTargetTransformInfo.h
llvm/trunk/lib/Target/ARC/CMakeLists.txt
llvm/trunk/lib/Target/ARC/Disassembler/
llvm/trunk/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
llvm/trunk/lib/Target/ARC/Disassembler/CMakeLists.txt
llvm/trunk/lib/Target/ARC/Disassembler/LLVMBuild.txt
llvm/trunk/lib/Target/ARC/InstPrinter/
llvm/trunk/lib/Target/ARC/InstPrinter/ARCInstPrinter.cpp
llvm/trunk/lib/Target/ARC/InstPrinter/ARCInstPrinter.h
llvm/trunk/lib/Target/ARC/InstPrinter/CMakeLists.txt
llvm/trunk/lib/Target/ARC/InstPrinter/LLVMBuild.txt
llvm/trunk/lib/Target/ARC/LLVMBuild.txt
llvm/trunk/lib/Target/ARC/MCTargetDesc/
llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCInfo.h
llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCAsmInfo.cpp
llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCAsmInfo.h
llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCTargetDesc.cpp
llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCTargetDesc.h
llvm/trunk/lib/Target/ARC/MCTargetDesc/CMakeLists.txt
llvm/trunk/lib/Target/ARC/MCTargetDesc/LLVMBuild.txt
llvm/trunk/lib/Target/ARC/TargetInfo/
llvm/trunk/lib/Target/ARC/TargetInfo/ARCTargetInfo.cpp
llvm/trunk/lib/Target/ARC/TargetInfo/CMakeLists.txt
llvm/trunk/lib/Target/ARC/TargetInfo/LLVMBuild.txt
llvm/trunk/test/CodeGen/ARC/
llvm/trunk/test/CodeGen/ARC/alu.ll
llvm/trunk/test/CodeGen/ARC/brcc.ll
llvm/trunk/test/CodeGen/ARC/call.ll
llvm/trunk/test/CodeGen/ARC/ldst.ll
llvm/trunk/test/CodeGen/ARC/lit.local.cfg
llvm/trunk/test/MC/Disassembler/ARC/
llvm/trunk/test/MC/Disassembler/ARC/alu.txt
llvm/trunk/test/MC/Disassembler/ARC/br.txt
llvm/trunk/test/MC/Disassembler/ARC/ldst.txt
llvm/trunk/test/MC/Disassembler/ARC/lit.local.cfg
llvm/trunk/test/MC/Disassembler/ARC/misc.txt
Modified:
llvm/trunk/CODE_OWNERS.TXT
llvm/trunk/include/llvm/ADT/Triple.h
llvm/trunk/lib/Support/Triple.cpp
llvm/trunk/lib/Target/LLVMBuild.txt
Modified: llvm/trunk/CODE_OWNERS.TXT
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/CODE_OWNERS.TXT?rev=311667&r1=311666&r2=311667&view=diff
==============================================================================
--- llvm/trunk/CODE_OWNERS.TXT (original)
+++ llvm/trunk/CODE_OWNERS.TXT Thu Aug 24 08:40:33 2017
@@ -44,6 +44,10 @@ N: Greg Clayton
E: clayborg at gmail.com
D: LLDB
+N: Pete Couperus
+E: petecoup at synopsys.com
+D: ARC backend (lib/Target/ARC/*)
+
N: Sanjoy Das
E: sanjoy at playingwithpointers.com
D: IndVar Simplify, Scalar Evolution
Modified: llvm/trunk/include/llvm/ADT/Triple.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/Triple.h?rev=311667&r1=311666&r2=311667&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/Triple.h (original)
+++ llvm/trunk/include/llvm/ADT/Triple.h Thu Aug 24 08:40:33 2017
@@ -50,6 +50,7 @@ public:
armeb, // ARM (big endian): armeb
aarch64, // AArch64 (little endian): aarch64
aarch64_be, // AArch64 (big endian): aarch64_be
+ arc, // ARC: Synopsys ARC
avr, // AVR: Atmel AVR microcontroller
bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
Modified: llvm/trunk/lib/Support/Triple.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Triple.cpp?rev=311667&r1=311666&r2=311667&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Triple.cpp (original)
+++ llvm/trunk/lib/Support/Triple.cpp Thu Aug 24 08:40:33 2017
@@ -25,6 +25,7 @@ StringRef Triple::getArchTypeName(ArchTy
case aarch64_be: return "aarch64_be";
case arm: return "arm";
case armeb: return "armeb";
+ case arc: return "arc";
case avr: return "avr";
case bpfel: return "bpfel";
case bpfeb: return "bpfeb";
@@ -83,6 +84,8 @@ StringRef Triple::getArchTypePrefix(Arch
case aarch64:
case aarch64_be: return "aarch64";
+ case arc: return "arc";
+
case arm:
case armeb:
case thumb:
@@ -255,6 +258,7 @@ Triple::ArchType Triple::getArchTypeForL
return StringSwitch<Triple::ArchType>(Name)
.Case("aarch64", aarch64)
.Case("aarch64_be", aarch64_be)
+ .Case("arc", arc)
.Case("arm64", aarch64) // "arm64" is an alias for "aarch64"
.Case("arm", arm)
.Case("armeb", armeb)
@@ -384,6 +388,7 @@ static Triple::ArchType parseArch(String
.Case("xscaleeb", Triple::armeb)
.Case("aarch64", Triple::aarch64)
.Case("aarch64_be", Triple::aarch64_be)
+ .Case("arc", Triple::arc)
.Case("arm64", Triple::aarch64)
.Case("arm", Triple::arm)
.Case("armeb", Triple::armeb)
@@ -620,6 +625,7 @@ static Triple::ObjectFormatType getDefau
return Triple::ELF;
case Triple::aarch64_be:
+ case Triple::arc:
case Triple::amdgcn:
case Triple::amdil:
case Triple::amdil64:
@@ -1173,6 +1179,7 @@ static unsigned getArchPointerBitWidth(l
case llvm::Triple::msp430:
return 16;
+ case llvm::Triple::arc:
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::hexagon:
@@ -1256,6 +1263,7 @@ Triple Triple::get32BitArchVariant() con
case Triple::amdil:
case Triple::hsail:
case Triple::spir:
+ case Triple::arc:
case Triple::arm:
case Triple::armeb:
case Triple::hexagon:
@@ -1306,6 +1314,7 @@ Triple Triple::get64BitArchVariant() con
Triple T(*this);
switch (getArch()) {
case Triple::UnknownArch:
+ case Triple::arc:
case Triple::avr:
case Triple::hexagon:
case Triple::kalimba:
Added: llvm/trunk/lib/Target/ARC/ARC.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARC.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARC.h (added)
+++ llvm/trunk/lib/Target/ARC/ARC.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,33 @@
+//===- 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
Added: llvm/trunk/lib/Target/ARC/ARC.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARC.td?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARC.td (added)
+++ llvm/trunk/lib/Target/ARC/ARC.td Thu Aug 24 08:40:33 2017
@@ -0,0 +1,25 @@
+//===- 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;
+}
Added: llvm/trunk/lib/Target/ARC/ARCAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCAsmPrinter.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCAsmPrinter.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCAsmPrinter.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,83 @@
+//===- 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/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 "llvm/Target/TargetLoweringObjectFile.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());
+}
Added: llvm/trunk/lib/Target/ARC/ARCBranchFinalize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCBranchFinalize.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCBranchFinalize.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCBranchFinalize.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,183 @@
+//===- 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/Support/Debug.h"
+#include "llvm/Target/TargetInstrInfo.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.getFunction()->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.getFunction()->getName()
+ << ": " << MaxSize << "\n");
+
+ return Changed;
+}
+
+FunctionPass *llvm::createARCBranchFinalizePass() {
+ return new ARCBranchFinalize();
+}
Added: llvm/trunk/lib/Target/ARC/ARCCallingConv.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCCallingConv.td?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCCallingConv.td (added)
+++ llvm/trunk/lib/Target/ARC/ARCCallingConv.td Thu Aug 24 08:40:33 2017
@@ -0,0 +1,41 @@
+//===- 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)>;
Added: llvm/trunk/lib/Target/ARC/ARCExpandPseudos.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCExpandPseudos.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCExpandPseudos.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCExpandPseudos.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,103 @@
+//===- 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();
+}
Added: llvm/trunk/lib/Target/ARC/ARCFrameLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCFrameLowering.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCFrameLowering.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCFrameLowering.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,472 @@
+//===- 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/IR/Function.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetRegisterInfo.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.getFunction()->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.getFunction()->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.getFunction()->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()->getFunction()->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()->getFunction()->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.getFunction()->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.getFunction()->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;
+}
Added: llvm/trunk/lib/Target/ARC/ARCFrameLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCFrameLowering.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCFrameLowering.h (added)
+++ llvm/trunk/lib/Target/ARC/ARCFrameLowering.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,78 @@
+//===- 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/Target/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
Added: llvm/trunk/lib/Target/ARC/ARCISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCISelDAGToDAG.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCISelDAGToDAG.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCISelDAGToDAG.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,182 @@
+//===- 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/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"
+#include "llvm/Target/TargetLowering.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);
+}
Added: llvm/trunk/lib/Target/ARC/ARCISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCISelLowering.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCISelLowering.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCISelLowering.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,767 @@
+//===- ARCISelLowering.cpp - ARC DAG Lowering Impl --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ARCTargetLowering class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARCISelLowering.h"
+#include "ARC.h"
+#include "ARCMachineFunctionInfo.h"
+#include "ARCSubtarget.h"
+#include "ARCTargetMachine.h"
+#include "MCTargetDesc/ARCInfo.h"
+#include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/Support/Debug.h"
+#include <algorithm>
+
+#define DEBUG_TYPE "arc-lower"
+
+using namespace llvm;
+
+static SDValue lowerCallResult(SDValue Chain, SDValue InFlag,
+ const SmallVectorImpl<CCValAssign> &RVLocs,
+ SDLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals);
+
+static ARCCC::CondCode ISDCCtoARCCC(ISD::CondCode isdCC) {
+ switch (isdCC) {
+ case ISD::SETUEQ:
+ return ARCCC::EQ;
+ case ISD::SETUGT:
+ return ARCCC::HI;
+ case ISD::SETUGE:
+ return ARCCC::HS;
+ case ISD::SETULT:
+ return ARCCC::LO;
+ case ISD::SETULE:
+ return ARCCC::LS;
+ case ISD::SETUNE:
+ return ARCCC::NE;
+ case ISD::SETEQ:
+ return ARCCC::EQ;
+ case ISD::SETGT:
+ return ARCCC::GT;
+ case ISD::SETGE:
+ return ARCCC::GE;
+ case ISD::SETLT:
+ return ARCCC::LT;
+ case ISD::SETLE:
+ return ARCCC::LE;
+ case ISD::SETNE:
+ return ARCCC::NE;
+ default:
+ llvm_unreachable("Unhandled ISDCC code.");
+ }
+}
+
+ARCTargetLowering::ARCTargetLowering(const TargetMachine &TM,
+ const ARCSubtarget &Subtarget)
+ : TargetLowering(TM), TM(TM), Subtarget(Subtarget) {
+ // Set up the register classes.
+ addRegisterClass(MVT::i32, &ARC::GPR32RegClass);
+
+ // Compute derived properties from the register classes
+ computeRegisterProperties(Subtarget.getRegisterInfo());
+
+ setStackPointerRegisterToSaveRestore(ARC::SP);
+
+ setSchedulingPreference(Sched::Source);
+
+ // Use i32 for setcc operations results (slt, sgt, ...).
+ setBooleanContents(ZeroOrOneBooleanContent);
+ setBooleanVectorContents(ZeroOrOneBooleanContent);
+
+ for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
+ setOperationAction(Opc, MVT::i32, Expand);
+
+ // Operations to get us off of the ground.
+ // Basic.
+ setOperationAction(ISD::ADD, MVT::i32, Legal);
+ setOperationAction(ISD::SUB, MVT::i32, Legal);
+ setOperationAction(ISD::AND, MVT::i32, Legal);
+ setOperationAction(ISD::SMAX, MVT::i32, Legal);
+ setOperationAction(ISD::SMIN, MVT::i32, Legal);
+
+ // Need barrel shifter.
+ setOperationAction(ISD::SHL, MVT::i32, Legal);
+ setOperationAction(ISD::SRA, MVT::i32, Legal);
+ setOperationAction(ISD::SRL, MVT::i32, Legal);
+ setOperationAction(ISD::ROTR, MVT::i32, Legal);
+
+ setOperationAction(ISD::Constant, MVT::i32, Legal);
+ setOperationAction(ISD::UNDEF, MVT::i32, Legal);
+
+ // Need multiplier
+ setOperationAction(ISD::MUL, MVT::i32, Legal);
+ setOperationAction(ISD::MULHS, MVT::i32, Legal);
+ setOperationAction(ISD::MULHU, MVT::i32, Legal);
+ setOperationAction(ISD::LOAD, MVT::i32, Legal);
+ setOperationAction(ISD::STORE, MVT::i32, Legal);
+
+ setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
+ setOperationAction(ISD::BR_CC, MVT::i32, Custom);
+ setOperationAction(ISD::BRCOND, MVT::Other, Expand);
+ setOperationAction(ISD::BR_JT, MVT::Other, Expand);
+ setOperationAction(ISD::JumpTable, MVT::i32, Custom);
+
+ // Have psuedo instruction for frame addresses.
+ setOperationAction(ISD::FRAMEADDR, MVT::i32, Legal);
+ // Custom lower global addresses.
+ setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
+
+ // Expand var-args ops.
+ setOperationAction(ISD::VASTART, MVT::Other, Custom);
+ setOperationAction(ISD::VAEND, MVT::Other, Expand);
+ setOperationAction(ISD::VAARG, MVT::Other, Expand);
+ setOperationAction(ISD::VACOPY, MVT::Other, Expand);
+
+ // Other expansions
+ setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
+ setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
+
+ // Sign extend inreg
+ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Custom);
+}
+
+const char *ARCTargetLowering::getTargetNodeName(unsigned Opcode) const {
+ switch (Opcode) {
+ case ARCISD::BL:
+ return "ARCISD::BL";
+ case ARCISD::CMOV:
+ return "ARCISD::CMOV";
+ case ARCISD::CMP:
+ return "ARCISD::CMP";
+ case ARCISD::BRcc:
+ return "ARCISD::BRcc";
+ case ARCISD::RET:
+ return "ARCISD::RET";
+ case ARCISD::GAWRAPPER:
+ return "ARCISD::GAWRAPPER";
+ }
+ return nullptr;
+}
+
+//===----------------------------------------------------------------------===//
+// Misc Lower Operation implementation
+//===----------------------------------------------------------------------===//
+
+SDValue ARCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
+ SDValue LHS = Op.getOperand(0);
+ SDValue RHS = Op.getOperand(1);
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
+ SDValue TVal = Op.getOperand(2);
+ SDValue FVal = Op.getOperand(3);
+ SDLoc dl(Op);
+ ARCCC::CondCode ArcCC = ISDCCtoARCCC(CC);
+ assert(LHS.getValueType() == MVT::i32 && "Only know how to SELECT_CC i32");
+ SDValue Cmp = DAG.getNode(ARCISD::CMP, dl, MVT::Glue, LHS, RHS);
+ return DAG.getNode(ARCISD::CMOV, dl, TVal.getValueType(), TVal, FVal,
+ DAG.getConstant(ArcCC, dl, MVT::i32), Cmp);
+}
+
+SDValue ARCTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDValue Op0 = Op.getOperand(0);
+ SDLoc dl(Op);
+ assert(Op.getValueType() == MVT::i32 &&
+ "Unhandled target sign_extend_inreg.");
+ // These are legal
+ unsigned Width = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();
+ if (Width == 16 || Width == 8)
+ return Op;
+ if (Width >= 32) {
+ return {};
+ }
+ SDValue LS = DAG.getNode(ISD::SHL, dl, MVT::i32, Op0,
+ DAG.getConstant(32 - Width, dl, MVT::i32));
+ SDValue SR = DAG.getNode(ISD::SRA, dl, MVT::i32, LS,
+ DAG.getConstant(32 - Width, dl, MVT::i32));
+ return SR;
+}
+
+SDValue ARCTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
+ SDValue Chain = Op.getOperand(0);
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
+ SDValue LHS = Op.getOperand(2);
+ SDValue RHS = Op.getOperand(3);
+ SDValue Dest = Op.getOperand(4);
+ SDLoc dl(Op);
+ ARCCC::CondCode arcCC = ISDCCtoARCCC(CC);
+ assert(LHS.getValueType() == MVT::i32 && "Only know how to BR_CC i32");
+ return DAG.getNode(ARCISD::BRcc, dl, MVT::Other, Chain, Dest, LHS, RHS,
+ DAG.getConstant(arcCC, dl, MVT::i32));
+}
+
+SDValue ARCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
+ auto *N = cast<JumpTableSDNode>(Op);
+ SDValue GA = DAG.getTargetJumpTable(N->getIndex(), MVT::i32);
+ return DAG.getNode(ARCISD::GAWRAPPER, SDLoc(N), MVT::i32, GA);
+}
+
+#include "ARCGenCallingConv.inc"
+
+//===----------------------------------------------------------------------===//
+// Call Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+
+/// ARC call implementation
+SDValue ARCTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
+ SmallVectorImpl<SDValue> &InVals) const {
+ SelectionDAG &DAG = CLI.DAG;
+ SDLoc &dl = CLI.DL;
+ SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
+ SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
+ SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
+ SDValue Chain = CLI.Chain;
+ SDValue Callee = CLI.Callee;
+ CallingConv::ID CallConv = CLI.CallConv;
+ bool IsVarArg = CLI.IsVarArg;
+ bool &IsTailCall = CLI.IsTailCall;
+
+ IsTailCall = false; // Do not support tail calls yet.
+
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
+ *DAG.getContext());
+
+ CCInfo.AnalyzeCallOperands(Outs, CC_ARC);
+
+ SmallVector<CCValAssign, 16> RVLocs;
+ // Analyze return values to determine the number of bytes of stack required.
+ CCState RetCCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
+ *DAG.getContext());
+ RetCCInfo.AllocateStack(CCInfo.getNextStackOffset(), 4);
+ RetCCInfo.AnalyzeCallResult(Ins, RetCC_ARC);
+
+ // Get a count of how many bytes are to be pushed on the stack.
+ unsigned NumBytes = RetCCInfo.getNextStackOffset();
+ auto PtrVT = getPointerTy(DAG.getDataLayout());
+
+ Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
+
+ SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass;
+ SmallVector<SDValue, 12> MemOpChains;
+
+ SDValue StackPtr;
+ // Walk the register/memloc assignments, inserting copies/loads.
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ CCValAssign &VA = ArgLocs[i];
+ SDValue Arg = OutVals[i];
+
+ // Promote the value if needed.
+ switch (VA.getLocInfo()) {
+ default:
+ llvm_unreachable("Unknown loc info!");
+ case CCValAssign::Full:
+ break;
+ case CCValAssign::SExt:
+ Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg);
+ break;
+ case CCValAssign::ZExt:
+ Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg);
+ break;
+ case CCValAssign::AExt:
+ Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg);
+ break;
+ }
+
+ // Arguments that can be passed on register must be kept at
+ // RegsToPass vector
+ if (VA.isRegLoc()) {
+ RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
+ } else {
+ assert(VA.isMemLoc() && "Must be register or memory argument.");
+ if (!StackPtr.getNode())
+ StackPtr = DAG.getCopyFromReg(Chain, dl, ARC::SP,
+ getPointerTy(DAG.getDataLayout()));
+ // Calculate the stack position.
+ SDValue SOffset = DAG.getIntPtrConstant(VA.getLocMemOffset(), dl);
+ SDValue PtrOff = DAG.getNode(
+ ISD::ADD, dl, getPointerTy(DAG.getDataLayout()), StackPtr, SOffset);
+
+ SDValue Store =
+ DAG.getStore(Chain, dl, Arg, PtrOff, MachinePointerInfo());
+ MemOpChains.push_back(Store);
+ IsTailCall = false;
+ }
+ }
+
+ // Transform all store nodes into one single node because
+ // all store nodes are independent of each other.
+ if (!MemOpChains.empty())
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
+
+ // Build a sequence of copy-to-reg nodes chained together with token
+ // chain and flag operands which copy the outgoing args into registers.
+ // The InFlag in necessary since all emitted instructions must be
+ // stuck together.
+ SDValue Glue;
+ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
+ Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
+ RegsToPass[i].second, Glue);
+ Glue = Chain.getValue(1);
+ }
+
+ // If the callee is a GlobalAddress node (quite common, every direct call is)
+ // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
+ // Likewise ExternalSymbol -> TargetExternalSymbol.
+ bool IsDirect = true;
+ if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
+ Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, MVT::i32);
+ else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee))
+ Callee = DAG.getTargetExternalSymbol(E->getSymbol(), MVT::i32);
+ else
+ IsDirect = false;
+ // Branch + Link = #chain, #target_address, #opt_in_flags...
+ // = Chain, Callee, Reg#1, Reg#2, ...
+ //
+ // Returns a chain & a flag for retval copy to use.
+ SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
+ SmallVector<SDValue, 8> Ops;
+ Ops.push_back(Chain);
+ Ops.push_back(Callee);
+
+ for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i)
+ Ops.push_back(DAG.getRegister(RegsToPass[i].first,
+ RegsToPass[i].second.getValueType()));
+
+ // Add a register mask operand representing the call-preserved registers.
+ const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
+ const uint32_t *Mask =
+ TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
+ assert(Mask && "Missing call preserved mask for calling convention");
+ Ops.push_back(DAG.getRegisterMask(Mask));
+
+ if (Glue.getNode())
+ Ops.push_back(Glue);
+
+ Chain = DAG.getNode(IsDirect ? ARCISD::BL : ARCISD::JL, dl, NodeTys, Ops);
+ Glue = Chain.getValue(1);
+
+ // Create the CALLSEQ_END node.
+ Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, dl, PtrVT, true),
+ DAG.getConstant(0, dl, PtrVT, true), Glue, dl);
+ Glue = Chain.getValue(1);
+
+ // Handle result values, copying them out of physregs into vregs that we
+ // return.
+ if (IsTailCall)
+ return Chain;
+ return lowerCallResult(Chain, Glue, RVLocs, dl, DAG, InVals);
+}
+
+/// Lower the result values of a call into the appropriate copies out of
+/// physical registers / memory locations.
+static SDValue lowerCallResult(SDValue Chain, SDValue Glue,
+ const SmallVectorImpl<CCValAssign> &RVLocs,
+ SDLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) {
+ SmallVector<std::pair<int, unsigned>, 4> ResultMemLocs;
+ // Copy results out of physical registers.
+ for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
+ const CCValAssign &VA = RVLocs[i];
+ if (VA.isRegLoc()) {
+ SDValue RetValue;
+ RetValue =
+ DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), VA.getValVT(), Glue);
+ Chain = RetValue.getValue(1);
+ Glue = RetValue.getValue(2);
+ InVals.push_back(RetValue);
+ } else {
+ assert(VA.isMemLoc() && "Must be memory location.");
+ ResultMemLocs.push_back(
+ std::make_pair(VA.getLocMemOffset(), InVals.size()));
+
+ // Reserve space for this result.
+ InVals.push_back(SDValue());
+ }
+ }
+
+ // Copy results out of memory.
+ SmallVector<SDValue, 4> MemOpChains;
+ for (unsigned i = 0, e = ResultMemLocs.size(); i != e; ++i) {
+ int Offset = ResultMemLocs[i].first;
+ unsigned Index = ResultMemLocs[i].second;
+ SDValue StackPtr = DAG.getRegister(ARC::SP, MVT::i32);
+ SDValue SpLoc = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr,
+ DAG.getConstant(Offset, dl, MVT::i32));
+ SDValue Load =
+ DAG.getLoad(MVT::i32, dl, Chain, SpLoc, MachinePointerInfo());
+ InVals[Index] = Load;
+ MemOpChains.push_back(Load.getValue(1));
+ }
+
+ // Transform all loads nodes into one single node because
+ // all load nodes are independent of each other.
+ if (!MemOpChains.empty())
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
+
+ return Chain;
+}
+
+//===----------------------------------------------------------------------===//
+// Formal Arguments Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+struct ArgDataPair {
+ SDValue SDV;
+ ISD::ArgFlagsTy Flags;
+};
+
+} // end anonymous namespace
+
+/// ARC formal arguments implementation
+SDValue ARCTargetLowering::LowerFormalArguments(
+ SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
+ SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
+ switch (CallConv) {
+ default:
+ llvm_unreachable("Unsupported calling convention");
+ case CallingConv::C:
+ case CallingConv::Fast:
+ return LowerCallArguments(Chain, CallConv, IsVarArg, Ins, dl, DAG, InVals);
+ }
+}
+
+/// Transform physical registers into virtual registers, and generate load
+/// operations for argument places on the stack.
+SDValue ARCTargetLowering::LowerCallArguments(
+ SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const {
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ MachineRegisterInfo &RegInfo = MF.getRegInfo();
+ auto *AFI = MF.getInfo<ARCFunctionInfo>();
+
+ // Assign locations to all of the incoming arguments.
+ SmallVector<CCValAssign, 16> ArgLocs;
+ CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
+ *DAG.getContext());
+
+ CCInfo.AnalyzeFormalArguments(Ins, CC_ARC);
+
+ unsigned StackSlotSize = 4;
+
+ if (!IsVarArg)
+ AFI->setReturnStackOffset(CCInfo.getNextStackOffset());
+
+ // All getCopyFromReg ops must precede any getMemcpys to prevent the
+ // scheduler clobbering a register before it has been copied.
+ // The stages are:
+ // 1. CopyFromReg (and load) arg & vararg registers.
+ // 2. Chain CopyFromReg nodes into a TokenFactor.
+ // 3. Memcpy 'byVal' args & push final InVals.
+ // 4. Chain mem ops nodes into a TokenFactor.
+ SmallVector<SDValue, 4> CFRegNode;
+ SmallVector<ArgDataPair, 4> ArgData;
+ SmallVector<SDValue, 4> MemOps;
+
+ // 1a. CopyFromReg (and load) arg registers.
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ CCValAssign &VA = ArgLocs[i];
+ SDValue ArgIn;
+
+ if (VA.isRegLoc()) {
+ // Arguments passed in registers
+ EVT RegVT = VA.getLocVT();
+ switch (RegVT.getSimpleVT().SimpleTy) {
+ default: {
+ DEBUG(errs() << "LowerFormalArguments Unhandled argument type: "
+ << RegVT.getSimpleVT().SimpleTy << "\n");
+ llvm_unreachable("Unhandled LowerFormalArguments type.");
+ }
+ case MVT::i32:
+ unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
+ RegInfo.addLiveIn(VA.getLocReg(), VReg);
+ ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
+ CFRegNode.push_back(ArgIn.getValue(ArgIn->getNumValues() - 1));
+ }
+ } else {
+ // sanity check
+ assert(VA.isMemLoc());
+ // Load the argument to a virtual register
+ unsigned ObjSize = VA.getLocVT().getStoreSize();
+ assert((ObjSize <= StackSlotSize) && "Unhandled argument");
+
+ // Create the frame index object for this incoming parameter...
+ int FI = MFI.CreateFixedObject(ObjSize, VA.getLocMemOffset(), true);
+
+ // Create the SelectionDAG nodes corresponding to a load
+ // from this parameter
+ SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
+ ArgIn = DAG.getLoad(VA.getLocVT(), dl, Chain, FIN,
+ MachinePointerInfo::getFixedStack(MF, FI));
+ }
+ const ArgDataPair ADP = {ArgIn, Ins[i].Flags};
+ ArgData.push_back(ADP);
+ }
+
+ // 1b. CopyFromReg vararg registers.
+ if (IsVarArg) {
+ // Argument registers
+ static const MCPhysReg ArgRegs[] = {ARC::R0, ARC::R1, ARC::R2, ARC::R3,
+ ARC::R4, ARC::R5, ARC::R6, ARC::R7};
+ auto *AFI = MF.getInfo<ARCFunctionInfo>();
+ unsigned FirstVAReg = CCInfo.getFirstUnallocated(ArgRegs);
+ if (FirstVAReg < array_lengthof(ArgRegs)) {
+ int Offset = 0;
+ // Save remaining registers, storing higher register numbers at a higher
+ // address
+ // There are (array_lengthof(ArgRegs) - FirstVAReg) registers which
+ // need to be saved.
+ int VarFI =
+ MFI.CreateFixedObject((array_lengthof(ArgRegs) - FirstVAReg) * 4,
+ CCInfo.getNextStackOffset(), true);
+ AFI->setVarArgsFrameIndex(VarFI);
+ SDValue FIN = DAG.getFrameIndex(VarFI, MVT::i32);
+ for (unsigned i = FirstVAReg; i < array_lengthof(ArgRegs); i++) {
+ // Move argument from phys reg -> virt reg
+ unsigned VReg = RegInfo.createVirtualRegister(&ARC::GPR32RegClass);
+ RegInfo.addLiveIn(ArgRegs[i], VReg);
+ SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
+ CFRegNode.push_back(Val.getValue(Val->getNumValues() - 1));
+ SDValue VAObj = DAG.getNode(ISD::ADD, dl, MVT::i32, FIN,
+ DAG.getConstant(Offset, dl, MVT::i32));
+ // Move argument from virt reg -> stack
+ SDValue Store =
+ DAG.getStore(Val.getValue(1), dl, Val, VAObj, MachinePointerInfo());
+ MemOps.push_back(Store);
+ Offset += 4;
+ }
+ } else {
+ llvm_unreachable("Too many var args parameters.");
+ }
+ }
+
+ // 2. Chain CopyFromReg nodes into a TokenFactor.
+ if (!CFRegNode.empty())
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, CFRegNode);
+
+ // 3. Memcpy 'byVal' args & push final InVals.
+ // Aggregates passed "byVal" need to be copied by the callee.
+ // The callee will use a pointer to this copy, rather than the original
+ // pointer.
+ for (const auto &ArgDI : ArgData) {
+ if (ArgDI.Flags.isByVal() && ArgDI.Flags.getByValSize()) {
+ unsigned Size = ArgDI.Flags.getByValSize();
+ unsigned Align = std::max(StackSlotSize, ArgDI.Flags.getByValAlign());
+ // Create a new object on the stack and copy the pointee into it.
+ int FI = MFI.CreateStackObject(Size, Align, false);
+ SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
+ InVals.push_back(FIN);
+ MemOps.push_back(DAG.getMemcpy(
+ Chain, dl, FIN, ArgDI.SDV, DAG.getConstant(Size, dl, MVT::i32), Align,
+ false, false, false, MachinePointerInfo(), MachinePointerInfo()));
+ } else {
+ InVals.push_back(ArgDI.SDV);
+ }
+ }
+
+ // 4. Chain mem ops nodes into a TokenFactor.
+ if (!MemOps.empty()) {
+ MemOps.push_back(Chain);
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
+ }
+
+ return Chain;
+}
+
+//===----------------------------------------------------------------------===//
+// Return Value Calling Convention Implementation
+//===----------------------------------------------------------------------===//
+
+bool ARCTargetLowering::CanLowerReturn(
+ CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
+ SmallVector<CCValAssign, 16> RVLocs;
+ CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
+ if (!CCInfo.CheckReturn(Outs, RetCC_ARC))
+ return false;
+ if (CCInfo.getNextStackOffset() != 0 && IsVarArg)
+ return false;
+ return true;
+}
+
+SDValue
+ARCTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
+ bool IsVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<SDValue> &OutVals,
+ const SDLoc &dl, SelectionDAG &DAG) const {
+ auto *AFI = DAG.getMachineFunction().getInfo<ARCFunctionInfo>();
+ MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
+
+ // CCValAssign - represent the assignment of
+ // the return value to a location
+ SmallVector<CCValAssign, 16> RVLocs;
+
+ // CCState - Info about the registers and stack slot.
+ CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
+ *DAG.getContext());
+
+ // Analyze return values.
+ if (!IsVarArg)
+ CCInfo.AllocateStack(AFI->getReturnStackOffset(), 4);
+
+ CCInfo.AnalyzeReturn(Outs, RetCC_ARC);
+
+ SDValue Flag;
+ SmallVector<SDValue, 4> RetOps(1, Chain);
+ SmallVector<SDValue, 4> MemOpChains;
+ // Handle return values that must be copied to memory.
+ for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
+ CCValAssign &VA = RVLocs[i];
+ if (VA.isRegLoc())
+ continue;
+ assert(VA.isMemLoc());
+ if (IsVarArg) {
+ report_fatal_error("Can't return value from vararg function in memory");
+ }
+
+ int Offset = VA.getLocMemOffset();
+ unsigned ObjSize = VA.getLocVT().getStoreSize();
+ // Create the frame index object for the memory location.
+ int FI = MFI.CreateFixedObject(ObjSize, Offset, false);
+
+ // Create a SelectionDAG node corresponding to a store
+ // to this memory location.
+ SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
+ MemOpChains.push_back(DAG.getStore(
+ Chain, dl, OutVals[i], FIN,
+ MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)));
+ }
+
+ // Transform all store nodes into one single node because
+ // all stores are independent of each other.
+ if (!MemOpChains.empty())
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
+
+ // Now handle return values copied to registers.
+ for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
+ CCValAssign &VA = RVLocs[i];
+ if (!VA.isRegLoc())
+ continue;
+ // Copy the result values into the output registers.
+ Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Flag);
+
+ // guarantee that all emitted copies are
+ // stuck together, avoiding something bad
+ Flag = Chain.getValue(1);
+ RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
+ }
+
+ RetOps[0] = Chain; // Update chain.
+
+ // Add the flag if we have it.
+ if (Flag.getNode())
+ RetOps.push_back(Flag);
+
+ // What to do with the RetOps?
+ return DAG.getNode(ARCISD::RET, dl, MVT::Other, RetOps);
+}
+
+//===----------------------------------------------------------------------===//
+// Target Optimization Hooks
+//===----------------------------------------------------------------------===//
+
+SDValue ARCTargetLowering::PerformDAGCombine(SDNode *N,
+ DAGCombinerInfo &DCI) const {
+ return {};
+}
+
+//===----------------------------------------------------------------------===//
+// Addressing mode description hooks
+//===----------------------------------------------------------------------===//
+
+/// Return true if the addressing mode represented by AM is legal for this
+/// target, for a load/store of the specified type.
+bool ARCTargetLowering::isLegalAddressingMode(const DataLayout &DL,
+ const AddrMode &AM, Type *Ty,
+ unsigned AS,
+ Instruction *I) const {
+ return AM.Scale == 0;
+}
+
+// Don't emit tail calls for the time being.
+bool ARCTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
+ return false;
+}
+
+SDValue ARCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
+ const ARCRegisterInfo &ARI = *Subtarget.getRegisterInfo();
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo &MFI = MF.getFrameInfo();
+ MFI.setFrameAddressIsTaken(true);
+
+ EVT VT = Op.getValueType();
+ SDLoc dl(Op);
+ assert(cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() == 0 &&
+ "Only support lowering frame addr of current frame.");
+ unsigned FrameReg = ARI.getFrameRegister(MF);
+ return DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
+}
+
+SDValue ARCTargetLowering::LowerGlobalAddress(SDValue Op,
+ SelectionDAG &DAG) const {
+ const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
+ const GlobalValue *GV = GN->getGlobal();
+ SDLoc dl(GN);
+ int64_t Offset = GN->getOffset();
+ SDValue GA = DAG.getTargetGlobalAddress(GV, dl, MVT::i32, Offset);
+ return DAG.getNode(ARCISD::GAWRAPPER, dl, MVT::i32, GA);
+}
+
+static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) {
+ MachineFunction &MF = DAG.getMachineFunction();
+ auto *FuncInfo = MF.getInfo<ARCFunctionInfo>();
+
+ // vastart just stores the address of the VarArgsFrameIndex slot into the
+ // memory location argument.
+ SDLoc dl(Op);
+ EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(DAG.getDataLayout());
+ SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
+ const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
+ return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1),
+ MachinePointerInfo(SV));
+}
+
+SDValue ARCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
+ switch (Op.getOpcode()) {
+ case ISD::GlobalAddress:
+ return LowerGlobalAddress(Op, DAG);
+ case ISD::FRAMEADDR:
+ return LowerFRAMEADDR(Op, DAG);
+ case ISD::SELECT_CC:
+ return LowerSELECT_CC(Op, DAG);
+ case ISD::BR_CC:
+ return LowerBR_CC(Op, DAG);
+ case ISD::SIGN_EXTEND_INREG:
+ return LowerSIGN_EXTEND_INREG(Op, DAG);
+ case ISD::JumpTable:
+ return LowerJumpTable(Op, DAG);
+ case ISD::VASTART:
+ return LowerVASTART(Op, DAG);
+ default:
+ llvm_unreachable("unimplemented operand");
+ }
+}
Added: llvm/trunk/lib/Target/ARC/ARCISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCISelLowering.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCISelLowering.h (added)
+++ llvm/trunk/lib/Target/ARC/ARCISelLowering.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,121 @@
+//===- 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/Target/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
Added: llvm/trunk/lib/Target/ARC/ARCInstrFormats.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCInstrFormats.td?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCInstrFormats.td (added)
+++ llvm/trunk/lib/Target/ARC/ARCInstrFormats.td Thu Aug 24 08:40:33 2017
@@ -0,0 +1,508 @@
+//===- ARCInstrFormats.td - ARC Instruction Formats --------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Instruction format superclass
+//===----------------------------------------------------------------------===//
+
+class Encoding64 {
+ field bits<64> Inst;
+ field bits<64> SoftFail = 0;
+}
+
+// Address operands
+def immU6 : Operand<i32>, PatLeaf<(imm), [{
+ return isUInt<6>(N->getSExtValue()); }]> {
+}
+
+def immS12 : Operand<i32>, PatLeaf<(imm), [{
+ return isInt<12>(N->getSExtValue()); }]> {
+ let DecoderMethod = "DecodeS12Operand";
+}
+
+def immS9 : Operand<i32>, PatLeaf<(imm), [{
+ return isInt<9>(N->getSExtValue()); }]> {
+ let DecoderMethod = "DecodeS9Operand";
+}
+
+def MEMii : Operand<i32> {
+ let MIOperandInfo = (ops i32imm, i32imm);
+}
+
+def MEMrs9 : Operand<iAny> {
+ let MIOperandInfo = (ops GPR32:$B, immS9:$S9);
+ let PrintMethod = "printMemOperandRI";
+ let DecoderMethod = "DecodeMEMrs9";
+}
+
+def MEMrlimm : Operand<iAny> {
+ let MIOperandInfo = (ops GPR32:$B, i32imm:$LImm);
+ let PrintMethod = "printMemOperandRI";
+ let DecoderMethod = "DecodeMEMrlimm";
+}
+
+class InstARC<int sz, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : Instruction, Encoding64 {
+
+ let Namespace = "ARC";
+ dag OutOperandList = outs;
+ dag InOperandList = ins;
+ let AsmString = asmstr;
+ let Pattern = pattern;
+ let Size = sz;
+}
+
+// ARC pseudo instructions format
+class PseudoInstARC<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : InstARC<0, outs, ins, asmstr, pattern> {
+ let isPseudo = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction formats
+//===----------------------------------------------------------------------===//
+
+// All 32-bit ARC instructions have a 5-bit "major" opcode class designator
+// in bits 27-31.
+//
+// Some general naming conventions:
+// N - Delay Slot bit. ARC v2 branch instructions have an optional delay slot
+// which is encoded with this bit. When set, a delay slot exists.
+// cc - Condition code.
+// SX - Signed X-bit immediate.
+// UX - Unsigned X-bit immediate.
+//
+// [ABC] - 32-bit register operand. These are 6-bit fields. This encodes the
+// standard 32 general purpose registers, and allows use of additional
+// (extension) registers. This also encodes an instruction that uses
+// a 32-bit Long Immediate (LImm), using 0x3e==62 as the field value.
+// This makes 32-bit format instructions with Long Immediates
+// 64-bit instructions, with the Long Immediate in bits 32-63.
+// A - Inst[5-0] = A[5-0], when the format has A. A is always a register.
+// B - Inst[14-12] = B[5-3], Inst[26-24] = B[2-0], when the format has B.
+// B is always a register.
+// C - Inst[11-6] = C[5-0], when the format has C. C can either be a register,
+// or a 6-bit unsigned immediate (immU6), depending on the format.
+// F - Many instructions specify a flag bit. When set, the result of these
+// instructions will set the ZNCV flags of the STATUS32 register
+// (Zero/Negative/Carry/oVerflow).
+
+// Branch Instructions.
+class F32_BR<bits<5> major, dag outs, dag ins, bit b16, string asmstr,
+ list<dag> pattern> :
+ InstARC<4, outs, ins, asmstr, pattern> {
+ bit N;
+
+ let Inst{31-27} = major;
+ let Inst{16} = b16;
+ let Inst{5} = N;
+}
+
+class F32_BR_COND<bits<5> major, dag outs, dag ins, bit b16, string asmstr,
+ list<dag> pattern> :
+ F32_BR<major, outs, ins, b16, asmstr, pattern> {
+ bits<21> S21; // 2-byte aligned 21-bit byte-offset.
+ bits<5> cc;
+ let Inst{26-18} = S21{10-2};
+ let Inst{15-6} = S21{20-11};
+ let Inst{4-0} = cc;
+}
+
+class F32_BR_UCOND_FAR<bits<5> major, dag outs, dag ins, bit b16, string asmstr,
+ list<dag> pattern> :
+ F32_BR<major, outs, ins, b16, asmstr, pattern> {
+ bits<25> S25; // 2-byte aligned 25-bit byte-offset.
+ let Inst{26-18} = S25{10-2};
+ let Inst{15-6} = S25{20-11};
+ let Inst{4} = 0;
+ let Inst{3-0} = S25{24-21};
+}
+
+class F32_BR0_COND<dag outs, dag ins, string asmstr, list<dag> pat> :
+ F32_BR_COND<0b00000, outs, ins, 0, asmstr, pat> {
+ let Inst{17} = S21{1};
+}
+
+// Branch targets are 2-byte aligned, so S25[0] is implied 0.
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0 |
+// |S25[10-1] | 1|S25[20-11] |N|0|S25[24-21]|
+class F32_BR0_UCOND_FAR<dag outs, dag ins, string asmstr, list<dag> pat> :
+ F32_BR_UCOND_FAR<0b00000, outs, ins, 1, asmstr, pat> {
+ let Inst{17} = S25{1};
+}
+
+// BL targets (functions) are 4-byte aligned, so S25[1-0] = 0b00
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0 |
+// |S25[10-2] | 1| 0|S25[20-11] |N|0|S25[24-21]|
+class F32_BR1_BL_UCOND_FAR<dag outs, dag ins, string asmstr, list<dag> pat> :
+ F32_BR_UCOND_FAR<0b00001, outs, ins, 0, asmstr, pat> {
+ let Inst{17} = 1;
+}
+
+// BLcc targets have 21 bit range, and are 4-byte aligned.
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+// |S25[10-2] | 0| 0|S25[20-11] |N|0|cc |
+class F32_BR1_BL_COND<dag outs, dag ins, string asmstr, list<dag> pat> :
+ F32_BR_COND<0b00001, outs, ins, 0, asmstr, pat> {
+ let Inst{17} = 0;
+}
+
+
+// BRcc targets have limited 9-bit range. These are for compare and branch
+// in single instruction. Their targets are 2-byte aligned. They also use
+// a different (3-bit) set of condition codes.
+// |26|25|24|23|22|21|20|19|18|17|16|15 |14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+// |B[2-0] |S9[7-1] | 1|S9[8]|B[5-3] |C |N|u|0|cc |
+class F32_BR1_BCC<dag outs, dag ins, string asmstr, bit IsU6,
+ list<dag> pattern> :
+ InstARC<4, outs, ins, asmstr, pattern> {
+
+ bits<3> cc;
+ bits<6> B;
+ bits<6> C;
+ bit N;
+ bits<9> S9; // 2-byte aligned 9-bit byte-offset.
+
+ let Inst{31-27} = 0b00001;
+ let Inst{26-24} = B{2-0};
+ let Inst{23-17} = S9{7-1};
+ let Inst{16} = 1;
+ let Inst{15} = S9{8};
+ let Inst{14-12} = B{5-3};
+ let Inst{11-6} = C;
+ let Inst{5} = N;
+ let Inst{4} = IsU6;
+ let Inst{3} = 0;
+ let Inst{2-0} = cc;
+}
+
+// General operations instructions.
+// Single Operand Instructions. Inst[5-0] specifies the specific operation
+// for this format.
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+// |B[2-0] | 0| 0| 1| 0| 1| 1| 1| 1| F|B[5-3] |C |subop |
+class F32_SOP_RR<bits<5> major, bits<6> subop, bit F, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<4, outs, ins, asmstr, pattern> {
+
+ bits<6> C;
+ bits<6> B;
+
+ let Inst{31-27} = major;
+ let Inst{26-24} = B{2-0};
+ let Inst{23-22} = 0b00;
+ let Inst{21-16} = 0b101111;
+ let Inst{15} = F;
+ let Inst{14-12} = B{5-3};
+ let Inst{11-6} = C;
+ let Inst{5-0} = subop;
+}
+
+// Dual Operand Instructions. Inst[21-16] specifies the specific operation
+// for this format.
+
+// 3-register Dual Operand instruction.
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+// |B[2-0] | 0| 0| subop| F|B[5-3] |C |A |
+class F32_DOP_RR<bits<5> major, bits<6> subop, bit F, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<4, outs, ins, asmstr, pattern> {
+ bits<6> C;
+ bits<6> B;
+ bits<6> A;
+
+ let Inst{31-27} = major;
+ let Inst{26-24} = B{2-0};
+ let Inst{23-22} = 0b00;
+ let Inst{21-16} = subop;
+ let Inst{15} = F;
+ let Inst{14-12} = B{5-3};
+ let Inst{11-6} = C;
+ let Inst{5-0} = A;
+}
+
+// Conditional Dual Operand instruction. This instruction uses B as the
+// first 2 operands (i.e, add.cc B, B, C).
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+// |B[2-0] | 1| 1| subop| F|B[5-3] |C |A |
+class F32_DOP_CC_RR<bits<5> major, bits<6> subop, bit F, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<4, outs, ins, asmstr, pattern> {
+ bits<5> cc;
+ bits<6> C;
+ bits<6> B;
+
+ let Inst{31-27} = major;
+ let Inst{26-24} = B{2-0};
+ let Inst{23-22} = 0b11;
+ let Inst{21-16} = subop;
+ let Inst{15} = F;
+ let Inst{14-12} = B{5-3};
+ let Inst{11-6} = C;
+ let Inst{5} = 0;
+ let Inst{4-0} = cc;
+}
+
+
+// 2-register, unsigned 6-bit immediate Dual Operand instruction.
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+// |B[2-0] | 0| 1| subop| F|B[5-3] |U6 |A |
+class F32_DOP_RU6<bits<5> major, bits<6> subop, bit F, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<4, outs, ins, asmstr, pattern> {
+ bits<6> U6;
+ bits<6> B;
+ bits<6> A;
+
+ let Inst{31-27} = major;
+ let Inst{26-24} = B{2-0};
+ let Inst{23-22} = 0b01;
+ let Inst{21-16} = subop;
+ let Inst{15} = F;
+ let Inst{14-12} = B{5-3};
+ let Inst{11-6} = U6;
+ let Inst{5-0} = A;
+}
+
+// 2-register, signed 12-bit immediate Dual Operand instruction.
+// This instruction uses B as the first 2 operands (i.e., add B, B, -128).
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+// |B[2-0] | 1| 0| subop| F|B[5-3] |S12[5-0] |S12[11-6] |
+class F32_DOP_RS12<bits<5> major, bits<6> subop, bit F, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<4, outs, ins, asmstr, pattern> {
+ bits<6> B;
+ bits<12> S12;
+
+ let Inst{31-27} = major;
+ let Inst{26-24} = B{2-0};
+ let Inst{23-22} = 0b10;
+ let Inst{21-16} = subop;
+ let Inst{15} = F;
+ let Inst{14-12} = B{5-3};
+ let Inst{11-6} = S12{5-0};
+ let Inst{5-0} = S12{11-6};
+}
+
+// 2-register, 32-bit immediate (LImm) Dual Operand instruction.
+// This instruction has the 32-bit immediate in bits 32-63, and
+// 62 in the C register operand slot, but is otherwise F32_DOP_RR.
+class F32_DOP_RLIMM<bits<5> major, bits<6> subop, bit F, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<8, outs, ins, asmstr, pattern> {
+ bits<6> B;
+ bits<6> A;
+ bits<32> LImm;
+
+ let Inst{63-32} = LImm;
+ let Inst{31-27} = major;
+ let Inst{26-24} = B{2-0};
+ let Inst{23-22} = 0b00;
+ let Inst{21-16} = subop;
+ let Inst{15} = F;
+ let Inst{14-12} = B{5-3};
+ let Inst{11-6} = 0b111110;
+ let Inst{5-0} = A;
+}
+
+
+// Load and store instructions.
+// In addition to the previous naming conventions, load and store instructions
+// have:
+// di - Uncached bit. When set, loads/stores bypass the cache and access
+// memory directly.
+// aa - Incrementing mode. Loads and stores can write-back address pre- or
+// post- memory operation.
+// zz - Memory size (can be 8/16/32 bit load/store).
+// x - Sign-extending. When set, short loads can be sign-extended to 32-bits.
+// Loads and Stores support different memory addressing modes:
+// Base Register + Signed 9-bit Immediate: Both Load/Store.
+// LImm: Both Load/Store (Load/Store from a fixed 32-bit address).
+// Register + Register: Load Only.
+// Register + LImm: Load Only.
+
+// Register + S9 Load. (B + S9)
+// |26|25|24|23|22|21|20|19|18|17|16|15 |14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+// |B[2-0] |S9[7-0] |S9[8]|B[5-3] |di|aa |zz |x|A |
+class F32_LD_RS9<bit x, bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<4, outs, ins, asmstr, pattern> {
+ bits<6> B;
+ bits<6> A;
+ bits<9> S9;
+
+ let Inst{31-27} = 0b00010;
+ let Inst{26-24} = B{2-0};
+ let Inst{23-16} = S9{7-0};
+ let Inst{15} = S9{8};
+ let Inst{14-12} = B{5-3};
+ let Inst{11} = di;
+ let Inst{10-9} = aa;
+ let Inst{8-7} = zz;
+ let Inst{6} = x;
+ let Inst{5-0} = A;
+}
+
+class F32_LD_ADDR<bit x, bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ F32_LD_RS9<x, aa, di, zz, outs, ins, asmstr, pattern> {
+ bits<15> addr;
+
+ let B = addr{14-9};
+ let S9 = addr{8-0};
+}
+
+
+// LImm Load. The 32-bit immediate address is in Inst[63-32].
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+// | 1| 1| 0| 0 | 1| 1| 1|di| 0|0|zz |x|A |
+class F32_LD_LIMM<bit x, bit di, bits<2> zz, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<8, outs, ins, asmstr, pattern> {
+ bits<6> LImmReg = 0b111110;
+ bits<6> A;
+ bits<32> LImm;
+
+ let Inst{63-32} = LImm;
+ let Inst{31-27} = 0b00010;
+ let Inst{26-24} = LImmReg{2-0};
+ let Inst{23-15} = 0;
+ let Inst{14-12} = LImmReg{5-3};
+ let Inst{11} = di;
+ let Inst{10-9} = 0;
+ let Inst{8-7} = zz;
+ let Inst{6} = x;
+ let Inst{5-0} = A;
+ let DecoderMethod = "DecodeLdLImmInstruction";
+}
+
+// Register + LImm load. The 32-bit immediate address is in Inst[63-32].
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|
+// |B[2-0] |aa | 1| 1| 0|zz | x|di|B[5-3] | 1| 1|1|1|1|0|A |
+class F32_LD_RLIMM<bit x, bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<8, outs, ins, asmstr, pattern> {
+ bits<6> LImmReg = 0b111110;
+ bits<32> LImm;
+ bits<6> B;
+ bits<6> A;
+ bits<38> addr;
+ let B = addr{37-32};
+ let LImm = addr{31-0};
+
+ let Inst{63-32} = LImm;
+ let Inst{31-27} = 0b00100;
+ let Inst{26-24} = B{2-0};
+ let Inst{23-22} = aa;
+ let Inst{21-19} = 0b110;
+ let Inst{18-17} = zz;
+ let Inst{16} = x;
+ let Inst{15} = di;
+ let Inst{14-12} = B{5-3};
+ let Inst{11-6} = LImmReg;
+ let Inst{5-0} = A;
+ let DecoderMethod = "DecodeLdRLImmInstruction";
+}
+
+// Register + S9 Store. (B + S9)
+// |26|25|24|23|22|21|20|19|18|17|16|15 |14|13|12|11|10|9|8|7|6|5 |4|3|2|1|0|
+// |B[2-0] |S9[7-0] |S9[8]|B[5-3] |C |di|aa |zz |0|
+class F32_ST_RS9<bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<4, outs, ins, asmstr, pattern> {
+ bits<6> B;
+ bits<6> C;
+ bits<9> S9;
+
+ let Inst{31-27} = 0b00011;
+ let Inst{26-24} = B{2-0};
+ let Inst{23-16} = S9{7-0};
+ let Inst{15} = S9{8};
+ let Inst{14-12} = B{5-3};
+ let Inst{11-6} = C;
+ let Inst{5} = di;
+ let Inst{4-3} = aa;
+ let Inst{2-1} = zz;
+ let Inst{0} = 0;
+}
+
+class F32_ST_ADDR<bits<2> aa, bit di, bits<2> zz, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ F32_ST_RS9<aa, di, zz, outs, ins, asmstr, pattern> {
+ bits<15> addr;
+
+ let B = addr{14-9};
+ let S9 = addr{8-0};
+}
+
+// LImm Store.
+// |26|25|24|23|22|21|20|19|18|17|16|15|14|13|12|11|10|9|8|7|6|5 |4|3|2|1|0|
+// | 1| 1| 0| 0 | 1| 1| 1|C |di|0|0|zz |0|
+class F32_ST_LIMM<bit di, bits<2> zz, dag outs, dag ins,
+ string asmstr, list<dag> pattern> :
+ InstARC<8, outs, ins, asmstr, pattern> {
+ bits<6> LImmReg = 0b111110;
+ bits<6> C;
+ bits<32> LImm;
+
+ let Inst{63-32} = LImm;
+ let Inst{31-27} = 0b00011;
+ let Inst{26-24} = LImmReg{2-0};
+ let Inst{23-15} = 0;
+ let Inst{14-12} = LImmReg{5-3};
+ let Inst{11-6} = C;
+ let Inst{5} = di;
+ let Inst{4-3} = 0;
+ let Inst{2-1} = zz;
+ let Inst{0} = 0;
+ let DecoderMethod = "DecodeStLImmInstruction";
+}
+
+// Special types for different instruction operands.
+def cmovpred : Operand<i32>, PredicateOp,
+ ComplexPattern<i32, 2, "SelectCMOVPred"> {
+ let MIOperandInfo = (ops i32imm, i32imm);
+ let PrintMethod = "printPredicateOperand";
+}
+
+def ccond : Operand<i32> {
+ let MIOperandInfo = (ops i32imm);
+ let PrintMethod = "printPredicateOperand";
+}
+
+def brccond : Operand<i32> {
+ let MIOperandInfo = (ops i32imm);
+ let PrintMethod = "printBRCCPredicateOperand";
+}
+
+// Branch targets of different offset sizes.
+def btarget : Operand<OtherVT> {
+ let OperandType = "OPERAND_PCREL";
+}
+
+def btargetS9 : Operand<OtherVT> {
+ let OperandType = "OPERAND_PCREL";
+ let DecoderMethod = "DecodeBranchTargetS9";
+}
+
+def btargetS21 : Operand<OtherVT> {
+ let OperandType = "OPERAND_PCREL";
+ let DecoderMethod = "DecodeBranchTargetS21";
+}
+
+def btargetS25 : Operand<OtherVT> {
+ let OperandType = "OPERAND_PCREL";
+ let DecoderMethod = "DecodeBranchTargetS25";
+}
+
+def calltargetS25: Operand<i32> {
+ let OperandType = "OPERAND_PCREL";
+ let DecoderMethod = "DecodeBranchTargetS25";
+}
+
Added: llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCInstrInfo.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,394 @@
+//===- 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();
+}
Added: llvm/trunk/lib/Target/ARC/ARCInstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCInstrInfo.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCInstrInfo.h (added)
+++ llvm/trunk/lib/Target/ARC/ARCInstrInfo.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,94 @@
+//===- 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/Target/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
Added: llvm/trunk/lib/Target/ARC/ARCInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCInstrInfo.td?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCInstrInfo.td (added)
+++ llvm/trunk/lib/Target/ARC/ARCInstrInfo.td Thu Aug 24 08:40:33 2017
@@ -0,0 +1,504 @@
+//===- ARCInstrInfo.td - Target Description 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 file describes the ARC instructions in TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
+include "ARCInstrFormats.td"
+
+// ---------------------------------------------------------------------------
+// Selection DAG Nodes.
+// ---------------------------------------------------------------------------
+
+// Selection DAG types.
+def SDT_ARCcmptst : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
+def SDT_ARCcmov : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>;
+def SDT_ARCmov : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>]>;
+def SDT_ARCbrcc : SDTypeProfile<0, 4, []>;
+def SDT_ARCBranchLink : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
+def SDT_ARCCallSeqStart : SDCallSeqStart<[ SDTCisVT<0, i32>,
+ SDTCisVT<1, i32> ]>;
+def SDT_ARCCallSeqEnd : SDCallSeqEnd<[ SDTCisVT<0, i32>,
+ SDTCisVT<1, i32> ]>;
+
+
+// Global Address.
+def ARCGAWrapper : SDNode<"ARCISD::GAWRAPPER", SDT_ARCmov, []>;
+
+// Comparison
+def ARCcmp : SDNode<"ARCISD::CMP", SDT_ARCcmptst, [SDNPOutGlue]>;
+
+// Conditionanal mov
+def ARCcmov : SDNode<"ARCISD::CMOV", SDT_ARCcmov, [SDNPInGlue]>;
+
+// Conditional Branch
+def ARCbrcc : SDNode<"ARCISD::BRcc", SDT_ARCbrcc,
+ [SDNPHasChain, SDNPInGlue, SDNPOutGlue]>;
+
+// Direct Call
+def ARCBranchLink : SDNode<"ARCISD::BL",SDT_ARCBranchLink,
+ [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
+ SDNPVariadic]>;
+
+// Indirect Call
+def ARCJumpLink : SDNode<"ARCISD::JL",SDT_ARCBranchLink,
+ [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
+ SDNPVariadic]>;
+// Call return
+def ret : SDNode<"ARCISD::RET", SDTNone,
+ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
+
+// Call sequencing nodes.
+// These are target-independent nodes, but have target-specific formats.
+def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_ARCCallSeqStart,
+ [SDNPHasChain, SDNPOutGlue]>;
+def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_ARCCallSeqEnd,
+ [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>;
+
+//===----------------------------------------------------------------------===//
+// Instruction Pattern Stuff
+//===----------------------------------------------------------------------===//
+
+def imm32 : ImmLeaf<i32, [{
+ return (Imm & 0xFFFFFFFF) == Imm;
+}]>;
+
+// Addressing modes
+def FrameADDR_ri : ComplexPattern<i32, 2, "SelectFrameADDR_ri",
+ [add, frameindex], []>;
+def AddrModeS9 : ComplexPattern<i32, 2, "SelectAddrModeS9", []>;
+def AddrModeImm : ComplexPattern<i32, 2, "SelectAddrModeImm", []>;
+def AddrModeFar : ComplexPattern<i32, 2, "SelectAddrModeFar", []>;
+
+//===----------------------------------------------------------------------===//
+// Instruction Class Templates
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Pseudo Instructions
+//===----------------------------------------------------------------------===//
+
+let Defs = [SP], Uses = [SP] in {
+def ADJCALLSTACKDOWN : PseudoInstARC<(outs), (ins i32imm:$amt, i32imm:$amt2),
+ "# ADJCALLSTACKDOWN $amt, $amt2",
+ [(callseq_start timm:$amt, timm:$amt2)]>;
+def ADJCALLSTACKUP : PseudoInstARC<(outs), (ins i32imm:$amt1, i32imm:$amt2),
+ "# ADJCALLSTACKUP $amt1",
+ [(callseq_end timm:$amt1, timm:$amt2)]>;
+}
+
+def GETFI : PseudoInstARC<(outs GPR32:$dst), (ins MEMii:$addr),
+ "pldfi $dst, $addr",
+ [(set GPR32:$dst, FrameADDR_ri:$addr)]>;
+
+
+def ST_FAR : PseudoInstARC<(outs), (ins GPR32:$dst, MEMrlimm:$addr),
+ "ST_FAR $dst, $addr",
+ [(store GPR32:$dst, AddrModeFar:$addr)]>;
+
+def STH_FAR : PseudoInstARC<(outs), (ins GPR32:$dst, MEMrlimm:$addr),
+ "STH_FAR $dst, $addr",
+ [(truncstorei16 GPR32:$dst, AddrModeFar:$addr)]>;
+
+def STB_FAR : PseudoInstARC<(outs), (ins GPR32:$dst, MEMrlimm:$addr),
+ "STB_FAR $dst, $addr",
+ [(truncstorei8 GPR32:$dst, AddrModeFar:$addr)]>;
+
+//===----------------------------------------------------------------------===//
+// Instruction Generation multiclasses.
+// Generate many variants of a single instruction with a single defining
+// multiclass. These classes do not contain Selection DAG patterns.
+//===----------------------------------------------------------------------===//
+
+// Generic 3 operand binary instructions (i.e., add, r0, r1, r2).
+multiclass ArcBinaryInst<bits<5> major, bits<6> mincode,
+ string opasm> {
+ // 3 register variant.
+ def _rrr : F32_DOP_RR<major, mincode, 0, (outs GPR32:$A),
+ (ins GPR32:$B, GPR32:$C),
+ !strconcat(opasm, "\t$A, $B, $C"),
+ []>;
+
+ // 2 register with unsigned 6-bit immediate variant.
+ def _rru6 : F32_DOP_RU6<major, mincode, 0, (outs GPR32:$A),
+ (ins GPR32:$B, immU6:$U6),
+ !strconcat(opasm, "\t$A, $B, $U6"),
+ []>;
+ // 2 register with 32-bit immediate variant.
+ def _rrlimm : F32_DOP_RLIMM<major, mincode, 0,
+ (outs GPR32:$A),
+ (ins GPR32:$B, i32imm:$LImm),
+ !strconcat(opasm, "\t$A, $B, $LImm"),
+ []>;
+ // 2 matched-register with signed 12-bit immediate variant (add r0, r0, -1).
+ def _rrs12 : F32_DOP_RS12<major, mincode, 0,
+ (outs GPR32:$B),
+ (ins GPR32:$in, immS12:$S12),
+ !strconcat(opasm, "\t$B, $in, $S12"),
+ []>
+ { let Constraints = "$B = $in"; }
+}
+
+// Special multivariant GEN4 DOP format instruction that take 2 registers.
+// This is the class that is used for various comparison instructions.
+multiclass ArcSpecialDOPInst<bits<6> subop, string opasm, bit F> {
+ def _rr : F32_DOP_RR<0b00100, subop, F, (outs), (ins GPR32:$B, GPR32:$C),
+ !strconcat(opasm, "\t$B, $C"),
+ []>;
+
+ def _ru6 : F32_DOP_RU6<0b00100, subop, F, (outs), (ins GPR32:$B, i32imm:$U6),
+ !strconcat(opasm, "\t$B, $U6"),
+ []>;
+
+ def _rlimm : F32_DOP_RLIMM<0b00100, subop, F, (outs),
+ (ins GPR32:$B, i32imm:$LImm),
+ !strconcat(opasm, "\t$B, $LImm"),
+ []>;
+}
+
+// Generic 2-operand unary instructions.
+multiclass ArcUnaryInst<bits<5> major, bits<6> subop,
+ string opasm> {
+ def _rr : F32_SOP_RR<major, subop, 0, (outs GPR32:$B), (ins GPR32:$C),
+ !strconcat(opasm, "\t$B, $C"), []>;
+}
+
+
+multiclass ArcBinaryGEN4Inst<bits<6> mincode, string opasm> :
+ ArcBinaryInst<0b00100, mincode, opasm>;
+multiclass ArcBinaryEXT5Inst<bits<6> mincode, string opasm> :
+ ArcBinaryInst<0b00101, mincode, opasm>;
+
+multiclass ArcUnaryGEN4Inst<bits<6> mincode, string opasm> :
+ ArcUnaryInst<0b00100, mincode, opasm>;
+
+// Pattern generation for differnt instruction variants.
+multiclass MultiPat<SDPatternOperator InFrag,
+ Instruction RRR, Instruction RRU6, Instruction RRLImm> {
+ def _rrr : Pat<(InFrag i32:$B, i32:$C), (RRR i32:$B, i32:$C)>;
+ def _rru6 : Pat<(InFrag i32:$B, immU6:$U6), (RRU6 i32:$B, immU6:$U6)>;
+ def _rrlimm : Pat<(InFrag i32:$B, imm32:$LImm), (RRLImm i32:$B, imm32:$LImm)>;
+}
+
+// ---------------------------------------------------------------------------
+// Instruction defintions and patterns for 3 operand binary instructions.
+// ---------------------------------------------------------------------------
+
+// Definitions for 3 operand binary instructions.
+defm ADD : ArcBinaryGEN4Inst<0b000000, "add">;
+defm SUB : ArcBinaryGEN4Inst<0b000010, "sub">;
+defm OR : ArcBinaryGEN4Inst<0b000101, "or">;
+defm AND : ArcBinaryGEN4Inst<0b000100, "and">;
+defm XOR : ArcBinaryGEN4Inst<0b000111, "xor">;
+defm MAX : ArcBinaryGEN4Inst<0b001000, "max">;
+defm MIN : ArcBinaryGEN4Inst<0b001001, "min">;
+defm ASL : ArcBinaryEXT5Inst<0b000000, "asl">;
+defm LSR : ArcBinaryEXT5Inst<0b000001, "lsr">;
+defm ASR : ArcBinaryEXT5Inst<0b000010, "asr">;
+defm ROR : ArcBinaryEXT5Inst<0b000011, "ror">;
+defm MPY : ArcBinaryGEN4Inst<0b011010, "mpy">;
+defm MPYM : ArcBinaryGEN4Inst<0b011011, "mpym">;
+defm MPYMU : ArcBinaryGEN4Inst<0b011100, "mpymu">;
+
+// Patterns for 3 operand binary instructions.
+defm : MultiPat<add, ADD_rrr, ADD_rru6, ADD_rrlimm>;
+defm : MultiPat<sub, SUB_rrr, SUB_rru6, SUB_rrlimm>;
+defm : MultiPat<or, OR_rrr, OR_rru6, OR_rrlimm>;
+defm : MultiPat<and, AND_rrr, AND_rru6, AND_rrlimm>;
+defm : MultiPat<xor, XOR_rrr, XOR_rru6, XOR_rrlimm>;
+defm : MultiPat<smax, MAX_rrr, MAX_rru6, MAX_rrlimm>;
+defm : MultiPat<smin, MIN_rrr, MIN_rru6, MIN_rrlimm>;
+defm : MultiPat<shl, ASL_rrr, ASL_rru6, ASL_rrlimm>;
+defm : MultiPat<srl, LSR_rrr, LSR_rru6, LSR_rrlimm>;
+defm : MultiPat<sra, ASR_rrr, ASR_rru6, ASR_rrlimm>;
+defm : MultiPat<rotr, ROR_rrr, ROR_rru6, ROR_rrlimm>;
+defm : MultiPat<mul, MPY_rrr, MPY_rru6, MPY_rrlimm>;
+defm : MultiPat<mulhs, MPYM_rrr, MPYM_rru6, MPYM_rrlimm>;
+defm : MultiPat<mulhu, MPYMU_rrr, MPYMU_rru6, MPYMU_rrlimm>;
+
+
+// ---------------------------------------------------------------------------
+// Unary Instruction definitions.
+// ---------------------------------------------------------------------------
+// General unary instruction definitions.
+defm SEXB : ArcUnaryGEN4Inst<0b000101, "sexb">;
+defm SEXH : ArcUnaryGEN4Inst<0b000110, "sexh">;
+
+// General Unary Instruction fragments.
+def : Pat<(sext_inreg i32:$a, i8), (SEXB_rr i32:$a)>;
+def : Pat<(sext_inreg i32:$a, i16), (SEXH_rr i32:$a)>;
+
+// Comparison instruction definition
+let isCompare = 1, Defs = [STATUS32] in {
+defm CMP : ArcSpecialDOPInst<0b001100, "cmp", 1>;
+}
+
+def cmp : PatFrag<(ops node:$op1, node:$op2), (ARCcmp $op1, $op2)>;
+defm : MultiPat<cmp, CMP_rr, CMP_ru6, CMP_rlimm>;
+
+// ---------------------------------------------------------------------------
+// MOV instruction and variants (conditional mov).
+// ---------------------------------------------------------------------------
+let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in {
+def MOV_rs12 : F32_DOP_RS12<0b00100, 0b001010, 0,
+ (outs GPR32:$B), (ins immS12:$S12),
+ "mov\t$B, $S12",
+ [(set GPR32:$B, immS12:$S12)]>;
+}
+
+def MOV_rr : F32_DOP_RR<0b00100, 0b001010, 0,
+ (outs GPR32:$B), (ins GPR32:$C),
+ "mov\t$B, $C", []>;
+
+def MOV_rlimm : F32_DOP_RLIMM<0b00100, 0b001010, 0,
+ (outs GPR32:$B), (ins i32imm:$LImm),
+ "mov\t$B, $LImm", []>;
+
+def MOV_ru6 : F32_DOP_RU6<0b00100, 0b001010, 0,
+ (outs GPR32:$B), (ins immU6:$U6),
+ "mov\t$B, $U6", []>;
+
+def cmov : PatFrag<(ops node:$op1, node:$op2, node:$cc),
+ (ARCcmov $op1, $op2, $cc)>;
+let Uses = [STATUS32] in {
+def MOVcc : F32_DOP_CC_RR<0b00100, 0b001010, 0,
+ (outs GPR32:$B),
+ (ins GPR32:$C, GPR32:$fval, cmovpred:$cc),
+ !strconcat("mov.", "$cc\t$B, $C"),
+ [(set GPR32:$B, (cmov i32:$C, i32:$fval, cmovpred:$cc))]> {
+ let Constraints = "$B = $fval";
+}
+}
+def : Pat<(ARCGAWrapper tglobaladdr:$addr),
+ (MOV_rlimm tglobaladdr:$addr)>;
+
+def : Pat<(ARCGAWrapper tjumptable:$addr),
+ (MOV_rlimm tjumptable:$addr)>;
+
+
+// ---------------------------------------------------------------------------
+// Control flow instructions (branch, return, calls, etc).
+// ---------------------------------------------------------------------------
+
+// Branch instructions
+let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
+// Unconditional branch.
+def BR : F32_BR0_UCOND_FAR<(outs), (ins btargetS25:$S25),
+ "b\t$S25", [(br bb:$S25)]>;
+
+let Uses=[STATUS32] in {
+// Conditional branch.
+def Bcc : F32_BR0_COND<(outs), (ins btargetS21:$S21, ccond:$cc),
+ "b$cc\t$S21", []>;
+}
+
+// Compare and branch (limited range).
+def BRcc_rr : F32_BR1_BCC<(outs),
+ (ins btargetS9:$S9, GPR32:$B, GPR32:$C, brccond:$cc),
+ "br$cc\t$B, $C, $S9", 0, []>;
+def BRcc_ru6 : F32_BR1_BCC<(outs),
+ (ins btargetS9:$S9, GPR32:$B, immU6:$C, brccond:$cc),
+ "br$cc\t$B, $C, $S9", 1, []>;
+
+// Pseudo compare and branch.
+// After register allocation, this can expand into either a limited range
+// Compare and branch (BRcc), or into CMP + Bcc.
+// At worst, this expands into 2 4-byte instructions.
+def BRcc_rr_p : PseudoInstARC<(outs),
+ (ins btarget:$T, GPR32:$B, GPR32:$C, ccond:$cc),
+ "pbr$cc\t$B, $C, $T",
+ [(ARCbrcc bb:$T, i32:$B, i32:$C, imm32:$cc)]>
+ { let Size = 8; }
+
+def BRcc_ru6_p : PseudoInstARC<(outs),
+ (ins btarget:$T, GPR32:$B, i32imm:$C, ccond:$cc),
+ "pbr$cc\t$B, $C, $T",
+ [(ARCbrcc bb:$T, i32:$B, immU6:$C, imm32:$cc)]>
+ { let Size = 8; }
+}
+
+// Indirect, unconditional Jump.
+let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
+def J : F32_DOP_RR<0b00100, 0b100000, 0,
+ (outs), (ins GPR32:$C),
+ "j\t[$C]", [(brind i32:$C)]>;
+}
+
+// Call instructions.
+let isCall = 1, Defs = [BLINK], Uses = [SP] in {
+// Direct unconditional call.
+def BL : F32_BR1_BL_UCOND_FAR<(outs), (ins calltargetS25:$S25),
+ "bl\t$S25", [(ARCBranchLink tglobaladdr:$S25)]>;
+
+// Indirect unconditional call.
+let isIndirectBranch = 1, Defs = [BLINK], Uses = [SP] in {
+def JL : F32_DOP_RR<0b00100, 0b100010, 0, (outs), (ins GPR32:$C),
+ "jl\t[$C]", [(ARCJumpLink i32:$C)]>;
+}
+}
+
+// Pattern to generate BL instruction.
+def : Pat<(ARCBranchLink texternalsym:$dst), (BL texternalsym:$dst)>;
+
+// Return from call.
+let isReturn = 1, isTerminator = 1, isBarrier = 1 in {
+// This is a specialized 2-byte instruction that doesn't generalize
+// to any larger 2-byte class, so go ahead and define it here.
+def J_S_BLINK : InstARC<2, (outs), (ins), "j_s\t[%blink]", [(ret)]> {
+ let Inst{15-0} = 0b0111111011100000;
+}
+}
+
+//----------------------------------------------------------------------------
+// Load/Store instructions.
+//----------------------------------------------------------------------------
+
+// 2-byte push/pop blink instructions commonly used for prolog/epilog
+// generation. These 2 instructions are actually specialized 2-byte
+// format instructions that aren't generalized to a larger 2-byte
+// class, so we might as well have them here.
+let Uses = [BLINK], Defs = [SP] in {
+def PUSH_S_BLINK : InstARC<2, (outs), (ins),
+ "push_s\t%blink", []> {
+ let Inst{15-0} = 0b1100000011110001;
+}
+}
+
+let Defs = [BLINK, SP] in {
+def POP_S_BLINK : InstARC<2, (outs), (ins),
+ "pop_s\t%blink", []> {
+ let Inst{15-0} = 0b1100000011010001;
+}
+}
+
+// Load instruction variants:
+// Control bits: x, aa, di, zz
+// x - sign extend.
+// aa - incrementing mode. (N/A for LIMM).
+// di - uncached.
+// zz - data size.
+multiclass ArcLdInst<bits<2> zz, string asmop> {
+ let mayLoad = 1 in {
+ def _rs9 : F32_LD_ADDR<0, 0b00, 0, zz,
+ (outs GPR32:$A), (ins MEMrs9:$addr),
+ !strconcat(asmop, "\t$A, [$addr]"), []>;
+
+ def _limm : F32_LD_LIMM<0, 0, zz,
+ (outs GPR32:$A), (ins MEMii:$addr),
+ !strconcat(asmop, "\t$A, [$addr]"), []>;
+
+ def _rlimm : F32_LD_RLIMM<0, 0b00, 0, zz,
+ (outs GPR32:$A), (ins MEMrlimm:$addr),
+ !strconcat(asmop, "\t$A, [$addr]"), []>;
+
+ def _X_rs9 : F32_LD_ADDR<1, 0b00, 0, zz,
+ (outs GPR32:$A), (ins MEMrs9:$addr),
+ !strconcat(asmop, ".x\t$A, [$addr]"), []>;
+
+ def _X_limm : F32_LD_LIMM<1, 0, zz,
+ (outs GPR32:$A), (ins MEMii:$addr),
+ !strconcat(asmop, ".x\t$A, [$addr]"), []>;
+
+ def _X_rlimm : F32_LD_RLIMM<1, 0b00, 0, zz,
+ (outs GPR32:$A), (ins MEMrlimm:$addr),
+ !strconcat(asmop, ".x\t$A, [$addr]"), []>;
+
+ def _AB_rs9 : F32_LD_RS9<0, 0b10, 0, zz,
+ (outs GPR32:$addrout, GPR32:$A),
+ (ins GPR32:$B, immS9:$S9),
+ !strconcat(asmop, ".ab\t$A, [$B,$S9]"), []>
+ { let Constraints = "$addrout = $B"; }
+ }
+}
+
+// Load instruction definitions.
+defm LD : ArcLdInst<0b00, "ld">;
+defm LDH : ArcLdInst<0b10, "ldh">;
+defm LDB : ArcLdInst<0b01, "ldb">;
+
+// Load instruction patterns.
+// 32-bit loads.
+def : Pat<(load AddrModeS9:$addr), (LD_rs9 AddrModeS9:$addr)>;
+def : Pat<(load AddrModeImm:$addr), (LD_limm AddrModeImm:$addr)>;
+def : Pat<(load AddrModeFar:$addr), (LD_rs9 AddrModeFar:$addr)>;
+
+// 16-bit loads
+def : Pat<(zextloadi16 AddrModeS9:$addr), (LDH_rs9 AddrModeS9:$addr)>;
+def : Pat<(extloadi16 AddrModeS9:$addr), (LDH_rs9 AddrModeS9:$addr)>;
+def : Pat<(zextloadi16 AddrModeImm:$addr), (LDH_limm AddrModeImm:$addr)>;
+def : Pat<(extloadi16 AddrModeImm:$addr), (LDH_limm AddrModeImm:$addr)>;
+def : Pat<(zextloadi16 AddrModeFar:$addr), (LDH_rlimm AddrModeFar:$addr)>;
+def : Pat<(extloadi16 AddrModeFar:$addr), (LDH_rlimm AddrModeFar:$addr)>;
+def : Pat<(sextloadi16 AddrModeImm:$addr),(LDH_X_limm AddrModeImm:$addr)>;
+def : Pat<(sextloadi16 AddrModeFar:$addr),(LDH_X_rlimm AddrModeFar:$addr)>;
+def : Pat<(sextloadi16 AddrModeS9:$addr),(LDH_X_rs9 AddrModeS9:$addr)>;
+
+// 8-bit loads.
+def : Pat<(zextloadi8 AddrModeS9:$addr), (LDB_rs9 AddrModeS9:$addr)>;
+def : Pat<(extloadi8 AddrModeS9:$addr), (LDB_rs9 AddrModeS9:$addr)>;
+def : Pat<(zextloadi8 AddrModeImm:$addr), (LDB_limm AddrModeImm:$addr)>;
+def : Pat<(extloadi8 AddrModeImm:$addr), (LDB_limm AddrModeImm:$addr)>;
+def : Pat<(zextloadi8 AddrModeFar:$addr), (LDB_rlimm AddrModeFar:$addr)>;
+def : Pat<(extloadi8 AddrModeFar:$addr), (LDB_rlimm AddrModeFar:$addr)>;
+def : Pat<(zextloadi1 AddrModeS9:$addr), (LDB_rs9 AddrModeS9:$addr)>;
+def : Pat<(extloadi1 AddrModeS9:$addr), (LDB_rs9 AddrModeS9:$addr)>;
+def : Pat<(zextloadi1 AddrModeImm:$addr), (LDB_limm AddrModeImm:$addr)>;
+def : Pat<(extloadi1 AddrModeImm:$addr), (LDB_limm AddrModeImm:$addr)>;
+def : Pat<(zextloadi1 AddrModeFar:$addr), (LDB_rlimm AddrModeFar:$addr)>;
+def : Pat<(extloadi1 AddrModeFar:$addr), (LDB_rlimm AddrModeFar:$addr)>;
+def : Pat<(sextloadi8 AddrModeImm:$addr),(LDB_X_limm AddrModeImm:$addr)>;
+def : Pat<(sextloadi8 AddrModeFar:$addr),(LDB_X_rlimm AddrModeFar:$addr)>;
+def : Pat<(sextloadi8 AddrModeS9:$addr),(LDB_X_rs9 AddrModeS9:$addr)>;
+
+
+// Store instruction variants:
+// Control bits: aa, di, zz
+// aa - incrementing mode. (N/A for LIMM).
+// di - uncached.
+// zz - data size.
+multiclass ArcStInst<bits<2> zz, string asmop> {
+ let mayStore = 1 in {
+ def _rs9 : F32_ST_ADDR<0b00, 0, zz, (outs), (ins GPR32:$C, MEMrs9:$addr),
+ !strconcat(asmop, "\t$C, [$addr]"), []>;
+
+ def _limm : F32_ST_LIMM<0, zz, (outs), (ins GPR32:$C, MEMii:$addr),
+ !strconcat(asmop, "\t$C, [$addr]"), []>;
+
+ def _AW_rs9 : F32_ST_RS9<0b01, 0, zz, (outs GPR32:$addrout),
+ (ins GPR32:$C, GPR32:$B, immS9:$S9),
+ !strconcat(asmop, ".aw\t$C, [$B,$S9]"), []>
+ { let Constraints = "$addrout = $B"; }
+ }
+}
+
+// Store instruction definitions.
+defm ST : ArcStInst<0b00, "st">;
+defm STH : ArcStInst<0b10, "sth">;
+defm STB : ArcStInst<0b01, "stb">;
+
+// Store instruction patterns.
+// 32-bit stores
+def : Pat<(store i32:$C, AddrModeS9:$addr),
+ (ST_rs9 i32:$C, AddrModeS9:$addr)>;
+def : Pat<(store i32:$C, AddrModeImm:$addr),
+ (ST_limm i32:$C, AddrModeImm:$addr)>;
+
+// 16-bit stores
+def : Pat<(truncstorei16 i32:$C, AddrModeS9:$addr),
+ (STH_rs9 i32:$C, AddrModeS9:$addr)>;
+def : Pat<(truncstorei16 i32:$C, AddrModeImm:$addr),
+ (STH_limm i32:$C, AddrModeImm:$addr)>;
+
+// 8-bit stores
+def : Pat<(truncstorei8 i32:$C, AddrModeS9:$addr),
+ (STB_rs9 i32:$C, AddrModeS9:$addr)>;
+def : Pat<(truncstorei8 i32:$C, AddrModeImm:$addr),
+ (STB_limm i32:$C, AddrModeImm:$addr)>;
+
Added: llvm/trunk/lib/Target/ARC/ARCMCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCMCInstLower.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCMCInstLower.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCMCInstLower.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,115 @@
+//===- 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);
+ }
+}
Added: llvm/trunk/lib/Target/ARC/ARCMCInstLower.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCMCInstLower.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCMCInstLower.h (added)
+++ llvm/trunk/lib/Target/ARC/ARCMCInstLower.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,44 @@
+//===- 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
Added: llvm/trunk/lib/Target/ARC/ARCMachineFunctionInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCMachineFunctionInfo.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCMachineFunctionInfo.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCMachineFunctionInfo.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,14 @@
+//===- 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() {}
Added: llvm/trunk/lib/Target/ARC/ARCMachineFunctionInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCMachineFunctionInfo.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCMachineFunctionInfo.h (added)
+++ llvm/trunk/lib/Target/ARC/ARCMachineFunctionInfo.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,64 @@
+//===- 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
Added: llvm/trunk/lib/Target/ARC/ARCRegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCRegisterInfo.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCRegisterInfo.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCRegisterInfo.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,233 @@
+//===- 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/Target/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;
+}
Added: llvm/trunk/lib/Target/ARC/ARCRegisterInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCRegisterInfo.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCRegisterInfo.h (added)
+++ llvm/trunk/lib/Target/ARC/ARCRegisterInfo.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,58 @@
+//===- ARCRegisterInfo.h - ARC Register Information Impl --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the ARC implementation of the MRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_ARC_ARCREGISTERINFO_H
+#define LLVM_LIB_TARGET_ARC_ARCREGISTERINFO_H
+
+#include "llvm/Target/TargetRegisterInfo.h"
+
+#define GET_REGINFO_HEADER
+#include "ARCGenRegisterInfo.inc"
+
+namespace llvm {
+
+class TargetInstrInfo;
+
+struct ARCRegisterInfo : public ARCGenRegisterInfo {
+public:
+ ARCRegisterInfo();
+
+ /// Code Generation virtual methods...
+
+ const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override;
+
+ BitVector getReservedRegs(const MachineFunction &MF) const override;
+
+ bool requiresRegisterScavenging(const MachineFunction &MF) const override;
+
+ bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override;
+
+ bool useFPForScavengingIndex(const MachineFunction &MF) const override;
+
+ void eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
+ unsigned FIOperandNum,
+ RegScavenger *RS = nullptr) const override;
+
+ const uint32_t *getCallPreservedMask(const MachineFunction &MF,
+ CallingConv::ID CC) const override;
+
+ // Debug information queries.
+ unsigned getFrameRegister(const MachineFunction &MF) const override;
+
+ //! Return whether to emit frame moves
+ static bool needsFrameMoves(const MachineFunction &MF);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_ARC_ARCREGISTERINFO_H
Added: llvm/trunk/lib/Target/ARC/ARCRegisterInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCRegisterInfo.td?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCRegisterInfo.td (added)
+++ llvm/trunk/lib/Target/ARC/ARCRegisterInfo.td Thu Aug 24 08:40:33 2017
@@ -0,0 +1,80 @@
+//===- ARCRegisterInfo.td - ARC Register defs --------------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Declarations that describe the ARC register file
+//===----------------------------------------------------------------------===//
+
+class ARCReg<string n, list<string> altNames> : Register<n, altNames> {
+ field bits<6> HwEncoding;
+ let Namespace = "ARC";
+}
+
+// Registers are identified with 6-bit ID numbers.
+// Core - 32-bit core registers
+class Core<int num, string n, list<string>altNames=[]> : ARCReg<n, altNames> {
+ let HWEncoding = num;
+}
+
+class Status<string n> : ARCReg<n, []> {
+}
+
+// Integer registers
+def R0 : Core< 0, "%r0">, DwarfRegNum<[0]>;
+def R1 : Core< 1, "%r1">, DwarfRegNum<[1]>;
+def R2 : Core< 2, "%r2">, DwarfRegNum<[2]>;
+def R3 : Core< 3, "%r3">, DwarfRegNum<[3]>;
+let CostPerUse=1 in {
+def R4 : Core< 4, "%r4">, DwarfRegNum<[4]>;
+def R5 : Core< 5, "%r5">, DwarfRegNum<[5]>;
+def R6 : Core< 6, "%r6">, DwarfRegNum<[6]>;
+def R7 : Core< 7, "%r7">, DwarfRegNum<[7]>;
+def R8 : Core< 8, "%r8">, DwarfRegNum<[8]>;
+def R9 : Core< 9, "%r9">, DwarfRegNum<[9]>;
+def R10 : Core<10, "%r10">, DwarfRegNum<[10]>;
+def R11 : Core<11, "%r11">, DwarfRegNum<[11]>;
+}
+def R12 : Core<12, "%r12">, DwarfRegNum<[12]>;
+def R13 : Core<13, "%r13">, DwarfRegNum<[13]>;
+def R14 : Core<14, "%r14">, DwarfRegNum<[14]>;
+def R15 : Core<15, "%r15">, DwarfRegNum<[15]>;
+
+let CostPerUse=1 in {
+def R16 : Core<16, "%r16">, DwarfRegNum<[16]>;
+def R17 : Core<17, "%r17">, DwarfRegNum<[17]>;
+def R18 : Core<18, "%r18">, DwarfRegNum<[18]>;
+def R19 : Core<19, "%r19">, DwarfRegNum<[19]>;
+def R20 : Core<20, "%r20">, DwarfRegNum<[20]>;
+def R21 : Core<21, "%r21">, DwarfRegNum<[21]>;
+def R22 : Core<22, "%r22">, DwarfRegNum<[22]>;
+def R23 : Core<23, "%r23">, DwarfRegNum<[23]>;
+def R24 : Core<24, "%r24">, DwarfRegNum<[24]>;
+def R25 : Core<25, "%r25">, DwarfRegNum<[25]>;
+def GP : Core<26, "%gp",["%r26"]>, DwarfRegNum<[26]>;
+def FP : Core<27, "%fp", ["%r27"]>, DwarfRegNum<[27]>;
+def SP : Core<28, "%sp", ["%r28"]>, DwarfRegNum<[28]>;
+def ILINK : Core<29, "%ilink">, DwarfRegNum<[29]>;
+def R30 : Core<30, "%r30">, DwarfRegNum<[30]>;
+def BLINK: Core<31, "%blink">, DwarfRegNum<[31]>;
+
+def STATUS32 : Status<"status32">, DwarfRegNum<[32]>;
+}
+
+// Register classes.
+//
+def GPR32: RegisterClass<"ARC", [i32], 32,
+ (add R0, R1, R2, R3,
+ R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19,
+ R20, R21, R22, R23, R24, R25, GP, FP, SP, ILINK, R30, BLINK)>;
+
+def SREG : RegisterClass<"ARC", [i32], 1, (add STATUS32)>;
+
+def GPR_S : RegisterClass<"ARC", [i32], 8,
+ (add R0, R1, R2, R3, R12, R13, R14, R15)>;
+
Added: llvm/trunk/lib/Target/ARC/ARCSubtarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCSubtarget.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCSubtarget.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCSubtarget.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,31 @@
+//===- ARCSubtarget.cpp - ARC Subtarget Information -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the ARC specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARCSubtarget.h"
+#include "ARC.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "arc-subtarget"
+
+#define GET_SUBTARGETINFO_TARGET_DESC
+#define GET_SUBTARGETINFO_CTOR
+#include "ARCGenSubtargetInfo.inc"
+
+void ARCSubtarget::anchor() {}
+
+ARCSubtarget::ARCSubtarget(const Triple &TT, const std::string &CPU,
+ const std::string &FS, const TargetMachine &TM)
+ : ARCGenSubtargetInfo(TT, CPU, FS), FrameLowering(*this),
+ TLInfo(TM, *this) {}
Added: llvm/trunk/lib/Target/ARC/ARCSubtarget.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCSubtarget.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCSubtarget.h (added)
+++ llvm/trunk/lib/Target/ARC/ARCSubtarget.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,66 @@
+//===- ARCSubtarget.h - Define Subtarget for the ARC ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the ARC specific subclass of TargetSubtargetInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_ARC_ARCSUBTARGET_H
+#define LLVM_LIB_TARGET_ARC_ARCSUBTARGET_H
+
+#include "ARCFrameLowering.h"
+#include "ARCISelLowering.h"
+#include "ARCInstrInfo.h"
+#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+#include <string>
+
+#define GET_SUBTARGETINFO_HEADER
+#include "ARCGenSubtargetInfo.inc"
+
+namespace llvm {
+
+class StringRef;
+class TargetMachine;
+
+class ARCSubtarget : public ARCGenSubtargetInfo {
+ virtual void anchor();
+ ARCInstrInfo InstrInfo;
+ ARCFrameLowering FrameLowering;
+ ARCTargetLowering TLInfo;
+ SelectionDAGTargetInfo TSInfo;
+
+public:
+ /// This constructor initializes the data members to match that
+ /// of the specified triple.
+ ARCSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS,
+ const TargetMachine &TM);
+
+ /// Parses features string setting specified subtarget options.
+ /// Definition of function is auto generated by tblgen.
+ void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
+
+ const ARCInstrInfo *getInstrInfo() const override { return &InstrInfo; }
+ const ARCFrameLowering *getFrameLowering() const override {
+ return &FrameLowering;
+ }
+ const ARCTargetLowering *getTargetLowering() const override {
+ return &TLInfo;
+ }
+ const ARCRegisterInfo *getRegisterInfo() const override {
+ return &InstrInfo.getRegisterInfo();
+ }
+ const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
+ return &TSInfo;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_ARC_ARCSUBTARGET_H
Added: llvm/trunk/lib/Target/ARC/ARCTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCTargetMachine.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCTargetMachine.cpp (added)
+++ llvm/trunk/lib/Target/ARC/ARCTargetMachine.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,95 @@
+//===- ARCTargetMachine.cpp - Define TargetMachine for ARC ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARCTargetMachine.h"
+#include "ARC.h"
+#include "ARCTargetTransformInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+static Reloc::Model getRelocModel(Optional<Reloc::Model> RM) {
+ if (!RM.hasValue())
+ return Reloc::Static;
+ return *RM;
+}
+
+static CodeModel::Model getEffectiveCodeModel(Optional<CodeModel::Model> CM) {
+ if (CM)
+ return *CM;
+ return CodeModel::Small;
+}
+
+/// ARCTargetMachine ctor - Create an ILP32 architecture model
+ARCTargetMachine::ARCTargetMachine(const Target &T, const Triple &TT,
+ StringRef CPU, StringRef FS,
+ const TargetOptions &Options,
+ Optional<Reloc::Model> RM,
+ Optional<CodeModel::Model> CM,
+ CodeGenOpt::Level OL, bool JIT)
+ : LLVMTargetMachine(T,
+ "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-"
+ "f32:32:32-i64:32-f64:32-a:0:32-n32",
+ TT, CPU, FS, Options, getRelocModel(RM),
+ getEffectiveCodeModel(CM), OL),
+ TLOF(make_unique<TargetLoweringObjectFileELF>()),
+ Subtarget(TT, CPU, FS, *this) {
+ initAsmInfo();
+}
+
+ARCTargetMachine::~ARCTargetMachine() = default;
+
+namespace {
+
+/// ARC Code Generator Pass Configuration Options.
+class ARCPassConfig : public TargetPassConfig {
+public:
+ ARCPassConfig(ARCTargetMachine &TM, PassManagerBase &PM)
+ : TargetPassConfig(TM, PM) {}
+
+ ARCTargetMachine &getARCTargetMachine() const {
+ return getTM<ARCTargetMachine>();
+ }
+
+ bool addInstSelector() override;
+ void addPreEmitPass() override;
+ void addPreRegAlloc() override;
+};
+
+} // end anonymous namespace
+
+TargetPassConfig *ARCTargetMachine::createPassConfig(PassManagerBase &PM) {
+ return new ARCPassConfig(*this, PM);
+}
+
+bool ARCPassConfig::addInstSelector() {
+ addPass(createARCISelDag(getARCTargetMachine(), getOptLevel()));
+ return false;
+}
+
+void ARCPassConfig::addPreEmitPass() { addPass(createARCBranchFinalizePass()); }
+
+void ARCPassConfig::addPreRegAlloc() { addPass(createARCExpandPseudosPass()); }
+
+// Force static initialization.
+extern "C" void LLVMInitializeARCTarget() {
+ RegisterTargetMachine<ARCTargetMachine> X(getTheARCTarget());
+}
+
+TargetIRAnalysis ARCTargetMachine::getTargetIRAnalysis() {
+ return TargetIRAnalysis([this](const Function &F) {
+ return TargetTransformInfo(ARCTTIImpl(this, F));
+ });
+}
Added: llvm/trunk/lib/Target/ARC/ARCTargetMachine.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCTargetMachine.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCTargetMachine.h (added)
+++ llvm/trunk/lib/Target/ARC/ARCTargetMachine.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,51 @@
+//===- ARCTargetMachine.h - Define TargetMachine 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 file declares the ARC specific subclass of TargetMachine.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_ARC_ARCTARGETMACHINE_H
+#define LLVM_LIB_TARGET_ARC_ARCTARGETMACHINE_H
+
+#include "ARCSubtarget.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+
+class TargetPassConfig;
+
+class ARCTargetMachine : public LLVMTargetMachine {
+ std::unique_ptr<TargetLoweringObjectFile> TLOF;
+ ARCSubtarget Subtarget;
+
+public:
+ ARCTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
+ StringRef FS, const TargetOptions &Options,
+ Optional<Reloc::Model> RM, Optional<CodeModel::Model> CM,
+ CodeGenOpt::Level OL, bool JIT);
+ ~ARCTargetMachine() override;
+
+ const ARCSubtarget *getSubtargetImpl() const { return &Subtarget; }
+ const ARCSubtarget *getSubtargetImpl(const Function &) const override {
+ return &Subtarget;
+ }
+
+ // Pass Pipeline Configuration
+ TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
+
+ TargetIRAnalysis getTargetIRAnalysis() override;
+ TargetLoweringObjectFile *getObjFileLowering() const override {
+ return TLOF.get();
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_ARC_ARCTARGETMACHINE_H
Added: llvm/trunk/lib/Target/ARC/ARCTargetStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCTargetStreamer.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCTargetStreamer.h (added)
+++ llvm/trunk/lib/Target/ARC/ARCTargetStreamer.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,25 @@
+//===- ARCTargetStreamer.h - ARC Target Streamer ----------------*- 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_ARCTARGETSTREAMER_H
+#define LLVM_LIB_TARGET_ARC_ARCTARGETSTREAMER_H
+
+#include "llvm/MC/MCStreamer.h"
+
+namespace llvm {
+
+class ARCTargetStreamer : public MCTargetStreamer {
+public:
+ ARCTargetStreamer(MCStreamer &S);
+ ~ARCTargetStreamer() override;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_ARC_ARCTARGETSTREAMER_H
Added: llvm/trunk/lib/Target/ARC/ARCTargetTransformInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/ARCTargetTransformInfo.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/ARCTargetTransformInfo.h (added)
+++ llvm/trunk/lib/Target/ARC/ARCTargetTransformInfo.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,55 @@
+//===- ARCTargetTransformInfo.h - ARC specific TTI --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// \file
+// This file contains a TargetTransformInfo::Concept conforming object specific
+// to the ARC target machine. It uses the target's detailed information to
+// provide more precise answers to certain TTI queries, while letting the
+// target independent and default TTI implementations handle the rest.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_ARC_ARCTARGETTRANSFORMINFO_H
+#define LLVM_LIB_TARGET_ARC_ARCTARGETTRANSFORMINFO_H
+
+#include "ARC.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/BasicTTIImpl.h"
+
+namespace llvm {
+
+class ARCSubtarget;
+class ARCTargetLowering;
+class ARCTargetMachine;
+
+class ARCTTIImpl : public BasicTTIImplBase<ARCTTIImpl> {
+ using BaseT = BasicTTIImplBase<ARCTTIImpl>;
+ friend BaseT;
+
+ const ARCSubtarget *ST;
+ const ARCTargetLowering *TLI;
+
+ const ARCSubtarget *getST() const { return ST; }
+ const ARCTargetLowering *getTLI() const { return TLI; }
+
+public:
+ explicit ARCTTIImpl(const ARCTargetMachine *TM, const Function &F)
+ : BaseT(TM, F.getParent()->getDataLayout()), ST(TM->getSubtargetImpl()),
+ TLI(ST->getTargetLowering()) {}
+
+ // Provide value semantics. MSVC requires that we spell all of these out.
+ ARCTTIImpl(const ARCTTIImpl &Arg)
+ : BaseT(static_cast<const BaseT &>(Arg)), ST(Arg.ST), TLI(Arg.TLI) {}
+ ARCTTIImpl(ARCTTIImpl &&Arg)
+ : BaseT(std::move(static_cast<BaseT &>(Arg))), ST(std::move(Arg.ST)),
+ TLI(std::move(Arg.TLI)) {}
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_ARC_ARCTARGETTRANSFORMINFO_H
Added: llvm/trunk/lib/Target/ARC/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/CMakeLists.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/CMakeLists.txt (added)
+++ llvm/trunk/lib/Target/ARC/CMakeLists.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,30 @@
+set(LLVM_TARGET_DEFINITIONS ARC.td)
+
+tablegen(LLVM ARCGenRegisterInfo.inc -gen-register-info)
+tablegen(LLVM ARCGenInstrInfo.inc -gen-instr-info)
+tablegen(LLVM ARCGenDisassemblerTables.inc -gen-disassembler)
+tablegen(LLVM ARCGenAsmWriter.inc -gen-asm-writer)
+tablegen(LLVM ARCGenDAGISel.inc -gen-dag-isel)
+tablegen(LLVM ARCGenCallingConv.inc -gen-callingconv)
+tablegen(LLVM ARCGenSubtargetInfo.inc -gen-subtarget)
+add_public_tablegen_target(ARCCommonTableGen)
+
+add_llvm_target(ARCCodeGen
+ ARCAsmPrinter.cpp
+ ARCBranchFinalize.cpp
+ ARCExpandPseudos.cpp
+ ARCFrameLowering.cpp
+ ARCInstrInfo.cpp
+ ARCISelDAGToDAG.cpp
+ ARCISelLowering.cpp
+ ARCMachineFunctionInfo.cpp
+ ARCMCInstLower.cpp
+ ARCRegisterInfo.cpp
+ ARCSubtarget.cpp
+ ARCTargetMachine.cpp
+ )
+
+add_subdirectory(InstPrinter)
+add_subdirectory(TargetInfo)
+add_subdirectory(MCTargetDesc)
+add_subdirectory(Disassembler)
Added: llvm/trunk/lib/Target/ARC/Disassembler/ARCDisassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/Disassembler/ARCDisassembler.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/Disassembler/ARCDisassembler.cpp (added)
+++ llvm/trunk/lib/Target/ARC/Disassembler/ARCDisassembler.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,298 @@
+//===- ARCDisassembler.cpp - Disassembler for ARC ---------------*- 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 is part of the ARC Disassembler.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ARC.h"
+#include "ARCRegisterInfo.h"
+#include "MCTargetDesc/ARCMCTargetDesc.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/MC/MCFixedLenDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "arc-disassembler"
+
+using DecodeStatus = MCDisassembler::DecodeStatus;
+
+namespace {
+
+/// \brief A disassembler class for ARC.
+class ARCDisassembler : public MCDisassembler {
+public:
+ std::unique_ptr<MCInstrInfo const> const MCII;
+
+ ARCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
+ MCInstrInfo const *MCII)
+ : MCDisassembler(STI, Ctx), MCII(MCII) {}
+
+ DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const override;
+};
+
+} // end anonymous namespace
+
+static bool readInstruction32(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ uint64_t &Size, uint32_t &Insn) {
+ Size = 4;
+ // Read 2 16-bit values, but swap hi/lo parts.
+ Insn =
+ (Bytes[0] << 16) | (Bytes[1] << 24) | (Bytes[2] << 0) | (Bytes[3] << 8);
+ return true;
+}
+
+static bool readInstruction64(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ uint64_t &Size, uint64_t &Insn) {
+ Size = 8;
+ Insn = ((uint64_t)Bytes[0] << 16) | ((uint64_t)Bytes[1] << 24) |
+ ((uint64_t)Bytes[2] << 0) | ((uint64_t)Bytes[3] << 8) |
+ ((uint64_t)Bytes[4] << 48) | ((uint64_t)Bytes[5] << 56) |
+ ((uint64_t)Bytes[6] << 32) | ((uint64_t)Bytes[7] << 40);
+ return true;
+}
+
+static bool readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address,
+ uint64_t &Size, uint32_t &Insn) {
+ Size = 2;
+ Insn = (Bytes[0] << 0) | (Bytes[1] << 8);
+ return true;
+}
+
+static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &, unsigned,
+ uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &, unsigned,
+ uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeBranchTargetS9(MCInst &, unsigned, uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeBranchTargetS21(MCInst &, unsigned, uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeBranchTargetS25(MCInst &, unsigned, uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus DecodeMEMrs9(MCInst &, unsigned, uint64_t,
+ const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeLdLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeStLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
+
+static MCDisassembler::DecodeStatus
+DecodeLdRLImmInstruction(MCInst &, uint64_t, uint64_t, const void *);
+
+static const uint16_t GPR32DecoderTable[] = {
+ ARC::R0, ARC::R1, ARC::R2, ARC::R3, ARC::R4, ARC::R5, ARC::R6,
+ ARC::R7, ARC::R8, ARC::R9, ARC::R10, ARC::R11, ARC::R12, ARC::R13,
+ ARC::R14, ARC::R15, ARC::R16, ARC::R17, ARC::R18, ARC::R19, ARC::R20,
+ ARC::R21, ARC::R22, ARC::R23, ARC::R24, ARC::R25, ARC::GP, ARC::FP,
+ ARC::SP, ARC::ILINK, ARC::R30, ARC::BLINK};
+
+static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo >= 32) {
+ DEBUG(dbgs() << "Not a GPR32 register.");
+ return MCDisassembler::Fail;
+ }
+ unsigned Reg = GPR32DecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Reg));
+ return MCDisassembler::Success;
+}
+
+#include "ARCGenDisassemblerTables.inc"
+
+static unsigned decodeCField(unsigned Insn) {
+ return fieldFromInstruction(Insn, 6, 6);
+}
+
+static unsigned decodeBField(unsigned Insn) {
+ return (fieldFromInstruction(Insn, 12, 3) << 3) |
+ fieldFromInstruction(Insn, 24, 3);
+}
+
+static unsigned decodeAField(unsigned Insn) {
+ return fieldFromInstruction(Insn, 0, 6);
+}
+
+static MCDisassembler::DecodeStatus
+DecodeMEMrs9(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Dec) {
+ // We have the 9-bit immediate in the low bits, 6-bit register in high bits.
+ unsigned S9 = Insn & 0x1ff;
+ unsigned R = (Insn & (0x7fff & ~0x1ff)) >> 9;
+ DecodeGPR32RegisterClass(Inst, R, Address, Dec);
+ Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S9)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus DecodeS9Operand(MCInst &Inst,
+ unsigned InsnS9,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::createImm(SignExtend32<9>(0x1ff & InsnS9)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus DecodeS12Operand(MCInst &Inst,
+ unsigned InsnS12,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::createImm(SignExtend32<12>(0xfff & InsnS12)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus DecodeBranchTargetS9(MCInst &Inst,
+ unsigned S,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::createImm(SignExtend32<9>(S)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus DecodeBranchTargetS21(MCInst &Inst,
+ unsigned S,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::createImm(SignExtend32<21>(S)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus DecodeBranchTargetS25(MCInst &Inst,
+ unsigned S,
+ uint64_t Address,
+ const void *Decoder) {
+ Inst.addOperand(MCOperand::createImm(SignExtend32<25>(S)));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus
+DecodeStLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
+ const void *Decoder) {
+ unsigned SrcC, DstB, LImm;
+ DstB = decodeBField(Insn);
+ if (DstB != 62) {
+ DEBUG(dbgs() << "Decoding StLImm found non-limm register.");
+ return MCDisassembler::Fail;
+ }
+ SrcC = decodeCField(Insn);
+ DecodeGPR32RegisterClass(Inst, SrcC, Address, Decoder);
+ LImm = (Insn >> 32);
+ Inst.addOperand(MCOperand::createImm(LImm));
+ Inst.addOperand(MCOperand::createImm(0));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus
+DecodeLdLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
+ const void *Decoder) {
+ unsigned DstA, SrcB, LImm;
+ DEBUG(dbgs() << "Decoding LdLImm:\n");
+ SrcB = decodeBField(Insn);
+ if (SrcB != 62) {
+ DEBUG(dbgs() << "Decoding LdLImm found non-limm register.");
+ return MCDisassembler::Fail;
+ }
+ DstA = decodeAField(Insn);
+ DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
+ LImm = (Insn >> 32);
+ Inst.addOperand(MCOperand::createImm(LImm));
+ Inst.addOperand(MCOperand::createImm(0));
+ return MCDisassembler::Success;
+}
+
+static MCDisassembler::DecodeStatus
+DecodeLdRLImmInstruction(MCInst &Inst, uint64_t Insn, uint64_t Address,
+ const void *Decoder) {
+ unsigned DstA, SrcB;
+ DEBUG(dbgs() << "Decoding LdRLimm\n");
+ DstA = decodeAField(Insn);
+ DecodeGPR32RegisterClass(Inst, DstA, Address, Decoder);
+ SrcB = decodeBField(Insn);
+ DecodeGPR32RegisterClass(Inst, SrcB, Address, Decoder);
+ if (decodeCField(Insn) != 62) {
+ DEBUG(dbgs() << "Decoding LdRLimm found non-limm register.");
+ return MCDisassembler::Fail;
+ }
+ Inst.addOperand(MCOperand::createImm((uint32_t)(Insn >> 32)));
+ return MCDisassembler::Success;
+}
+
+MCDisassembler::DecodeStatus ARCDisassembler::getInstruction(
+ MCInst &Instr, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &vStream, raw_ostream &cStream) const {
+ MCDisassembler::DecodeStatus Result;
+ if (Bytes.size() < 2) {
+ Size = 0;
+ return Fail;
+ }
+ uint8_t DecodeByte = (Bytes[1] & 0xF7) >> 3;
+ // 0x00 -> 0x07 are 32-bit instructions.
+ // 0x08 -> 0x1F are 16-bit instructions.
+ if (DecodeByte < 0x08) {
+ // 32-bit instruction.
+ if (Bytes.size() < 4) {
+ // Did we decode garbage?
+ Size = 0;
+ return Fail;
+ }
+ if (Bytes.size() >= 8) {
+ // Attempt to decode 64-bit instruction.
+ uint64_t Insn64;
+ if (!readInstruction64(Bytes, Address, Size, Insn64))
+ return Fail;
+ Result =
+ decodeInstruction(DecoderTable64, Instr, Insn64, Address, this, STI);
+ if (Result == MCDisassembler::Success) {
+ DEBUG(dbgs() << "Successfully decoded 64-bit instruction.");
+ return MCDisassembler::Success;
+ }
+ DEBUG(dbgs() << "Not a 64-bit instruction, falling back to 32-bit.");
+ }
+ uint32_t Insn32;
+ if (!readInstruction32(Bytes, Address, Size, Insn32)) {
+ return Fail;
+ }
+ // Calling the auto-generated decoder function.
+ return decodeInstruction(DecoderTable32, Instr, Insn32, Address, this, STI);
+ }
+
+ // 16-bit instruction.
+ uint32_t Insn16;
+ if (!readInstruction16(Bytes, Address, Size, Insn16)) {
+ return Fail;
+ }
+ // Calling the auto-generated decoder function.
+ return decodeInstruction(DecoderTable16, Instr, Insn16, Address, this, STI);
+}
+
+static MCDisassembler *createARCDisassembler(const Target &T,
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new ARCDisassembler(STI, Ctx, T.createMCInstrInfo());
+}
+
+extern "C" void LLVMInitializeARCDisassembler() {
+ // Register the disassembler.
+ TargetRegistry::RegisterMCDisassembler(getTheARCTarget(),
+ createARCDisassembler);
+}
Added: llvm/trunk/lib/Target/ARC/Disassembler/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/Disassembler/CMakeLists.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/Disassembler/CMakeLists.txt (added)
+++ llvm/trunk/lib/Target/ARC/Disassembler/CMakeLists.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,3 @@
+add_llvm_library(LLVMARCDisassembler
+ ARCDisassembler.cpp
+ )
Added: llvm/trunk/lib/Target/ARC/Disassembler/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/Disassembler/LLVMBuild.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/Disassembler/LLVMBuild.txt (added)
+++ llvm/trunk/lib/Target/ARC/Disassembler/LLVMBuild.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,23 @@
+;===- ./lib/Target/ARC/Disassembler/LLVMBuild.txt ------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = ARCDisassembler
+parent = ARC
+required_libraries = MCDisassembler Support ARCInfo
+add_to_library_groups = ARC
Added: llvm/trunk/lib/Target/ARC/InstPrinter/ARCInstPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/InstPrinter/ARCInstPrinter.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/InstPrinter/ARCInstPrinter.cpp (added)
+++ llvm/trunk/lib/Target/ARC/InstPrinter/ARCInstPrinter.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,166 @@
+//===- ARCInstPrinter.cpp - ARC MCInst to assembly syntax -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class prints an ARC MCInst to a .s file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARCInstPrinter.h"
+#include "MCTargetDesc/ARCInfo.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-printer"
+
+#include "ARCGenAsmWriter.inc"
+
+static const char *ARCBRCondCodeToString(ARCCC::BRCondCode BRCC) {
+ switch (BRCC) {
+ case ARCCC::BREQ:
+ return "eq";
+ case ARCCC::BRNE:
+ return "ne";
+ case ARCCC::BRLT:
+ return "lt";
+ case ARCCC::BRGE:
+ return "ge";
+ case ARCCC::BRLO:
+ return "lo";
+ case ARCCC::BRHS:
+ return "hs";
+ default:
+ llvm_unreachable("Unhandled ARCCC::BRCondCode");
+ }
+}
+
+static const char *ARCCondCodeToString(ARCCC::CondCode CC) {
+ switch (CC) {
+ case ARCCC::EQ:
+ return "eq";
+ case ARCCC::NE:
+ return "ne";
+ case ARCCC::P:
+ return "p";
+ case ARCCC::N:
+ return "n";
+ case ARCCC::HS:
+ return "hs";
+ case ARCCC::LO:
+ return "lo";
+ case ARCCC::GT:
+ return "gt";
+ case ARCCC::GE:
+ return "ge";
+ case ARCCC::LT:
+ return "lt";
+ case ARCCC::LE:
+ return "le";
+ case ARCCC::HI:
+ return "hi";
+ case ARCCC::LS:
+ return "ls";
+ case ARCCC::PNZ:
+ return "pnz";
+ case ARCCC::AL:
+ return "al";
+ case ARCCC::NZ:
+ return "nz";
+ case ARCCC::Z:
+ return "z";
+ }
+ llvm_unreachable("Unhandled ARCCC::CondCode");
+}
+
+void ARCInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
+ OS << StringRef(getRegisterName(RegNo)).lower();
+}
+
+void ARCInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
+ StringRef Annot, const MCSubtargetInfo &STI) {
+ printInstruction(MI, O);
+ printAnnotation(O, Annot);
+}
+
+static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI,
+ raw_ostream &OS) {
+ int Offset = 0;
+ const MCSymbolRefExpr *SRE;
+
+ if (const auto *BE = dyn_cast<MCBinaryExpr>(Expr)) {
+ SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
+ const auto *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
+ assert(SRE && CE && "Binary expression must be sym+const.");
+ Offset = CE->getValue();
+ } else {
+ SRE = dyn_cast<MCSymbolRefExpr>(Expr);
+ assert(SRE && "Unexpected MCExpr type.");
+ }
+ assert(SRE->getKind() == MCSymbolRefExpr::VK_None);
+
+ // Symbols are prefixed with '@'
+ OS << '@';
+ SRE->getSymbol().print(OS, MAI);
+
+ if (Offset) {
+ if (Offset > 0)
+ OS << '+';
+ OS << Offset;
+ }
+}
+
+void ARCInstPrinter::printOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ const MCOperand &Op = MI->getOperand(OpNum);
+ if (Op.isReg()) {
+ printRegName(O, Op.getReg());
+ return;
+ }
+
+ if (Op.isImm()) {
+ O << Op.getImm();
+ return;
+ }
+
+ assert(Op.isExpr() && "unknown operand kind in printOperand");
+ printExpr(Op.getExpr(), &MAI, O);
+}
+
+void ARCInstPrinter::printMemOperandRI(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ const MCOperand &base = MI->getOperand(OpNum);
+ const MCOperand &offset = MI->getOperand(OpNum + 1);
+ assert(base.isReg() && "Base should be register.");
+ assert(offset.isImm() && "Offset should be immediate.");
+ printRegName(O, base.getReg());
+ O << "," << offset.getImm();
+}
+
+void ARCInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+
+ const MCOperand &Op = MI->getOperand(OpNum);
+ assert(Op.isImm() && "Predicate operand is immediate.");
+ O << ARCCondCodeToString((ARCCC::CondCode)Op.getImm());
+}
+
+void ARCInstPrinter::printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O) {
+ const MCOperand &Op = MI->getOperand(OpNum);
+ assert(Op.isImm() && "Predicate operand is immediate.");
+ O << ARCBRCondCodeToString((ARCCC::BRCondCode)Op.getImm());
+}
Added: llvm/trunk/lib/Target/ARC/InstPrinter/ARCInstPrinter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/InstPrinter/ARCInstPrinter.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/InstPrinter/ARCInstPrinter.h (added)
+++ llvm/trunk/lib/Target/ARC/InstPrinter/ARCInstPrinter.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,46 @@
+//===- ARCInstPrinter.h - Convert ARC MCInst to assembly syntax -*- 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 the declaration of the ARCInstPrinter class,
+/// which is used to print ARC MCInst to a .s file.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_ARC_INSTPRINTER_ARCINSTPRINTER_H
+#define LLVM_LIB_TARGET_ARC_INSTPRINTER_ARCINSTPRINTER_H
+
+#include "llvm/MC/MCInstPrinter.h"
+
+namespace llvm {
+
+class ARCInstPrinter : public MCInstPrinter {
+public:
+ ARCInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI)
+ : MCInstPrinter(MAI, MII, MRI) {}
+
+ // Autogenerated by tblgen.
+ void printInstruction(const MCInst *MI, raw_ostream &O);
+ static const char *getRegisterName(unsigned RegNo);
+
+ void printRegName(raw_ostream &OS, unsigned RegNo) const override;
+ void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot,
+ const MCSubtargetInfo &STI) override;
+
+private:
+ void printMemOperandRI(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printPredicateOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
+ void printBRCCPredicateOperand(const MCInst *MI, unsigned OpNum,
+ raw_ostream &O);
+};
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_ARC_INSTPRINTER_ARCINSTPRINTER_H
Added: llvm/trunk/lib/Target/ARC/InstPrinter/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/InstPrinter/CMakeLists.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/InstPrinter/CMakeLists.txt (added)
+++ llvm/trunk/lib/Target/ARC/InstPrinter/CMakeLists.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,3 @@
+add_llvm_library(LLVMARCAsmPrinter
+ ARCInstPrinter.cpp
+ )
Added: llvm/trunk/lib/Target/ARC/InstPrinter/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/InstPrinter/LLVMBuild.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/InstPrinter/LLVMBuild.txt (added)
+++ llvm/trunk/lib/Target/ARC/InstPrinter/LLVMBuild.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,23 @@
+;===- ./lib/Target/ARC/InstPrinter/LLVMBuild.txt -------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = ARCAsmPrinter
+parent = ARC
+required_libraries = MC Support
+add_to_library_groups = ARC
Added: llvm/trunk/lib/Target/ARC/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/LLVMBuild.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/LLVMBuild.txt (added)
+++ llvm/trunk/lib/Target/ARC/LLVMBuild.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,45 @@
+;===- ./lib/Target/ARC/LLVMBuild.txt -------------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[common]
+subdirectories = Disassembler InstPrinter MCTargetDesc TargetInfo
+
+[component_0]
+type = TargetGroup
+name = ARC
+parent = Target
+has_asmprinter = 1
+has_disassembler = 1
+
+[component_1]
+type = Library
+name = ARCCodeGen
+parent = ARC
+required_libraries =
+ Analysis
+ AsmPrinter
+ CodeGen
+ Core
+ MC
+ SelectionDAG
+ Support
+ Target
+ TransformUtils
+ ARCAsmPrinter
+ ARCDesc
+ ARCInfo
+add_to_library_groups = ARC
Added: llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCInfo.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCInfo.h (added)
+++ llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCInfo.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,57 @@
+//===- ARCInfo.h - Additional ARC 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 contains small standalone helper functions and enum definitions for
+// the ARC target useful for the compiler back-end and the MC libraries.
+// As such, it deliberately does not include references to LLVM core
+// code gen types, passes, etc..
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_ARC_MCTARGETDESC_ARCINFO_H
+#define LLVM_LIB_TARGET_ARC_MCTARGETDESC_ARCINFO_H
+
+namespace llvm {
+
+// Enums corresponding to ARC condition codes
+namespace ARCCC {
+
+enum CondCode {
+ AL = 0x0,
+ EQ = 0x1,
+ NE = 0x2,
+ P = 0x3,
+ N = 0x4,
+ LO = 0x5,
+ HS = 0x6,
+ GT = 0x9,
+ GE = 0xa,
+ LT = 0xb,
+ LE = 0xc,
+ HI = 0xd,
+ LS = 0xe,
+ PNZ = 0xf,
+ Z = 0x11, // Low 4-bits = EQ
+ NZ = 0x12 // Low 4-bits = NE
+};
+
+enum BRCondCode {
+ BREQ = 0x0,
+ BRNE = 0x1,
+ BRLT = 0x2,
+ BRGE = 0x3,
+ BRLO = 0x4,
+ BRHS = 0x5
+};
+
+} // end namespace ARCCC
+
+} // end namespace llvm
+
+#endif
Added: llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCAsmInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCAsmInfo.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCAsmInfo.cpp (added)
+++ llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCAsmInfo.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,32 @@
+//===- ARCMCAsmInfo.cpp - ARC asm properties --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARCMCAsmInfo.h"
+using namespace llvm;
+
+void ARCMCAsmInfo::anchor() {}
+
+ARCMCAsmInfo::ARCMCAsmInfo(const Triple &TT) {
+ SupportsDebugInformation = true;
+ Data16bitsDirective = "\t.short\t";
+ Data32bitsDirective = "\t.word\t";
+ Data64bitsDirective = nullptr;
+ ZeroDirective = "\t.space\t";
+ CommentString = ";";
+
+ UsesELFSectionDirectiveForBSS = true;
+ AllowAtInName = true;
+ HiddenVisibilityAttr = MCSA_Invalid;
+ HiddenDeclarationVisibilityAttr = MCSA_Invalid;
+ ProtectedVisibilityAttr = MCSA_Invalid;
+
+ // Debug
+ ExceptionsType = ExceptionHandling::DwarfCFI;
+ DwarfRegNumForCFI = true;
+}
Added: llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCAsmInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCAsmInfo.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCAsmInfo.h (added)
+++ llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCAsmInfo.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,32 @@
+//===- ARCMCAsmInfo.h - ARC asm properties ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declaration of the ARCMCAsmInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_ARC_MCTARGETDESC_ARCMCASMINFO_H
+#define LLVM_LIB_TARGET_ARC_MCTARGETDESC_ARCMCASMINFO_H
+
+#include "llvm/MC/MCAsmInfoELF.h"
+
+namespace llvm {
+
+class Triple;
+
+class ARCMCAsmInfo : public MCAsmInfoELF {
+ void anchor() override;
+
+public:
+ explicit ARCMCAsmInfo(const Triple &TT);
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_TARGET_ARC_MCTARGETDESC_ARCMCASMINFO_H
Added: llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCTargetDesc.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCTargetDesc.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCTargetDesc.cpp (added)
+++ llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCTargetDesc.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,103 @@
+//===- ARCMCTargetDesc.cpp - ARC Target Descriptions ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides ARC specific target descriptions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARCMCTargetDesc.h"
+#include "ARCMCAsmInfo.h"
+#include "ARCTargetStreamer.h"
+#include "InstPrinter/ARCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+#define GET_INSTRINFO_MC_DESC
+#include "ARCGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_MC_DESC
+#include "ARCGenSubtargetInfo.inc"
+
+#define GET_REGINFO_MC_DESC
+#include "ARCGenRegisterInfo.inc"
+
+static MCInstrInfo *createARCMCInstrInfo() {
+ auto *X = new MCInstrInfo();
+ InitARCMCInstrInfo(X);
+ return X;
+}
+
+static MCRegisterInfo *createARCMCRegisterInfo(const Triple &TT) {
+ auto *X = new MCRegisterInfo();
+ InitARCMCRegisterInfo(X, ARC::BLINK);
+ return X;
+}
+
+static MCSubtargetInfo *createARCMCSubtargetInfo(const Triple &TT,
+ StringRef CPU, StringRef FS) {
+ return createARCMCSubtargetInfoImpl(TT, CPU, FS);
+}
+
+static MCAsmInfo *createARCMCAsmInfo(const MCRegisterInfo &MRI,
+ const Triple &TT) {
+ MCAsmInfo *MAI = new ARCMCAsmInfo(TT);
+
+ // Initial state of the frame pointer is SP.
+ MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, ARC::SP, 0);
+ MAI->addInitialFrameState(Inst);
+
+ return MAI;
+}
+
+static MCInstPrinter *createARCMCInstPrinter(const Triple &T,
+ unsigned SyntaxVariant,
+ const MCAsmInfo &MAI,
+ const MCInstrInfo &MII,
+ const MCRegisterInfo &MRI) {
+ return new ARCInstPrinter(MAI, MII, MRI);
+}
+
+ARCTargetStreamer::ARCTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {}
+ARCTargetStreamer::~ARCTargetStreamer() = default;
+
+static MCTargetStreamer *createTargetAsmStreamer(MCStreamer &S,
+ formatted_raw_ostream &OS,
+ MCInstPrinter *InstPrint,
+ bool isVerboseAsm) {
+ return new ARCTargetStreamer(S);
+}
+
+// Force static initialization.
+extern "C" void LLVMInitializeARCTargetMC() {
+ // Register the MC asm info.
+ Target &TheARCTarget = getTheARCTarget();
+ RegisterMCAsmInfoFn X(TheARCTarget, createARCMCAsmInfo);
+
+ // Register the MC instruction info.
+ TargetRegistry::RegisterMCInstrInfo(TheARCTarget, createARCMCInstrInfo);
+
+ // Register the MC register info.
+ TargetRegistry::RegisterMCRegInfo(TheARCTarget, createARCMCRegisterInfo);
+
+ // Register the MC subtarget info.
+ TargetRegistry::RegisterMCSubtargetInfo(TheARCTarget,
+ createARCMCSubtargetInfo);
+
+ // Register the MCInstPrinter
+ TargetRegistry::RegisterMCInstPrinter(TheARCTarget, createARCMCInstPrinter);
+
+ TargetRegistry::RegisterAsmTargetStreamer(TheARCTarget,
+ createTargetAsmStreamer);
+}
Added: llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCTargetDesc.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCTargetDesc.h?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCTargetDesc.h (added)
+++ llvm/trunk/lib/Target/ARC/MCTargetDesc/ARCMCTargetDesc.h Thu Aug 24 08:40:33 2017
@@ -0,0 +1,39 @@
+//===- ARCMCTargetDesc.h - ARC Target Descriptions --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides ARC specific target descriptions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_ARC_MCTARGETDESC_ARCMCTARGETDESC_H
+#define LLVM_LIB_TARGET_ARC_MCTARGETDESC_ARCMCTARGETDESC_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+class Target;
+
+Target &getTheARCTarget();
+
+} // end namespace llvm
+
+// Defines symbolic names for ARC registers. This defines a mapping from
+// register name to register number.
+#define GET_REGINFO_ENUM
+#include "ARCGenRegisterInfo.inc"
+
+// Defines symbolic names for the ARC instructions.
+#define GET_INSTRINFO_ENUM
+#include "ARCGenInstrInfo.inc"
+
+#define GET_SUBTARGETINFO_ENUM
+#include "ARCGenSubtargetInfo.inc"
+
+#endif // LLVM_LIB_TARGET_ARC_MCTARGETDESC_ARCMCTARGETDESC_H
Added: llvm/trunk/lib/Target/ARC/MCTargetDesc/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/MCTargetDesc/CMakeLists.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/MCTargetDesc/CMakeLists.txt (added)
+++ llvm/trunk/lib/Target/ARC/MCTargetDesc/CMakeLists.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,4 @@
+add_llvm_library(LLVMARCDesc
+ ARCMCTargetDesc.cpp
+ ARCMCAsmInfo.cpp
+ )
Added: llvm/trunk/lib/Target/ARC/MCTargetDesc/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/MCTargetDesc/LLVMBuild.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/MCTargetDesc/LLVMBuild.txt (added)
+++ llvm/trunk/lib/Target/ARC/MCTargetDesc/LLVMBuild.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,23 @@
+;===- ./lib/Target/ARC/MCTargetDesc/LLVMBuild.txt ------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = ARCDesc
+parent = ARC
+required_libraries = MC Support ARCAsmPrinter ARCInfo
+add_to_library_groups = ARC
Added: llvm/trunk/lib/Target/ARC/TargetInfo/ARCTargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/TargetInfo/ARCTargetInfo.cpp?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/TargetInfo/ARCTargetInfo.cpp (added)
+++ llvm/trunk/lib/Target/ARC/TargetInfo/ARCTargetInfo.cpp Thu Aug 24 08:40:33 2017
@@ -0,0 +1,22 @@
+//===- ARCTargetInfo.cpp - ARC Target Implementation ----------- *- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ARC.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+Target &llvm::getTheARCTarget() {
+ static Target TheARCTarget;
+ return TheARCTarget;
+}
+
+extern "C" void LLVMInitializeARCTargetInfo() {
+ RegisterTarget<Triple::arc> X(getTheARCTarget(), "arc", "ARC");
+}
Added: llvm/trunk/lib/Target/ARC/TargetInfo/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/TargetInfo/CMakeLists.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/TargetInfo/CMakeLists.txt (added)
+++ llvm/trunk/lib/Target/ARC/TargetInfo/CMakeLists.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,3 @@
+add_llvm_library(LLVMARCInfo
+ ARCTargetInfo.cpp
+ )
Added: llvm/trunk/lib/Target/ARC/TargetInfo/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARC/TargetInfo/LLVMBuild.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/lib/Target/ARC/TargetInfo/LLVMBuild.txt (added)
+++ llvm/trunk/lib/Target/ARC/TargetInfo/LLVMBuild.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,23 @@
+;===- ./lib/Target/ARC/TargetInfo/LLVMBuild.txt --------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Library
+name = ARCInfo
+parent = ARC
+required_libraries = Support
+add_to_library_groups = ARC
Modified: llvm/trunk/lib/Target/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/LLVMBuild.txt?rev=311667&r1=311666&r2=311667&view=diff
==============================================================================
--- llvm/trunk/lib/Target/LLVMBuild.txt (original)
+++ llvm/trunk/lib/Target/LLVMBuild.txt Thu Aug 24 08:40:33 2017
@@ -20,6 +20,7 @@
[common]
subdirectories =
AMDGPU
+ ARC
ARM
AArch64
AVR
Added: llvm/trunk/test/CodeGen/ARC/alu.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARC/alu.ll?rev=311667&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARC/alu.ll (added)
+++ llvm/trunk/test/CodeGen/ARC/alu.ll Thu Aug 24 08:40:33 2017
@@ -0,0 +1,255 @@
+; RUN: llc -march=arc < %s | FileCheck %s
+
+; CHECK-LABEL: add_r
+; CHECK: add %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @add_r(i32 %a, i32 %b) nounwind {
+entry:
+ %v = add i32 %a, %b
+ ret i32 %v
+}
+
+; CHECK-LABEL: add_u6
+; CHECK: add %r0, %r0, 15
+define i32 @add_u6(i32 %a) nounwind {
+ %v = add i32 %a, 15
+ ret i32 %v
+}
+
+; CHECK-LABEL: add_limm
+; CHECK: add %r0, %r0, 12345
+define i32 @add_limm(i32 %a) nounwind {
+ %v = add i32 %a, 12345
+ ret i32 %v
+}
+
+; CHECK-LABEL: mpy_r
+; CHECK: mpy %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @mpy_r(i32 %a, i32 %b) nounwind {
+entry:
+ %v = mul i32 %a, %b
+ ret i32 %v
+}
+
+; CHECK-LABEL: mpy_u6
+; CHECK: mpy %r0, %r0, 10
+define i32 @mpy_u6(i32 %a) nounwind {
+ %v = mul i32 %a, 10
+ ret i32 %v
+}
+
+; CHECK-LABEL: mpy_limm
+; CHECK: mpy %r0, %r0, 12345
+define i32 @mpy_limm(i32 %a) nounwind {
+ %v = mul i32 %a, 12345
+ ret i32 %v
+}
+
+; CHECK-LABEL: max_r
+; CHECK: max %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @max_r(i32 %a, i32 %b) nounwind {
+ %i = icmp sgt i32 %a, %b
+ %v = select i1 %i, i32 %a, i32 %b
+ ret i32 %v
+}
+
+; CHECK-LABEL: max_u6
+; CHECK: max %r0, %r0, 12
+define i32 @max_u6(i32 %a) nounwind {
+ %i = icmp sgt i32 %a, 12
+ %v = select i1 %i, i32 %a, i32 12
+ ret i32 %v
+}
+
+; CHECK-LABEL: max_limm
+; CHECK: max %r0, %r0, 2345
+define i32 @max_limm(i32 %a) nounwind {
+ %i = icmp sgt i32 %a, 2345
+ %v = select i1 %i, i32 %a, i32 2345
+ ret i32 %v
+}
+
+; CHECK-LABEL: min_r
+; CHECK: min %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @min_r(i32 %a, i32 %b) nounwind {
+ %i = icmp slt i32 %a, %b
+ %v = select i1 %i, i32 %a, i32 %b
+ ret i32 %v
+}
+
+; CHECK-LABEL: min_u6
+; CHECK: min %r0, %r0, 20
+define i32 @min_u6(i32 %a) nounwind {
+ %i = icmp slt i32 %a, 20
+ %v = select i1 %i, i32 %a, i32 20
+ ret i32 %v
+}
+
+; CHECK-LABEL: min_limm
+; CHECK: min %r0, %r0, 2040
+define i32 @min_limm(i32 %a) nounwind {
+ %i = icmp slt i32 %a, 2040
+ %v = select i1 %i, i32 %a, i32 2040
+ ret i32 %v
+}
+
+; CHECK-LABEL: and_r
+; CHECK: and %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @and_r(i32 %a, i32 %b) nounwind {
+ %v = and i32 %a, %b
+ ret i32 %v
+}
+
+; CHECK-LABEL: and_u6
+; CHECK: and %r0, %r0, 7
+define i32 @and_u6(i32 %a) nounwind {
+ %v = and i32 %a, 7
+ ret i32 %v
+}
+
+; 0xfffff == 1048575
+; CHECK-LABEL: and_limm
+; CHECK: and %r0, %r0, 1048575
+define i32 @and_limm(i32 %a) nounwind {
+ %v = and i32 %a, 1048575
+ ret i32 %v
+}
+
+; CHECK-LABEL: or_r
+; CHECK: or %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @or_r(i32 %a, i32 %b) nounwind {
+ %v = or i32 %a, %b
+ ret i32 %v
+}
+
+; CHECK-LABEL: or_u6
+; CHECK: or %r0, %r0, 7
+define i32 @or_u6(i32 %a) nounwind {
+ %v = or i32 %a, 7
+ ret i32 %v
+}
+
+; 0xf0f0f == 986895
+; CHECK-LABEL: or_limm
+define i32 @or_limm(i32 %a) nounwind {
+ %v = or i32 %a, 986895
+ ret i32 %v
+}
+
+; CHECK-LABEL: xor_r
+; CHECK: xor %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @xor_r(i32 %a, i32 %b) nounwind {
+ %v = xor i32 %a, %b
+ ret i32 %v
+}
+
+; CHECK-LABEL: xor_u6
+; CHECK: xor %r0, %r0, 3
+define i32 @xor_u6(i32 %a) nounwind {
+ %v = xor i32 %a, 3
+ ret i32 %v
+}
+
+; CHECK-LABEL: xor_limm
+; CHECK: xor %r0, %r0, 986895
+define i32 @xor_limm(i32 %a) nounwind {
+ %v = xor i32 %a, 986895
+ ret i32 %v
+}
+
+; CHECK-LABEL: asl_r
+; CHECK: asl %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @asl_r(i32 %a, i32 %b) nounwind {
+ %v = shl i32 %a, %b
+ ret i32 %v
+}
+
+; CHECK-LABEL: asl_u6
+; CHECK: asl %r0, %r0, 4
+define i32 @asl_u6(i32 %a) nounwind {
+ %v = shl i32 %a, 4
+ ret i32 %v
+}
+
+; CHECK-LABEL: lsr_r
+; CHECK: lsr %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @lsr_r(i32 %a, i32 %b) nounwind {
+ %v = lshr i32 %a, %b
+ ret i32 %v
+}
+
+; CHECK-LABEL: lsr_u6
+; CHECK: lsr %r0, %r0, 6
+define i32 @lsr_u6(i32 %a) nounwind {
+ %v = lshr i32 %a, 6
+ ret i32 %v
+}
+
+; CHECK-LABEL: asr_r
+; CHECK: asr %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @asr_r(i32 %a, i32 %b) nounwind {
+ %v = ashr i32 %a, %b
+ ret i32 %v
+}
+
+; CHECK-LABEL: asr_u6
+; CHECK: asr %r0, %r0, 8
+define i32 @asr_u6(i32 %a) nounwind {
+ %v = ashr i32 %a, 8
+ ret i32 %v
+}
+
+; CHECK-LABEL: ror_r
+; CHECK: ror %r0, %r{{[01]}}, %r{{[01]}}
+define i32 @ror_r(i32 %a, i32 %b) nounwind {
+ %v1 = lshr i32 %a, %b
+ %ls = sub i32 32, %b
+ %v2 = shl i32 %a, %ls
+ %v = or i32 %v1, %v2
+ ret i32 %v
+}
+
+; CHECK-LABEL: ror_u6
+; CHECK: ror %r0, %r0, 10
+define i32 @ror_u6(i32 %a) nounwind {
+ %v1 = lshr i32 %a, 10
+ %v2 = shl i32 %a, 22
+ %v = or i32 %v1, %v2
+ ret i32 %v
+}
+
+; CHECK-LABEL: sexh_r
+; CHECK: sexh %r0, %r0
+define i32 @sexh_r(i32 %a) nounwind {
+ %v1 = shl i32 %a, 16
+ %v = ashr i32 %v1, 16
+ ret i32 %v
+}
+
+; CHECK-LABEL: sexb_r
+; CHECK: sexb %r0, %r0
+define i32 @sexb_r(i32 %a) nounwind {
+ %v1 = shl i32 %a, 24
+ %v = ashr i32 %v1, 24
+ ret i32 %v
+}
+
+; CHECK-LABEL: mulu64
+; CHECK-DAG: mpy %r[[REG:[0-9]+]], %r{{[01]}}, %r{{[01]}}
+; CHECK-DAG: mpymu %r[[REG:[0-9]+]], %r{{[01]}}, %r{{[01]}}
+define i64 @mulu64(i32 %a, i32 %b) nounwind {
+ %a64 = zext i32 %a to i64
+ %b64 = zext i32 %b to i64
+ %v = mul i64 %a64, %b64
+ ret i64 %v
+}
+
+; CHECK-LABEL: muls64
+; CHECK-DAG: mpy %r[[REG:[0-9]+]], %r{{[01]}}, %r{{[01]}}
+; CHECK-DAG: mpym %r[[REG:[0-9]+]], %r{{[01]}}, %r{{[01]}}
+define i64 @muls64(i32 %a, i32 %b) nounwind {
+ %a64 = sext i32 %a to i64
+ %b64 = sext i32 %b to i64
+ %v = mul i64 %a64, %b64
+ ret i64 %v
+}
+
Added: llvm/trunk/test/CodeGen/ARC/brcc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARC/brcc.ll?rev=311667&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARC/brcc.ll (added)
+++ llvm/trunk/test/CodeGen/ARC/brcc.ll Thu Aug 24 08:40:33 2017
@@ -0,0 +1,37 @@
+; RUN: llc -march=arc < %s | FileCheck %s
+
+; CHECK-LABEL: brcc1
+; CHECK: brne %r0, %r1
+define i32 @brcc1(i32 %a, i32 %b) nounwind {
+entry:
+ %wb = icmp eq i32 %a, %b
+ br i1 %wb, label %t1, label %t2
+t1:
+ %t1v = add i32 %a, 4
+ br label %exit
+t2:
+ %t2v = add i32 %b, 8
+ br label %exit
+exit:
+ %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+ ret i32 %v
+}
+
+; CHECK-LABEL: brcc2
+; CHECK: breq %r0, %r1
+define i32 @brcc2(i32 %a, i32 %b) nounwind {
+entry:
+ %wb = icmp ne i32 %a, %b
+ br i1 %wb, label %t1, label %t2
+t1:
+ %t1v = add i32 %a, 4
+ br label %exit
+t2:
+ %t2v = add i32 %b, 8
+ br label %exit
+exit:
+ %v = phi i32 [ %t1v, %t1 ], [ %t2v, %t2 ]
+ ret i32 %v
+}
+
+
Added: llvm/trunk/test/CodeGen/ARC/call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARC/call.ll?rev=311667&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARC/call.ll (added)
+++ llvm/trunk/test/CodeGen/ARC/call.ll Thu Aug 24 08:40:33 2017
@@ -0,0 +1,88 @@
+; RUN: llc -march=arc < %s | FileCheck %s
+
+
+declare i32 @goo1(i32) nounwind
+
+; CHECK-LABEL: call1
+; CHECK: bl @goo1
+define i32 @call1(i32 %a) nounwind {
+entry:
+ %x = call i32 @goo1(i32 %a)
+ ret i32 %x
+}
+
+declare i32 @goo2(i32, i32, i32, i32, i32, i32, i32, i32) nounwind
+
+; CHECK-LABEL: call2
+; CHECK-DAG: mov %r0, 0
+; CHECK-DAG: mov %r1, 1
+; CHECK-DAG: mov %r2, 2
+; CHECK-DAG: mov %r3, 3
+; CHECK-DAG: mov %r4, 4
+; CHECK-DAG: mov %r5, 5
+; CHECK-DAG: mov %r6, 6
+; CHECK-DAG: mov %r7, 7
+; CHECK: bl @goo2
+define i32 @call2() nounwind {
+entry:
+ %x = call i32 @goo2(i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7)
+ ret i32 %x
+}
+
+declare i32 @goo3(i64, i32, i64) nounwind
+; call goo3(0xEEEEEEEE77777777, 0x55555555, 0xAAAAAAAA33333333)
+; 0xEEEEEEEE == -286331154
+; 0x77777777 == 2004318071
+; 0x55555555 == 1431655765
+; 0xAAAAAAAA == -1431655766
+; 0x33333333 == 858993459
+; CHECK-LABEL: call3
+; CHECK-DAG: mov %r0, 2004318071
+; CHECK-DAG: mov %r1, -286331154
+; CHECK-DAG: mov %r2, 1431655765
+; CHECK-DAG: mov %r3, 858993459
+; CHECK-DAG: mov %r4, -1431655766
+; CHECK: bl @goo3
+define i32 @call3() nounwind {
+entry:
+ %x = call i32 @goo3(i64 17216961133457930103,
+ i32 1431655765,
+ i64 12297829380468716339)
+ ret i32 %x
+}
+
+declare i64 @goo4()
+
+; 64-bit values are returned in r0r1
+; CHECK-LABEL: call4
+; CHECK: bl @goo4
+; CHECK: lsr %r0, %r1, 16
+define i32 @call4() nounwind {
+ %x = call i64 @goo4()
+ %v1 = lshr i64 %x, 48
+ %v = trunc i64 %v1 to i32
+ ret i32 %v
+}
+
+; 0x0000ffff00ff00ff=281470698455295
+; returned as r0=0x00ff00ff=16711935, r1=0x0000ffff=65535
+; CHECK-LABEL: ret1
+; CHECK-DAG: mov %r1, 65535
+; CHECK-DAG: mov %r0, 16711935
+define i64 @ret1() nounwind {
+ ret i64 281470698455295
+}
+
+ at funcptr = external global i32 (i32)*, align 4
+; Indirect calls use JL
+; CHECK-LABEL: call_indirect
+; CHECK-DAG: ld %r[[REG:[0-9]+]], [@funcptr]
+; CHECK-DAG: mov %r0, 12
+; CHECK: jl [%r[[REG]]]
+define i32 @call_indirect(i32 %x) nounwind {
+ %f = load i32 (i32)*, i32 (i32)** @funcptr, align 4
+ %call = call i32 %f(i32 12)
+ %add = add nsw i32 %call, %x
+ ret i32 %add
+}
+
Added: llvm/trunk/test/CodeGen/ARC/ldst.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARC/ldst.ll?rev=311667&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARC/ldst.ll (added)
+++ llvm/trunk/test/CodeGen/ARC/ldst.ll Thu Aug 24 08:40:33 2017
@@ -0,0 +1,272 @@
+; RUN: llc -march=arc < %s | FileCheck %s
+
+; CHECK-LABEL: load32
+; CHECK: ld %r0, [%r0,16000]
+
+define i32 @load32(i32* %bp) nounwind {
+entry:
+ %gep = getelementptr i32, i32* %bp, i32 4000
+ %v = load i32, i32* %gep, align 4
+ ret i32 %v
+}
+
+; CHECK-LABEL: load16
+; CHECK: ldh %r0, [%r0,8000]
+
+define i16 @load16(i16* %bp) nounwind {
+entry:
+ %gep = getelementptr i16, i16* %bp, i32 4000
+ %v = load i16, i16* %gep, align 2
+ ret i16 %v
+}
+
+; CHECK-LABEL: load8
+; CHECK: ldb %r0, [%r0,4000]
+
+define i8 @load8(i8* %bp) nounwind {
+entry:
+ %gep = getelementptr i8, i8* %bp, i32 4000
+ %v = load i8, i8* %gep, align 1
+ ret i8 %v
+}
+
+; CHECK-LABEL: sextload16
+; CHECK: ldh.x %r0, [%r0,8000]
+
+define i32 @sextload16(i16* %bp) nounwind {
+entry:
+ %gep = getelementptr i16, i16* %bp, i32 4000
+ %vl = load i16, i16* %gep, align 2
+ %v = sext i16 %vl to i32
+ ret i32 %v
+}
+
+; CHECK-LABEL: sextload8
+; CHECK: ldb.x %r0, [%r0,4000]
+
+define i32 @sextload8(i8* %bp) nounwind {
+entry:
+ %gep = getelementptr i8, i8* %bp, i32 4000
+ %vl = load i8, i8* %gep, align 1
+ %v = sext i8 %vl to i32
+ ret i32 %v
+}
+
+; CHECK-LABEL: s_sextload16
+; CHECK: ldh.x %r0, [%r0,32]
+
+define i32 @s_sextload16(i16* %bp) nounwind {
+entry:
+ %gep = getelementptr i16, i16* %bp, i32 16
+ %vl = load i16, i16* %gep, align 2
+ %v = sext i16 %vl to i32
+ ret i32 %v
+}
+
+; CHECK-LABEL: s_sextload8
+; CHECK: ldb.x %r0, [%r0,16]
+
+define i32 @s_sextload8(i8* %bp) nounwind {
+entry:
+ %gep = getelementptr i8, i8* %bp, i32 16
+ %vl = load i8, i8* %gep, align 1
+ %v = sext i8 %vl to i32
+ ret i32 %v
+}
+
+; CHECK-LABEL: store32
+; CHECK: add %r[[REG:[0-9]+]], %r1, 16000
+; CHECK: st %r0, [%r[[REG]],0]
+
+; Long range stores (offset does not fit in s9) must be add followed by st.
+define void @store32(i32 %val, i32* %bp) nounwind {
+entry:
+ %gep = getelementptr i32, i32* %bp, i32 4000
+ store i32 %val, i32* %gep, align 4
+ ret void
+}
+
+; CHECK-LABEL: store16
+; CHECK: add %r[[REG:[0-9]+]], %r1, 8000
+; CHECK: sth %r0, [%r[[REG]],0]
+
+define void @store16(i16 zeroext %val, i16* %bp) nounwind {
+entry:
+ %gep = getelementptr i16, i16* %bp, i32 4000
+ store i16 %val, i16* %gep, align 2
+ ret void
+}
+
+; CHECK-LABEL: store8
+; CHECK: add %r[[REG:[0-9]+]], %r1, 4000
+; CHECK: stb %r0, [%r[[REG]],0]
+
+define void @store8(i8 zeroext %val, i8* %bp) nounwind {
+entry:
+ %gep = getelementptr i8, i8* %bp, i32 4000
+ store i8 %val, i8* %gep, align 1
+ ret void
+}
+
+; Short range stores can be done with [reg, s9].
+; CHECK-LABEL: s_store32
+; CHECK-NOT: add
+; CHECK: st %r0, [%r1,64]
+define void @s_store32(i32 %val, i32* %bp) nounwind {
+entry:
+ %gep = getelementptr i32, i32* %bp, i32 16
+ store i32 %val, i32* %gep, align 4
+ ret void
+}
+
+; CHECK-LABEL: s_store16
+; CHECK-NOT: add
+; CHECK: sth %r0, [%r1,32]
+define void @s_store16(i16 zeroext %val, i16* %bp) nounwind {
+entry:
+ %gep = getelementptr i16, i16* %bp, i32 16
+ store i16 %val, i16* %gep, align 2
+ ret void
+}
+
+; CHECK-LABEL: s_store8
+; CHECK-NOT: add
+; CHECK: stb %r0, [%r1,16]
+define void @s_store8(i8 zeroext %val, i8* %bp) nounwind {
+entry:
+ %gep = getelementptr i8, i8* %bp, i32 16
+ store i8 %val, i8* %gep, align 1
+ ret void
+}
+
+
+ at aaaa = internal global [128 x i32] zeroinitializer
+ at bbbb = internal global [128 x i16] zeroinitializer
+ at cccc = internal global [128 x i8] zeroinitializer
+
+; CHECK-LABEL: g_store32
+; CHECK-NOT: add
+; CHECK: st %r0, [@aaaa+64]
+define void @g_store32(i32 %val) nounwind {
+entry:
+ store i32 %val, i32* getelementptr inbounds ([128 x i32], [128 x i32]* @aaaa, i32 0, i32 16), align 4
+ ret void
+}
+
+; CHECK-LABEL: g_load32
+; CHECK-NOT: add
+; CHECK: ld %r0, [@aaaa+64]
+define i32 @g_load32() nounwind {
+ %gep = getelementptr inbounds [128 x i32], [128 x i32]* @aaaa, i32 0, i32 16
+ %v = load i32, i32* %gep, align 4
+ ret i32 %v
+}
+
+; CHECK-LABEL: g_store16
+; CHECK-NOT: add
+; CHECK: sth %r0, [@bbbb+32]
+define void @g_store16(i16 %val) nounwind {
+entry:
+ store i16 %val, i16* getelementptr inbounds ([128 x i16], [128 x i16]* @bbbb, i16 0, i16 16), align 2
+ ret void
+}
+
+; CHECK-LABEL: g_load16
+; CHECK-NOT: add
+; CHECK: ldh %r0, [@bbbb+32]
+define i16 @g_load16() nounwind {
+ %gep = getelementptr inbounds [128 x i16], [128 x i16]* @bbbb, i16 0, i16 16
+ %v = load i16, i16* %gep, align 2
+ ret i16 %v
+}
+
+; CHECK-LABEL: g_store8
+; CHECK-NOT: add
+; CHECK: stb %r0, [@cccc+16]
+define void @g_store8(i8 %val) nounwind {
+entry:
+ store i8 %val, i8* getelementptr inbounds ([128 x i8], [128 x i8]* @cccc, i8 0, i8 16), align 1
+ ret void
+}
+
+; CHECK-LABEL: g_load8
+; CHECK-NOT: add
+; CHECK: ldb %r0, [@cccc+16]
+define i8 @g_load8() nounwind {
+ %gep = getelementptr inbounds [128 x i8], [128 x i8]* @cccc, i8 0, i8 16
+ %v = load i8, i8* %gep, align 1
+ ret i8 %v
+}
+
+; CHECK-LABEL: align2_load32
+; CHECK-DAG: ldh %r[[REG0:[0-9]+]], [%r0,0]
+; CHECK-DAG: ldh %r[[REG1:[0-9]+]], [%r0,2]
+; CHECK-DAG: asl %r[[REG2:[0-9]+]], %r[[REG1]], 16
+define i32 @align2_load32(i8* %p) nounwind {
+entry:
+ %bp = bitcast i8* %p to i32*
+ %v = load i32, i32* %bp, align 2
+ ret i32 %v
+}
+
+; CHECK-LABEL: align1_load32
+; CHECK-DAG: ldb %r[[REG0:[0-9]+]], [%r0,0]
+; CHECK-DAG: ldb %r[[REG1:[0-9]+]], [%r0,1]
+; CHECK-DAG: ldb %r[[REG2:[0-9]+]], [%r0,2]
+; CHECK-DAG: ldb %r[[REG3:[0-9]+]], [%r0,3]
+; CHECK-DAG: asl %r[[AREG1:[0-9]+]], %r[[REG1]], 8
+; CHECK-DAG: asl %r[[AREG3:[0-9]+]], %r[[REG3]], 8
+define i32 @align1_load32(i8* %p) nounwind {
+entry:
+ %bp = bitcast i8* %p to i32*
+ %v = load i32, i32* %bp, align 1
+ ret i32 %v
+}
+
+; CHECK-LABEL: align1_load16
+; CHECK-DAG: ldb %r[[REG0:[0-9]+]], [%r0,0]
+; CHECK-DAG: ldb %r[[REG1:[0-9]+]], [%r0,1]
+; CHECK-DAG: asl %r[[REG2:[0-9]+]], %r[[REG1]], 8
+define i16 @align1_load16(i8* %p) nounwind {
+entry:
+ %bp = bitcast i8* %p to i16*
+ %v = load i16, i16* %bp, align 1
+ ret i16 %v
+}
+
+; CHECK-LABEL: align2_store32
+; CHECK-DAG: lsr %r[[REG:[0-9]+]], %r1, 16
+; CHECK-DAG: sth %r1, [%r0,0]
+; CHECK-DAG: sth %r[[REG:[0-9]+]], [%r0,2]
+define void @align2_store32(i8* %p, i32 %v) nounwind {
+entry:
+ %bp = bitcast i8* %p to i32*
+ store i32 %v, i32* %bp, align 2
+ ret void
+}
+
+; CHECK-LABEL: align1_store16
+; CHECK-DAG: lsr %r[[REG:[0-9]+]], %r1, 8
+; CHECK-DAG: stb %r1, [%r0,0]
+; CHECK-DAG: stb %r[[REG:[0-9]+]], [%r0,1]
+define void @align1_store16(i8* %p, i16 %v) nounwind {
+entry:
+ %bp = bitcast i8* %p to i16*
+ store i16 %v, i16* %bp, align 1
+ ret void
+}
+
+; CHECK-LABEL: align1_store32
+; CHECK-DAG: lsr %r[[REG0:[0-9]+]], %r1, 8
+; CHECK-DAG: lsr %r[[REG1:[0-9]+]], %r1, 16
+; CHECK-DAG: lsr %r[[REG2:[0-9]+]], %r1, 24
+; CHECK-DAG: stb %r1, [%r0,0]
+; CHECK-DAG: stb %r[[REG0]], [%r0,1]
+; CHECK-DAG: stb %r[[REG1]], [%r0,2]
+; CHECK-DAG: stb %r[[REG2]], [%r0,3]
+define void @align1_store32(i8* %p, i32 %v) nounwind {
+entry:
+ %bp = bitcast i8* %p to i32*
+ store i32 %v, i32* %bp, align 1
+ ret void
+}
Added: llvm/trunk/test/CodeGen/ARC/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARC/lit.local.cfg?rev=311667&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARC/lit.local.cfg (added)
+++ llvm/trunk/test/CodeGen/ARC/lit.local.cfg Thu Aug 24 08:40:33 2017
@@ -0,0 +1,3 @@
+if not 'ARC' in config.root.targets:
+ config.unsupported = True
+
Added: llvm/trunk/test/MC/Disassembler/ARC/alu.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARC/alu.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/test/MC/Disassembler/ARC/alu.txt (added)
+++ llvm/trunk/test/MC/Disassembler/ARC/alu.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,75 @@
+# RUN: llvm-mc -triple=arc -disassemble %s | FileCheck %s
+
+# CHECK: add %r0, %r0, %r0
+0x00 0x20 0x00 0x00
+
+# CHECK: add %r4, %r0, %r0
+0x00 0x20 0x04 0x00
+
+# CHECK: add %r2, %r0, %r3
+0x00 0x20 0xc2 0x00
+
+# CHECK: add %r2, %r0, %r4
+0x00 0x20 0x02 0x01
+
+# CHECK: add %r2, %r7, %r4
+0x00 0x27 0x02 0x01
+
+# CHECK: and %r2, %r7, %r4
+0x04 0x27 0x02 0x01
+
+# CHECK: and %r2, %r7, 4
+0x44 0x27 0x02 0x01
+
+# CHECK: and %r1, %r1, 255
+0x84 0x21 0xc3 0x0f
+
+# CHECK: asl %r1, %r1, 2
+0x40 0x29 0x81 0x00
+
+# CHECK: asl %r0, %r0, %r0
+0x00 0x28 0x00 0x00
+
+# CHECK: asr %r1, %r2, 31
+0x42 0x2a 0xc1 0x07
+
+# CHECK: asr %r1, %r3, 7
+0x42 0x2b 0xc1 0x01
+
+# CHECK: asr %r1, %r1, %r2
+0x02 0x29 0x81 0x00
+
+# CHECK: max %r0, %r2, %r1
+0x08 0x22 0x40 0x00
+
+# CHECK: max %r0, %r1, 15
+0x48 0x21 0xc0 0x03
+
+# CHECK: max %r0, %r2, 4000
+0x08 0x22 0x80 0x0f 0x00 0x00 0xa0 0x0f
+
+# CHECK: max %r2, %r2, 255
+0x88 0x22 0xc3 0x0f
+
+# CHECK: or %r18, %r16, 61440
+0x05 0x20 0x92 0x2f 0x00 0x00 0x00 0xf0
+
+# CHECK: or %r1, %r1, %r14
+0x05 0x21 0x81 0x03
+
+# CHECK: or %r1, %r14, %r1
+0x05 0x26 0x41 0x10
+
+# CHECK: or %r1, %r1, 128
+0x85 0x21 0x02 0x00
+
+# CHECK: sub %sp, %fp, 92
+0x02 0x23 0x9c 0x3f 0x00 0x00 0x5c 0x00
+
+# CHECK: sub %r2, %r7, %r4
+0x02 0x27 0x02 0x01
+
+# CHECK: sub %r0, %r22, %r0
+0x02 0x26 0x00 0x20
+
+
Added: llvm/trunk/test/MC/Disassembler/ARC/br.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARC/br.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/test/MC/Disassembler/ARC/br.txt (added)
+++ llvm/trunk/test/MC/Disassembler/ARC/br.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,29 @@
+# RUN: llvm-mc -triple=arc -disassemble %s | FileCheck %s
+
+# CHECK: brlt %r2, 0, 60
+0x3d 0x0a 0x12 0x00
+
+# CHECK: brlo %r10, %r4, -112
+0x91 0x0a 0x04 0x91
+
+# CHECK: breq %r2, %r1, 44
+0x2d 0x0a 0x40 0x00
+
+# CHECK: brne %r0, 0, -16
+0xf1 0x08 0x11 0x80
+
+# CHECK: brhs %r2, %r8, 38
+0x27 0x0a 0x05 0x02
+
+# CHECK: bne 304
+0x30 0x01 0x02 0x00
+
+# CHECK: beq 268
+0x0c 0x01 0x01 0x00
+
+# CHECK: bhi 416
+0xa0 0x01 0x0d 0x00
+
+# CHECK: b -68
+0xbd 0x07 0xcf 0xff
+
Added: llvm/trunk/test/MC/Disassembler/ARC/ldst.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARC/ldst.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/test/MC/Disassembler/ARC/ldst.txt (added)
+++ llvm/trunk/test/MC/Disassembler/ARC/ldst.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,47 @@
+# RUN: llvm-mc -triple=arc -disassemble %s | FileCheck %s
+
+# CHECK: ld %r0, [%r0,0]
+0x00 0x10 0x00 0x00
+
+# CHECK: ldh %r0, [%r0,0]
+0x00 0x10 0x00 0x01
+
+# CHECK: ldb %r0, [%r0,0]
+0x00 0x10 0x80 0x00
+
+# CHECK: ld %r1, [%r0,12]
+0x0c 0x10 0x01 0x00
+
+# CHECK: ld %r14, [%fp,-12]
+0xf4 0x13 0x0e 0xb0
+
+# CHECK: ld %r3, [%r0,-12]
+0xf4 0x10 0x03 0x80
+
+# CHECK: ld %r0, [%r0,244]
+0xf4 0x10 0x00 0x00
+
+# CHECK: ld %r0, [%r0,-12]
+0xf4 0x10 0x00 0x80
+
+# CHECK: ldh.x %r3, [%r1,0]
+0x00 0x11 0x43 0x01
+
+# CHECK: ldh.x %r2, [%r1,2]
+0x02 0x11 0x42 0x01
+
+# CHECK: ldh.x %r2, [%fp,-132]
+0x7c 0x13 0x42 0xb1
+
+# CHECK: ld %r0, [%r0,64000]
+0x30 0x20 0x80 0x0f 0x00 0x00 0x00 0xfa
+
+# CHECK: ld %r6, [63920]
+0x00 0x16 0x06 0x70 0x00 0x00 0xb0 0xf9
+
+# CHECK: stb %r2, [%sp,35]
+0x23 0x1c 0x82 0x30
+
+# CHECK: st %r7, [63920]
+0x00 0x1e 0xc0 0x71 0x00 0x00 0xb0 0xf9
+
Added: llvm/trunk/test/MC/Disassembler/ARC/lit.local.cfg
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARC/lit.local.cfg?rev=311667&view=auto
==============================================================================
--- llvm/trunk/test/MC/Disassembler/ARC/lit.local.cfg (added)
+++ llvm/trunk/test/MC/Disassembler/ARC/lit.local.cfg Thu Aug 24 08:40:33 2017
@@ -0,0 +1,3 @@
+if not 'ARC' in config.root.targets:
+ config.unsupported = True
+
Added: llvm/trunk/test/MC/Disassembler/ARC/misc.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARC/misc.txt?rev=311667&view=auto
==============================================================================
--- llvm/trunk/test/MC/Disassembler/ARC/misc.txt (added)
+++ llvm/trunk/test/MC/Disassembler/ARC/misc.txt Thu Aug 24 08:40:33 2017
@@ -0,0 +1,42 @@
+# RUN: llvm-mc -triple=arc -disassemble %s | FileCheck %s
+
+# CHECK: mov %r0, -1
+0x8a 0x20 0xff 0x0f
+
+# 32767 == 0x7fff
+# CHECK: mov %r4, 32767
+0x0a 0x24 0x80 0x0f 0x00 0x00 0xff 0x7f
+
+# CHECK: mov.eq %r2, %r6
+0xca 0x22 0x81 0x01
+
+# CHECK: mov %r13, %r2
+0x0a 0x25 0x80 0x10
+
+# CHECK: mov %r1, 20
+0x4a 0x21 0x00 0x05
+
+# CHECK: st.aw %fp, [%sp,-4]
+0xfc 0x1c 0xc8 0xb6
+
+# CHECK: ld.ab %fp, [%sp,4]
+0x04 0x14 0x1b 0x34
+
+# CHECK: bl -2028
+0x16 0x08 0xcf 0xff
+
+# CHECK: cmp %r13, %r10
+0x0c 0x25 0x80 0x92
+
+# CHECK: cmp %r14, 0
+0x4c 0x26 0x00 0x90
+
+# CHECK: cmp %r23, 1
+0x4c 0x27 0x40 0xa0
+
+# CHECK: jl [%r21]
+0x22 0x20 0x40 0x05
+
+# CHECK: j [%r3]
+0x20 0x20 0xc0 0x00
+
More information about the llvm-commits
mailing list