[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