mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
Hexagon backend support
llvm-svn: 146412
This commit is contained in:
parent
5b25b4d437
commit
61adbf8dc5
@ -72,6 +72,7 @@ set(LLVM_ALL_TARGETS
|
||||
CBackend
|
||||
CellSPU
|
||||
CppBackend
|
||||
Hexagon
|
||||
Mips
|
||||
MBlaze
|
||||
MSP430
|
||||
|
4
autoconf/config.sub
vendored
4
autoconf/config.sub
vendored
@ -4,7 +4,7 @@
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
# 2011 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2011-08-23'
|
||||
timestamp='2011-11-02'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
@ -256,6 +256,7 @@ case $basic_machine in
|
||||
| c4x | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fido | fr30 | frv \
|
||||
| hexagon \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
@ -367,6 +368,7 @@ case $basic_machine in
|
||||
| elxsi-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hexagon-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
|
@ -357,6 +357,7 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch],
|
||||
mips-*) llvm_cv_target_arch="Mips" ;;
|
||||
xcore-*) llvm_cv_target_arch="XCore" ;;
|
||||
msp430-*) llvm_cv_target_arch="MSP430" ;;
|
||||
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
|
||||
mblaze-*) llvm_cv_target_arch="MBlaze" ;;
|
||||
ptx-*) llvm_cv_target_arch="PTX" ;;
|
||||
*) llvm_cv_target_arch="Unknown" ;;
|
||||
@ -503,6 +504,7 @@ else
|
||||
Mips) AC_SUBST(TARGET_HAS_JIT,1) ;;
|
||||
XCore) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
MBlaze) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
PTX) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
*) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
@ -615,14 +617,14 @@ dnl Allow specific targets to be specified for building (or not)
|
||||
TARGETS_TO_BUILD=""
|
||||
AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets],
|
||||
[Build specific host targets: all or target1,target2,... Valid targets are:
|
||||
host, x86, x86_64, sparc, powerpc, arm, mips, spu,
|
||||
host, x86, x86_64, sparc, powerpc, arm, mips, spu, hexagon,
|
||||
xcore, msp430, ptx, cbe, and cpp (default=all)]),,
|
||||
enableval=all)
|
||||
if test "$enableval" = host-only ; then
|
||||
enableval=host
|
||||
fi
|
||||
case "$enableval" in
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX" ;;
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX Hexagon" ;;
|
||||
*)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do
|
||||
case "$a_target" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
@ -636,6 +638,7 @@ case "$enableval" in
|
||||
msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;;
|
||||
cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;;
|
||||
hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
ptx) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;;
|
||||
host) case "$llvm_cv_target_arch" in
|
||||
@ -649,6 +652,7 @@ case "$enableval" in
|
||||
CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;;
|
||||
XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||
MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
PTX) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;;
|
||||
*) AC_MSG_ERROR([Can not set target to build]) ;;
|
||||
esac ;;
|
||||
|
9
configure
vendored
9
configure
vendored
@ -1419,7 +1419,7 @@ Optional Features:
|
||||
--enable-targets Build specific host targets: all or
|
||||
target1,target2,... Valid targets are: host, x86,
|
||||
x86_64, sparc, powerpc, arm, mips, spu, xcore,
|
||||
msp430, ptx, cbe, and cpp (default=all)
|
||||
hexagon, msp430, ptx, cbe, and cpp (default=all)
|
||||
--enable-cbe-printf-a Enable C Backend output with hex floating point via
|
||||
%a (default is YES)
|
||||
--enable-bindings Build specific language bindings:
|
||||
@ -3883,6 +3883,7 @@ else
|
||||
mips-*) llvm_cv_target_arch="Mips" ;;
|
||||
xcore-*) llvm_cv_target_arch="XCore" ;;
|
||||
msp430-*) llvm_cv_target_arch="MSP430" ;;
|
||||
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
|
||||
mblaze-*) llvm_cv_target_arch="MBlaze" ;;
|
||||
ptx-*) llvm_cv_target_arch="PTX" ;;
|
||||
*) llvm_cv_target_arch="Unknown" ;;
|
||||
@ -5102,6 +5103,8 @@ else
|
||||
XCore) TARGET_HAS_JIT=0
|
||||
;;
|
||||
MSP430) TARGET_HAS_JIT=0
|
||||
;;
|
||||
Hexagon) TARGET_HAS_JIT=0
|
||||
;;
|
||||
MBlaze) TARGET_HAS_JIT=0
|
||||
;;
|
||||
@ -5291,7 +5294,7 @@ if test "$enableval" = host-only ; then
|
||||
enableval=host
|
||||
fi
|
||||
case "$enableval" in
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX" ;;
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX Hexagon" ;;
|
||||
*)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do
|
||||
case "$a_target" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
@ -5305,6 +5308,7 @@ case "$enableval" in
|
||||
msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;;
|
||||
cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;;
|
||||
hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
ptx) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;;
|
||||
host) case "$llvm_cv_target_arch" in
|
||||
@ -5318,6 +5322,7 @@ case "$enableval" in
|
||||
CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;;
|
||||
XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||
MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
PTX) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;;
|
||||
*) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5
|
||||
echo "$as_me: error: Can not set target to build" >&2;}
|
||||
|
@ -2288,6 +2288,7 @@ is the key:</p>
|
||||
<th>Feature</th>
|
||||
<th>ARM</th>
|
||||
<th>CellSPU</th>
|
||||
<th>Hexagon</th>
|
||||
<th>MBlaze</th>
|
||||
<th>MSP430</th>
|
||||
<th>Mips</th>
|
||||
@ -2302,6 +2303,7 @@ is the key:</p>
|
||||
<td><a href="#feat_reliable">is generally reliable</a></td>
|
||||
<td class="yes"></td> <!-- ARM -->
|
||||
<td class="no"></td> <!-- CellSPU -->
|
||||
<td class="yes"></td> <!-- Hexagon -->
|
||||
<td class="no"></td> <!-- MBlaze -->
|
||||
<td class="unknown"></td> <!-- MSP430 -->
|
||||
<td class="yes"></td> <!-- Mips -->
|
||||
@ -2316,6 +2318,7 @@ is the key:</p>
|
||||
<td><a href="#feat_asmparser">assembly parser</a></td>
|
||||
<td class="no"></td> <!-- ARM -->
|
||||
<td class="no"></td> <!-- CellSPU -->
|
||||
<td class="no"></td> <!-- Hexagon -->
|
||||
<td class="yes"></td> <!-- MBlaze -->
|
||||
<td class="no"></td> <!-- MSP430 -->
|
||||
<td class="no"></td> <!-- Mips -->
|
||||
@ -2330,6 +2333,7 @@ is the key:</p>
|
||||
<td><a href="#feat_disassembler">disassembler</a></td>
|
||||
<td class="yes"></td> <!-- ARM -->
|
||||
<td class="no"></td> <!-- CellSPU -->
|
||||
<td class="no"></td> <!-- Hexagon -->
|
||||
<td class="yes"></td> <!-- MBlaze -->
|
||||
<td class="no"></td> <!-- MSP430 -->
|
||||
<td class="no"></td> <!-- Mips -->
|
||||
@ -2344,6 +2348,7 @@ is the key:</p>
|
||||
<td><a href="#feat_inlineasm">inline asm</a></td>
|
||||
<td class="yes"></td> <!-- ARM -->
|
||||
<td class="no"></td> <!-- CellSPU -->
|
||||
<td class="yes"></td> <!-- Hexagon -->
|
||||
<td class="yes"></td> <!-- MBlaze -->
|
||||
<td class="unknown"></td> <!-- MSP430 -->
|
||||
<td class="no"></td> <!-- Mips -->
|
||||
@ -2358,6 +2363,7 @@ is the key:</p>
|
||||
<td><a href="#feat_jit">jit</a></td>
|
||||
<td class="partial"><a href="#feat_jit_arm">*</a></td> <!-- ARM -->
|
||||
<td class="no"></td> <!-- CellSPU -->
|
||||
<td class="no"></td> <!-- Hexagon -->
|
||||
<td class="no"></td> <!-- MBlaze -->
|
||||
<td class="unknown"></td> <!-- MSP430 -->
|
||||
<td class="yes"></td> <!-- Mips -->
|
||||
@ -2372,6 +2378,7 @@ is the key:</p>
|
||||
<td><a href="#feat_objectwrite">.o file writing</a></td>
|
||||
<td class="no"></td> <!-- ARM -->
|
||||
<td class="no"></td> <!-- CellSPU -->
|
||||
<td class="no"></td> <!-- Hexagon -->
|
||||
<td class="yes"></td> <!-- MBlaze -->
|
||||
<td class="no"></td> <!-- MSP430 -->
|
||||
<td class="no"></td> <!-- Mips -->
|
||||
@ -2386,6 +2393,7 @@ is the key:</p>
|
||||
<td><a href="#feat_tailcall">tail calls</a></td>
|
||||
<td class="yes"></td> <!-- ARM -->
|
||||
<td class="no"></td> <!-- CellSPU -->
|
||||
<td class="yes"></td> <!-- Hexagon -->
|
||||
<td class="no"></td> <!-- MBlaze -->
|
||||
<td class="unknown"></td> <!-- MSP430 -->
|
||||
<td class="no"></td> <!-- Mips -->
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
|
||||
arm, // ARM; arm, armv.*, xscale
|
||||
cellspu, // CellSPU: spu, cellspu
|
||||
hexagon, // Hexagon: hexagon
|
||||
mips, // MIPS: mips, mipsallegrex
|
||||
mipsel, // MIPSEL: mipsel, mipsallegrexel, psp
|
||||
mips64, // MIPS64: mips64
|
||||
|
@ -444,3 +444,4 @@ include "llvm/IntrinsicsARM.td"
|
||||
include "llvm/IntrinsicsCellSPU.td"
|
||||
include "llvm/IntrinsicsXCore.td"
|
||||
include "llvm/IntrinsicsPTX.td"
|
||||
include "llvm/IntrinsicsHexagon.td"
|
||||
|
3671
include/llvm/IntrinsicsHexagon.td
Normal file
3671
include/llvm/IntrinsicsHexagon.td
Normal file
File diff suppressed because it is too large
Load Diff
@ -51,6 +51,13 @@ inline bool isInt<32>(int64_t x) {
|
||||
return static_cast<int32_t>(x) == x;
|
||||
}
|
||||
|
||||
/// isShiftedInt<N,S> - Checks if a signed integer is an N bit number shifted
|
||||
/// left by S.
|
||||
template<unsigned N, unsigned S>
|
||||
inline bool isShiftedInt(int64_t x) {
|
||||
return isInt<N+S>(x) && (x % (1<<S) == 0);
|
||||
}
|
||||
|
||||
/// isUInt - Checks if an unsigned integer fits into the given bit width.
|
||||
template<unsigned N>
|
||||
inline bool isUInt(uint64_t x) {
|
||||
@ -70,6 +77,13 @@ inline bool isUInt<32>(uint64_t x) {
|
||||
return static_cast<uint32_t>(x) == x;
|
||||
}
|
||||
|
||||
/// isShiftedUInt<N,S> - Checks if a unsigned integer is an N bit number shifted
|
||||
/// left by S.
|
||||
template<unsigned N, unsigned S>
|
||||
inline bool isShiftedUInt(uint64_t x) {
|
||||
return isUInt<N+S>(x) && (x % (1<<S) == 0);
|
||||
}
|
||||
|
||||
/// isUIntN - Checks if an unsigned integer fits into the given (dynamic)
|
||||
/// bit width.
|
||||
inline bool isUIntN(unsigned N, uint64_t x) {
|
||||
|
@ -20,6 +20,7 @@ const char *Triple::getArchTypeName(ArchType Kind) {
|
||||
|
||||
case arm: return "arm";
|
||||
case cellspu: return "cellspu";
|
||||
case hexagon: return "hexagon";
|
||||
case mips: return "mips";
|
||||
case mipsel: return "mipsel";
|
||||
case mips64: return "mips64";
|
||||
@ -59,6 +60,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) {
|
||||
|
||||
case mblaze: return "mblaze";
|
||||
|
||||
case hexagon: return "hexagon";
|
||||
|
||||
case sparcv9:
|
||||
case sparc: return "sparc";
|
||||
|
||||
@ -150,6 +153,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) {
|
||||
return ppc;
|
||||
if (Name == "mblaze")
|
||||
return mblaze;
|
||||
if (Name == "hexagon")
|
||||
return hexagon;
|
||||
if (Name == "sparc")
|
||||
return sparc;
|
||||
if (Name == "sparcv9")
|
||||
@ -295,6 +300,8 @@ Triple::ArchType Triple::ParseArch(StringRef ArchName) {
|
||||
return mips64;
|
||||
else if (ArchName == "mips64el")
|
||||
return mips64el;
|
||||
else if (ArchName == "hexagon")
|
||||
return hexagon;
|
||||
else if (ArchName == "sparc")
|
||||
return sparc;
|
||||
else if (ArchName == "sparcv9")
|
||||
|
43
lib/Target/Hexagon/CMakeLists.txt
Normal file
43
lib/Target/Hexagon/CMakeLists.txt
Normal file
@ -0,0 +1,43 @@
|
||||
set(LLVM_TARGET_DEFINITIONS Hexagon.td)
|
||||
|
||||
tablegen(LLVM HexagonGenRegisterInfo.inc -gen-register-info)
|
||||
tablegen(LLVM HexagonGenInstrInfo.inc -gen-instr-info)
|
||||
tablegen(LLVM HexagonGenAsmWriter.inc -gen-asm-writer)
|
||||
tablegen(LLVM HexagonGenDAGISel.inc -gen-dag-isel)
|
||||
tablegen(LLVM HexagonGenCallingConv.inc -gen-callingconv)
|
||||
tablegen(LLVM HexagonGenSubtargetInfo.inc -gen-subtarget)
|
||||
tablegen(LLVM HexagonGenIntrinsics.inc -gen-tgt-intrinsic)
|
||||
add_public_tablegen_target(HexagonCommonTableGen)
|
||||
|
||||
add_llvm_target(HexagonCodeGen
|
||||
HexagonAsmPrinter.cpp
|
||||
HexagonCallingConvLower.cpp
|
||||
HexagonCFGOptimizer.cpp
|
||||
HexagonExpandPredSpillCode.cpp
|
||||
HexagonFrameLowering.cpp
|
||||
HexagonHardwareLoops.cpp
|
||||
HexagonInstrInfo.cpp
|
||||
HexagonISelDAGToDAG.cpp
|
||||
HexagonISelLowering.cpp
|
||||
HexagonMCAsmInfo.cpp
|
||||
HexagonOptimizeSZExtends.cpp
|
||||
HexagonRegisterInfo.cpp
|
||||
HexagonRemoveSZExtArgs.cpp
|
||||
HexagonSelectionDAGInfo.cpp
|
||||
HexagonSplitTFRCondSets.cpp
|
||||
HexagonSubtarget.cpp
|
||||
HexagonTargetMachine.cpp
|
||||
HexagonTargetObjectFile.cpp
|
||||
)
|
||||
|
||||
add_llvm_library_dependencies(LLVMHexagonCodeGen
|
||||
LLVMAsmPrinter
|
||||
LLVMCodeGen
|
||||
LLVMCore
|
||||
LLVMHexagonInfo
|
||||
LLVMSelectionDAG
|
||||
LLVMSupport
|
||||
LLVMTarget
|
||||
)
|
||||
|
||||
add_subdirectory(TargetInfo)
|
68
lib/Target/Hexagon/Hexagon.h
Normal file
68
lib/Target/Hexagon/Hexagon.h
Normal file
@ -0,0 +1,68 @@
|
||||
//=-- Hexagon.h - Top-level interface for Hexagon 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
|
||||
// Hexagon back-end.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef TARGET_Hexagon_H
|
||||
#define TARGET_Hexagon_H
|
||||
|
||||
#include <cassert>
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
class FunctionPass;
|
||||
class TargetMachine;
|
||||
class HexagonTargetMachine;
|
||||
class raw_ostream;
|
||||
|
||||
FunctionPass *createHexagonISelDag(HexagonTargetMachine &TM);
|
||||
FunctionPass *createHexagonDelaySlotFillerPass(TargetMachine &TM);
|
||||
FunctionPass *createHexagonFPMoverPass(TargetMachine &TM);
|
||||
FunctionPass *createHexagonRemoveExtendOps(HexagonTargetMachine &TM);
|
||||
FunctionPass *createHexagonCFGOptimizer(HexagonTargetMachine &TM);
|
||||
|
||||
FunctionPass* createHexagonSplitTFRCondSets(HexagonTargetMachine &TM);
|
||||
FunctionPass* createHexagonExpandPredSpillCode(HexagonTargetMachine &TM);
|
||||
|
||||
FunctionPass *createHexagonHardwareLoops();
|
||||
FunctionPass *createHexagonOptimizeSZExtends();
|
||||
FunctionPass *createHexagonFixupHwLoops();
|
||||
|
||||
extern Target TheHexagonTarget;
|
||||
|
||||
} // end namespace llvm;
|
||||
|
||||
// Defines symbolic names for Hexagon instructions and registers.
|
||||
// This defines a mapping from register name to register number.
|
||||
//
|
||||
|
||||
#define GET_REGINFO_ENUM
|
||||
#include "HexagonGenRegisterInfo.inc"
|
||||
|
||||
#define GET_INSTRINFO_ENUM
|
||||
#include "HexagonGenInstrInfo.inc"
|
||||
|
||||
#define GET_SUBTARGETINFO_ENUM
|
||||
#include "HexagonGenSubtargetInfo.inc"
|
||||
|
||||
#define Hexagon_POINTER_SIZE 4
|
||||
|
||||
#define Hexagon_PointerSize (Hexagon_POINTER_SIZE)
|
||||
#define Hexagon_PointerSize_Bits (Hexagon_POINTER_SIZE * 8)
|
||||
#define Hexagon_WordSize Hexagon_PointerSize
|
||||
#define Hexagon_WordSize_Bits Hexagon_PointerSize_Bits
|
||||
|
||||
// allocframe saves LR and FP on stack before allocating
|
||||
// a new stack frame. This takes 8 bytes.
|
||||
#define HEXAGON_LRFP_SIZE 8
|
||||
|
||||
#endif
|
66
lib/Target/Hexagon/Hexagon.td
Normal file
66
lib/Target/Hexagon/Hexagon.td
Normal file
@ -0,0 +1,66 @@
|
||||
//===- Hexagon.td - Describe the Hexagon Target Machine ---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Target-independent interfaces which we are implementing
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "llvm/Target/Target.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Hexagon Subtarget features.
|
||||
//
|
||||
|
||||
|
||||
// Hexagon Archtectures
|
||||
def ArchV2 : SubtargetFeature<"v2", "HexagonArchVersion", "V2",
|
||||
"Hexagon v2">;
|
||||
def ArchV3 : SubtargetFeature<"v3", "HexagonArchVersion", "V3",
|
||||
"Hexagon v3">;
|
||||
def ArchV4 : SubtargetFeature<"v4", "HexagonArchVersion", "V4",
|
||||
"Hexagon v4">;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Register File, Calling Conv, Instruction Descriptions
|
||||
//===----------------------------------------------------------------------===//
|
||||
include "HexagonSchedule.td"
|
||||
include "HexagonRegisterInfo.td"
|
||||
include "HexagonCallingConv.td"
|
||||
include "HexagonInstrInfo.td"
|
||||
include "HexagonIntrinsics.td"
|
||||
include "HexagonIntrinsicsDerived.td"
|
||||
|
||||
|
||||
def HexagonInstrInfo : InstrInfo {
|
||||
// Define how we want to layout our target-specific information field.
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Hexagon processors supported.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class Proc<string Name, ProcessorItineraries Itin,
|
||||
list<SubtargetFeature> Features>
|
||||
: Processor<Name, Itin, Features>;
|
||||
|
||||
def : Proc<"hexagonv2", HexagonItineraries, [ArchV2]>;
|
||||
def : Proc<"hexagonv3", HexagonItineraries, [ArchV2, ArchV3]>;
|
||||
def : Proc<"hexagonv4", HexagonItinerariesV4, [ArchV2, ArchV3, ArchV4]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Declare the target which we are implementing
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def Hexagon : Target {
|
||||
// Pull in Instruction Info:
|
||||
let InstructionSet = HexagonInstrInfo;
|
||||
}
|
555
lib/Target/Hexagon/HexagonAsmPrinter.cpp
Normal file
555
lib/Target/Hexagon/HexagonAsmPrinter.cpp
Normal file
@ -0,0 +1,555 @@
|
||||
//===-- HexagonAsmPrinter.cpp - Print machine instrs to Hexagon assembly ----=//
|
||||
//
|
||||
// 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 Hexagon assembly language. This printer is
|
||||
// the output mechanism used by `llc'.
|
||||
//
|
||||
// Documentation at http://developer.apple.com/documentation/DeveloperTools/
|
||||
// Reference/Assembler/ASMIntroduction/chapter_1_section_1.html
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#define DEBUG_TYPE "asm-printer"
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Assembly/Writer.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/Mangler.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetLoweringObjectFile.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool> AlignCalls(
|
||||
"hexagon-align-calls", cl::Hidden, cl::init(true),
|
||||
cl::desc("Insert falign after call instruction for Hexagon target"));
|
||||
|
||||
|
||||
namespace {
|
||||
class HexagonAsmPrinter : public AsmPrinter {
|
||||
const HexagonSubtarget *Subtarget;
|
||||
|
||||
public:
|
||||
explicit HexagonAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
|
||||
: AsmPrinter(TM, Streamer) {
|
||||
Subtarget = &TM.getSubtarget<HexagonSubtarget>();
|
||||
}
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "Hexagon Assembly Printer";
|
||||
}
|
||||
|
||||
/// printInstruction - This method is automatically generated by tablegen
|
||||
/// from the instruction set description. This method returns true if the
|
||||
/// machine instruction was sufficiently described to print it, otherwise it
|
||||
void printInstruction(const MachineInstr *MI, raw_ostream &O);
|
||||
virtual void EmitInstruction(const MachineInstr *MI);
|
||||
|
||||
void printOp(const MachineOperand &MO, raw_ostream &O);
|
||||
|
||||
/// printRegister - Print register according to target requirements.
|
||||
///
|
||||
void printRegister(const MachineOperand &MO, bool R0AsZero,
|
||||
raw_ostream &O) {
|
||||
unsigned RegNo = MO.getReg();
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(RegNo) && "Not physreg??");
|
||||
O << getRegisterName(RegNo);
|
||||
}
|
||||
|
||||
void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &OS) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
if (MO.isReg()) {
|
||||
printRegister(MO, false, OS);
|
||||
} else if (MO.isImm()) {
|
||||
OS << MO.getImm();
|
||||
} else {
|
||||
printOp(MO, OS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const;
|
||||
|
||||
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &OS);
|
||||
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &OS);
|
||||
|
||||
|
||||
void printHexagonImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
int value = MI->getOperand(OpNo).getImm();
|
||||
O << value;
|
||||
}
|
||||
|
||||
|
||||
void printHexagonNegImmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
int value = MI->getOperand(OpNo).getImm();
|
||||
O << -value;
|
||||
}
|
||||
|
||||
void printHexagonMEMriOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO1 = MI->getOperand(OpNo);
|
||||
const MachineOperand &MO2 = MI->getOperand(OpNo+1);
|
||||
|
||||
O << getRegisterName(MO1.getReg())
|
||||
<< " + #"
|
||||
<< (int) MO2.getImm();
|
||||
}
|
||||
|
||||
|
||||
void printHexagonFrameIndexOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO1 = MI->getOperand(OpNo);
|
||||
const MachineOperand &MO2 = MI->getOperand(OpNo+1);
|
||||
|
||||
O << getRegisterName(MO1.getReg())
|
||||
<< ", #"
|
||||
<< MO2.getImm();
|
||||
}
|
||||
|
||||
void printBranchOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
// Branches can take an immediate operand. This is used by the branch
|
||||
// selection pass to print $+8, an eight byte displacement from the PC.
|
||||
if (MI->getOperand(OpNo).isImm()) {
|
||||
O << "$+" << MI->getOperand(OpNo).getImm()*4;
|
||||
} else {
|
||||
printOp(MI->getOperand(OpNo), O);
|
||||
}
|
||||
}
|
||||
|
||||
void printCallOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
}
|
||||
|
||||
void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
}
|
||||
|
||||
|
||||
void printSymbolHi(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
O << "#HI(";
|
||||
if (MI->getOperand(OpNo).isImm()) {
|
||||
printHexagonImmOperand(MI, OpNo, O);
|
||||
} else {
|
||||
printOp(MI->getOperand(OpNo), O);
|
||||
}
|
||||
O << ")";
|
||||
}
|
||||
|
||||
void printSymbolLo(const MachineInstr *MI, unsigned OpNo, raw_ostream &O) {
|
||||
O << "#HI(";
|
||||
if (MI->getOperand(OpNo).isImm()) {
|
||||
printHexagonImmOperand(MI, OpNo, O);
|
||||
} else {
|
||||
printOp(MI->getOperand(OpNo), O);
|
||||
}
|
||||
O << ")";
|
||||
}
|
||||
|
||||
void printPredicateOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
raw_ostream &O);
|
||||
|
||||
void printAddrModeBasePlusOffset(const MachineInstr *MI, int OpNo,
|
||||
raw_ostream &O);
|
||||
|
||||
void printGlobalOperand(const MachineInstr *MI, int OpNo, raw_ostream &O);
|
||||
void printJumpTable(const MachineInstr *MI, int OpNo, raw_ostream &O);
|
||||
|
||||
void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const;
|
||||
|
||||
static const char *getRegisterName(unsigned RegNo);
|
||||
};
|
||||
|
||||
} // end of anonymous namespace
|
||||
|
||||
// Include the auto-generated portion of the assembly writer.
|
||||
#include "HexagonGenAsmWriter.inc"
|
||||
|
||||
|
||||
void HexagonAsmPrinter::EmitAlignment(unsigned NumBits,
|
||||
const GlobalValue *GV) const {
|
||||
|
||||
// For basic block level alignment, use falign.
|
||||
if (!GV) {
|
||||
OutStreamer.EmitRawText(StringRef("\t.falign"));
|
||||
return;
|
||||
}
|
||||
|
||||
AsmPrinter::EmitAlignment(NumBits, GV);
|
||||
}
|
||||
|
||||
void HexagonAsmPrinter::printOp(const MachineOperand &MO, raw_ostream &O) {
|
||||
switch (MO.getType()) {
|
||||
case MachineOperand::MO_Immediate:
|
||||
dbgs() << "printOp() does not handle immediate values\n";
|
||||
abort();
|
||||
return;
|
||||
|
||||
case MachineOperand::MO_MachineBasicBlock:
|
||||
O << *MO.getMBB()->getSymbol();
|
||||
return;
|
||||
case MachineOperand::MO_JumpTableIndex:
|
||||
O << *GetJTISymbol(MO.getIndex());
|
||||
// FIXME: PIC relocation model.
|
||||
return;
|
||||
case MachineOperand::MO_ConstantPoolIndex:
|
||||
O << *GetCPISymbol(MO.getIndex());
|
||||
return;
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
O << *GetExternalSymbolSymbol(MO.getSymbolName());
|
||||
return;
|
||||
case MachineOperand::MO_GlobalAddress: {
|
||||
// Computing the address of a global symbol, not calling it.
|
||||
O << *Mang->getSymbol(MO.getGlobal());
|
||||
printOffset(MO.getOffset(), O);
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
O << "<unknown operand type: " << MO.getType() << ">";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// isBlockOnlyReachableByFallthrough - We need to override this since the
|
||||
// default AsmPrinter does not print labels for any basic block that
|
||||
// is only reachable by a fall through. That works for all cases except
|
||||
// for the case in which the basic block is reachable by a fall through but
|
||||
// through an indirect from a jump table. In this case, the jump table
|
||||
// will contain a label not defined by AsmPrinter.
|
||||
//
|
||||
bool HexagonAsmPrinter::
|
||||
isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
|
||||
if (MBB->hasAddressTaken()) {
|
||||
return false;
|
||||
}
|
||||
return AsmPrinter::isBlockOnlyReachableByFallthrough(MBB);
|
||||
}
|
||||
|
||||
|
||||
/// PrintAsmOperand - Print out an operand for an inline asm expression.
|
||||
///
|
||||
bool HexagonAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant,
|
||||
const char *ExtraCode,
|
||||
raw_ostream &OS) {
|
||||
// Does this asm operand have a single letter operand modifier?
|
||||
if (ExtraCode && ExtraCode[0]) {
|
||||
if (ExtraCode[1] != 0) return true; // Unknown modifier.
|
||||
|
||||
switch (ExtraCode[0]) {
|
||||
default: return true; // Unknown modifier.
|
||||
case 'c': // Don't print "$" before a global var name or constant.
|
||||
// Hexagon never has a prefix.
|
||||
printOperand(MI, OpNo, OS);
|
||||
return false;
|
||||
case 'L': // Write second word of DImode reference.
|
||||
// Verify that this operand has two consecutive registers.
|
||||
if (!MI->getOperand(OpNo).isReg() ||
|
||||
OpNo+1 == MI->getNumOperands() ||
|
||||
!MI->getOperand(OpNo+1).isReg())
|
||||
return true;
|
||||
++OpNo; // Return the high-part.
|
||||
break;
|
||||
case 'I':
|
||||
// Write 'i' if an integer constant, otherwise nothing. Used to print
|
||||
// addi vs add, etc.
|
||||
if (MI->getOperand(OpNo).isImm())
|
||||
OS << "i";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
printOperand(MI, OpNo, OS);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HexagonAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
|
||||
unsigned OpNo, unsigned AsmVariant,
|
||||
const char *ExtraCode,
|
||||
raw_ostream &O) {
|
||||
if (ExtraCode && ExtraCode[0])
|
||||
return true; // Unknown modifier.
|
||||
|
||||
const MachineOperand &Base = MI->getOperand(OpNo);
|
||||
const MachineOperand &Offset = MI->getOperand(OpNo+1);
|
||||
|
||||
if (Base.isReg())
|
||||
printOperand(MI, OpNo, O);
|
||||
else
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
if (Offset.isImm()) {
|
||||
if (Offset.getImm())
|
||||
O << " + #" << Offset.getImm();
|
||||
}
|
||||
else
|
||||
assert(0 && "Unimplemented");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void HexagonAsmPrinter::printPredicateOperand(const MachineInstr *MI,
|
||||
unsigned OpNo,
|
||||
raw_ostream &O) {
|
||||
assert(0 && "Unimplemented");
|
||||
}
|
||||
|
||||
|
||||
/// printMachineInstruction -- Print out a single Hexagon MI in Darwin syntax to
|
||||
/// the current output stream.
|
||||
///
|
||||
void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
SmallString<128> Str;
|
||||
raw_svector_ostream O(Str);
|
||||
|
||||
const MachineFunction* MF = MI->getParent()->getParent();
|
||||
const HexagonMachineFunctionInfo* MFI =
|
||||
(const HexagonMachineFunctionInfo*)
|
||||
MF->getInfo<HexagonMachineFunctionInfo>();
|
||||
|
||||
|
||||
|
||||
// Print a brace for the beginning of the packet.
|
||||
if (MFI->isStartPacket(MI)) {
|
||||
O << "\t{" << '\n';
|
||||
}
|
||||
|
||||
DEBUG( O << "// MI = " << *MI << '\n';);
|
||||
|
||||
// Indent
|
||||
O << "\t";
|
||||
|
||||
|
||||
if (MI->getOpcode() == Hexagon::ENDLOOP0) {
|
||||
if (MFI->isEndPacket(MI) && MFI->isStartPacket(MI)) {
|
||||
O << "\t{ nop }";
|
||||
} else {
|
||||
O << "}";
|
||||
}
|
||||
printInstruction(MI, O);
|
||||
} else if (MI->getOpcode() == Hexagon::STriwt) {
|
||||
//
|
||||
// Handle truncated store on Hexagon.
|
||||
//
|
||||
O << "\tmemw(";
|
||||
printHexagonMEMriOperand(MI, 0, O);
|
||||
|
||||
O << ") = ";
|
||||
unsigned SubRegNum =
|
||||
TM.getRegisterInfo()->getSubReg(MI->getOperand(2)
|
||||
.getReg(), Hexagon::subreg_loreg);
|
||||
const char *SubRegName = getRegisterName(SubRegNum);
|
||||
O << SubRegName << '\n';
|
||||
} else if (MI->getOpcode() == Hexagon::MPYI_rin) {
|
||||
// Handle multipy with -ve constant on Hexagon:
|
||||
// "$dst =- mpyi($src1, #$src2)"
|
||||
printOperand(MI, 0, O);
|
||||
O << " =- mpyi(";
|
||||
printOperand(MI, 1, O);
|
||||
O << ", #";
|
||||
printHexagonNegImmOperand(MI, 2, O);
|
||||
O << ")";
|
||||
} else if (MI->getOpcode() == Hexagon::MEMw_ADDSUBi_indexed_MEM_V4) {
|
||||
//
|
||||
// Handle memw(Rs+u6:2) [+-]= #U5
|
||||
//
|
||||
O << "\tmemw("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
|
||||
int addend = MI->getOperand(2).getImm();
|
||||
if (addend < 0)
|
||||
O << "-= " << "#" << -addend << '\n';
|
||||
else
|
||||
O << "+= " << "#" << addend << '\n';
|
||||
} else if (MI->getOpcode() == Hexagon::MEMw_ADDSUBi_MEM_V4) {
|
||||
//
|
||||
// Handle memw(Rs+u6:2) [+-]= #U5
|
||||
//
|
||||
O << "\tmemw("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
|
||||
int addend = MI->getOperand(2).getImm();
|
||||
if (addend < 0)
|
||||
O << "-= " << "#" << -addend << '\n';
|
||||
else
|
||||
O << "+= " << "#" << addend << '\n';
|
||||
} else if (MI->getOpcode() == Hexagon::MEMh_ADDSUBi_indexed_MEM_V4) {
|
||||
//
|
||||
// Handle memh(Rs+u6:1) [+-]= #U5
|
||||
//
|
||||
O << "\tmemh("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
|
||||
int addend = MI->getOperand(2).getImm();
|
||||
if (addend < 0)
|
||||
O << "-= " << "#" << -addend << '\n';
|
||||
else
|
||||
O << "+= " << "#" << addend << '\n';
|
||||
} else if (MI->getOpcode() == Hexagon::MEMh_ADDSUBi_MEM_V4) {
|
||||
//
|
||||
// Handle memh(Rs+u6:1) [+-]= #U5
|
||||
//
|
||||
O << "\tmemh("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
|
||||
int addend = MI->getOperand(2).getImm();
|
||||
if (addend < 0)
|
||||
O << "-= " << "#" << -addend << '\n';
|
||||
else
|
||||
O << "+= " << "#" << addend << '\n';
|
||||
} else if (MI->getOpcode() == Hexagon::MEMb_ADDSUBi_indexed_MEM_V4) {
|
||||
//
|
||||
// Handle memb(Rs+u6:1) [+-]= #U5
|
||||
//
|
||||
O << "\tmemb("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
|
||||
int addend = MI->getOperand(2).getImm();
|
||||
if (addend < 0)
|
||||
O << "-= " << "#" << -addend << '\n';
|
||||
else
|
||||
O << "+= " << "#" << addend << '\n';
|
||||
} else if (MI->getOpcode() == Hexagon::MEMb_ADDSUBi_MEM_V4) {
|
||||
//
|
||||
// Handle memb(Rs+u6:1) [+-]= #U5
|
||||
//
|
||||
O << "\tmemb("; printHexagonMEMriOperand(MI, 0, O); O << ") ";
|
||||
int addend = MI->getOperand(2).getImm();
|
||||
if (addend < 0)
|
||||
O << "-= " << "#" << -addend << '\n';
|
||||
else
|
||||
O << "+= " << "#" << addend << '\n';
|
||||
} else if (MI->getOpcode() == Hexagon::CMPbGTri_V4) {
|
||||
//
|
||||
// Handle Pd=cmpb.gt(Rs,#s8)
|
||||
//
|
||||
O << "\t";
|
||||
printRegister(MI->getOperand(0), false, O);
|
||||
O << " = cmpb.gt(";
|
||||
printRegister(MI->getOperand(1), false, O);
|
||||
O << ", ";
|
||||
int val = MI->getOperand(2).getImm() >> 24;
|
||||
O << "#" << val << ")" << '\n';
|
||||
} else if (MI->getOpcode() == Hexagon::CMPhEQri_V4) {
|
||||
//
|
||||
// Handle Pd=cmph.eq(Rs,#8)
|
||||
//
|
||||
O << "\t";
|
||||
printRegister(MI->getOperand(0), false, O);
|
||||
O << " = cmph.eq(";
|
||||
printRegister(MI->getOperand(1), false, O);
|
||||
O << ", ";
|
||||
int val = MI->getOperand(2).getImm();
|
||||
assert((((0 <= val) && (val <= 127)) ||
|
||||
((65408 <= val) && (val <= 65535))) &&
|
||||
"Not in correct range!");
|
||||
if (val >= 65408) val -= 65536;
|
||||
O << "#" << val << ")" << '\n';
|
||||
} else if (MI->getOpcode() == Hexagon::CMPhGTri_V4) {
|
||||
//
|
||||
// Handle Pd=cmph.gt(Rs,#8)
|
||||
//
|
||||
O << "\t";
|
||||
printRegister(MI->getOperand(0), false, O);
|
||||
O << " = cmph.gt(";
|
||||
printRegister(MI->getOperand(1), false, O);
|
||||
O << ", ";
|
||||
int val = MI->getOperand(2).getImm() >> 16;
|
||||
O << "#" << val << ")" << '\n';
|
||||
} else {
|
||||
printInstruction(MI, O);
|
||||
}
|
||||
|
||||
// Print a brace for the end of the packet.
|
||||
if (MFI->isEndPacket(MI) && MI->getOpcode() != Hexagon::ENDLOOP0) {
|
||||
O << "\n\t}" << '\n';
|
||||
}
|
||||
|
||||
if (AlignCalls && MI->getDesc().isCall()) {
|
||||
O << "\n\t.falign" << "\n";
|
||||
}
|
||||
|
||||
OutStreamer.EmitRawText(O.str());
|
||||
return;
|
||||
}
|
||||
|
||||
/// PrintUnmangledNameSafely - Print out the printable characters in the name.
|
||||
/// Don't print things like \n or \0.
|
||||
// static void PrintUnmangledNameSafely(const Value *V, raw_ostream &OS) {
|
||||
// for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
|
||||
// Name != E; ++Name)
|
||||
// if (isprint(*Name))
|
||||
// OS << *Name;
|
||||
// }
|
||||
|
||||
|
||||
void HexagonAsmPrinter::printAddrModeBasePlusOffset(const MachineInstr *MI,
|
||||
int OpNo, raw_ostream &O) {
|
||||
const MachineOperand &MO1 = MI->getOperand(OpNo);
|
||||
const MachineOperand &MO2 = MI->getOperand(OpNo+1);
|
||||
|
||||
O << getRegisterName(MO1.getReg())
|
||||
<< " + #"
|
||||
<< MO2.getImm();
|
||||
}
|
||||
|
||||
|
||||
void HexagonAsmPrinter::printGlobalOperand(const MachineInstr *MI, int OpNo,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
assert( (MO.getType() == MachineOperand::MO_GlobalAddress) &&
|
||||
"Expecting global address");
|
||||
|
||||
O << *Mang->getSymbol(MO.getGlobal());
|
||||
if (MO.getOffset() != 0) {
|
||||
O << " + ";
|
||||
O << MO.getOffset();
|
||||
}
|
||||
}
|
||||
|
||||
void HexagonAsmPrinter::printJumpTable(const MachineInstr *MI, int OpNo,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
assert( (MO.getType() == MachineOperand::MO_JumpTableIndex) &&
|
||||
"Expecting jump table index");
|
||||
|
||||
// Hexagon_TODO: Do we need name mangling?
|
||||
O << *GetJTISymbol(MO.getIndex());
|
||||
}
|
||||
|
||||
extern "C" void LLVMInitializeHexagonAsmPrinter() {
|
||||
RegisterAsmPrinter<HexagonAsmPrinter> X(TheHexagonTarget);
|
||||
}
|
240
lib/Target/Hexagon/HexagonCFGOptimizer.cpp
Normal file
240
lib/Target/Hexagon/HexagonCFGOptimizer.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
//===---- HexagonCFGOptimizer.cpp - CFG optimizations ---------------------===//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#define DEBUG_TYPE "hexagon_cfg"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include <iostream>
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class HexagonCFGOptimizer : public MachineFunctionPass {
|
||||
|
||||
private:
|
||||
HexagonTargetMachine& QTM;
|
||||
const HexagonSubtarget &QST;
|
||||
|
||||
void InvertAndChangeJumpTarget(MachineInstr*, MachineBasicBlock*);
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
HexagonCFGOptimizer(HexagonTargetMachine& TM) : MachineFunctionPass(ID),
|
||||
QTM(TM),
|
||||
QST(*TM.getSubtargetImpl()) {}
|
||||
|
||||
const char *getPassName() const {
|
||||
return "Hexagon CFG Optimizer";
|
||||
}
|
||||
bool runOnMachineFunction(MachineFunction &Fn);
|
||||
};
|
||||
|
||||
|
||||
char HexagonCFGOptimizer::ID = 0;
|
||||
|
||||
static bool IsConditionalBranch(int Opc) {
|
||||
return (Opc == Hexagon::JMP_Pred) || (Opc == Hexagon::JMP_PredNot)
|
||||
|| (Opc == Hexagon::JMP_PredPt) || (Opc == Hexagon::JMP_PredNotPt);
|
||||
}
|
||||
|
||||
|
||||
static bool IsUnconditionalJump(int Opc) {
|
||||
return (Opc == Hexagon::JMP);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HexagonCFGOptimizer::InvertAndChangeJumpTarget(MachineInstr* MI,
|
||||
MachineBasicBlock* NewTarget) {
|
||||
const HexagonInstrInfo *QII = QTM.getInstrInfo();
|
||||
int NewOpcode = 0;
|
||||
switch(MI->getOpcode()) {
|
||||
case Hexagon::JMP_Pred:
|
||||
NewOpcode = Hexagon::JMP_PredNot;
|
||||
break;
|
||||
|
||||
case Hexagon::JMP_PredNot:
|
||||
NewOpcode = Hexagon::JMP_Pred;
|
||||
break;
|
||||
|
||||
case Hexagon::JMP_PredPt:
|
||||
NewOpcode = Hexagon::JMP_PredNotPt;
|
||||
break;
|
||||
|
||||
case Hexagon::JMP_PredNotPt:
|
||||
NewOpcode = Hexagon::JMP_PredPt;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0 && "Cannot handle this case");
|
||||
}
|
||||
|
||||
MI->setDesc(QII->get(NewOpcode));
|
||||
MI->getOperand(1).setMBB(NewTarget);
|
||||
}
|
||||
|
||||
|
||||
bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) {
|
||||
|
||||
// Loop over all of the basic blocks.
|
||||
for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
|
||||
MBBb != MBBe; ++MBBb) {
|
||||
MachineBasicBlock* MBB = MBBb;
|
||||
|
||||
// Traverse the basic block.
|
||||
MachineBasicBlock::iterator MII = MBB->getFirstTerminator();
|
||||
if (MII != MBB->end()) {
|
||||
MachineInstr *MI = MII;
|
||||
int Opc = MI->getOpcode();
|
||||
if (IsConditionalBranch(Opc)) {
|
||||
|
||||
//
|
||||
// (Case 1) Transform the code if the following condition occurs:
|
||||
// BB1: if (p0) jump BB3
|
||||
// ...falls-through to BB2 ...
|
||||
// BB2: jump BB4
|
||||
// ...next block in layout is BB3...
|
||||
// BB3: ...
|
||||
//
|
||||
// Transform this to:
|
||||
// BB1: if (!p0) jump BB4
|
||||
// Remove BB2
|
||||
// BB3: ...
|
||||
//
|
||||
// (Case 2) A variation occurs when BB3 contains a JMP to BB4:
|
||||
// BB1: if (p0) jump BB3
|
||||
// ...falls-through to BB2 ...
|
||||
// BB2: jump BB4
|
||||
// ...other basic blocks ...
|
||||
// BB4:
|
||||
// ...not a fall-thru
|
||||
// BB3: ...
|
||||
// jump BB4
|
||||
//
|
||||
// Transform this to:
|
||||
// BB1: if (!p0) jump BB4
|
||||
// Remove BB2
|
||||
// BB3: ...
|
||||
// BB4: ...
|
||||
//
|
||||
unsigned NumSuccs = MBB->succ_size();
|
||||
MachineBasicBlock::succ_iterator SI = MBB->succ_begin();
|
||||
MachineBasicBlock* FirstSucc = *SI;
|
||||
MachineBasicBlock* SecondSucc = *(++SI);
|
||||
MachineBasicBlock* LayoutSucc = NULL;
|
||||
MachineBasicBlock* JumpAroundTarget = NULL;
|
||||
|
||||
if (MBB->isLayoutSuccessor(FirstSucc)) {
|
||||
LayoutSucc = FirstSucc;
|
||||
JumpAroundTarget = SecondSucc;
|
||||
} else if (MBB->isLayoutSuccessor(SecondSucc)) {
|
||||
LayoutSucc = SecondSucc;
|
||||
JumpAroundTarget = FirstSucc;
|
||||
} else {
|
||||
// Odd case...cannot handle.
|
||||
}
|
||||
|
||||
// The target of the unconditional branch must be JumpAroundTarget.
|
||||
// TODO: If not, we should not invert the unconditional branch.
|
||||
MachineBasicBlock* CondBranchTarget = NULL;
|
||||
if ((MI->getOpcode() == Hexagon::JMP_Pred) ||
|
||||
(MI->getOpcode() == Hexagon::JMP_PredNot)) {
|
||||
CondBranchTarget = MI->getOperand(1).getMBB();
|
||||
}
|
||||
|
||||
if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) {
|
||||
|
||||
// Ensure that BB2 has one instruction -- an unconditional jump.
|
||||
if ((LayoutSucc->size() == 1) &&
|
||||
IsUnconditionalJump(LayoutSucc->front().getOpcode())) {
|
||||
MachineBasicBlock* UncondTarget =
|
||||
LayoutSucc->front().getOperand(0).getMBB();
|
||||
// Check if the layout successor of BB2 is BB3.
|
||||
bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget);
|
||||
bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) &&
|
||||
JumpAroundTarget->size() >= 1 &&
|
||||
IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) &&
|
||||
JumpAroundTarget->pred_size() == 1 &&
|
||||
JumpAroundTarget->succ_size() == 1;
|
||||
|
||||
if (case1 || case2) {
|
||||
InvertAndChangeJumpTarget(MI, UncondTarget);
|
||||
MBB->removeSuccessor(JumpAroundTarget);
|
||||
MBB->addSuccessor(UncondTarget);
|
||||
|
||||
// Remove the unconditional branch in LayoutSucc.
|
||||
LayoutSucc->erase(LayoutSucc->begin());
|
||||
LayoutSucc->removeSuccessor(UncondTarget);
|
||||
LayoutSucc->addSuccessor(JumpAroundTarget);
|
||||
|
||||
// This code performs the conversion for case 2, which moves
|
||||
// the block to the fall-thru case (BB3 in the code above).
|
||||
if (case2 && !case1) {
|
||||
JumpAroundTarget->moveAfter(LayoutSucc);
|
||||
// only move a block if it doesn't have a fall-thru. otherwise
|
||||
// the CFG will be incorrect.
|
||||
if (!UncondTarget->canFallThrough()) {
|
||||
UncondTarget->moveAfter(JumpAroundTarget);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Correct live-in information. Is used by post-RA scheduler
|
||||
// The live-in to LayoutSucc is now all values live-in to
|
||||
// JumpAroundTarget.
|
||||
//
|
||||
std::vector<unsigned> OrigLiveIn(LayoutSucc->livein_begin(),
|
||||
LayoutSucc->livein_end());
|
||||
std::vector<unsigned> NewLiveIn(JumpAroundTarget->livein_begin(),
|
||||
JumpAroundTarget->livein_end());
|
||||
for (unsigned i = 0; i < OrigLiveIn.size(); ++i) {
|
||||
LayoutSucc->removeLiveIn(OrigLiveIn[i]);
|
||||
}
|
||||
for (unsigned i = 0; i < NewLiveIn.size(); ++i) {
|
||||
LayoutSucc->addLiveIn(NewLiveIn[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Public Constructor Functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
FunctionPass *llvm::createHexagonCFGOptimizer(HexagonTargetMachine &TM) {
|
||||
return new HexagonCFGOptimizer(TM);
|
||||
}
|
35
lib/Target/Hexagon/HexagonCallingConv.td
Normal file
35
lib/Target/Hexagon/HexagonCallingConv.td
Normal file
@ -0,0 +1,35 @@
|
||||
//===- HexagonCallingConv.td - Calling Conventions Hexagon -*- 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 the Hexagon architectures.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Return Value Calling Conventions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Hexagon 32-bit C return-value convention.
|
||||
def RetCC_Hexagon32 : CallingConv<[
|
||||
CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3, R4, R5]>>,
|
||||
CCIfType<[i64], CCAssignToReg<[D0, D1, D2]>>,
|
||||
|
||||
// Alternatively, they are assigned to the stack in 4-byte aligned units.
|
||||
CCAssignToStack<4, 4>
|
||||
]>;
|
||||
|
||||
// Hexagon 32-bit C Calling convention.
|
||||
def CC_Hexagon32 : CallingConv<[
|
||||
// All arguments get passed in integer registers if there is space.
|
||||
CCIfType<[i32, i16, i8], CCAssignToReg<[R0, R1, R2, R3, R4, R5]>>,
|
||||
CCIfType<[i64], CCAssignToReg<[D0, D1, D2]>>,
|
||||
|
||||
// Alternatively, they are assigned to the stack in 4-byte aligned units.
|
||||
CCAssignToStack<4, 4>
|
||||
]>;
|
207
lib/Target/Hexagon/HexagonCallingConvLower.cpp
Normal file
207
lib/Target/Hexagon/HexagonCallingConvLower.cpp
Normal file
@ -0,0 +1,207 @@
|
||||
//===-- llvm/CallingConvLower.cpp - Calling Convention lowering -----------===//
|
||||
//
|
||||
// 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 Hexagon_CCState class, used for lowering and
|
||||
// implementing calling conventions. Adapted from the machine independent
|
||||
// version of the class (CCState) but this handles calls to varargs functions
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonCallingConvLower.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "Hexagon.h"
|
||||
using namespace llvm;
|
||||
|
||||
Hexagon_CCState::Hexagon_CCState(CallingConv::ID CC, bool isVarArg,
|
||||
const TargetMachine &tm,
|
||||
SmallVector<CCValAssign, 16> &locs,
|
||||
LLVMContext &c)
|
||||
: CallingConv(CC), IsVarArg(isVarArg), TM(tm),
|
||||
TRI(*TM.getRegisterInfo()), Locs(locs), Context(c) {
|
||||
// No stack is used.
|
||||
StackOffset = 0;
|
||||
|
||||
UsedRegs.resize((TRI.getNumRegs()+31)/32);
|
||||
}
|
||||
|
||||
// HandleByVal - Allocate a stack slot large enough to pass an argument by
|
||||
// value. The size and alignment information of the argument is encoded in its
|
||||
// parameter attribute.
|
||||
void Hexagon_CCState::HandleByVal(unsigned ValNo, EVT ValVT,
|
||||
EVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||
int MinSize, int MinAlign,
|
||||
ISD::ArgFlagsTy ArgFlags) {
|
||||
unsigned Align = ArgFlags.getByValAlign();
|
||||
unsigned Size = ArgFlags.getByValSize();
|
||||
if (MinSize > (int)Size)
|
||||
Size = MinSize;
|
||||
if (MinAlign > (int)Align)
|
||||
Align = MinAlign;
|
||||
unsigned Offset = AllocateStack(Size, Align);
|
||||
|
||||
addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset,
|
||||
LocVT.getSimpleVT(), LocInfo));
|
||||
}
|
||||
|
||||
/// MarkAllocated - Mark a register and all of its aliases as allocated.
|
||||
void Hexagon_CCState::MarkAllocated(unsigned Reg) {
|
||||
UsedRegs[Reg/32] |= 1 << (Reg&31);
|
||||
|
||||
if (const unsigned *RegAliases = TRI.getAliasSet(Reg))
|
||||
for (; (Reg = *RegAliases); ++RegAliases)
|
||||
UsedRegs[Reg/32] |= 1 << (Reg&31);
|
||||
}
|
||||
|
||||
/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node,
|
||||
/// incorporating info about the formals into this state.
|
||||
void
|
||||
Hexagon_CCState::AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg>
|
||||
&Ins,
|
||||
Hexagon_CCAssignFn Fn,
|
||||
unsigned SretValueInRegs) {
|
||||
unsigned NumArgs = Ins.size();
|
||||
unsigned i = 0;
|
||||
|
||||
// If the function returns a small struct in registers, skip
|
||||
// over the first (dummy) argument.
|
||||
if (SretValueInRegs != 0) {
|
||||
++i;
|
||||
}
|
||||
|
||||
|
||||
for (; i != NumArgs; ++i) {
|
||||
EVT ArgVT = Ins[i].VT;
|
||||
ISD::ArgFlagsTy ArgFlags = Ins[i].Flags;
|
||||
if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, 0, 0, false)) {
|
||||
dbgs() << "Formal argument #" << i << " has unhandled type "
|
||||
<< ArgVT.getEVTString() << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// AnalyzeReturn - Analyze the returned values of an ISD::RET node,
|
||||
/// incorporating info about the result values into this state.
|
||||
void
|
||||
Hexagon_CCState::AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
Hexagon_CCAssignFn Fn,
|
||||
unsigned SretValueInRegs) {
|
||||
|
||||
// For Hexagon, Return small structures in registers.
|
||||
if (SretValueInRegs != 0) {
|
||||
if (SretValueInRegs <= 32) {
|
||||
unsigned Reg = Hexagon::R0;
|
||||
addLoc(CCValAssign::getReg(0, MVT::i32, Reg, MVT::i32,
|
||||
CCValAssign::Full));
|
||||
return;
|
||||
}
|
||||
if (SretValueInRegs <= 64) {
|
||||
unsigned Reg = Hexagon::D0;
|
||||
addLoc(CCValAssign::getReg(0, MVT::i64, Reg, MVT::i64,
|
||||
CCValAssign::Full));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Determine which register each value should be copied into.
|
||||
for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
|
||||
EVT VT = Outs[i].VT;
|
||||
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
|
||||
if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this, -1, -1, false)){
|
||||
dbgs() << "Return operand #" << i << " has unhandled type "
|
||||
<< VT.getEVTString() << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info
|
||||
/// about the passed values into this state.
|
||||
void
|
||||
Hexagon_CCState::AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg>
|
||||
&Outs,
|
||||
Hexagon_CCAssignFn Fn,
|
||||
int NonVarArgsParams,
|
||||
unsigned SretValueSize) {
|
||||
unsigned NumOps = Outs.size();
|
||||
|
||||
unsigned i = 0;
|
||||
// If the called function returns a small struct in registers, skip
|
||||
// the first actual parameter. We do not want to pass a pointer to
|
||||
// the stack location.
|
||||
if (SretValueSize != 0) {
|
||||
++i;
|
||||
}
|
||||
|
||||
for (; i != NumOps; ++i) {
|
||||
EVT ArgVT = Outs[i].VT;
|
||||
ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
|
||||
if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this,
|
||||
NonVarArgsParams, i+1, false)) {
|
||||
dbgs() << "Call operand #" << i << " has unhandled type "
|
||||
<< ArgVT.getEVTString() << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// AnalyzeCallOperands - Same as above except it takes vectors of types
|
||||
/// and argument flags.
|
||||
void
|
||||
Hexagon_CCState::AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs,
|
||||
SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
|
||||
Hexagon_CCAssignFn Fn) {
|
||||
unsigned NumOps = ArgVTs.size();
|
||||
for (unsigned i = 0; i != NumOps; ++i) {
|
||||
EVT ArgVT = ArgVTs[i];
|
||||
ISD::ArgFlagsTy ArgFlags = Flags[i];
|
||||
if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this, -1, -1,
|
||||
false)) {
|
||||
dbgs() << "Call operand #" << i << " has unhandled type "
|
||||
<< ArgVT.getEVTString() << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node,
|
||||
/// incorporating info about the passed values into this state.
|
||||
void
|
||||
Hexagon_CCState::AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
Hexagon_CCAssignFn Fn,
|
||||
unsigned SretValueInRegs) {
|
||||
|
||||
for (unsigned i = 0, e = Ins.size(); i != e; ++i) {
|
||||
EVT VT = Ins[i].VT;
|
||||
ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy();
|
||||
if (Fn(i, VT, VT, CCValAssign::Full, Flags, *this, -1, -1, false)) {
|
||||
dbgs() << "Call result #" << i << " has unhandled type "
|
||||
<< VT.getEVTString() << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// AnalyzeCallResult - Same as above except it's specialized for calls which
|
||||
/// produce a single value.
|
||||
void Hexagon_CCState::AnalyzeCallResult(EVT VT, Hexagon_CCAssignFn Fn) {
|
||||
if (Fn(0, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this, -1, -1,
|
||||
false)) {
|
||||
dbgs() << "Call result has unhandled type "
|
||||
<< VT.getEVTString() << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
189
lib/Target/Hexagon/HexagonCallingConvLower.h
Normal file
189
lib/Target/Hexagon/HexagonCallingConvLower.h
Normal file
@ -0,0 +1,189 @@
|
||||
//===-- HexagonCallingConvLower.h - Calling Conventions ---------*- 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 Hexagon_CCState class, used for lowering
|
||||
// and implementing calling conventions. Adapted from the target independent
|
||||
// version but this handles calls to varargs functions
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_Hexagon_CODEGEN_CALLINGCONVLOWER_H
|
||||
#define LLVM_Hexagon_CODEGEN_CALLINGCONVLOWER_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/CodeGen/ValueTypes.h"
|
||||
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
||||
#include "llvm/CodeGen/CallingConvLower.h"
|
||||
|
||||
//
|
||||
// Need to handle varargs.
|
||||
//
|
||||
namespace llvm {
|
||||
class TargetRegisterInfo;
|
||||
class TargetMachine;
|
||||
class Hexagon_CCState;
|
||||
class SDNode;
|
||||
|
||||
|
||||
/// Hexagon_CCAssignFn - This function assigns a location for Val, updating
|
||||
/// State to reflect the change.
|
||||
typedef bool Hexagon_CCAssignFn(unsigned ValNo, EVT ValVT,
|
||||
EVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||
ISD::ArgFlagsTy ArgFlags, Hexagon_CCState &State,
|
||||
int NonVarArgsParams,
|
||||
int CurrentParam,
|
||||
bool ForceMem);
|
||||
|
||||
|
||||
/// CCState - This class holds information needed while lowering arguments and
|
||||
/// return values. It captures which registers are already assigned and which
|
||||
/// stack slots are used. It provides accessors to allocate these values.
|
||||
class Hexagon_CCState {
|
||||
CallingConv::ID CallingConv;
|
||||
bool IsVarArg;
|
||||
const TargetMachine &TM;
|
||||
const TargetRegisterInfo &TRI;
|
||||
SmallVector<CCValAssign, 16> &Locs;
|
||||
LLVMContext &Context;
|
||||
|
||||
unsigned StackOffset;
|
||||
SmallVector<uint32_t, 16> UsedRegs;
|
||||
public:
|
||||
Hexagon_CCState(CallingConv::ID CC, bool isVarArg, const TargetMachine &TM,
|
||||
SmallVector<CCValAssign, 16> &locs, LLVMContext &c);
|
||||
|
||||
void addLoc(const CCValAssign &V) {
|
||||
Locs.push_back(V);
|
||||
}
|
||||
|
||||
LLVMContext &getContext() const { return Context; }
|
||||
const TargetMachine &getTarget() const { return TM; }
|
||||
unsigned getCallingConv() const { return CallingConv; }
|
||||
bool isVarArg() const { return IsVarArg; }
|
||||
|
||||
unsigned getNextStackOffset() const { return StackOffset; }
|
||||
|
||||
/// isAllocated - Return true if the specified register (or an alias) is
|
||||
/// allocated.
|
||||
bool isAllocated(unsigned Reg) const {
|
||||
return UsedRegs[Reg/32] & (1 << (Reg&31));
|
||||
}
|
||||
|
||||
/// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node,
|
||||
/// incorporating info about the formals into this state.
|
||||
void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
Hexagon_CCAssignFn Fn, unsigned SretValueInRegs);
|
||||
|
||||
/// AnalyzeReturn - Analyze the returned values of an ISD::RET node,
|
||||
/// incorporating info about the result values into this state.
|
||||
void AnalyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
Hexagon_CCAssignFn Fn, unsigned SretValueInRegs);
|
||||
|
||||
/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info
|
||||
/// about the passed values into this state.
|
||||
void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
Hexagon_CCAssignFn Fn, int NonVarArgsParams,
|
||||
unsigned SretValueSize);
|
||||
|
||||
/// AnalyzeCallOperands - Same as above except it takes vectors of types
|
||||
/// and argument flags.
|
||||
void AnalyzeCallOperands(SmallVectorImpl<EVT> &ArgVTs,
|
||||
SmallVectorImpl<ISD::ArgFlagsTy> &Flags,
|
||||
Hexagon_CCAssignFn Fn);
|
||||
|
||||
/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node,
|
||||
/// incorporating info about the passed values into this state.
|
||||
void AnalyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
Hexagon_CCAssignFn Fn, unsigned SretValueInRegs);
|
||||
|
||||
/// AnalyzeCallResult - Same as above except it's specialized for calls which
|
||||
/// produce a single value.
|
||||
void AnalyzeCallResult(EVT VT, Hexagon_CCAssignFn Fn);
|
||||
|
||||
/// getFirstUnallocated - Return the first unallocated register in the set, or
|
||||
/// NumRegs if they are all allocated.
|
||||
unsigned getFirstUnallocated(const unsigned *Regs, unsigned NumRegs) const {
|
||||
for (unsigned i = 0; i != NumRegs; ++i)
|
||||
if (!isAllocated(Regs[i]))
|
||||
return i;
|
||||
return NumRegs;
|
||||
}
|
||||
|
||||
/// AllocateReg - Attempt to allocate one register. If it is not available,
|
||||
/// return zero. Otherwise, return the register, marking it and any aliases
|
||||
/// as allocated.
|
||||
unsigned AllocateReg(unsigned Reg) {
|
||||
if (isAllocated(Reg)) return 0;
|
||||
MarkAllocated(Reg);
|
||||
return Reg;
|
||||
}
|
||||
|
||||
/// Version of AllocateReg with extra register to be shadowed.
|
||||
unsigned AllocateReg(unsigned Reg, unsigned ShadowReg) {
|
||||
if (isAllocated(Reg)) return 0;
|
||||
MarkAllocated(Reg);
|
||||
MarkAllocated(ShadowReg);
|
||||
return Reg;
|
||||
}
|
||||
|
||||
/// AllocateReg - Attempt to allocate one of the specified registers. If none
|
||||
/// are available, return zero. Otherwise, return the first one available,
|
||||
/// marking it and any aliases as allocated.
|
||||
unsigned AllocateReg(const unsigned *Regs, unsigned NumRegs) {
|
||||
unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
|
||||
if (FirstUnalloc == NumRegs)
|
||||
return 0; // Didn't find the reg.
|
||||
|
||||
// Mark the register and any aliases as allocated.
|
||||
unsigned Reg = Regs[FirstUnalloc];
|
||||
MarkAllocated(Reg);
|
||||
return Reg;
|
||||
}
|
||||
|
||||
/// Version of AllocateReg with list of registers to be shadowed.
|
||||
unsigned AllocateReg(const unsigned *Regs, const unsigned *ShadowRegs,
|
||||
unsigned NumRegs) {
|
||||
unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs);
|
||||
if (FirstUnalloc == NumRegs)
|
||||
return 0; // Didn't find the reg.
|
||||
|
||||
// Mark the register and any aliases as allocated.
|
||||
unsigned Reg = Regs[FirstUnalloc], ShadowReg = ShadowRegs[FirstUnalloc];
|
||||
MarkAllocated(Reg);
|
||||
MarkAllocated(ShadowReg);
|
||||
return Reg;
|
||||
}
|
||||
|
||||
/// AllocateStack - Allocate a chunk of stack space with the specified size
|
||||
/// and alignment.
|
||||
unsigned AllocateStack(unsigned Size, unsigned Align) {
|
||||
assert(Align && ((Align-1) & Align) == 0); // Align is power of 2.
|
||||
StackOffset = ((StackOffset + Align-1) & ~(Align-1));
|
||||
unsigned Result = StackOffset;
|
||||
StackOffset += Size;
|
||||
return Result;
|
||||
}
|
||||
|
||||
// HandleByVal - Allocate a stack slot large enough to pass an argument by
|
||||
// value. The size and alignment information of the argument is encoded in its
|
||||
// parameter attribute.
|
||||
void HandleByVal(unsigned ValNo, EVT ValVT,
|
||||
EVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||
int MinSize, int MinAlign, ISD::ArgFlagsTy ArgFlags);
|
||||
|
||||
private:
|
||||
/// MarkAllocated - Mark a register and all of its aliases as allocated.
|
||||
void MarkAllocated(unsigned Reg);
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
184
lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp
Normal file
184
lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
//===--- HexagonExpandPredSpillCode.cpp - Expand Predicate Spill Code ----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===////
|
||||
// The Hexagon processor has no instructions that load or store predicate
|
||||
// registers directly. So, when these registers must be spilled a general
|
||||
// purpose register must be found and the value copied to/from it from/to
|
||||
// the predicate register. This code currently does not use the register
|
||||
// scavenger mechanism available in the allocator. There are two registers
|
||||
// reserved to allow spilling/restoring predicate registers. One is used to
|
||||
// hold the predicate value. The other is used when stack frame offsets are
|
||||
// too large.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/LatencyPriorityQueue.h"
|
||||
#include "llvm/CodeGen/SchedulerRegistry.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
class HexagonExpandPredSpillCode : public MachineFunctionPass {
|
||||
HexagonTargetMachine& QTM;
|
||||
const HexagonSubtarget &QST;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
HexagonExpandPredSpillCode(HexagonTargetMachine& TM) :
|
||||
MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {}
|
||||
|
||||
const char *getPassName() const {
|
||||
return "Hexagon Expand Predicate Spill Code";
|
||||
}
|
||||
bool runOnMachineFunction(MachineFunction &Fn);
|
||||
};
|
||||
|
||||
|
||||
char HexagonExpandPredSpillCode::ID = 0;
|
||||
|
||||
|
||||
bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
|
||||
|
||||
const HexagonInstrInfo *TII = QTM.getInstrInfo();
|
||||
const HexagonRegisterInfo *RegInfo = QTM.getRegisterInfo();
|
||||
|
||||
// Loop over all of the basic blocks.
|
||||
for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
|
||||
MBBb != MBBe; ++MBBb) {
|
||||
MachineBasicBlock* MBB = MBBb;
|
||||
// Traverse the basic block.
|
||||
for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
|
||||
++MII) {
|
||||
MachineInstr *MI = MII;
|
||||
int Opc = MI->getOpcode();
|
||||
if (Opc == Hexagon::STriw_pred) {
|
||||
// STriw_pred [R30], ofst, SrcReg;
|
||||
unsigned FP = MI->getOperand(0).getReg();
|
||||
assert(FP == RegInfo->getFrameRegister() &&
|
||||
"Not a Frame Pointer, Nor a Spill Slot");
|
||||
assert(MI->getOperand(1).isImm() && "Not an offset");
|
||||
int Offset = MI->getOperand(1).getImm();
|
||||
int SrcReg = MI->getOperand(2).getReg();
|
||||
assert(Hexagon::PredRegsRegClass.contains(SrcReg) &&
|
||||
"Not a predicate register");
|
||||
if (!TII->isValidOffset(Hexagon::STriw, Offset)) {
|
||||
if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||
TII->get(Hexagon::CONST32_Int_Real),
|
||||
HEXAGON_RESERVED_REG_1).addImm(Offset);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr),
|
||||
HEXAGON_RESERVED_REG_1)
|
||||
.addReg(FP).addReg(HEXAGON_RESERVED_REG_1);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
||||
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||
TII->get(Hexagon::STriw))
|
||||
.addReg(HEXAGON_RESERVED_REG_1)
|
||||
.addImm(0).addReg(HEXAGON_RESERVED_REG_2);
|
||||
} else {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri),
|
||||
HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
||||
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw))
|
||||
.addReg(HEXAGON_RESERVED_REG_1)
|
||||
.addImm(0)
|
||||
.addReg(HEXAGON_RESERVED_REG_2);
|
||||
}
|
||||
} else {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
||||
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw)).
|
||||
addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2);
|
||||
}
|
||||
MII = MBB->erase(MI);
|
||||
--MII;
|
||||
} else if (Opc == Hexagon::LDriw_pred) {
|
||||
// DstReg = LDriw_pred [R30], ofst.
|
||||
int DstReg = MI->getOperand(0).getReg();
|
||||
assert(Hexagon::PredRegsRegClass.contains(DstReg) &&
|
||||
"Not a predicate register");
|
||||
unsigned FP = MI->getOperand(1).getReg();
|
||||
assert(FP == RegInfo->getFrameRegister() &&
|
||||
"Not a Frame Pointer, Nor a Spill Slot");
|
||||
assert(MI->getOperand(2).isImm() && "Not an offset");
|
||||
int Offset = MI->getOperand(2).getImm();
|
||||
if (!TII->isValidOffset(Hexagon::LDriw, Offset)) {
|
||||
if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||
TII->get(Hexagon::CONST32_Int_Real),
|
||||
HEXAGON_RESERVED_REG_1).addImm(Offset);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr),
|
||||
HEXAGON_RESERVED_REG_1)
|
||||
.addReg(FP)
|
||||
.addReg(HEXAGON_RESERVED_REG_1);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw),
|
||||
HEXAGON_RESERVED_REG_2)
|
||||
.addReg(HEXAGON_RESERVED_REG_1)
|
||||
.addImm(0);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs),
|
||||
DstReg).addReg(HEXAGON_RESERVED_REG_2);
|
||||
} else {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri),
|
||||
HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw),
|
||||
HEXAGON_RESERVED_REG_2)
|
||||
.addReg(HEXAGON_RESERVED_REG_1)
|
||||
.addImm(0);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs),
|
||||
DstReg).addReg(HEXAGON_RESERVED_REG_2);
|
||||
}
|
||||
} else {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw),
|
||||
HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs),
|
||||
DstReg).addReg(HEXAGON_RESERVED_REG_2);
|
||||
}
|
||||
MII = MBB->erase(MI);
|
||||
--MII;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Public Constructor Functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
FunctionPass *llvm::createHexagonExpandPredSpillCode(HexagonTargetMachine &TM) {
|
||||
return new HexagonExpandPredSpillCode(TM);
|
||||
}
|
333
lib/Target/Hexagon/HexagonFrameLowering.cpp
Normal file
333
lib/Target/Hexagon/HexagonFrameLowering.cpp
Normal file
@ -0,0 +1,333 @@
|
||||
//==-- HexagonFrameLowering.cpp - Define frame lowering --*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonInstrInfo.h"
|
||||
#include "HexagonRegisterInfo.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include "HexagonFrameLowering.h"
|
||||
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/MC/MachineLocation.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include <iostream>
|
||||
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/Function.h"
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool> DisableDeallocRet(
|
||||
"disable-hexagon-dealloc-ret",
|
||||
cl::Hidden,
|
||||
cl::desc("Disable Dealloc Return for Hexagon target"));
|
||||
|
||||
/// determineFrameLayout - Determine the size of the frame and maximum call
|
||||
/// frame size.
|
||||
void HexagonFrameLowering::determineFrameLayout(MachineFunction &MF) const {
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo.
|
||||
unsigned FrameSize = MFI->getStackSize();
|
||||
|
||||
// Get the alignments provided by the target.
|
||||
unsigned TargetAlign = MF.getTarget().getFrameLowering()->getStackAlignment();
|
||||
// Get the maximum call frame size of all the calls.
|
||||
unsigned maxCallFrameSize = MFI->getMaxCallFrameSize();
|
||||
|
||||
// If we have dynamic alloca then maxCallFrameSize needs to be aligned so
|
||||
// that allocations will be aligned.
|
||||
if (MFI->hasVarSizedObjects())
|
||||
maxCallFrameSize = RoundUpToAlignment(maxCallFrameSize, TargetAlign);
|
||||
|
||||
// Update maximum call frame size.
|
||||
MFI->setMaxCallFrameSize(maxCallFrameSize);
|
||||
|
||||
// Include call frame size in total.
|
||||
FrameSize += maxCallFrameSize;
|
||||
|
||||
// Make sure the frame is aligned.
|
||||
FrameSize = RoundUpToAlignment(FrameSize, TargetAlign);
|
||||
|
||||
// Update frame info.
|
||||
MFI->setStackSize(FrameSize);
|
||||
}
|
||||
|
||||
|
||||
void HexagonFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
MachineBasicBlock &MBB = MF.front();
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MachineModuleInfo &MMI = MF.getMMI();
|
||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
||||
const HexagonRegisterInfo *QRI =
|
||||
static_cast<const HexagonRegisterInfo *>(MF.getTarget().getRegisterInfo());
|
||||
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
||||
determineFrameLayout(MF);
|
||||
|
||||
// Check if frame moves are needed for EH.
|
||||
bool needsFrameMoves = MMI.hasDebugInfo() ||
|
||||
!MF.getFunction()->needsUnwindTableEntry();
|
||||
|
||||
// Get the number of bytes to allocate from the FrameInfo.
|
||||
int NumBytes = (int) MFI->getStackSize();
|
||||
|
||||
// LLVM expects allocframe not to be the first instruction in the
|
||||
// basic block.
|
||||
MachineBasicBlock::iterator InsertPt = MBB.begin();
|
||||
|
||||
//
|
||||
// ALLOCA adjust regs. Iterate over ADJDYNALLOC nodes and change the offset.
|
||||
//
|
||||
HexagonMachineFunctionInfo *FuncInfo =
|
||||
MF.getInfo<HexagonMachineFunctionInfo>();
|
||||
const std::vector<MachineInstr*>& AdjustRegs =
|
||||
FuncInfo->getAllocaAdjustInsts();
|
||||
for (std::vector<MachineInstr*>::const_iterator i = AdjustRegs.begin(),
|
||||
e = AdjustRegs.end();
|
||||
i != e; ++i) {
|
||||
MachineInstr* MI = *i;
|
||||
assert((MI->getOpcode() == Hexagon::ADJDYNALLOC) &&
|
||||
"Expected adjust alloca node");
|
||||
|
||||
MachineOperand& MO = MI->getOperand(2);
|
||||
assert(MO.isImm() && "Expected immediate");
|
||||
MO.setImm(MFI->getMaxCallFrameSize());
|
||||
}
|
||||
|
||||
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
|
||||
|
||||
if (needsFrameMoves) {
|
||||
// Advance CFA. DW_CFA_def_cfa
|
||||
unsigned FPReg = QRI->getFrameRegister();
|
||||
unsigned RAReg = QRI->getRARegister();
|
||||
|
||||
MachineLocation Dst(MachineLocation::VirtualFP);
|
||||
MachineLocation Src(FPReg, -8);
|
||||
Moves.push_back(MachineMove(0, Dst, Src));
|
||||
|
||||
// R31 = (R31 - #4)
|
||||
MachineLocation LRDst(RAReg, -4);
|
||||
MachineLocation LRSrc(RAReg);
|
||||
Moves.push_back(MachineMove(0, LRDst, LRSrc));
|
||||
|
||||
// R30 = (R30 - #8)
|
||||
MachineLocation SPDst(FPReg, -8);
|
||||
MachineLocation SPSrc(FPReg);
|
||||
Moves.push_back(MachineMove(0, SPDst, SPSrc));
|
||||
}
|
||||
|
||||
//
|
||||
// Only insert ALLOCFRAME if we need to.
|
||||
//
|
||||
if (hasFP(MF)) {
|
||||
// Check for overflow.
|
||||
// Hexagon_TODO: Ugh! hardcoding. Is there an API that can be used?
|
||||
const unsigned int ALLOCFRAME_MAX = 16384;
|
||||
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
||||
|
||||
if (NumBytes >= ALLOCFRAME_MAX) {
|
||||
// Emit allocframe(#0).
|
||||
BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(0);
|
||||
|
||||
// Subtract offset from frame pointer.
|
||||
BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::CONST32_Int_Real),
|
||||
HEXAGON_RESERVED_REG_1).addImm(NumBytes);
|
||||
BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::SUB_rr),
|
||||
QRI->getStackRegister()).
|
||||
addReg(QRI->getStackRegister()).
|
||||
addReg(HEXAGON_RESERVED_REG_1);
|
||||
} else {
|
||||
BuildMI(MBB, InsertPt, dl, TII.get(Hexagon::ALLOCFRAME)).addImm(NumBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Returns true if MBB has a machine instructions that indicates a tail call
|
||||
// in the block.
|
||||
bool HexagonFrameLowering::hasTailCall(MachineBasicBlock &MBB) const {
|
||||
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
||||
unsigned RetOpcode = MBBI->getOpcode();
|
||||
|
||||
return RetOpcode == Hexagon::TCRETURNtg || RetOpcode == Hexagon::TCRETURNtext;}
|
||||
|
||||
void HexagonFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB) const {
|
||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||
DebugLoc dl = MBBI->getDebugLoc();
|
||||
//
|
||||
// Only insert deallocframe if we need to.
|
||||
//
|
||||
if (hasFP(MF)) {
|
||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||
MachineBasicBlock::iterator MBBI_end = MBB.end();
|
||||
//
|
||||
// For Hexagon, we don't need the frame size.
|
||||
//
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
int NumBytes = (int) MFI->getStackSize();
|
||||
|
||||
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
||||
|
||||
// Replace 'jumpr r31' instruction with dealloc_return for V4 and higher
|
||||
// versions.
|
||||
if (STI.hasV4TOps() && MBBI->getOpcode() == Hexagon::JMPR
|
||||
&& !DisableDeallocRet) {
|
||||
// Remove jumpr node.
|
||||
MBB.erase(MBBI);
|
||||
// Add dealloc_return.
|
||||
BuildMI(MBB, MBBI_end, dl, TII.get(Hexagon::DEALLOC_RET_V4))
|
||||
.addImm(NumBytes);
|
||||
} else { // Add deallocframe for V2 and V3.
|
||||
BuildMI(MBB, MBBI, dl, TII.get(Hexagon::DEALLOCFRAME)).addImm(NumBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
const HexagonMachineFunctionInfo *FuncInfo =
|
||||
MF.getInfo<HexagonMachineFunctionInfo>();
|
||||
return (MFI->hasCalls() || (MFI->getStackSize() > 0) ||
|
||||
FuncInfo->hasClobberLR() );
|
||||
}
|
||||
|
||||
bool
|
||||
HexagonFrameLowering::spillCalleeSavedRegisters(
|
||||
MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
MachineFunction *MF = MBB.getParent();
|
||||
const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
|
||||
|
||||
if (CSI.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can only schedule double loads if we spill contiguous callee-saved regs
|
||||
// For instance, we cannot scheduled double-word loads if we spill r24,
|
||||
// r26, and r27.
|
||||
// Hexagon_TODO: We can try to double-word align odd registers for -O2 and
|
||||
// above.
|
||||
bool ContiguousRegs = true;
|
||||
|
||||
for (unsigned i = 0; i < CSI.size(); ++i) {
|
||||
unsigned Reg = CSI[i].getReg();
|
||||
|
||||
//
|
||||
// Check if we can use a double-word store.
|
||||
//
|
||||
const unsigned* SuperReg = TRI->getSuperRegisters(Reg);
|
||||
|
||||
// Assume that there is exactly one superreg.
|
||||
assert(SuperReg[0] && !SuperReg[1] && "Expected exactly one superreg");
|
||||
bool CanUseDblStore = false;
|
||||
const TargetRegisterClass* SuperRegClass = 0;
|
||||
|
||||
if (ContiguousRegs && (i < CSI.size()-1)) {
|
||||
const unsigned* SuperRegNext = TRI->getSuperRegisters(CSI[i+1].getReg());
|
||||
assert(SuperRegNext[0] && !SuperRegNext[1] &&
|
||||
"Expected exactly one superreg");
|
||||
SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg[0]);
|
||||
CanUseDblStore = (SuperRegNext[0] == SuperReg[0]);
|
||||
}
|
||||
|
||||
|
||||
if (CanUseDblStore) {
|
||||
TII.storeRegToStackSlot(MBB, MI, SuperReg[0], true,
|
||||
CSI[i+1].getFrameIdx(), SuperRegClass, TRI);
|
||||
MBB.addLiveIn(SuperReg[0]);
|
||||
++i;
|
||||
} else {
|
||||
// Cannot use a double-word store.
|
||||
ContiguousRegs = false;
|
||||
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
|
||||
TII.storeRegToStackSlot(MBB, MI, Reg, true, CSI[i].getFrameIdx(), RC,
|
||||
TRI);
|
||||
MBB.addLiveIn(Reg);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonFrameLowering::restoreCalleeSavedRegisters(
|
||||
MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
|
||||
MachineFunction *MF = MBB.getParent();
|
||||
const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
|
||||
|
||||
if (CSI.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can only schedule double loads if we spill contiguous callee-saved regs
|
||||
// For instance, we cannot scheduled double-word loads if we spill r24,
|
||||
// r26, and r27.
|
||||
// Hexagon_TODO: We can try to double-word align odd registers for -O2 and
|
||||
// above.
|
||||
bool ContiguousRegs = true;
|
||||
|
||||
for (unsigned i = 0; i < CSI.size(); ++i) {
|
||||
unsigned Reg = CSI[i].getReg();
|
||||
|
||||
//
|
||||
// Check if we can use a double-word load.
|
||||
//
|
||||
const unsigned* SuperReg = TRI->getSuperRegisters(Reg);
|
||||
const TargetRegisterClass* SuperRegClass = 0;
|
||||
|
||||
// Assume that there is exactly one superreg.
|
||||
assert(SuperReg[0] && !SuperReg[1] && "Expected exactly one superreg");
|
||||
bool CanUseDblLoad = false;
|
||||
if (ContiguousRegs && (i < CSI.size()-1)) {
|
||||
const unsigned* SuperRegNext = TRI->getSuperRegisters(CSI[i+1].getReg());
|
||||
assert(SuperRegNext[0] && !SuperRegNext[1] &&
|
||||
"Expected exactly one superreg");
|
||||
SuperRegClass = TRI->getMinimalPhysRegClass(SuperReg[0]);
|
||||
CanUseDblLoad = (SuperRegNext[0] == SuperReg[0]);
|
||||
}
|
||||
|
||||
|
||||
if (CanUseDblLoad) {
|
||||
TII.loadRegFromStackSlot(MBB, MI, SuperReg[0], CSI[i+1].getFrameIdx(),
|
||||
SuperRegClass, TRI);
|
||||
MBB.addLiveIn(SuperReg[0]);
|
||||
++i;
|
||||
} else {
|
||||
// Cannot use a double-word load.
|
||||
ContiguousRegs = false;
|
||||
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
|
||||
TII.loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RC, TRI);
|
||||
MBB.addLiveIn(Reg);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int HexagonFrameLowering::getFrameIndexOffset(const MachineFunction &MF,
|
||||
int FI) const {
|
||||
return MF.getFrameInfo()->getObjectOffset(FI);
|
||||
}
|
50
lib/Target/Hexagon/HexagonFrameLowering.h
Normal file
50
lib/Target/Hexagon/HexagonFrameLowering.h
Normal file
@ -0,0 +1,50 @@
|
||||
//=- HexagonFrameLowering.h - Define frame lowering for Hexagon --*- C++ -*--=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef HEXAGON_FRAMEINFO_H
|
||||
#define HEXAGON_FRAMEINFO_H
|
||||
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class HexagonFrameLowering : public TargetFrameLowering {
|
||||
private:
|
||||
const HexagonSubtarget &STI;
|
||||
void determineFrameLayout(MachineFunction &MF) const;
|
||||
|
||||
public:
|
||||
explicit HexagonFrameLowering(const HexagonSubtarget &sti)
|
||||
: TargetFrameLowering(StackGrowsDown, 8, 0), STI(sti) {
|
||||
}
|
||||
|
||||
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
|
||||
/// the function.
|
||||
void emitPrologue(MachineFunction &MF) const;
|
||||
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
||||
virtual bool
|
||||
spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const;
|
||||
virtual bool
|
||||
restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
const std::vector<CalleeSavedInfo> &CSI,
|
||||
const TargetRegisterInfo *TRI) const;
|
||||
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
|
||||
bool hasFP(const MachineFunction &MF) const;
|
||||
bool hasTailCall(MachineBasicBlock &MBB) const;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
644
lib/Target/Hexagon/HexagonHardwareLoops.cpp
Normal file
644
lib/Target/Hexagon/HexagonHardwareLoops.cpp
Normal file
@ -0,0 +1,644 @@
|
||||
//===-- HexagonHardwareLoops.cpp - Identify and generate hardware loops ---===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This pass identifies loops where we can generate the Hexagon hardware
|
||||
// loop instruction. The hardware loop can perform loop branches with a
|
||||
// zero-cycle overhead.
|
||||
//
|
||||
// The pattern that defines the induction variable can changed depending on
|
||||
// prior optimizations. For example, the IndVarSimplify phase run by 'opt'
|
||||
// normalizes induction variables, and the Loop Strength Reduction pass
|
||||
// run by 'llc' may also make changes to the induction variable.
|
||||
// The pattern detected by this phase is due to running Strength Reduction.
|
||||
//
|
||||
// Criteria for hardware loops:
|
||||
// - Countable loops (w/ ind. var for a trip count)
|
||||
// - Assumes loops are normalized by IndVarSimplify
|
||||
// - Try inner-most loops first
|
||||
// - No nested hardware loops.
|
||||
// - No function calls in loops.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "hwloops"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/PassSupport.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include <algorithm>
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(NumHWLoops, "Number of loops converted to hardware loops");
|
||||
|
||||
namespace {
|
||||
class CountValue;
|
||||
struct HexagonHardwareLoops : public MachineFunctionPass {
|
||||
MachineLoopInfo *MLI;
|
||||
MachineRegisterInfo *MRI;
|
||||
const TargetInstrInfo *TII;
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
|
||||
HexagonHardwareLoops() : MachineFunctionPass(ID) {}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
const char *getPassName() const { return "Hexagon Hardware Loops"; }
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
AU.addRequired<MachineDominatorTree>();
|
||||
AU.addPreserved<MachineDominatorTree>();
|
||||
AU.addRequired<MachineLoopInfo>();
|
||||
AU.addPreserved<MachineLoopInfo>();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
private:
|
||||
/// getCanonicalInductionVariable - Check to see if the loop has a canonical
|
||||
/// induction variable.
|
||||
/// Should be defined in MachineLoop. Based upon version in class Loop.
|
||||
const MachineInstr *getCanonicalInductionVariable(MachineLoop *L) const;
|
||||
|
||||
/// getTripCount - Return a loop-invariant LLVM register indicating the
|
||||
/// number of times the loop will be executed. If the trip-count cannot
|
||||
/// be determined, this return null.
|
||||
CountValue *getTripCount(MachineLoop *L) const;
|
||||
|
||||
/// isInductionOperation - Return true if the instruction matches the
|
||||
/// pattern for an opertion that defines an induction variable.
|
||||
bool isInductionOperation(const MachineInstr *MI, unsigned IVReg) const;
|
||||
|
||||
/// isInvalidOperation - Return true if the instruction is not valid within
|
||||
/// a hardware loop.
|
||||
bool isInvalidLoopOperation(const MachineInstr *MI) const;
|
||||
|
||||
/// containsInavlidInstruction - Return true if the loop contains an
|
||||
/// instruction that inhibits using the hardware loop.
|
||||
bool containsInvalidInstruction(MachineLoop *L) const;
|
||||
|
||||
/// converToHardwareLoop - Given a loop, check if we can convert it to a
|
||||
/// hardware loop. If so, then perform the conversion and return true.
|
||||
bool convertToHardwareLoop(MachineLoop *L);
|
||||
|
||||
};
|
||||
|
||||
char HexagonHardwareLoops::ID = 0;
|
||||
|
||||
|
||||
// CountValue class - Abstraction for a trip count of a loop. A
|
||||
// smaller vesrsion of the MachineOperand class without the concerns
|
||||
// of changing the operand representation.
|
||||
class CountValue {
|
||||
public:
|
||||
enum CountValueType {
|
||||
CV_Register,
|
||||
CV_Immediate
|
||||
};
|
||||
private:
|
||||
CountValueType Kind;
|
||||
union Values {
|
||||
unsigned RegNum;
|
||||
int64_t ImmVal;
|
||||
Values(unsigned r) : RegNum(r) {}
|
||||
Values(int64_t i) : ImmVal(i) {}
|
||||
} Contents;
|
||||
bool isNegative;
|
||||
|
||||
public:
|
||||
CountValue(unsigned r, bool neg) : Kind(CV_Register), Contents(r),
|
||||
isNegative(neg) {}
|
||||
explicit CountValue(int64_t i) : Kind(CV_Immediate), Contents(i),
|
||||
isNegative(i < 0) {}
|
||||
CountValueType getType() const { return Kind; }
|
||||
bool isReg() const { return Kind == CV_Register; }
|
||||
bool isImm() const { return Kind == CV_Immediate; }
|
||||
bool isNeg() const { return isNegative; }
|
||||
|
||||
unsigned getReg() const {
|
||||
assert(isReg() && "Wrong CountValue accessor");
|
||||
return Contents.RegNum;
|
||||
}
|
||||
void setReg(unsigned Val) {
|
||||
Contents.RegNum = Val;
|
||||
}
|
||||
int64_t getImm() const {
|
||||
assert(isImm() && "Wrong CountValue accessor");
|
||||
if (isNegative) {
|
||||
return -Contents.ImmVal;
|
||||
}
|
||||
return Contents.ImmVal;
|
||||
}
|
||||
void setImm(int64_t Val) {
|
||||
Contents.ImmVal = Val;
|
||||
}
|
||||
|
||||
void print(raw_ostream &OS, const TargetMachine *TM = 0) const {
|
||||
if (isReg()) { OS << PrintReg(getReg()); }
|
||||
if (isImm()) { OS << getImm(); }
|
||||
}
|
||||
};
|
||||
|
||||
struct HexagonFixupHwLoops : public MachineFunctionPass {
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid.
|
||||
|
||||
HexagonFixupHwLoops() : MachineFunctionPass(ID) {}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
const char *getPassName() const { return "Hexagon Hardware Loop Fixup"; }
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
private:
|
||||
/// Maximum distance between the loop instr and the basic block.
|
||||
/// Just an estimate.
|
||||
static const unsigned MAX_LOOP_DISTANCE = 200;
|
||||
|
||||
/// fixupLoopInstrs - Check the offset between each loop instruction and
|
||||
/// the loop basic block to determine if we can use the LOOP instruction
|
||||
/// or if we need to set the LC/SA registers explicitly.
|
||||
bool fixupLoopInstrs(MachineFunction &MF);
|
||||
|
||||
/// convertLoopInstr - Add the instruction to set the LC and SA registers
|
||||
/// explicitly.
|
||||
void convertLoopInstr(MachineFunction &MF,
|
||||
MachineBasicBlock::iterator &MII,
|
||||
RegScavenger &RS);
|
||||
|
||||
};
|
||||
|
||||
char HexagonFixupHwLoops::ID = 0;
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
|
||||
/// isHardwareLoop - Returns true if the instruction is a hardware loop
|
||||
/// instruction.
|
||||
static bool isHardwareLoop(const MachineInstr *MI) {
|
||||
return MI->getOpcode() == Hexagon::LOOP0_r ||
|
||||
MI->getOpcode() == Hexagon::LOOP0_i;
|
||||
}
|
||||
|
||||
/// isCompareEquals - Returns true if the instruction is a compare equals
|
||||
/// instruction with an immediate operand.
|
||||
static bool isCompareEqualsImm(const MachineInstr *MI) {
|
||||
return MI->getOpcode() == Hexagon::CMPEQri;
|
||||
}
|
||||
|
||||
|
||||
/// createHexagonHardwareLoops - Factory for creating
|
||||
/// the hardware loop phase.
|
||||
FunctionPass *llvm::createHexagonHardwareLoops() {
|
||||
return new HexagonHardwareLoops();
|
||||
}
|
||||
|
||||
|
||||
bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) {
|
||||
DEBUG(dbgs() << "********* Hexagon Hardware Loops *********\n");
|
||||
|
||||
bool Changed = false;
|
||||
|
||||
// get the loop information
|
||||
MLI = &getAnalysis<MachineLoopInfo>();
|
||||
// get the register information
|
||||
MRI = &MF.getRegInfo();
|
||||
// the target specific instructio info.
|
||||
TII = MF.getTarget().getInstrInfo();
|
||||
|
||||
for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end();
|
||||
I != E; ++I) {
|
||||
MachineLoop *L = *I;
|
||||
if (!L->getParentLoop()) {
|
||||
Changed |= convertToHardwareLoop(L);
|
||||
}
|
||||
}
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
/// getCanonicalInductionVariable - Check to see if the loop has a canonical
|
||||
/// induction variable. We check for a simple recurrence pattern - an
|
||||
/// integer recurrence that decrements by one each time through the loop and
|
||||
/// ends at zero. If so, return the phi node that corresponds to it.
|
||||
///
|
||||
/// Based upon the similar code in LoopInfo except this code is specific to
|
||||
/// the machine.
|
||||
/// This method assumes that the IndVarSimplify pass has been run by 'opt'.
|
||||
///
|
||||
const MachineInstr
|
||||
*HexagonHardwareLoops::getCanonicalInductionVariable(MachineLoop *L) const {
|
||||
MachineBasicBlock *TopMBB = L->getTopBlock();
|
||||
MachineBasicBlock::pred_iterator PI = TopMBB->pred_begin();
|
||||
assert(PI != TopMBB->pred_end() &&
|
||||
"Loop must have more than one incoming edge!");
|
||||
MachineBasicBlock *Backedge = *PI++;
|
||||
if (PI == TopMBB->pred_end()) return 0; // dead loop
|
||||
MachineBasicBlock *Incoming = *PI++;
|
||||
if (PI != TopMBB->pred_end()) return 0; // multiple backedges?
|
||||
|
||||
// make sure there is one incoming and one backedge and determine which
|
||||
// is which.
|
||||
if (L->contains(Incoming)) {
|
||||
if (L->contains(Backedge))
|
||||
return 0;
|
||||
std::swap(Incoming, Backedge);
|
||||
} else if (!L->contains(Backedge))
|
||||
return 0;
|
||||
|
||||
// Loop over all of the PHI nodes, looking for a canonical induction variable:
|
||||
// - The PHI node is "reg1 = PHI reg2, BB1, reg3, BB2".
|
||||
// - The recurrence comes from the backedge.
|
||||
// - the definition is an induction operatio.n
|
||||
for (MachineBasicBlock::iterator I = TopMBB->begin(), E = TopMBB->end();
|
||||
I != E && I->isPHI(); ++I) {
|
||||
const MachineInstr *MPhi = &*I;
|
||||
unsigned DefReg = MPhi->getOperand(0).getReg();
|
||||
for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) {
|
||||
// Check each operand for the value from the backedge.
|
||||
MachineBasicBlock *MBB = MPhi->getOperand(i+1).getMBB();
|
||||
if (L->contains(MBB)) { // operands comes from the backedge
|
||||
// Check if the definition is an induction operation.
|
||||
const MachineInstr *DI = MRI->getVRegDef(MPhi->getOperand(i).getReg());
|
||||
if (isInductionOperation(DI, DefReg)) {
|
||||
return MPhi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getTripCount - Return a loop-invariant LLVM value indicating the
|
||||
/// number of times the loop will be executed. The trip count can
|
||||
/// be either a register or a constant value. If the trip-count
|
||||
/// cannot be determined, this returns null.
|
||||
///
|
||||
/// We find the trip count from the phi instruction that defines the
|
||||
/// induction variable. We follow the links to the CMP instruction
|
||||
/// to get the trip count.
|
||||
///
|
||||
/// Based upon getTripCount in LoopInfo.
|
||||
///
|
||||
CountValue *HexagonHardwareLoops::getTripCount(MachineLoop *L) const {
|
||||
// Check that the loop has a induction variable.
|
||||
const MachineInstr *IV_Inst = getCanonicalInductionVariable(L);
|
||||
if (IV_Inst == 0) return 0;
|
||||
|
||||
// Canonical loops will end with a 'cmpeq_ri IV, Imm',
|
||||
// if Imm is 0, get the count from the PHI opnd
|
||||
// if Imm is -M, than M is the count
|
||||
// Otherwise, Imm is the count
|
||||
const MachineOperand *IV_Opnd;
|
||||
const MachineOperand *InitialValue;
|
||||
if (!L->contains(IV_Inst->getOperand(2).getMBB())) {
|
||||
InitialValue = &IV_Inst->getOperand(1);
|
||||
IV_Opnd = &IV_Inst->getOperand(3);
|
||||
} else {
|
||||
InitialValue = &IV_Inst->getOperand(3);
|
||||
IV_Opnd = &IV_Inst->getOperand(1);
|
||||
}
|
||||
|
||||
// Look for the cmp instruction to determine if we
|
||||
// can get a useful trip count. The trip count can
|
||||
// be either a register or an immediate. The location
|
||||
// of the value depends upon the type (reg or imm).
|
||||
while ((IV_Opnd = IV_Opnd->getNextOperandForReg())) {
|
||||
const MachineInstr *MI = IV_Opnd->getParent();
|
||||
if (L->contains(MI) && isCompareEqualsImm(MI)) {
|
||||
const MachineOperand &MO = MI->getOperand(2);
|
||||
assert(MO.isImm() && "IV Cmp Operand should be 0");
|
||||
int64_t ImmVal = MO.getImm();
|
||||
|
||||
const MachineInstr *IV_DefInstr = MRI->getVRegDef(IV_Opnd->getReg());
|
||||
assert(L->contains(IV_DefInstr->getParent()) &&
|
||||
"IV definition should occurs in loop");
|
||||
int64_t iv_value = IV_DefInstr->getOperand(2).getImm();
|
||||
|
||||
if (ImmVal == 0) {
|
||||
// Make sure the induction variable changes by one on each iteration.
|
||||
if (iv_value != 1 && iv_value != -1) {
|
||||
return 0;
|
||||
}
|
||||
return new CountValue(InitialValue->getReg(), iv_value > 0);
|
||||
} else {
|
||||
assert(InitialValue->isReg() && "Expecting register for init value");
|
||||
const MachineInstr *DefInstr = MRI->getVRegDef(InitialValue->getReg());
|
||||
if (DefInstr && DefInstr->getOpcode() == Hexagon::TFRI) {
|
||||
int64_t count = ImmVal - DefInstr->getOperand(1).getImm();
|
||||
if ((count % iv_value) != 0) {
|
||||
return 0;
|
||||
}
|
||||
return new CountValue(count/iv_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// isInductionOperation - return true if the operation is matches the
|
||||
/// pattern that defines an induction variable:
|
||||
/// add iv, c
|
||||
///
|
||||
bool
|
||||
HexagonHardwareLoops::isInductionOperation(const MachineInstr *MI,
|
||||
unsigned IVReg) const {
|
||||
return (MI->getOpcode() ==
|
||||
Hexagon::ADD_ri && MI->getOperand(1).getReg() == IVReg);
|
||||
}
|
||||
|
||||
/// isInvalidOperation - Return true if the operation is invalid within
|
||||
/// hardware loop.
|
||||
bool
|
||||
HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI) const {
|
||||
|
||||
// call is not allowed because the callee may use a hardware loop
|
||||
if (MI->getDesc().isCall()) {
|
||||
return true;
|
||||
}
|
||||
// do not allow nested hardware loops
|
||||
if (isHardwareLoop(MI)) {
|
||||
return true;
|
||||
}
|
||||
// check if the instruction defines a hardware loop register
|
||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
const MachineOperand &MO = MI->getOperand(i);
|
||||
if (MO.isReg() && MO.isDef() &&
|
||||
(MO.getReg() == Hexagon::LC0 || MO.getReg() == Hexagon::LC1 ||
|
||||
MO.getReg() == Hexagon::SA0 || MO.getReg() == Hexagon::SA0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// containsInvalidInstruction - Return true if the loop contains
|
||||
/// an instruction that inhibits the use of the hardware loop function.
|
||||
///
|
||||
bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L) const {
|
||||
const std::vector<MachineBasicBlock*> Blocks = L->getBlocks();
|
||||
for (unsigned i = 0, e = Blocks.size(); i != e; ++i) {
|
||||
MachineBasicBlock *MBB = Blocks[i];
|
||||
for (MachineBasicBlock::iterator
|
||||
MII = MBB->begin(), E = MBB->end(); MII != E; ++MII) {
|
||||
const MachineInstr *MI = &*MII;
|
||||
if (isInvalidLoopOperation(MI)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// converToHardwareLoop - check if the loop is a candidate for
|
||||
/// converting to a hardware loop. If so, then perform the
|
||||
/// transformation.
|
||||
///
|
||||
/// This function works on innermost loops first. A loop can
|
||||
/// be converted if it is a counting loop; either a register
|
||||
/// value or an immediate.
|
||||
///
|
||||
/// The code makes several assumptions about the representation
|
||||
/// of the loop in llvm.
|
||||
bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) {
|
||||
bool Changed = false;
|
||||
// Process nested loops first.
|
||||
for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I) {
|
||||
Changed |= convertToHardwareLoop(*I);
|
||||
}
|
||||
// If a nested loop has been converted, then we can't convert this loop.
|
||||
if (Changed) {
|
||||
return Changed;
|
||||
}
|
||||
// Are we able to determine the trip count for the loop?
|
||||
CountValue *TripCount = getTripCount(L);
|
||||
if (TripCount == 0) {
|
||||
return false;
|
||||
}
|
||||
// Does the loop contain any invalid instructions?
|
||||
if (containsInvalidInstruction(L)) {
|
||||
return false;
|
||||
}
|
||||
MachineBasicBlock *Preheader = L->getLoopPreheader();
|
||||
// No preheader means there's not place for the loop instr.
|
||||
if (Preheader == 0) {
|
||||
return false;
|
||||
}
|
||||
MachineBasicBlock::iterator InsertPos = Preheader->getFirstTerminator();
|
||||
|
||||
MachineBasicBlock *LastMBB = L->getExitingBlock();
|
||||
// Don't generate hw loop if the loop has more than one exit.
|
||||
if (LastMBB == 0) {
|
||||
return false;
|
||||
}
|
||||
MachineBasicBlock::iterator LastI = LastMBB->getFirstTerminator();
|
||||
|
||||
// Determine the loop start.
|
||||
MachineBasicBlock *LoopStart = L->getTopBlock();
|
||||
if (L->getLoopLatch() != LastMBB) {
|
||||
// When the exit and latch are not the same, use the latch block as the
|
||||
// start.
|
||||
// The loop start address is used only after the 1st iteration, and the loop
|
||||
// latch may contains instrs. that need to be executed after the 1st iter.
|
||||
LoopStart = L->getLoopLatch();
|
||||
// Make sure the latch is a successor of the exit, otherwise it won't work.
|
||||
if (!LastMBB->isSuccessor(LoopStart)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the loop to a hardware loop
|
||||
DEBUG(dbgs() << "Change to hardware loop at "; L->dump());
|
||||
|
||||
if (TripCount->isReg()) {
|
||||
// Create a copy of the loop count register.
|
||||
MachineFunction *MF = LastMBB->getParent();
|
||||
const TargetRegisterClass *RC =
|
||||
MF->getRegInfo().getRegClass(TripCount->getReg());
|
||||
unsigned CountReg = MF->getRegInfo().createVirtualRegister(RC);
|
||||
BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(),
|
||||
TII->get(TargetOpcode::COPY), CountReg).addReg(TripCount->getReg());
|
||||
if (TripCount->isNeg()) {
|
||||
unsigned CountReg1 = CountReg;
|
||||
CountReg = MF->getRegInfo().createVirtualRegister(RC);
|
||||
BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(),
|
||||
TII->get(Hexagon::NEG), CountReg).addReg(CountReg1);
|
||||
}
|
||||
|
||||
// Add the Loop instruction to the begining of the loop.
|
||||
BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(),
|
||||
TII->get(Hexagon::LOOP0_r)).addMBB(LoopStart).addReg(CountReg);
|
||||
} else {
|
||||
assert(TripCount->isImm() && "Expecting immedate vaule for trip count");
|
||||
// Add the Loop immediate instruction to the beginning of the loop.
|
||||
int64_t CountImm = TripCount->getImm();
|
||||
BuildMI(*Preheader, InsertPos, InsertPos->getDebugLoc(),
|
||||
TII->get(Hexagon::LOOP0_i)).addMBB(LoopStart).addImm(CountImm);
|
||||
}
|
||||
|
||||
// Make sure the loop start always has a reference in the CFG. We need to
|
||||
// create a BlockAddress operand to get this mechanism to work both the
|
||||
// MachineBasicBlock and BasicBlock objects need the flag set.
|
||||
LoopStart->setHasAddressTaken();
|
||||
// This line is needed to set the hasAddressTaken flag on the BasicBlock
|
||||
// object
|
||||
BlockAddress::get(const_cast<BasicBlock *>(LoopStart->getBasicBlock()));
|
||||
|
||||
// Replace the loop branch with an endloop instruction.
|
||||
DebugLoc dl = LastI->getDebugLoc();
|
||||
BuildMI(*LastMBB, LastI, dl, TII->get(Hexagon::ENDLOOP0)).addMBB(LoopStart);
|
||||
|
||||
// The loop ends with either:
|
||||
// - a conditional branch followed by an unconditional branch, or
|
||||
// - a conditional branch to the loop start.
|
||||
if (LastI->getOpcode() == Hexagon::JMP_Pred ||
|
||||
LastI->getOpcode() == Hexagon::JMP_PredNot) {
|
||||
// delete one and change/add an uncond. branch to out of the loop
|
||||
MachineBasicBlock *BranchTarget = LastI->getOperand(1).getMBB();
|
||||
LastI = LastMBB->erase(LastI);
|
||||
if (!L->contains(BranchTarget)) {
|
||||
if (LastI != LastMBB->end()) {
|
||||
TII->RemoveBranch(*LastMBB);
|
||||
}
|
||||
SmallVector<MachineOperand, 0> Cond;
|
||||
TII->InsertBranch(*LastMBB, BranchTarget, 0, Cond, dl);
|
||||
}
|
||||
} else {
|
||||
// Conditional branch to loop start; just delete it.
|
||||
LastMBB->erase(LastI);
|
||||
}
|
||||
delete TripCount;
|
||||
|
||||
++NumHWLoops;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// createHexagonFixupHwLoops - Factory for creating the hardware loop
|
||||
/// phase.
|
||||
FunctionPass *llvm::createHexagonFixupHwLoops() {
|
||||
return new HexagonFixupHwLoops();
|
||||
}
|
||||
|
||||
bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
|
||||
DEBUG(dbgs() << "****** Hexagon Hardware Loop Fixup ******\n");
|
||||
|
||||
bool Changed = fixupLoopInstrs(MF);
|
||||
return Changed;
|
||||
}
|
||||
|
||||
/// fixupLoopInsts - For Hexagon, if the loop label is to far from the
|
||||
/// loop instruction then we need to set the LC0 and SA0 registers
|
||||
/// explicitly instead of using LOOP(start,count). This function
|
||||
/// checks the distance, and generates register assignments if needed.
|
||||
///
|
||||
/// This function makes two passes over the basic blocks. The first
|
||||
/// pass computes the offset of the basic block from the start.
|
||||
/// The second pass checks all the loop instructions.
|
||||
bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
|
||||
|
||||
// Offset of the current instruction from the start.
|
||||
unsigned InstOffset = 0;
|
||||
// Map for each basic block to it's first instruction.
|
||||
DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset;
|
||||
|
||||
// First pass - compute the offset of each basic block.
|
||||
for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
|
||||
MBB != MBBe; ++MBB) {
|
||||
BlockToInstOffset[MBB] = InstOffset;
|
||||
InstOffset += (MBB->size() * 4);
|
||||
}
|
||||
|
||||
// Second pass - check each loop instruction to see if it needs to
|
||||
// be converted.
|
||||
InstOffset = 0;
|
||||
bool Changed = false;
|
||||
RegScavenger RS;
|
||||
|
||||
// Loop over all the basic blocks.
|
||||
for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
|
||||
MBB != MBBe; ++MBB) {
|
||||
InstOffset = BlockToInstOffset[MBB];
|
||||
RS.enterBasicBlock(MBB);
|
||||
|
||||
// Loop over all the instructions.
|
||||
MachineBasicBlock::iterator MIE = MBB->end();
|
||||
MachineBasicBlock::iterator MII = MBB->begin();
|
||||
while (MII != MIE) {
|
||||
if (isHardwareLoop(MII)) {
|
||||
RS.forward(MII);
|
||||
assert(MII->getOperand(0).isMBB() &&
|
||||
"Expect a basic block as loop operand");
|
||||
int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
|
||||
diff = (diff > 0 ? diff : -diff);
|
||||
if ((unsigned)diff > MAX_LOOP_DISTANCE) {
|
||||
// Convert to explicity setting LC0 and SA0.
|
||||
convertLoopInstr(MF, MII, RS);
|
||||
MII = MBB->erase(MII);
|
||||
Changed = true;
|
||||
} else {
|
||||
++MII;
|
||||
}
|
||||
} else {
|
||||
++MII;
|
||||
}
|
||||
InstOffset += 4;
|
||||
}
|
||||
}
|
||||
|
||||
return Changed;
|
||||
|
||||
}
|
||||
|
||||
/// convertLoopInstr - convert a loop instruction to a sequence of instructions
|
||||
/// that set the lc and sa register explicitly.
|
||||
void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF,
|
||||
MachineBasicBlock::iterator &MII,
|
||||
RegScavenger &RS) {
|
||||
const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
|
||||
MachineBasicBlock *MBB = MII->getParent();
|
||||
DebugLoc DL = MII->getDebugLoc();
|
||||
unsigned Scratch = RS.scavengeRegister(Hexagon::IntRegsRegisterClass, MII, 0);
|
||||
|
||||
// First, set the LC0 with the trip count.
|
||||
if (MII->getOperand(1).isReg()) {
|
||||
// Trip count is a register
|
||||
BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
|
||||
.addReg(MII->getOperand(1).getReg());
|
||||
} else {
|
||||
// Trip count is an immediate.
|
||||
BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch)
|
||||
.addImm(MII->getOperand(1).getImm());
|
||||
BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
|
||||
.addReg(Scratch);
|
||||
}
|
||||
// Then, set the SA0 with the loop start address.
|
||||
BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch)
|
||||
.addMBB(MII->getOperand(0).getMBB());
|
||||
BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0).addReg(Scratch);
|
||||
}
|
1495
lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
Normal file
1495
lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1503
lib/Target/Hexagon/HexagonISelLowering.cpp
Normal file
1503
lib/Target/Hexagon/HexagonISelLowering.cpp
Normal file
File diff suppressed because it is too large
Load Diff
162
lib/Target/Hexagon/HexagonISelLowering.h
Normal file
162
lib/Target/Hexagon/HexagonISelLowering.h
Normal file
@ -0,0 +1,162 @@
|
||||
//==-- HexagonISelLowering.h - Hexagon 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 Hexagon uses to lower LLVM code into a
|
||||
// selection DAG.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef Hexagon_ISELLOWERING_H
|
||||
#define Hexagon_ISELLOWERING_H
|
||||
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
#include "llvm/CallingConv.h"
|
||||
#include "llvm/CodeGen/CallingConvLower.h"
|
||||
#include "Hexagon.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace HexagonISD {
|
||||
enum {
|
||||
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
||||
|
||||
CONST32,
|
||||
CONST32_GP, // For marking data present in GP.
|
||||
SETCC,
|
||||
ADJDYNALLOC,
|
||||
ARGEXTEND,
|
||||
|
||||
CMPICC, // Compare two GPR operands, set icc.
|
||||
CMPFCC, // Compare two FP operands, set fcc.
|
||||
BRICC, // Branch to dest on icc condition
|
||||
BRFCC, // Branch to dest on fcc condition
|
||||
SELECT_ICC, // Select between two values using the current ICC flags.
|
||||
SELECT_FCC, // Select between two values using the current FCC flags.
|
||||
|
||||
Hi, Lo, // Hi/Lo operations, typically on a global address.
|
||||
|
||||
FTOI, // FP to Int within a FP register.
|
||||
ITOF, // Int to FP within a FP register.
|
||||
|
||||
CALL, // A call instruction.
|
||||
RET_FLAG, // Return with a flag operand.
|
||||
BR_JT, // Jump table.
|
||||
BARRIER, // Memory barrier.
|
||||
WrapperJT,
|
||||
TC_RETURN
|
||||
};
|
||||
}
|
||||
|
||||
class HexagonTargetLowering : public TargetLowering {
|
||||
int VarArgsFrameOffset; // Frame offset to start of varargs area.
|
||||
|
||||
bool CanReturnSmallStruct(const Function* CalleeFn,
|
||||
unsigned& RetSize) const;
|
||||
|
||||
public:
|
||||
HexagonTargetMachine &TM;
|
||||
explicit HexagonTargetLowering(HexagonTargetMachine &targetmachine);
|
||||
|
||||
/// IsEligibleForTailCallOptimization - Check whether the call is eligible
|
||||
/// for tail call optimization. Targets which want to do tail call
|
||||
/// optimization should implement this function.
|
||||
bool
|
||||
IsEligibleForTailCallOptimization(SDValue Callee,
|
||||
CallingConv::ID CalleeCC,
|
||||
bool isVarArg,
|
||||
bool isCalleeStructRet,
|
||||
bool isCallerStructRet,
|
||||
const
|
||||
SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
const SmallVectorImpl<SDValue> &OutVals,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
SelectionDAG& DAG) const;
|
||||
|
||||
virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const;
|
||||
virtual bool isTruncateFree(EVT VT1, EVT VT2) const;
|
||||
|
||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
virtual const char *getTargetNodeName(unsigned Opcode) const;
|
||||
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerEH_LABEL(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFormalArguments(SDValue Chain,
|
||||
CallingConv::ID CallConv, bool isVarArg,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
DebugLoc dl, SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &InVals) const;
|
||||
SDValue LowerGLOBALADDRESS(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
SDValue LowerCall(SDValue Chain, SDValue Callee,
|
||||
CallingConv::ID CallConv, bool isVarArg,
|
||||
bool &isTailCall,
|
||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
const SmallVectorImpl<SDValue> &OutVals,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
DebugLoc dl, SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &InVals) const;
|
||||
|
||||
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
|
||||
CallingConv::ID CallConv, bool isVarArg,
|
||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
||||
DebugLoc dl, SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &InVals,
|
||||
const SmallVectorImpl<SDValue> &OutVals,
|
||||
SDValue Callee) const;
|
||||
|
||||
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const;
|
||||
SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const;
|
||||
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
SDValue LowerReturn(SDValue Chain,
|
||||
CallingConv::ID CallConv, bool isVarArg,
|
||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
||||
const SmallVectorImpl<SDValue> &OutVals,
|
||||
DebugLoc dl, SelectionDAG &DAG) const;
|
||||
|
||||
virtual MachineBasicBlock
|
||||
*EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
MachineBasicBlock *BB) const;
|
||||
|
||||
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
||||
virtual EVT getSetCCResultType(EVT VT) const {
|
||||
return MVT::i1;
|
||||
}
|
||||
|
||||
virtual bool getPostIndexedAddressParts(SDNode *N, SDNode *Op,
|
||||
SDValue &Base, SDValue &Offset,
|
||||
ISD::MemIndexedMode &AM,
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
std::pair<unsigned, const TargetRegisterClass*>
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
EVT VT) const;
|
||||
|
||||
// Intrinsics
|
||||
virtual SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op,
|
||||
SelectionDAG &DAG) const;
|
||||
/// isLegalAddressingMode - Return true if the addressing mode represented
|
||||
/// by AM is legal for this target, for a load/store of the specified type.
|
||||
/// The type may be VoidTy, in which case only return true if the addressing
|
||||
/// mode is legal for a load/store of any legal type.
|
||||
/// TODO: Handle pre/postinc as well.
|
||||
virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const;
|
||||
|
||||
/// isLegalICmpImmediate - Return true if the specified immediate is legal
|
||||
/// icmp immediate, that is the target has icmp instructions which can
|
||||
/// compare a register against the immediate without having to materialize
|
||||
/// the immediate into a register.
|
||||
virtual bool isLegalICmpImmediate(int64_t Imm) const;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // Hexagon_ISELLOWERING_H
|
491
lib/Target/Hexagon/HexagonImmediates.td
Normal file
491
lib/Target/Hexagon/HexagonImmediates.td
Normal file
@ -0,0 +1,491 @@
|
||||
//=- HexagonImmediates.td - Hexagon immediate processing --*- tablegen -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illnois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// From IA64's InstrInfo file
|
||||
def s32Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s16Imm : Operand<i32> {
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s12Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s11Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s11_0Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s11_1Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s11_2Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s11_3Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s10Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s8Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s9Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s8Imm64 : Operand<i64> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s6Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s4Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s4_0Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s4_1Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s4_2Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def s4_3Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u64Imm : Operand<i64> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u32Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u16Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u16_0Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u16_1Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u16_2Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u11_3Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u10Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u9Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u8Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u7Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u6Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u6_0Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u6_1Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u6_2Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u6_3Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u5Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u4Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u3Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def u2Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def n8Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
def m6Imm : Operand<i32> {
|
||||
// For now, we use a generic print function for all operands.
|
||||
let PrintMethod = "printHexagonImmOperand";
|
||||
}
|
||||
|
||||
//
|
||||
// Immediate predicates
|
||||
//
|
||||
def s32ImmPred : PatLeaf<(i32 imm), [{
|
||||
// immS16 predicate - True if the immediate fits in a 16-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<32>(v);
|
||||
}]>;
|
||||
|
||||
def s32_24ImmPred : PatLeaf<(i32 imm), [{
|
||||
// s32_24ImmPred predicate - True if the immediate fits in a 32-bit sign
|
||||
// extended field that is a multiple of 0x1000000.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedInt<32,24>(v);
|
||||
}]>;
|
||||
|
||||
def s32_16s8ImmPred : PatLeaf<(i32 imm), [{
|
||||
// s32_16s8ImmPred predicate - True if the immediate fits in a 32-bit sign
|
||||
// extended field that is a multiple of 0x10000.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedInt<24,16>(v);
|
||||
}]>;
|
||||
|
||||
def s16ImmPred : PatLeaf<(i32 imm), [{
|
||||
// immS16 predicate - True if the immediate fits in a 16-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<16>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s13ImmPred : PatLeaf<(i32 imm), [{
|
||||
// immS13 predicate - True if the immediate fits in a 13-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<13>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s12ImmPred : PatLeaf<(i32 imm), [{
|
||||
// immS16 predicate - True if the immediate fits in a 16-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<12>(v);
|
||||
}]>;
|
||||
|
||||
def s11_0ImmPred : PatLeaf<(i32 imm), [{
|
||||
// immS16 predicate - True if the immediate fits in a 16-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<11>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s11_1ImmPred : PatLeaf<(i32 imm), [{
|
||||
// immS16 predicate - True if the immediate fits in a 16-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedInt<11,1>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s11_2ImmPred : PatLeaf<(i32 imm), [{
|
||||
// immS16 predicate - True if the immediate fits in a 16-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedInt<11,2>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s11_3ImmPred : PatLeaf<(i32 imm), [{
|
||||
// immS16 predicate - True if the immediate fits in a 16-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedInt<11,3>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s10ImmPred : PatLeaf<(i32 imm), [{
|
||||
// s10ImmPred predicate - True if the immediate fits in a 10-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<10>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s9ImmPred : PatLeaf<(i32 imm), [{
|
||||
// s9ImmPred predicate - True if the immediate fits in a 9-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<9>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s8ImmPred : PatLeaf<(i32 imm), [{
|
||||
// s8ImmPred predicate - True if the immediate fits in a 8-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<8>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s8Imm64Pred : PatLeaf<(i64 imm), [{
|
||||
// s8ImmPred predicate - True if the immediate fits in a 8-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<8>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s6ImmPred : PatLeaf<(i32 imm), [{
|
||||
// s6ImmPred predicate - True if the immediate fits in a 6-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<6>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s4_0ImmPred : PatLeaf<(i32 imm), [{
|
||||
// s4_0ImmPred predicate - True if the immediate fits in a 4-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<4>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s4_1ImmPred : PatLeaf<(i32 imm), [{
|
||||
// s4_1ImmPred predicate - True if the immediate fits in a 4-bit sign extended
|
||||
// field of 2.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedInt<4,1>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s4_2ImmPred : PatLeaf<(i32 imm), [{
|
||||
// s4_2ImmPred predicate - True if the immediate fits in a 4-bit sign extended
|
||||
// field that is a multiple of 4.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedInt<4,2>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def s4_3ImmPred : PatLeaf<(i32 imm), [{
|
||||
// s4_3ImmPred predicate - True if the immediate fits in a 4-bit sign extended
|
||||
// field that is a multiple of 8.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedInt<4,3>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def u64ImmPred : PatLeaf<(i64 imm), [{
|
||||
// immS16 predicate - True if the immediate fits in a 16-bit sign extended
|
||||
// field.
|
||||
// Adding "N ||" to supress gcc unused warning.
|
||||
return (N || true);
|
||||
}]>;
|
||||
|
||||
def u32ImmPred : PatLeaf<(i32 imm), [{
|
||||
// immS16 predicate - True if the immediate fits in a 16-bit sign extended
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<32>(v);
|
||||
}]>;
|
||||
|
||||
def u16ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u16ImmPred predicate - True if the immediate fits in a 16-bit unsigned
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<16>(v);
|
||||
}]>;
|
||||
|
||||
def u16_s8ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u16_s8ImmPred predicate - True if the immediate fits in a 16-bit sign
|
||||
// extended s8 field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedUInt<16,8>(v);
|
||||
}]>;
|
||||
|
||||
def u9ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u9ImmPred predicate - True if the immediate fits in a 9-bit unsigned
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<9>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def u8ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u8ImmPred predicate - True if the immediate fits in a 8-bit unsigned
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<8>(v);
|
||||
}]>;
|
||||
|
||||
def u7ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u7ImmPred predicate - True if the immediate fits in a 8-bit unsigned
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<7>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def u6ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u6ImmPred predicate - True if the immediate fits in a 6-bit unsigned
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<6>(v);
|
||||
}]>;
|
||||
|
||||
def u6_0ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u6_0ImmPred predicate - True if the immediate fits in a 6-bit unsigned
|
||||
// field. Same as u6ImmPred.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<6>(v);
|
||||
}]>;
|
||||
|
||||
def u6_1ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u6_1ImmPred predicate - True if the immediate fits in a 6-bit unsigned
|
||||
// field that is 1 bit alinged - multiple of 2.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedUInt<6,1>(v);
|
||||
}]>;
|
||||
|
||||
def u6_2ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u6_2ImmPred predicate - True if the immediate fits in a 6-bit unsigned
|
||||
// field that is 2 bits alinged - multiple of 4.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedUInt<6,2>(v);
|
||||
}]>;
|
||||
|
||||
def u6_3ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u6_3ImmPred predicate - True if the immediate fits in a 6-bit unsigned
|
||||
// field that is 3 bits alinged - multiple of 8.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isShiftedUInt<6,3>(v);
|
||||
}]>;
|
||||
|
||||
def u5ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u5ImmPred predicate - True if the immediate fits in a 5-bit unsigned
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<5>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def u3ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u3ImmPred predicate - True if the immediate fits in a 3-bit unsigned
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<3>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def u2ImmPred : PatLeaf<(i32 imm), [{
|
||||
// u2ImmPred predicate - True if the immediate fits in a 2-bit unsigned
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<2>(v);
|
||||
}]>;
|
||||
|
||||
|
||||
def u1ImmPred : PatLeaf<(i1 imm), [{
|
||||
// u1ImmPred predicate - True if the immediate fits in a 1-bit unsigned
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isUInt<1>(v);
|
||||
}]>;
|
||||
|
||||
def m6ImmPred : PatLeaf<(i32 imm), [{
|
||||
// m6ImmPred predicate - True if the immediate is negative and fits in
|
||||
// a 6-bit negative number.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return isInt<6>(v);
|
||||
}]>;
|
||||
|
||||
//InN means negative integers in [-(2^N - 1), 0]
|
||||
def n8ImmPred : PatLeaf<(i32 imm), [{
|
||||
// n8ImmPred predicate - True if the immediate fits in a 8-bit unsigned
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
return (-255 <= v && v <= 0);
|
||||
}]>;
|
242
lib/Target/Hexagon/HexagonInstrFormats.td
Normal file
242
lib/Target/Hexagon/HexagonInstrFormats.td
Normal file
@ -0,0 +1,242 @@
|
||||
//==- HexagonInstrFormats.td - Hexagon Instruction Formats --*- tablegen -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class InstHexagon<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr,
|
||||
InstrItinClass itin> : Instruction {
|
||||
field bits<32> Inst;
|
||||
|
||||
let Namespace = "Hexagon";
|
||||
|
||||
/* Commented out for Hexagon
|
||||
bits<2> op;
|
||||
let Inst{31-30} = op; */ // Top two bits are the 'op' field
|
||||
|
||||
dag OutOperandList = outs;
|
||||
dag InOperandList = ins;
|
||||
let AsmString = asmstr;
|
||||
let Pattern = pattern;
|
||||
let Constraints = cstr;
|
||||
let Itinerary = itin;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Intruction Classes Definitions +
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
// LD Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class LDInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", LD> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<13> imm13;
|
||||
}
|
||||
|
||||
// LD Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class LDInstPost<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, LD> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
bits<13> imm13;
|
||||
}
|
||||
|
||||
// ST Instruction Class in V2/V3 can take SLOT0 only.
|
||||
// ST Instruction Class in V4 can take SLOT0 & SLOT1.
|
||||
// Definition of the instruction class CHANGED from V2/V3 to V4.
|
||||
class STInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", ST> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<13> imm13;
|
||||
}
|
||||
|
||||
// ST Instruction Class in V2/V3 can take SLOT0 only.
|
||||
// ST Instruction Class in V4 can take SLOT0 & SLOT1.
|
||||
// Definition of the instruction class CHANGED from V2/V3 to V4.
|
||||
class STInstPost<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, ST> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
bits<13> imm13;
|
||||
}
|
||||
|
||||
// ALU32 Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class ALU32Type<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", ALU32> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
bits<16> imm16;
|
||||
bits<16> imm16_2;
|
||||
}
|
||||
|
||||
// ALU64 Instruction Class in V2/V3.
|
||||
// XTYPE Instruction Class in V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
// Name of the Instruction Class changed from ALU64 to XTYPE from V2/V3 to V4.
|
||||
class ALU64Type<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", ALU64> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
bits<16> imm16;
|
||||
bits<16> imm16_2;
|
||||
}
|
||||
|
||||
// M Instruction Class in V2/V3.
|
||||
// XTYPE Instruction Class in V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
// Name of the Instruction Class changed from M to XTYPE from V2/V3 to V4.
|
||||
class MInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", M> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
}
|
||||
|
||||
// M Instruction Class in V2/V3.
|
||||
// XTYPE Instruction Class in V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
// Name of the Instruction Class changed from M to XTYPE from V2/V3 to V4.
|
||||
class MInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, M> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
}
|
||||
|
||||
// S Instruction Class in V2/V3.
|
||||
// XTYPE Instruction Class in V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
// Name of the Instruction Class changed from S to XTYPE from V2/V3 to V4.
|
||||
class SInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
//: InstHexagon<outs, ins, asmstr, pattern, cstr, !if(V4T, XTYPE_V4, M)> {
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", S> {
|
||||
// : InstHexagon<outs, ins, asmstr, pattern, "", S> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
}
|
||||
|
||||
// S Instruction Class in V2/V3.
|
||||
// XTYPE Instruction Class in V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
// Name of the Instruction Class changed from S to XTYPE from V2/V3 to V4.
|
||||
class SInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, S> {
|
||||
// : InstHexagon<outs, ins, asmstr, pattern, cstr, S> {
|
||||
// : InstHexagon<outs, ins, asmstr, pattern, cstr, !if(V4T, XTYPE_V4, S)> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
}
|
||||
|
||||
// J Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class JType<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", J> {
|
||||
bits<16> imm16;
|
||||
}
|
||||
|
||||
// JR Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class JRType<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", JR> {
|
||||
bits<5> rs;
|
||||
bits<5> pu; // Predicate register
|
||||
}
|
||||
|
||||
// CR Instruction Class in V2/V3/V4.
|
||||
// Definition of the instruction class NOT CHANGED.
|
||||
class CRInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", CR> {
|
||||
bits<5> rs;
|
||||
bits<10> imm10;
|
||||
}
|
||||
|
||||
|
||||
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", PSEUDO>;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// Intruction Classes Definitions -
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
|
||||
//
|
||||
// ALU32 patterns
|
||||
//.
|
||||
class ALU32_rr<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: ALU32Type<outs, ins, asmstr, pattern> {
|
||||
}
|
||||
|
||||
class ALU32_ir<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: ALU32Type<outs, ins, asmstr, pattern> {
|
||||
let rt{0-4} = 0;
|
||||
}
|
||||
|
||||
class ALU32_ri<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: ALU32Type<outs, ins, asmstr, pattern> {
|
||||
let rt{0-4} = 0;
|
||||
}
|
||||
|
||||
class ALU32_ii<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: ALU32Type<outs, ins, asmstr, pattern> {
|
||||
let rt{0-4} = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// ALU64 patterns.
|
||||
//
|
||||
class ALU64_rr<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: ALU64Type<outs, ins, asmstr, pattern> {
|
||||
}
|
||||
|
||||
// J Type Instructions.
|
||||
class JInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: JType<outs, ins, asmstr, pattern> {
|
||||
}
|
||||
|
||||
// JR type Instructions.
|
||||
class JRInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: JRType<outs, ins, asmstr, pattern> {
|
||||
}
|
||||
|
||||
|
||||
// Post increment ST Instruction.
|
||||
class STInstPI<dag outs, dag ins, string asmstr, list<dag> pattern, string cstr>
|
||||
: STInstPost<outs, ins, asmstr, pattern, cstr> {
|
||||
let rt{0-4} = 0;
|
||||
}
|
||||
|
||||
// Post increment LD Instruction.
|
||||
class LDInstPI<dag outs, dag ins, string asmstr, list<dag> pattern, string cstr>
|
||||
: LDInstPost<outs, ins, asmstr, pattern, cstr> {
|
||||
let rt{0-4} = 0;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// V4 Instruction Format Definitions +
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "HexagonInstrFormatsV4.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// V4 Instruction Format Definitions +
|
||||
//===----------------------------------------------------------------------===//
|
46
lib/Target/Hexagon/HexagonInstrFormatsV4.td
Normal file
46
lib/Target/Hexagon/HexagonInstrFormatsV4.td
Normal file
@ -0,0 +1,46 @@
|
||||
//==- HexagonInstrFormats.td - Hexagon Instruction Formats --*- 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 Hexagon V4 instruction classes in TableGen format.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//
|
||||
// NV type instructions.
|
||||
//
|
||||
class NVInst_V4<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", NV_V4> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<13> imm13;
|
||||
}
|
||||
|
||||
// Definition of Post increment new value store.
|
||||
class NVInstPost_V4<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, NV_V4> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<5> rt;
|
||||
bits<13> imm13;
|
||||
}
|
||||
|
||||
// Post increment ST Instruction.
|
||||
class NVInstPI_V4<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||
string cstr>
|
||||
: NVInstPost_V4<outs, ins, asmstr, pattern, cstr> {
|
||||
let rt{0-4} = 0;
|
||||
}
|
||||
|
||||
class MEMInst_V4<dag outs, dag ins, string asmstr, list<dag> pattern>
|
||||
: InstHexagon<outs, ins, asmstr, pattern, "", MEM_V4> {
|
||||
bits<5> rd;
|
||||
bits<5> rs;
|
||||
bits<6> imm6;
|
||||
}
|
1460
lib/Target/Hexagon/HexagonInstrInfo.cpp
Normal file
1460
lib/Target/Hexagon/HexagonInstrInfo.cpp
Normal file
File diff suppressed because it is too large
Load Diff
166
lib/Target/Hexagon/HexagonInstrInfo.h
Normal file
166
lib/Target/Hexagon/HexagonInstrInfo.h
Normal file
@ -0,0 +1,166 @@
|
||||
//=- HexagonInstrInfo.h - Hexagon 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 Hexagon implementation of the TargetInstrInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef HexagonINSTRUCTIONINFO_H
|
||||
#define HexagonINSTRUCTIONINFO_H
|
||||
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetFrameLowering.h"
|
||||
#include "HexagonRegisterInfo.h"
|
||||
|
||||
|
||||
#define GET_INSTRINFO_HEADER
|
||||
#include "HexagonGenInstrInfo.inc"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class HexagonInstrInfo : public HexagonGenInstrInfo {
|
||||
const HexagonRegisterInfo RI;
|
||||
const HexagonSubtarget& Subtarget;
|
||||
public:
|
||||
explicit HexagonInstrInfo(HexagonSubtarget &ST);
|
||||
|
||||
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
|
||||
/// such, whenever a client has an instance of instruction info, it should
|
||||
/// always be able to get register info as well (through this method).
|
||||
///
|
||||
virtual const HexagonRegisterInfo &getRegisterInfo() const { return RI; }
|
||||
|
||||
/// isLoadFromStackSlot - 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.
|
||||
virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
|
||||
/// isStoreToStackSlot - 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.
|
||||
virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
|
||||
int &FrameIndex) const;
|
||||
|
||||
|
||||
virtual bool AnalyzeBranch(MachineBasicBlock &MBB,MachineBasicBlock *&TBB,
|
||||
MachineBasicBlock *&FBB,
|
||||
SmallVectorImpl<MachineOperand> &Cond,
|
||||
bool AllowModify) const;
|
||||
|
||||
virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const;
|
||||
|
||||
virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
||||
MachineBasicBlock *FBB,
|
||||
const SmallVectorImpl<MachineOperand> &Cond,
|
||||
DebugLoc DL) const;
|
||||
|
||||
virtual void copyPhysReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I, DebugLoc DL,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
bool KillSrc) const;
|
||||
|
||||
virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned SrcReg, bool isKill, int FrameIndex,
|
||||
const TargetRegisterClass *RC,
|
||||
const TargetRegisterInfo *TRI) const;
|
||||
|
||||
virtual void storeRegToAddr(MachineFunction &MF, unsigned SrcReg, bool isKill,
|
||||
SmallVectorImpl<MachineOperand> &Addr,
|
||||
const TargetRegisterClass *RC,
|
||||
SmallVectorImpl<MachineInstr*> &NewMIs) const;
|
||||
|
||||
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, int FrameIndex,
|
||||
const TargetRegisterClass *RC,
|
||||
const TargetRegisterInfo *TRI) const;
|
||||
|
||||
virtual void loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
|
||||
SmallVectorImpl<MachineOperand> &Addr,
|
||||
const TargetRegisterClass *RC,
|
||||
SmallVectorImpl<MachineInstr*> &NewMIs) const;
|
||||
|
||||
virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
|
||||
MachineInstr* MI,
|
||||
const SmallVectorImpl<unsigned> &Ops,
|
||||
int FrameIndex) const;
|
||||
|
||||
virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
|
||||
MachineInstr* MI,
|
||||
const SmallVectorImpl<unsigned> &Ops,
|
||||
MachineInstr* LoadMI) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned createVR(MachineFunction* MF, MVT VT) const;
|
||||
|
||||
virtual bool isPredicable(MachineInstr *MI) const;
|
||||
virtual bool
|
||||
PredicateInstruction(MachineInstr *MI,
|
||||
const SmallVectorImpl<MachineOperand> &Cond) const;
|
||||
|
||||
virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCyles,
|
||||
unsigned ExtraPredCycles,
|
||||
const BranchProbability &Probability) const;
|
||||
|
||||
virtual bool isProfitableToIfCvt(MachineBasicBlock &TMBB,
|
||||
unsigned NumTCycles, unsigned ExtraTCycles,
|
||||
MachineBasicBlock &FMBB,
|
||||
unsigned NumFCycles, unsigned ExtraFCycles,
|
||||
const BranchProbability &Probability) const;
|
||||
|
||||
virtual bool isPredicated(const MachineInstr *MI) const;
|
||||
virtual bool DefinesPredicate(MachineInstr *MI,
|
||||
std::vector<MachineOperand> &Pred) const;
|
||||
virtual bool
|
||||
SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
|
||||
const SmallVectorImpl<MachineOperand> &Pred2) const;
|
||||
|
||||
virtual bool
|
||||
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
|
||||
|
||||
virtual bool
|
||||
isProfitableToDupForIfCvt(MachineBasicBlock &MBB,unsigned NumCycles,
|
||||
const BranchProbability &Probability) const;
|
||||
|
||||
bool isValidOffset(const int Opcode, const int Offset) const;
|
||||
bool isValidAutoIncImm(const EVT VT, const int Offset) const;
|
||||
bool isMemOp(const MachineInstr *MI) const;
|
||||
bool isSpillPredRegOp(const MachineInstr *MI) const;
|
||||
bool isU6_3Immediate(const int value) const;
|
||||
bool isU6_2Immediate(const int value) const;
|
||||
bool isU6_1Immediate(const int value) const;
|
||||
bool isU6_0Immediate(const int value) const;
|
||||
bool isS4_3Immediate(const int value) const;
|
||||
bool isS4_2Immediate(const int value) const;
|
||||
bool isS4_1Immediate(const int value) const;
|
||||
bool isS4_0Immediate(const int value) const;
|
||||
bool isS12_Immediate(const int value) const;
|
||||
bool isU6_Immediate(const int value) const;
|
||||
bool isS8_Immediate(const int value) const;
|
||||
bool isS6_Immediate(const int value) const;
|
||||
|
||||
bool isConditionalALU32 (const MachineInstr* MI) const;
|
||||
bool isConditionalLoad (const MachineInstr* MI) const;
|
||||
bool isDeallocRet(const MachineInstr *MI) const;
|
||||
|
||||
private:
|
||||
int getMatchingCondBranchOpcode(int Opc, bool sense) const;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
3014
lib/Target/Hexagon/HexagonInstrInfo.td
Normal file
3014
lib/Target/Hexagon/HexagonInstrInfo.td
Normal file
File diff suppressed because it is too large
Load Diff
134
lib/Target/Hexagon/HexagonInstrInfoV3.td
Normal file
134
lib/Target/Hexagon/HexagonInstrInfoV3.td
Normal file
@ -0,0 +1,134 @@
|
||||
//=- HexagonInstrInfoV3.td - Target Desc. for Hexagon Target -*- 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 Hexagon V3 instructions in TableGen format.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// J +
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Call subroutine.
|
||||
let isCall = 1, neverHasSideEffects = 1,
|
||||
Defs = [D0, D1, D2, D3, D4, D5, D6, D7, R28, R31,
|
||||
P0, P1, P2, P3, LC0, LC1, SA0, SA1] in {
|
||||
def CALLv3 : JInst<(outs), (ins calltarget:$dst, variable_ops),
|
||||
"call $dst", []>, Requires<[HasV3T]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// J -
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// JR +
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Call subroutine from register.
|
||||
let isCall = 1, neverHasSideEffects = 1,
|
||||
Defs = [D0, D1, D2, D3, D4, D5, D6, D7, R28, R31,
|
||||
P0, P1, P2, P3, LC0, LC1, SA0, SA1] in {
|
||||
def CALLRv3 : JRInst<(outs), (ins IntRegs:$dst, variable_ops),
|
||||
"callr $dst",
|
||||
[]>, Requires<[HasV3TOnly]>;
|
||||
}
|
||||
|
||||
|
||||
// if(p?.new) jumpr:t r?
|
||||
let isReturn = 1, isTerminator = 1, isBarrier = 1,
|
||||
Defs = [PC], Uses = [R31] in {
|
||||
def JMPR_cPnewt: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2),
|
||||
"if ($src1.new) jumpr:t $src2",
|
||||
[]>, Requires<[HasV3T]>;
|
||||
}
|
||||
|
||||
// if (!p?.new) jumpr:t r?
|
||||
let isReturn = 1, isTerminator = 1, isBarrier = 1,
|
||||
Defs = [PC], Uses = [R31] in {
|
||||
def JMPR_cNotPnewt: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2),
|
||||
"if (!$src1.new) jumpr:t $src2",
|
||||
[]>, Requires<[HasV3T]>;
|
||||
}
|
||||
|
||||
// Not taken.
|
||||
// if(p?.new) jumpr:nt r?
|
||||
let isReturn = 1, isTerminator = 1, isBarrier = 1,
|
||||
Defs = [PC], Uses = [R31] in {
|
||||
def JMPR_cPnewNt: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2),
|
||||
"if ($src1.new) jumpr:nt $src2",
|
||||
[]>, Requires<[HasV3T]>;
|
||||
}
|
||||
|
||||
// if (!p?.new) jumpr:nt r?
|
||||
let isReturn = 1, isTerminator = 1, isBarrier = 1,
|
||||
Defs = [PC], Uses = [R31] in {
|
||||
def JMPR_cNotPnewNt: JRInst<(outs), (ins PredRegs:$src1, IntRegs:$src2),
|
||||
"if (!$src1.new) jumpr:nt $src2",
|
||||
[]>, Requires<[HasV3T]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// JR -
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ALU64/ALU +
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
let AddedComplexity = 200 in
|
||||
def MAXw_dd : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
|
||||
DoubleRegs:$src2),
|
||||
"$dst = max($src2, $src1)",
|
||||
[(set DoubleRegs:$dst, (select (i1 (setlt DoubleRegs:$src2,
|
||||
DoubleRegs:$src1)),
|
||||
DoubleRegs:$src1,
|
||||
DoubleRegs:$src2))]>,
|
||||
Requires<[HasV3T]>;
|
||||
|
||||
let AddedComplexity = 200 in
|
||||
def MINw_dd : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
|
||||
DoubleRegs:$src2),
|
||||
"$dst = min($src2, $src1)",
|
||||
[(set DoubleRegs:$dst, (select (i1 (setgt DoubleRegs:$src2,
|
||||
DoubleRegs:$src1)),
|
||||
DoubleRegs:$src1,
|
||||
DoubleRegs:$src2))]>,
|
||||
Requires<[HasV3T]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ALU64/ALU -
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
|
||||
|
||||
//def : Pat <(brcond (i1 (seteq IntRegs:$src1, 0)), bb:$offset),
|
||||
// (JMP_RegEzt IntRegs:$src1, bb:$offset)>, Requires<[HasV3T]>;
|
||||
|
||||
//def : Pat <(brcond (i1 (setne IntRegs:$src1, 0)), bb:$offset),
|
||||
// (JMP_RegNzt IntRegs:$src1, bb:$offset)>, Requires<[HasV3T]>;
|
||||
|
||||
//def : Pat <(brcond (i1 (setle IntRegs:$src1, 0)), bb:$offset),
|
||||
// (JMP_RegLezt IntRegs:$src1, bb:$offset)>, Requires<[HasV3T]>;
|
||||
|
||||
//def : Pat <(brcond (i1 (setge IntRegs:$src1, 0)), bb:$offset),
|
||||
// (JMP_RegGezt IntRegs:$src1, bb:$offset)>, Requires<[HasV3T]>;
|
||||
|
||||
//def : Pat <(brcond (i1 (setgt IntRegs:$src1, -1)), bb:$offset),
|
||||
// (JMP_RegGezt IntRegs:$src1, bb:$offset)>, Requires<[HasV3T]>;
|
||||
|
||||
|
||||
// Map call instruction
|
||||
def : Pat<(call IntRegs:$dst),
|
||||
(CALLRv3 IntRegs:$dst)>, Requires<[HasV3T]>;
|
||||
def : Pat<(call tglobaladdr:$dst),
|
||||
(CALLv3 tglobaladdr:$dst)>, Requires<[HasV3T]>;
|
||||
def : Pat<(call texternalsym:$dst),
|
||||
(CALLv3 texternalsym:$dst)>, Requires<[HasV3T]>;
|
3392
lib/Target/Hexagon/HexagonInstrInfoV4.td
Normal file
3392
lib/Target/Hexagon/HexagonInstrInfoV4.td
Normal file
File diff suppressed because it is too large
Load Diff
3462
lib/Target/Hexagon/HexagonIntrinsics.td
Normal file
3462
lib/Target/Hexagon/HexagonIntrinsics.td
Normal file
File diff suppressed because it is too large
Load Diff
29
lib/Target/Hexagon/HexagonIntrinsicsDerived.td
Normal file
29
lib/Target/Hexagon/HexagonIntrinsicsDerived.td
Normal file
@ -0,0 +1,29 @@
|
||||
//===-- HexagonIntrinsicsDerived.td - Derived intrinsics ---*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Multiply 64-bit and use lower result
|
||||
//
|
||||
// Optimized with intrinisics accumulates
|
||||
//
|
||||
def : Pat <(mul DoubleRegs:$src1, DoubleRegs:$src2),
|
||||
(COMBINE_rr
|
||||
(Hexagon_M2_maci
|
||||
(Hexagon_M2_maci (EXTRACT_SUBREG (MPYU64 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg),
|
||||
(EXTRACT_SUBREG DoubleRegs:$src2, subreg_loreg)),
|
||||
subreg_hireg),
|
||||
(EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg),
|
||||
(EXTRACT_SUBREG DoubleRegs:$src2, subreg_hireg)),
|
||||
(EXTRACT_SUBREG DoubleRegs:$src2, subreg_loreg),
|
||||
(EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg)),
|
||||
(EXTRACT_SUBREG (MPYU64 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg),
|
||||
(EXTRACT_SUBREG DoubleRegs:$src2, subreg_loreg)),
|
||||
subreg_loreg))>;
|
||||
|
||||
|
||||
|
50
lib/Target/Hexagon/HexagonIntrinsicsV3.td
Normal file
50
lib/Target/Hexagon/HexagonIntrinsicsV3.td
Normal file
@ -0,0 +1,50 @@
|
||||
//=- HexagonIntrinsicsV3.td - Target Description for Hexagon -*- 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 Hexagon V3 Compiler Intrinsics in TableGen format.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
|
||||
|
||||
// MTYPE / COMPLEX / Vector reduce complex multiply real or imaginary.
|
||||
def Hexagon_M2_vrcmpys_s1:
|
||||
di_MInst_disi_s1_sat <"vrcmpys", int_hexagon_M2_vrcmpys_s1>;
|
||||
def Hexagon_M2_vrcmpys_acc_s1:
|
||||
di_MInst_didisi_acc_s1_sat <"vrcmpys", int_hexagon_M2_vrcmpys_acc_s1>;
|
||||
def Hexagon_M2_vrcmpys_s1rp:
|
||||
si_MInst_disi_s1_rnd_sat <"vrcmpys", int_hexagon_M2_vrcmpys_s1rp>;
|
||||
|
||||
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* MTYPE/VB *
|
||||
*********************************************************************/
|
||||
|
||||
// MTYPE / VB / Vector reduce add unsigned bytes.
|
||||
def Hexagon_M2_vradduh:
|
||||
si_MInst_didi <"vradduh", int_hexagon_M2_vradduh>;
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* ALU64/ALU *
|
||||
*********************************************************************/
|
||||
|
||||
// ALU64 / ALU / Add.
|
||||
def Hexagon_A2_addsp:
|
||||
di_ALU64_sidi <"add", int_hexagon_A2_addsp>;
|
||||
def Hexagon_A2_addpsat:
|
||||
di_ALU64_didi <"add", int_hexagon_A2_addpsat>;
|
||||
|
||||
def Hexagon_A2_maxp:
|
||||
di_ALU64_didi <"max", int_hexagon_A2_maxp>;
|
||||
def Hexagon_A2_maxup:
|
||||
di_ALU64_didi <"maxu", int_hexagon_A2_maxup>;
|
369
lib/Target/Hexagon/HexagonIntrinsicsV4.td
Normal file
369
lib/Target/Hexagon/HexagonIntrinsicsV4.td
Normal file
@ -0,0 +1,369 @@
|
||||
//===- HexagonIntrinsicsV4.td - V4 Instruction intrinsics --*- tablegen -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This is populated based on the following specs:
|
||||
// Hexagon V4 Architecture Extensions
|
||||
// Application-Level Specification
|
||||
// 80-V9418-12 Rev. A
|
||||
// June 15, 2010
|
||||
|
||||
|
||||
//
|
||||
// ALU 32 types.
|
||||
//
|
||||
|
||||
class si_ALU32_sisi_not<string opc, Intrinsic IntID>
|
||||
: ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
|
||||
!strconcat("$dst = ", !strconcat(opc , "($src1, ~$src2)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>;
|
||||
|
||||
class di_ALU32_s8si<string opc, Intrinsic IntID>
|
||||
: ALU32_rr<(outs DoubleRegs:$dst), (ins s8Imm:$src1, IntRegs:$src2),
|
||||
!strconcat("$dst = ", !strconcat(opc , "(#$src1, $src2)")),
|
||||
[(set DoubleRegs:$dst, (IntID imm:$src1, IntRegs:$src2))]>;
|
||||
|
||||
class di_ALU32_sis8<string opc, Intrinsic IntID>
|
||||
: ALU32_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src1, s8Imm:$src2),
|
||||
!strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")),
|
||||
[(set DoubleRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>;
|
||||
|
||||
class qi_neg_ALU32_sisi<string opc, Intrinsic IntID>
|
||||
: ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
|
||||
!strconcat("$dst = !", !strconcat(opc , "($src1, $src2)")),
|
||||
[(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>;
|
||||
|
||||
class qi_neg_ALU32_sis10<string opc, Intrinsic IntID>
|
||||
: ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, s10Imm:$src2),
|
||||
!strconcat("$dst = !", !strconcat(opc , "($src1, #$src2)")),
|
||||
[(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>;
|
||||
|
||||
class qi_neg_ALU32_siu9<string opc, Intrinsic IntID>
|
||||
: ALU32_rr<(outs PredRegs:$dst), (ins IntRegs:$src1, u9Imm:$src2),
|
||||
!strconcat("$dst = !", !strconcat(opc , "($src1, #$src2)")),
|
||||
[(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>;
|
||||
|
||||
class si_neg_ALU32_sisi<string opc, Intrinsic IntID>
|
||||
: ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
|
||||
!strconcat("$dst = !", !strconcat(opc , "($src1, $src2)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>;
|
||||
|
||||
class si_neg_ALU32_sis8<string opc, Intrinsic IntID>
|
||||
: ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, s8Imm:$src2),
|
||||
!strconcat("$dst = !", !strconcat(opc , "($src1, #$src2)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>;
|
||||
|
||||
class si_ALU32_sis8<string opc, Intrinsic IntID>
|
||||
: ALU32_rr<(outs IntRegs:$dst), (ins IntRegs:$src1, s8Imm:$src2),
|
||||
!strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>;
|
||||
|
||||
|
||||
//
|
||||
// SInst Classes.
|
||||
//
|
||||
class qi_neg_SInst_qiqi<string opc, Intrinsic IntID>
|
||||
: SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
|
||||
!strconcat("$dst = !", !strconcat(opc , "($src1, $src2)")),
|
||||
[(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>;
|
||||
|
||||
class qi_SInst_qi_andqiqi_neg<string opc, Intrinsic IntID>
|
||||
: SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2,
|
||||
IntRegs:$src3),
|
||||
!strconcat("$dst = ", !strconcat(opc ,
|
||||
"($src1, and($src2, !$src3)")),
|
||||
[(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class qi_SInst_qi_andqiqi<string opc, Intrinsic IntID>
|
||||
: SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2,
|
||||
IntRegs:$src3),
|
||||
!strconcat("$dst = ", !strconcat(opc ,
|
||||
"($src1, and($src2, $src3)")),
|
||||
[(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class qi_SInst_qi_orqiqi_neg<string opc, Intrinsic IntID>
|
||||
: SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2,
|
||||
IntRegs:$src3),
|
||||
!strconcat("$dst = ", !strconcat(opc ,
|
||||
"($src1, or($src2, !$src3)")),
|
||||
[(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class qi_SInst_qi_orqiqi<string opc, Intrinsic IntID>
|
||||
: SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2,
|
||||
IntRegs:$src3),
|
||||
!strconcat("$dst = ", !strconcat(opc ,
|
||||
"($src1, or($src2, $src3)")),
|
||||
[(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class si_SInst_si_addsis6<string opc, Intrinsic IntID>
|
||||
: SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, s6Imm:$src3),
|
||||
!strconcat("$dst = ", !strconcat(opc ,
|
||||
"($src1, add($src2, #$src3)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2,
|
||||
imm:$src3))]>;
|
||||
|
||||
class si_SInst_si_subs6si<string opc, Intrinsic IntID>
|
||||
: SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, s6Imm:$src2, IntRegs:$src3),
|
||||
!strconcat("$dst = ", !strconcat(opc ,
|
||||
"($src1, sub(#$src2, $src3)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class di_ALU64_didi_neg<string opc, Intrinsic IntID>
|
||||
: ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2),
|
||||
!strconcat("$dst = ", !strconcat(opc , "($src1, ~$src2)")),
|
||||
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>;
|
||||
|
||||
class di_MInst_dididi_xacc<string opc, Intrinsic IntID>
|
||||
: MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1,
|
||||
DoubleRegs:$src2),
|
||||
!strconcat("$dst ^= ", !strconcat(opc , "($src1, $src2)")),
|
||||
[(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, DoubleRegs:$src1,
|
||||
DoubleRegs:$src2))],
|
||||
"$dst2 = $dst">;
|
||||
|
||||
class si_MInst_sisisi_and<string opc, Intrinsic IntID>
|
||||
: MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3),
|
||||
!strconcat("$dst &= ", !strconcat(opc , "($src2, $src3)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class si_MInst_sisisi_andn<string opc, Intrinsic IntID>
|
||||
: MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3),
|
||||
!strconcat("$dst &= ", !strconcat(opc , "($src2, ~$src3)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class si_SInst_sisis10_andi<string opc, Intrinsic IntID>
|
||||
: SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2, s10Imm:$src3),
|
||||
!strconcat("$dst = ", !strconcat(opc ,
|
||||
"($src1, and($src2, #$src3))")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2,
|
||||
imm:$src3))]>;
|
||||
|
||||
class si_MInst_sisisi_xor<string opc, Intrinsic IntID>
|
||||
: MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3),
|
||||
!strconcat("$dst ^= ", !strconcat(opc , "($src2, $src3)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class si_MInst_sisisi_xorn<string opc, Intrinsic IntID>
|
||||
: MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3),
|
||||
!strconcat("$dst ^= ", !strconcat(opc , "($src2, ~$src3)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class si_SInst_sisis10_or<string opc, Intrinsic IntID>
|
||||
: SInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2, s10Imm:$src3),
|
||||
!strconcat("$dst |= ", !strconcat(opc , "($src2, #$src3)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2,
|
||||
imm:$src3))]>;
|
||||
|
||||
class si_MInst_sisisi_or<string opc, Intrinsic IntID>
|
||||
: MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3),
|
||||
!strconcat("$dst |= ", !strconcat(opc , "($src2, $src3)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class si_MInst_sisisi_orn<string opc, Intrinsic IntID>
|
||||
: MInst<(outs IntRegs:$dst), (ins IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3),
|
||||
!strconcat("$dst |= ", !strconcat(opc , "($src2, ~$src3)")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$dst1, IntRegs:$src2,
|
||||
IntRegs:$src3))]>;
|
||||
|
||||
class si_SInst_siu5_sat<string opc, Intrinsic IntID>
|
||||
: SInst<(outs IntRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
|
||||
!strconcat("$dst = ", !strconcat(opc , "($src1, #$src2):sat")),
|
||||
[(set IntRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>;
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* ALU32/ALU *
|
||||
*********************************************************************/
|
||||
|
||||
// ALU32 / ALU / Logical Operations.
|
||||
def Hexagon_A4_orn : si_ALU32_sisi_not <"or", int_hexagon_A4_orn>;
|
||||
def Hexagon_A4_andn : si_ALU32_sisi_not <"and", int_hexagon_A4_andn>;
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* ALU32/PERM *
|
||||
*********************************************************************/
|
||||
|
||||
// ALU32 / PERM / Combine Words Into Doublewords.
|
||||
def Hexagon_A4_combineir : di_ALU32_s8si <"combine", int_hexagon_A4_combineir>;
|
||||
def Hexagon_A4_combineri : di_ALU32_sis8 <"combine", int_hexagon_A4_combineri>;
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* ALU32/PRED *
|
||||
*********************************************************************/
|
||||
|
||||
// ALU32 / PRED / Conditional Shift Halfword.
|
||||
// ALU32 / PRED / Conditional Sign Extend.
|
||||
// ALU32 / PRED / Conditional Zero Extend.
|
||||
// ALU32 / PRED / Compare.
|
||||
def Hexagon_C4_cmpneq : qi_neg_ALU32_sisi <"cmp.eq", int_hexagon_C4_cmpneq>;
|
||||
def Hexagon_C4_cmpneqi : qi_neg_ALU32_sis10 <"cmp.eq", int_hexagon_C4_cmpneqi>;
|
||||
def Hexagon_C4_cmplte : qi_neg_ALU32_sisi <"cmp.gt", int_hexagon_C4_cmplte>;
|
||||
def Hexagon_C4_cmpltei : qi_neg_ALU32_sis10 <"cmp.gt", int_hexagon_C4_cmpltei>;
|
||||
def Hexagon_C4_cmplteu : qi_neg_ALU32_sisi <"cmp.gtu",int_hexagon_C4_cmplteu>;
|
||||
def Hexagon_C4_cmplteui: qi_neg_ALU32_siu9 <"cmp.gtu",int_hexagon_C4_cmplteui>;
|
||||
|
||||
// ALU32 / PRED / cmpare To General Register.
|
||||
def Hexagon_A4_rcmpneq : si_neg_ALU32_sisi <"cmp.eq", int_hexagon_A4_rcmpneq>;
|
||||
def Hexagon_A4_rcmpneqi: si_neg_ALU32_sis8 <"cmp.eq", int_hexagon_A4_rcmpneqi>;
|
||||
def Hexagon_A4_rcmpeq : si_ALU32_sisi <"cmp.eq", int_hexagon_A4_rcmpeq>;
|
||||
def Hexagon_A4_rcmpeqi : si_ALU32_sis8 <"cmp.eq", int_hexagon_A4_rcmpeqi>;
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* CR *
|
||||
*********************************************************************/
|
||||
|
||||
// CR / Corner Detection Acceleration.
|
||||
def Hexagon_C4_fastcorner9:
|
||||
qi_SInst_qiqi<"fastcorner9", int_hexagon_C4_fastcorner9>;
|
||||
def Hexagon_C4_fastcorner9_not:
|
||||
qi_neg_SInst_qiqi<"fastcorner9",int_hexagon_C4_fastcorner9_not>;
|
||||
|
||||
// CR / Logical Operations On Predicates.
|
||||
def Hexagon_C4_and_andn:
|
||||
qi_SInst_qi_andqiqi_neg <"and", int_hexagon_C4_and_andn>;
|
||||
def Hexagon_C4_and_and:
|
||||
qi_SInst_qi_andqiqi <"and", int_hexagon_C4_and_and>;
|
||||
def Hexagon_C4_and_orn:
|
||||
qi_SInst_qi_orqiqi_neg <"and", int_hexagon_C4_and_orn>;
|
||||
def Hexagon_C4_and_or:
|
||||
qi_SInst_qi_orqiqi <"and", int_hexagon_C4_and_or>;
|
||||
def Hexagon_C4_or_andn:
|
||||
qi_SInst_qi_andqiqi_neg <"or", int_hexagon_C4_or_andn>;
|
||||
def Hexagon_C4_or_and:
|
||||
qi_SInst_qi_andqiqi <"or", int_hexagon_C4_or_and>;
|
||||
def Hexagon_C4_or_orn:
|
||||
qi_SInst_qi_orqiqi_neg <"or", int_hexagon_C4_or_orn>;
|
||||
def Hexagon_C4_or_or:
|
||||
qi_SInst_qi_orqiqi <"or", int_hexagon_C4_or_or>;
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* XTYPE/ALU *
|
||||
*********************************************************************/
|
||||
|
||||
// XTYPE / ALU / Add And Accumulate.
|
||||
def Hexagon_S4_addaddi:
|
||||
si_SInst_si_addsis6 <"add", int_hexagon_S4_addaddi>;
|
||||
def Hexagon_S4_subaddi:
|
||||
si_SInst_si_subs6si <"add", int_hexagon_S4_subaddi>;
|
||||
|
||||
// XTYPE / ALU / Logical Doublewords.
|
||||
def Hexagon_S4_andnp:
|
||||
di_ALU64_didi_neg <"and", int_hexagon_A4_andnp>;
|
||||
def Hexagon_S4_ornp:
|
||||
di_ALU64_didi_neg <"or", int_hexagon_A4_ornp>;
|
||||
|
||||
// XTYPE / ALU / Logical-logical Doublewords.
|
||||
def Hexagon_M4_xor_xacc:
|
||||
di_MInst_dididi_xacc <"xor", int_hexagon_M4_xor_xacc>;
|
||||
|
||||
// XTYPE / ALU / Logical-logical Words.
|
||||
def HEXAGON_M4_and_and:
|
||||
si_MInst_sisisi_and <"and", int_hexagon_M4_and_and>;
|
||||
def HEXAGON_M4_and_or:
|
||||
si_MInst_sisisi_and <"or", int_hexagon_M4_and_or>;
|
||||
def HEXAGON_M4_and_xor:
|
||||
si_MInst_sisisi_and <"xor", int_hexagon_M4_and_xor>;
|
||||
def HEXAGON_M4_and_andn:
|
||||
si_MInst_sisisi_andn <"and", int_hexagon_M4_and_andn>;
|
||||
def HEXAGON_M4_xor_and:
|
||||
si_MInst_sisisi_xor <"and", int_hexagon_M4_xor_and>;
|
||||
def HEXAGON_M4_xor_or:
|
||||
si_MInst_sisisi_xor <"or", int_hexagon_M4_xor_or>;
|
||||
def HEXAGON_M4_xor_andn:
|
||||
si_MInst_sisisi_xorn <"and", int_hexagon_M4_xor_andn>;
|
||||
def HEXAGON_M4_or_and:
|
||||
si_MInst_sisisi_or <"and", int_hexagon_M4_or_and>;
|
||||
def HEXAGON_M4_or_or:
|
||||
si_MInst_sisisi_or <"or", int_hexagon_M4_or_or>;
|
||||
def HEXAGON_M4_or_xor:
|
||||
si_MInst_sisisi_or <"xor", int_hexagon_M4_or_xor>;
|
||||
def HEXAGON_M4_or_andn:
|
||||
si_MInst_sisisi_orn <"and", int_hexagon_M4_or_andn>;
|
||||
def HEXAGON_S4_or_andix:
|
||||
si_SInst_sisis10_andi <"or", int_hexagon_S4_or_andix>;
|
||||
def HEXAGON_S4_or_andi:
|
||||
si_SInst_sisis10_or <"and", int_hexagon_S4_or_andi>;
|
||||
def HEXAGON_S4_or_ori:
|
||||
si_SInst_sisis10_or <"or", int_hexagon_S4_or_ori>;
|
||||
|
||||
// XTYPE / ALU / Modulo wrap.
|
||||
def HEXAGON_A4_modwrapu:
|
||||
si_ALU64_sisi <"modwrap", int_hexagon_A4_modwrapu>;
|
||||
|
||||
// XTYPE / ALU / Round.
|
||||
def HEXAGON_A4_cround_ri:
|
||||
si_SInst_siu5 <"cround", int_hexagon_A4_cround_ri>;
|
||||
def HEXAGON_A4_cround_rr:
|
||||
si_SInst_sisi <"cround", int_hexagon_A4_cround_rr>;
|
||||
def HEXAGON_A4_round_ri:
|
||||
si_SInst_siu5 <"round", int_hexagon_A4_round_ri>;
|
||||
def HEXAGON_A4_round_rr:
|
||||
si_SInst_sisi <"round", int_hexagon_A4_round_rr>;
|
||||
def HEXAGON_A4_round_ri_sat:
|
||||
si_SInst_siu5_sat <"round", int_hexagon_A4_round_ri_sat>;
|
||||
def HEXAGON_A4_round_rr_sat:
|
||||
si_SInst_sisi_sat <"round", int_hexagon_A4_round_rr_sat>;
|
||||
|
||||
// XTYPE / ALU / Vector reduce add unsigned halfwords.
|
||||
// XTYPE / ALU / Vector add bytes.
|
||||
// XTYPE / ALU / Vector conditional negate.
|
||||
// XTYPE / ALU / Vector maximum bytes.
|
||||
// XTYPE / ALU / Vector reduce maximum halfwords.
|
||||
// XTYPE / ALU / Vector reduce maximum words.
|
||||
// XTYPE / ALU / Vector minimum bytes.
|
||||
// XTYPE / ALU / Vector reduce minimum halfwords.
|
||||
// XTYPE / ALU / Vector reduce minimum words.
|
||||
// XTYPE / ALU / Vector subtract bytes.
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* XTYPE/BIT *
|
||||
*********************************************************************/
|
||||
|
||||
// XTYPE / BIT / Count leading.
|
||||
// XTYPE / BIT / Count trailing.
|
||||
// XTYPE / BIT / Extract bitfield.
|
||||
// XTYPE / BIT / Masked parity.
|
||||
// XTYPE / BIT / Bit reverse.
|
||||
// XTYPE / BIT / Split bitfield.
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* XTYPE/COMPLEX *
|
||||
*********************************************************************/
|
||||
|
||||
// XTYPE / COMPLEX / Complex add/sub halfwords.
|
||||
// XTYPE / COMPLEX / Complex add/sub words.
|
||||
// XTYPE / COMPLEX / Complex multiply 32x16.
|
||||
// XTYPE / COMPLEX / Vector reduce complex rotate.
|
||||
|
||||
|
||||
/********************************************************************
|
||||
* XTYPE/MPY *
|
||||
*********************************************************************/
|
||||
|
||||
// XTYPE / COMPLEX / Complex add/sub halfwords.
|
36
lib/Target/Hexagon/HexagonMCAsmInfo.cpp
Normal file
36
lib/Target/Hexagon/HexagonMCAsmInfo.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
//===-- HexagonMCAsmInfo.cpp - Hexagon 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 declarations of the HexagonMCAsmInfo properties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonMCAsmInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
HexagonMCAsmInfo::HexagonMCAsmInfo(const Target &T, StringRef TT) {
|
||||
Data16bitsDirective = "\t.half\t";
|
||||
Data32bitsDirective = "\t.word\t";
|
||||
Data64bitsDirective = 0; // .xword is only supported by V9.
|
||||
ZeroDirective = "\t.skip\t";
|
||||
CommentString = "//";
|
||||
HasLEB128 = true;
|
||||
|
||||
PrivateGlobalPrefix = ".L";
|
||||
LCOMMDirectiveType = LCOMM::ByteAlignment;
|
||||
InlineAsmStart = "# InlineAsm Start";
|
||||
InlineAsmEnd = "# InlineAsm End";
|
||||
ZeroDirective = "\t.space\t";
|
||||
AscizDirective = "\t.string\t";
|
||||
WeakRefDirective = "\t.weak\t";
|
||||
|
||||
UsesELFSectionDirectiveForBSS = true;
|
||||
ExceptionsType = ExceptionHandling::DwarfCFI;
|
||||
}
|
30
lib/Target/Hexagon/HexagonMCAsmInfo.h
Normal file
30
lib/Target/Hexagon/HexagonMCAsmInfo.h
Normal file
@ -0,0 +1,30 @@
|
||||
//===-- HexagonTargetAsmInfo.h - Hexagon 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 HexagonMCAsmInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef HexagonMCASMINFO_H
|
||||
#define HexagonMCASMINFO_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
class Target;
|
||||
|
||||
class HexagonMCAsmInfo : public MCAsmInfo {
|
||||
public:
|
||||
explicit HexagonMCAsmInfo(const Target &T, StringRef TT);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
75
lib/Target/Hexagon/HexagonMachineFunctionInfo.h
Normal file
75
lib/Target/Hexagon/HexagonMachineFunctionInfo.h
Normal file
@ -0,0 +1,75 @@
|
||||
//=- HexagonMachineFuctionInfo.h - Hexagon 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef HexagonMACHINEFUNCTIONINFO_H
|
||||
#define HexagonMACHINEFUNCTIONINFO_H
|
||||
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace Hexagon {
|
||||
const unsigned int StartPacket = 0x1;
|
||||
const unsigned int EndPacket = 0x2;
|
||||
}
|
||||
|
||||
|
||||
/// Hexagon target-specific information for each MachineFunction.
|
||||
class HexagonMachineFunctionInfo : public MachineFunctionInfo {
|
||||
// SRetReturnReg - Some subtargets require that sret lowering includes
|
||||
// returning the value of the returned struct in a register. This field
|
||||
// holds the virtual register into which the sret argument is passed.
|
||||
unsigned SRetReturnReg;
|
||||
std::vector<MachineInstr*> AllocaAdjustInsts;
|
||||
int VarArgsFrameIndex;
|
||||
bool HasClobberLR;
|
||||
|
||||
std::map<const MachineInstr*, unsigned> PacketInfo;
|
||||
|
||||
|
||||
public:
|
||||
HexagonMachineFunctionInfo() : SRetReturnReg(0), HasClobberLR(0) {}
|
||||
|
||||
HexagonMachineFunctionInfo(MachineFunction &MF) : SRetReturnReg(0),
|
||||
HasClobberLR(0) {}
|
||||
|
||||
unsigned getSRetReturnReg() const { return SRetReturnReg; }
|
||||
void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }
|
||||
|
||||
void addAllocaAdjustInst(MachineInstr* MI) {
|
||||
AllocaAdjustInsts.push_back(MI);
|
||||
}
|
||||
const std::vector<MachineInstr*>& getAllocaAdjustInsts() {
|
||||
return AllocaAdjustInsts;
|
||||
}
|
||||
|
||||
void setVarArgsFrameIndex(int v) { VarArgsFrameIndex = v; }
|
||||
int getVarArgsFrameIndex() { return VarArgsFrameIndex; }
|
||||
|
||||
void setStartPacket(MachineInstr* MI) {
|
||||
PacketInfo[MI] |= Hexagon::StartPacket;
|
||||
}
|
||||
void setEndPacket(MachineInstr* MI) {
|
||||
PacketInfo[MI] |= Hexagon::EndPacket;
|
||||
}
|
||||
bool isStartPacket(const MachineInstr* MI) const {
|
||||
return (PacketInfo.count(MI) &&
|
||||
(PacketInfo.find(MI)->second & Hexagon::StartPacket));
|
||||
}
|
||||
bool isEndPacket(const MachineInstr* MI) const {
|
||||
return (PacketInfo.count(MI) &&
|
||||
(PacketInfo.find(MI)->second & Hexagon::EndPacket));
|
||||
}
|
||||
void setHasClobberLR(bool v) { HasClobberLR = v; }
|
||||
bool hasClobberLR() const { return HasClobberLR; }
|
||||
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
129
lib/Target/Hexagon/HexagonOptimizeSZExtends.cpp
Normal file
129
lib/Target/Hexagon/HexagonOptimizeSZExtends.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
//===-- HexagonOptimizeSZExtends.cpp - Identify and remove sign and -------===//
|
||||
//===-- zero extends. -------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/PassSupport.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include <algorithm>
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
struct HexagonOptimizeSZExtends : public MachineFunctionPass {
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
HexagonOptimizeSZExtends() : MachineFunctionPass(ID) {}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
const char *getPassName() const {
|
||||
return "Hexagon remove redundant zero and size extends";
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<MachineFunctionAnalysis>();
|
||||
AU.addPreserved<MachineFunctionAnalysis>();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
}
|
||||
|
||||
char HexagonOptimizeSZExtends::ID = 0;
|
||||
|
||||
// This is a brain dead pass to get rid of redundant sign extends for the
|
||||
// following case:
|
||||
//
|
||||
// Transform the following pattern
|
||||
// %vreg170<def> = SXTW %vreg166
|
||||
// ...
|
||||
// %vreg176<def> = COPY %vreg170:subreg_loreg
|
||||
//
|
||||
// Into
|
||||
// %vreg176<def> = COPY vreg166
|
||||
|
||||
bool HexagonOptimizeSZExtends::runOnMachineFunction(MachineFunction &MF) {
|
||||
DenseMap<unsigned, unsigned> SExtMap;
|
||||
|
||||
// Loop over all of the basic blocks
|
||||
for (MachineFunction::iterator MBBb = MF.begin(), MBBe = MF.end();
|
||||
MBBb != MBBe; ++MBBb) {
|
||||
MachineBasicBlock* MBB = MBBb;
|
||||
SExtMap.clear();
|
||||
|
||||
// Traverse the basic block.
|
||||
for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
|
||||
++MII) {
|
||||
MachineInstr *MI = MII;
|
||||
// Look for sign extends:
|
||||
// %vreg170<def> = SXTW %vreg166
|
||||
if (MI->getOpcode() == Hexagon::SXTW) {
|
||||
assert (MI->getNumOperands() == 2);
|
||||
MachineOperand &Dst = MI->getOperand(0);
|
||||
MachineOperand &Src = MI->getOperand(1);
|
||||
unsigned DstReg = Dst.getReg();
|
||||
unsigned SrcReg = Src.getReg();
|
||||
// Just handle virtual registers.
|
||||
if (TargetRegisterInfo::isVirtualRegister(DstReg) &&
|
||||
TargetRegisterInfo::isVirtualRegister(SrcReg)) {
|
||||
// Map the following:
|
||||
// %vreg170<def> = SXTW %vreg166
|
||||
// SExtMap[170] = vreg166
|
||||
SExtMap[DstReg] = SrcReg;
|
||||
}
|
||||
}
|
||||
// Look for copy:
|
||||
// %vreg176<def> = COPY %vreg170:subreg_loreg
|
||||
if (MI->isCopy()) {
|
||||
assert (MI->getNumOperands() == 2);
|
||||
MachineOperand &Dst = MI->getOperand(0);
|
||||
MachineOperand &Src = MI->getOperand(1);
|
||||
|
||||
// Make sure we are copying the lower 32 bits.
|
||||
if (Src.getSubReg() != Hexagon::subreg_loreg)
|
||||
continue;
|
||||
|
||||
unsigned DstReg = Dst.getReg();
|
||||
unsigned SrcReg = Src.getReg();
|
||||
if (TargetRegisterInfo::isVirtualRegister(DstReg) &&
|
||||
TargetRegisterInfo::isVirtualRegister(SrcReg)) {
|
||||
// Try to find in the map.
|
||||
if (unsigned SextSrc = SExtMap.lookup(SrcReg)) {
|
||||
// Change the 1st operand.
|
||||
MI->RemoveOperand(1);
|
||||
MI->addOperand(MachineOperand::CreateReg(SextSrc, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FunctionPass *llvm::createHexagonOptimizeSZExtends() {
|
||||
return new HexagonOptimizeSZExtends();
|
||||
}
|
322
lib/Target/Hexagon/HexagonRegisterInfo.cpp
Normal file
322
lib/Target/Hexagon/HexagonRegisterInfo.cpp
Normal file
@ -0,0 +1,322 @@
|
||||
//==- HexagonRegisterInfo.cpp - Hexagon 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 Hexagon implementation of the TargetRegisterInfo
|
||||
// class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonRegisterInfo.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/RegisterScavenging.h"
|
||||
#include "llvm/MC/MachineLocation.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include <iostream>
|
||||
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/Function.h"
|
||||
using namespace llvm;
|
||||
|
||||
|
||||
HexagonRegisterInfo::HexagonRegisterInfo(HexagonSubtarget &st,
|
||||
const HexagonInstrInfo &tii)
|
||||
: HexagonGenRegisterInfo(Hexagon::R31),
|
||||
Subtarget(st),
|
||||
TII(tii) {
|
||||
}
|
||||
|
||||
const unsigned* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction
|
||||
*MF)
|
||||
const {
|
||||
static const unsigned CalleeSavedRegsV2[] = {
|
||||
Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0
|
||||
};
|
||||
static const unsigned CalleeSavedRegsV3[] = {
|
||||
Hexagon::R16, Hexagon::R17, Hexagon::R18, Hexagon::R19,
|
||||
Hexagon::R20, Hexagon::R21, Hexagon::R22, Hexagon::R23,
|
||||
Hexagon::R24, Hexagon::R25, Hexagon::R26, Hexagon::R27, 0
|
||||
};
|
||||
|
||||
switch(Subtarget.getHexagonArchVersion()) {
|
||||
case HexagonSubtarget::V2:
|
||||
return CalleeSavedRegsV2;
|
||||
break;
|
||||
case HexagonSubtarget::V3:
|
||||
case HexagonSubtarget::V4:
|
||||
return CalleeSavedRegsV3;
|
||||
break;
|
||||
default:
|
||||
const char *ErrorString =
|
||||
"Callee saved registers requested for unknown archtecture version";
|
||||
llvm_unreachable(ErrorString);
|
||||
}
|
||||
}
|
||||
|
||||
BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
|
||||
const {
|
||||
BitVector Reserved(getNumRegs());
|
||||
Reserved.set(HEXAGON_RESERVED_REG_1);
|
||||
Reserved.set(HEXAGON_RESERVED_REG_2);
|
||||
Reserved.set(Hexagon::R29);
|
||||
Reserved.set(Hexagon::R30);
|
||||
Reserved.set(Hexagon::R31);
|
||||
Reserved.set(Hexagon::D14);
|
||||
Reserved.set(Hexagon::D15);
|
||||
Reserved.set(Hexagon::LC0);
|
||||
Reserved.set(Hexagon::LC1);
|
||||
Reserved.set(Hexagon::SA0);
|
||||
Reserved.set(Hexagon::SA1);
|
||||
return Reserved;
|
||||
}
|
||||
|
||||
|
||||
const TargetRegisterClass* const*
|
||||
HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
static const TargetRegisterClass * const CalleeSavedRegClassesV2[] = {
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
};
|
||||
static const TargetRegisterClass * const CalleeSavedRegClassesV3[] = {
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
&Hexagon::IntRegsRegClass, &Hexagon::IntRegsRegClass,
|
||||
};
|
||||
|
||||
switch(Subtarget.getHexagonArchVersion()) {
|
||||
case HexagonSubtarget::V2:
|
||||
return CalleeSavedRegClassesV2;
|
||||
break;
|
||||
case HexagonSubtarget::V3:
|
||||
case HexagonSubtarget::V4:
|
||||
return CalleeSavedRegClassesV3;
|
||||
break;
|
||||
default:
|
||||
const char *ErrorString =
|
||||
"Callee saved register classes requested for unknown archtecture version";
|
||||
llvm_unreachable(ErrorString);
|
||||
}
|
||||
}
|
||||
|
||||
void HexagonRegisterInfo::
|
||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const {
|
||||
MachineInstr &MI = *I;
|
||||
|
||||
if (MI.getOpcode() == Hexagon::ADJCALLSTACKDOWN) {
|
||||
// Hexagon_TODO: add code
|
||||
} else if (MI.getOpcode() == Hexagon::ADJCALLSTACKUP) {
|
||||
// Hexagon_TODO: add code
|
||||
} else {
|
||||
assert(0 && "Cannot handle this call frame pseudo instruction");
|
||||
}
|
||||
MBB.erase(I);
|
||||
}
|
||||
|
||||
void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, RegScavenger *RS) const {
|
||||
|
||||
//
|
||||
// Hexagon_TODO: Do we need to enforce this for Hexagon?
|
||||
assert(SPAdj == 0 && "Unexpected");
|
||||
|
||||
|
||||
unsigned i = 0;
|
||||
MachineInstr &MI = *II;
|
||||
while (!MI.getOperand(i).isFI()) {
|
||||
++i;
|
||||
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
|
||||
}
|
||||
|
||||
int FrameIndex = MI.getOperand(i).getIndex();
|
||||
|
||||
// Addressable stack objects are accessed using neg. offsets from %fp.
|
||||
MachineFunction &MF = *MI.getParent()->getParent();
|
||||
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
|
||||
MachineFrameInfo &MFI = *MF.getFrameInfo();
|
||||
|
||||
unsigned FrameReg = getFrameRegister(MF);
|
||||
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
||||
if (!TFI->hasFP(MF)) {
|
||||
// We will not reserve space on the stack for the lr and fp registers.
|
||||
Offset -= 2 * Hexagon_WordSize;
|
||||
}
|
||||
|
||||
const unsigned FrameSize = MFI.getStackSize();
|
||||
|
||||
if (!MFI.hasVarSizedObjects() &&
|
||||
TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset)) &&
|
||||
!TII.isSpillPredRegOp(&MI)) {
|
||||
// Replace frame index with a stack pointer reference.
|
||||
MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false, true);
|
||||
MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset);
|
||||
} else {
|
||||
// Replace frame index with a frame pointer reference.
|
||||
if (!TII.isValidOffset(MI.getOpcode(), Offset)) {
|
||||
|
||||
// If the offset overflows, then correct it.
|
||||
//
|
||||
// For loads, we do not need a reserved register
|
||||
// r0 = memw(r30 + #10000) to:
|
||||
//
|
||||
// r0 = add(r30, #10000)
|
||||
// r0 = memw(r0)
|
||||
if ( (MI.getOpcode() == Hexagon::LDriw) ||
|
||||
(MI.getOpcode() == Hexagon::LDrid) ||
|
||||
(MI.getOpcode() == Hexagon::LDrih) ||
|
||||
(MI.getOpcode() == Hexagon::LDriuh) ||
|
||||
(MI.getOpcode() == Hexagon::LDrib) ||
|
||||
(MI.getOpcode() == Hexagon::LDriub) ) {
|
||||
unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ?
|
||||
*getSubRegisters(MI.getOperand(0).getReg()) :
|
||||
MI.getOperand(0).getReg();
|
||||
|
||||
// Check if offset can fit in addi.
|
||||
if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::ADD_rr),
|
||||
dstReg).addReg(FrameReg).addReg(dstReg);
|
||||
} else {
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::ADD_ri),
|
||||
dstReg).addReg(FrameReg).addImm(Offset);
|
||||
}
|
||||
|
||||
MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
|
||||
MI.getOperand(i+1).ChangeToImmediate(0);
|
||||
} else if ((MI.getOpcode() == Hexagon::STriw) ||
|
||||
(MI.getOpcode() == Hexagon::STrid) ||
|
||||
(MI.getOpcode() == Hexagon::STrih) ||
|
||||
(MI.getOpcode() == Hexagon::STrib) ||
|
||||
(MI.getOpcode() == Hexagon::STriwt)) {
|
||||
// For stores, we need a reserved register. Change
|
||||
// memw(r30 + #10000) = r0 to:
|
||||
//
|
||||
// rs = add(r30, #10000);
|
||||
// memw(rs) = r0
|
||||
unsigned resReg = HEXAGON_RESERVED_REG_1;
|
||||
|
||||
// Check if offset can fit in addi.
|
||||
if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::ADD_rr),
|
||||
resReg).addReg(FrameReg).addReg(resReg);
|
||||
} else {
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::ADD_ri),
|
||||
resReg).addReg(FrameReg).addImm(Offset);
|
||||
}
|
||||
MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
|
||||
MI.getOperand(i+1).ChangeToImmediate(0);
|
||||
} else if (TII.isMemOp(&MI)) {
|
||||
unsigned resReg = HEXAGON_RESERVED_REG_1;
|
||||
if (!MFI.hasVarSizedObjects() &&
|
||||
TII.isValidOffset(MI.getOpcode(), (FrameSize+Offset))) {
|
||||
MI.getOperand(i).ChangeToRegister(getStackRegister(), false, false,
|
||||
true);
|
||||
MI.getOperand(i+1).ChangeToImmediate(FrameSize+Offset);
|
||||
} else if (!TII.isValidOffset(Hexagon::ADD_ri, Offset)) {
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::CONST32_Int_Real), resReg).addImm(Offset);
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::ADD_rr),
|
||||
resReg).addReg(FrameReg).addReg(resReg);
|
||||
MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
|
||||
MI.getOperand(i+1).ChangeToImmediate(0);
|
||||
} else {
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::ADD_ri),
|
||||
resReg).addReg(FrameReg).addImm(Offset);
|
||||
MI.getOperand(i).ChangeToRegister(resReg, false, false, true);
|
||||
MI.getOperand(i+1).ChangeToImmediate(0);
|
||||
}
|
||||
} else {
|
||||
unsigned dstReg = MI.getOperand(0).getReg();
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::CONST32_Int_Real), dstReg).addImm(Offset);
|
||||
BuildMI(*MI.getParent(), II, MI.getDebugLoc(),
|
||||
TII.get(Hexagon::ADD_rr),
|
||||
dstReg).addReg(FrameReg).addReg(dstReg);
|
||||
// Can we delete MI??? r2 = add (r2, #0).
|
||||
MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
|
||||
MI.getOperand(i+1).ChangeToImmediate(0);
|
||||
}
|
||||
} else {
|
||||
// If the offset is small enough to fit in the immediate field, directly
|
||||
// encode it.
|
||||
MI.getOperand(i).ChangeToRegister(FrameReg, false);
|
||||
MI.getOperand(i+1).ChangeToImmediate(Offset);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unsigned HexagonRegisterInfo::getRARegister() const {
|
||||
return Hexagon::R31;
|
||||
}
|
||||
|
||||
unsigned HexagonRegisterInfo::getFrameRegister(const MachineFunction
|
||||
&MF) const {
|
||||
const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering();
|
||||
if (TFI->hasFP(MF)) {
|
||||
return Hexagon::R30;
|
||||
}
|
||||
|
||||
return Hexagon::R29;
|
||||
}
|
||||
|
||||
unsigned HexagonRegisterInfo::getFrameRegister() const {
|
||||
return Hexagon::R30;
|
||||
}
|
||||
|
||||
unsigned HexagonRegisterInfo::getStackRegister() const {
|
||||
return Hexagon::R29;
|
||||
}
|
||||
|
||||
void HexagonRegisterInfo::getInitialFrameState(std::vector<MachineMove>
|
||||
&Moves) const
|
||||
{
|
||||
// VirtualFP = (R30 + #0).
|
||||
unsigned FPReg = getFrameRegister();
|
||||
MachineLocation Dst(MachineLocation::VirtualFP);
|
||||
MachineLocation Src(FPReg, 0);
|
||||
Moves.push_back(MachineMove(0, Dst, Src));
|
||||
}
|
||||
|
||||
unsigned HexagonRegisterInfo::getEHExceptionRegister() const {
|
||||
assert(0 && "What is the exception register");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned HexagonRegisterInfo::getEHHandlerRegister() const {
|
||||
assert(0 && "What is the exception handler register");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "HexagonGenRegisterInfo.inc"
|
89
lib/Target/Hexagon/HexagonRegisterInfo.h
Normal file
89
lib/Target/Hexagon/HexagonRegisterInfo.h
Normal file
@ -0,0 +1,89 @@
|
||||
//==- HexagonRegisterInfo.h - Hexagon 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 Hexagon implementation of the TargetRegisterInfo
|
||||
// class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef HexagonREGISTERINFO_H
|
||||
#define HexagonREGISTERINFO_H
|
||||
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#define GET_REGINFO_HEADER
|
||||
#include "HexagonGenRegisterInfo.inc"
|
||||
#include "llvm/MC/MachineLocation.h"
|
||||
|
||||
//
|
||||
// We try not to hard code the reserved registers in our code,
|
||||
// so the following two macros were defined. However, there
|
||||
// are still a few places that R11 and R10 are hard wired.
|
||||
// See below. If, in the future, we decided to change the reserved
|
||||
// register. Don't forget changing the following places.
|
||||
//
|
||||
// 1. the "Defs" set of STriw_pred in HexagonInstrInfo.td
|
||||
// 2. the "Defs" set of LDri_pred in HexagonInstrInfo.td
|
||||
// 3. the definition of "IntRegs" in HexagonRegisterInfo.td
|
||||
// 4. the definition of "DoubleRegs" in HexagonRegisterInfo.td
|
||||
//
|
||||
#define HEXAGON_RESERVED_REG_1 Hexagon::R10
|
||||
#define HEXAGON_RESERVED_REG_2 Hexagon::R11
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class HexagonSubtarget;
|
||||
class HexagonInstrInfo;
|
||||
class Type;
|
||||
|
||||
struct HexagonRegisterInfo : public HexagonGenRegisterInfo {
|
||||
HexagonSubtarget &Subtarget;
|
||||
const HexagonInstrInfo &TII;
|
||||
|
||||
HexagonRegisterInfo(HexagonSubtarget &st, const HexagonInstrInfo &tii);
|
||||
|
||||
/// Code Generation virtual methods...
|
||||
const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const;
|
||||
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses(
|
||||
const MachineFunction *MF = 0) const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
|
||||
void eliminateCallFramePseudoInstr(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I) const;
|
||||
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, RegScavenger *RS = NULL) const;
|
||||
|
||||
/// determineFrameLayout - Determine the size of the frame and maximum call
|
||||
/// frame size.
|
||||
void determineFrameLayout(MachineFunction &MF) const;
|
||||
|
||||
/// requiresRegisterScavenging - returns true since we may need scavenging for
|
||||
/// a temporary register when generating hardware loop instructions.
|
||||
bool requiresRegisterScavenging(const MachineFunction &MF) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Debug information queries.
|
||||
unsigned getRARegister() const;
|
||||
unsigned getFrameRegister(const MachineFunction &MF) const;
|
||||
unsigned getFrameRegister() const;
|
||||
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
|
||||
unsigned getStackRegister() const;
|
||||
|
||||
// Exception handling queries.
|
||||
unsigned getEHExceptionRegister() const;
|
||||
unsigned getEHHandlerRegister() const;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
169
lib/Target/Hexagon/HexagonRegisterInfo.td
Normal file
169
lib/Target/Hexagon/HexagonRegisterInfo.td
Normal file
@ -0,0 +1,169 @@
|
||||
//===- HexagonRegisterInfo.td - Hexagon 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 Hexagon register file.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class HexagonReg<string n> : Register<n> {
|
||||
field bits<5> Num;
|
||||
let Namespace = "Hexagon";
|
||||
}
|
||||
|
||||
class HexagonDoubleReg<string n, list<Register> subregs> :
|
||||
RegisterWithSubRegs<n, subregs> {
|
||||
field bits<5> Num;
|
||||
let Namespace = "Hexagon";
|
||||
}
|
||||
|
||||
// Registers are identified with 5-bit ID numbers.
|
||||
// Ri - 32-bit integer registers.
|
||||
class Ri<bits<5> num, string n> : HexagonReg<n> {
|
||||
let Num = num;
|
||||
}
|
||||
|
||||
// Rf - 32-bit floating-point registers.
|
||||
class Rf<bits<5> num, string n> : HexagonReg<n> {
|
||||
let Num = num;
|
||||
}
|
||||
|
||||
|
||||
// Rd - 64 bit registers.
|
||||
class Rd<bits<5> num, string n, list<Register> subregs> :
|
||||
HexagonDoubleReg<n, subregs> {
|
||||
let Num = num;
|
||||
let SubRegs = subregs;
|
||||
}
|
||||
|
||||
|
||||
class Rp<bits<5> num, string n> : HexagonReg<n> {
|
||||
let Num = num;
|
||||
}
|
||||
|
||||
class Rc<bits<5> num, string n> : HexagonReg<n> {
|
||||
let Num = num;
|
||||
}
|
||||
|
||||
let Namespace = "Hexagon" in {
|
||||
|
||||
def subreg_loreg : SubRegIndex;
|
||||
def subreg_hireg : SubRegIndex;
|
||||
|
||||
// Integer registers.
|
||||
def R0 : Ri< 0, "r0">, DwarfRegNum<[0]>;
|
||||
def R1 : Ri< 1, "r1">, DwarfRegNum<[1]>;
|
||||
def R2 : Ri< 2, "r2">, DwarfRegNum<[2]>;
|
||||
def R3 : Ri< 3, "r3">, DwarfRegNum<[3]>;
|
||||
def R4 : Ri< 4, "r4">, DwarfRegNum<[4]>;
|
||||
def R5 : Ri< 5, "r5">, DwarfRegNum<[5]>;
|
||||
def R6 : Ri< 6, "r6">, DwarfRegNum<[6]>;
|
||||
def R7 : Ri< 7, "r7">, DwarfRegNum<[7]>;
|
||||
def R8 : Ri< 8, "r8">, DwarfRegNum<[8]>;
|
||||
def R9 : Ri< 9, "r9">, DwarfRegNum<[9]>;
|
||||
def R10 : Ri<10, "r10">, DwarfRegNum<[10]>;
|
||||
def R11 : Ri<11, "r11">, DwarfRegNum<[11]>;
|
||||
def R12 : Ri<12, "r12">, DwarfRegNum<[12]>;
|
||||
def R13 : Ri<13, "r13">, DwarfRegNum<[13]>;
|
||||
def R14 : Ri<14, "r14">, DwarfRegNum<[14]>;
|
||||
def R15 : Ri<15, "r15">, DwarfRegNum<[15]>;
|
||||
def R16 : Ri<16, "r16">, DwarfRegNum<[16]>;
|
||||
def R17 : Ri<17, "r17">, DwarfRegNum<[17]>;
|
||||
def R18 : Ri<18, "r18">, DwarfRegNum<[18]>;
|
||||
def R19 : Ri<19, "r19">, DwarfRegNum<[19]>;
|
||||
def R20 : Ri<20, "r20">, DwarfRegNum<[20]>;
|
||||
def R21 : Ri<21, "r21">, DwarfRegNum<[21]>;
|
||||
def R22 : Ri<22, "r22">, DwarfRegNum<[22]>;
|
||||
def R23 : Ri<23, "r23">, DwarfRegNum<[23]>;
|
||||
def R24 : Ri<24, "r24">, DwarfRegNum<[24]>;
|
||||
def R25 : Ri<25, "r25">, DwarfRegNum<[25]>;
|
||||
def R26 : Ri<26, "r26">, DwarfRegNum<[26]>;
|
||||
def R27 : Ri<27, "r27">, DwarfRegNum<[27]>;
|
||||
def R28 : Ri<28, "r28">, DwarfRegNum<[28]>;
|
||||
def R29 : Ri<29, "r29">, DwarfRegNum<[29]>;
|
||||
def R30 : Ri<30, "r30">, DwarfRegNum<[30]>;
|
||||
def R31 : Ri<31, "r31">, DwarfRegNum<[31]>;
|
||||
|
||||
|
||||
def PC : Ri<31, "r31">, DwarfRegNum<[32]>;
|
||||
def GP : Ri<31, "r31">, DwarfRegNum<[33]>;
|
||||
|
||||
// Aliases of the R* registers used to hold 64-bit int values (doubles).
|
||||
let SubRegIndices = [subreg_loreg, subreg_hireg] in {
|
||||
def D0 : Rd< 0, "r1:0", [R0, R1]>, DwarfRegNum<[32]>;
|
||||
def D1 : Rd< 2, "r3:2", [R2, R3]>, DwarfRegNum<[34]>;
|
||||
def D2 : Rd< 4, "r5:4", [R4, R5]>, DwarfRegNum<[36]>;
|
||||
def D3 : Rd< 6, "r7:6", [R6, R7]>, DwarfRegNum<[38]>;
|
||||
def D4 : Rd< 8, "r9:8", [R8, R9]>, DwarfRegNum<[40]>;
|
||||
def D5 : Rd<10, "r11:10", [R10, R11]>, DwarfRegNum<[42]>;
|
||||
def D6 : Rd<12, "r13:12", [R12, R13]>, DwarfRegNum<[44]>;
|
||||
def D7 : Rd<14, "r15:14", [R14, R15]>, DwarfRegNum<[46]>;
|
||||
def D8 : Rd<16, "r17:16", [R16, R17]>, DwarfRegNum<[48]>;
|
||||
def D9 : Rd<18, "r19:18", [R18, R19]>, DwarfRegNum<[50]>;
|
||||
def D10 : Rd<20, "r21:20", [R20, R21]>, DwarfRegNum<[52]>;
|
||||
def D11 : Rd<22, "r23:22", [R22, R23]>, DwarfRegNum<[54]>;
|
||||
def D12 : Rd<24, "r25:24", [R24, R25]>, DwarfRegNum<[56]>;
|
||||
def D13 : Rd<26, "r27:26", [R26, R27]>, DwarfRegNum<[58]>;
|
||||
def D14 : Rd<28, "r29:28", [R28, R29]>, DwarfRegNum<[60]>;
|
||||
def D15 : Rd<30, "r31:30", [R30, R31]>, DwarfRegNum<[62]>;
|
||||
}
|
||||
|
||||
// Predicate registers.
|
||||
def P0 : Rp< 0, "p0">, DwarfRegNum<[63]>;
|
||||
def P1 : Rp< 0, "p1">, DwarfRegNum<[64]>;
|
||||
def P2 : Rp< 0, "p2">, DwarfRegNum<[65]>;
|
||||
def P3 : Rp< 0, "p3">, DwarfRegNum<[66]>;
|
||||
|
||||
// Control registers.
|
||||
def SA0 : Rc<0, "sa0">, DwarfRegNum<[67]>;
|
||||
def LC0 : Rc<0, "lc0">, DwarfRegNum<[68]>;
|
||||
|
||||
def SA1 : Rc<0, "sa1">, DwarfRegNum<[69]>;
|
||||
def LC1 : Rc<0, "lc1">, DwarfRegNum<[70]>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Register classes.
|
||||
//
|
||||
// FIXME: the register order should be defined in terms of the preferred
|
||||
// allocation order...
|
||||
//
|
||||
def IntRegs : RegisterClass<"Hexagon", [i32], 32, (add (sequence "R%u", 0, 9),
|
||||
(sequence "R%u", 12, 28),
|
||||
R10, R11, R29, R30,
|
||||
R31)> {
|
||||
}
|
||||
|
||||
|
||||
|
||||
def DoubleRegs : RegisterClass<"Hexagon", [i64], 64, (add (sequence "D%u", 0,
|
||||
4),
|
||||
(sequence "D%u", 6, 13),
|
||||
D5, D14, D15)> {
|
||||
let SubRegClasses = [(IntRegs subreg_loreg, subreg_hireg)];
|
||||
}
|
||||
|
||||
|
||||
def PredRegs : RegisterClass<"Hexagon", [i1], 32, (add (sequence "P%u", 0, 3))>
|
||||
{
|
||||
let Size = 32;
|
||||
}
|
||||
|
||||
def CRRegs : RegisterClass<"Hexagon", [i32], 32, (add (sequence "LC%u", 0, 1),
|
||||
(sequence "SA%u", 0, 1),
|
||||
PC)> {
|
||||
let Size = 32;
|
||||
}
|
85
lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp
Normal file
85
lib/Target/Hexagon/HexagonRemoveSZExtArgs.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
//=- HexagonRemoveExtendArgs.cpp - Remove unecessary argument sign extends --=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Pass that removes sign extends for function parameters. These parameters
|
||||
// are already sign extended by the caller per Hexagon's ABI
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace llvm;
|
||||
namespace {
|
||||
struct HexagonRemoveExtendArgs : public FunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
HexagonRemoveExtendArgs() : FunctionPass(ID) {}
|
||||
virtual bool runOnFunction(Function &F);
|
||||
|
||||
const char *getPassName() const {
|
||||
return "Remove sign extends";
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<MachineFunctionAnalysis>();
|
||||
AU.addPreserved<MachineFunctionAnalysis>();
|
||||
FunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
char HexagonRemoveExtendArgs::ID = 0;
|
||||
RegisterPass<HexagonRemoveExtendArgs> X("reargs",
|
||||
"Remove Sign and Zero Extends for Args"
|
||||
);
|
||||
|
||||
|
||||
|
||||
bool HexagonRemoveExtendArgs::runOnFunction(Function &F) {
|
||||
unsigned Idx = 1;
|
||||
for (Function::arg_iterator AI = F.arg_begin(), AE = F.arg_end(); AI != AE;
|
||||
++AI, ++Idx) {
|
||||
if (F.paramHasAttr(Idx, Attribute::SExt)) {
|
||||
Argument* Arg = AI;
|
||||
if (!isa<PointerType>(Arg->getType())) {
|
||||
for (Instruction::use_iterator UI = Arg->use_begin();
|
||||
UI != Arg->use_end();) {
|
||||
if (isa<SExtInst>(*UI)) {
|
||||
Instruction* Use = cast<Instruction>(*UI);
|
||||
SExtInst* SI = new SExtInst(Arg, Use->getType());
|
||||
assert (EVT::getEVT(SI->getType()) ==
|
||||
(EVT::getEVT(Use->getType())));
|
||||
++UI;
|
||||
Use->replaceAllUsesWith(SI);
|
||||
Instruction* First = F.getEntryBlock().begin();
|
||||
SI->insertBefore(First);
|
||||
Use->eraseFromParent();
|
||||
} else {
|
||||
++UI;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
FunctionPass *llvm::createHexagonRemoveExtendOps(HexagonTargetMachine &TM) {
|
||||
return new HexagonRemoveExtendArgs();
|
||||
}
|
53
lib/Target/Hexagon/HexagonSchedule.td
Normal file
53
lib/Target/Hexagon/HexagonSchedule.td
Normal file
@ -0,0 +1,53 @@
|
||||
//===-HexagonSchedule.td - Hexagon Scheduling Definitions -------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// Functional Units
|
||||
def LUNIT : FuncUnit;
|
||||
def LSUNIT : FuncUnit;
|
||||
def MUNIT : FuncUnit;
|
||||
def SUNIT : FuncUnit;
|
||||
|
||||
|
||||
// Itinerary classes
|
||||
def ALU32 : InstrItinClass;
|
||||
def ALU64 : InstrItinClass;
|
||||
def CR : InstrItinClass;
|
||||
def J : InstrItinClass;
|
||||
def JR : InstrItinClass;
|
||||
def LD : InstrItinClass;
|
||||
def M : InstrItinClass;
|
||||
def ST : InstrItinClass;
|
||||
def S : InstrItinClass;
|
||||
def PSEUDO : InstrItinClass;
|
||||
|
||||
|
||||
def HexagonItineraries :
|
||||
ProcessorItineraries<[LUNIT, LSUNIT, MUNIT, SUNIT], [], [
|
||||
InstrItinData<ALU32 , [InstrStage<1, [LUNIT, LSUNIT, MUNIT, SUNIT]>]>,
|
||||
InstrItinData<ALU64 , [InstrStage<1, [MUNIT, SUNIT]>]>,
|
||||
InstrItinData<CR , [InstrStage<1, [SUNIT]>]>,
|
||||
InstrItinData<J , [InstrStage<1, [SUNIT, MUNIT]>]>,
|
||||
InstrItinData<JR , [InstrStage<1, [MUNIT]>]>,
|
||||
InstrItinData<LD , [InstrStage<1, [LUNIT, LSUNIT]>]>,
|
||||
InstrItinData<M , [InstrStage<1, [MUNIT, SUNIT]>]>,
|
||||
InstrItinData<ST , [InstrStage<1, [LSUNIT]>]>,
|
||||
InstrItinData<S , [InstrStage<1, [SUNIT, MUNIT]>]>,
|
||||
InstrItinData<PSEUDO , [InstrStage<1, [LUNIT, LSUNIT, MUNIT, SUNIT]>]>
|
||||
]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// V4 Machine Info +
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
include "HexagonScheduleV4.td"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// V4 Machine Info -
|
||||
//===----------------------------------------------------------------------===//
|
56
lib/Target/Hexagon/HexagonScheduleV4.td
Normal file
56
lib/Target/Hexagon/HexagonScheduleV4.td
Normal file
@ -0,0 +1,56 @@
|
||||
//=-HexagonScheduleV4.td - HexagonV4 Scheduling Definitions --*- tablegen -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// There are four SLOTS (four parallel pipelines) in Hexagon V4 machine.
|
||||
// This file describes that machine information.
|
||||
|
||||
//
|
||||
// |===========|==================================================|
|
||||
// | PIPELINE | Instruction Classes |
|
||||
// |===========|==================================================|
|
||||
// | SLOT0 | LD ST ALU32 MEMOP NV SYSTEM |
|
||||
// |-----------|--------------------------------------------------|
|
||||
// | SLOT1 | LD ST ALU32 |
|
||||
// |-----------|--------------------------------------------------|
|
||||
// | SLOT2 | XTYPE ALU32 J JR |
|
||||
// |-----------|--------------------------------------------------|
|
||||
// | SLOT3 | XTYPE ALU32 J CR |
|
||||
// |===========|==================================================|
|
||||
|
||||
|
||||
// Functional Units.
|
||||
def SLOT0 : FuncUnit;
|
||||
def SLOT1 : FuncUnit;
|
||||
def SLOT2 : FuncUnit;
|
||||
def SLOT3 : FuncUnit;
|
||||
|
||||
// Itinerary classes.
|
||||
def NV_V4 : InstrItinClass;
|
||||
def MEM_V4 : InstrItinClass;
|
||||
// ALU64/M/S Instruction classes of V2 are collectively knownn as XTYPE in V4.
|
||||
|
||||
def HexagonItinerariesV4 : ProcessorItineraries<
|
||||
[SLOT0, SLOT1, SLOT2, SLOT3], [], [
|
||||
InstrItinData<LD , [InstrStage<1, [SLOT0, SLOT1]>]>,
|
||||
InstrItinData<ST , [InstrStage<1, [SLOT0, SLOT1]>]>,
|
||||
InstrItinData<ALU32 , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>,
|
||||
InstrItinData<NV_V4 , [InstrStage<1, [SLOT0]>]>,
|
||||
InstrItinData<MEM_V4 , [InstrStage<1, [SLOT0]>]>,
|
||||
InstrItinData<J , [InstrStage<1, [SLOT2, SLOT3]>]>,
|
||||
InstrItinData<JR , [InstrStage<1, [SLOT2]>]>,
|
||||
InstrItinData<CR , [InstrStage<1, [SLOT3]>]>,
|
||||
InstrItinData<PSEUDO , [InstrStage<1, [SLOT0, SLOT1, SLOT2, SLOT3]>]>,
|
||||
InstrItinData<ALU64 , [InstrStage<1, [SLOT2, SLOT3]>]>,
|
||||
InstrItinData<M , [InstrStage<1, [SLOT2, SLOT3]>]>,
|
||||
InstrItinData<S , [InstrStage<1, [SLOT2, SLOT3]>]>
|
||||
]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Hexagon V4 Resource Definitions -
|
||||
//===----------------------------------------------------------------------===//
|
121
lib/Target/Hexagon/HexagonSelectCCInfo.td
Normal file
121
lib/Target/Hexagon/HexagonSelectCCInfo.td
Normal file
@ -0,0 +1,121 @@
|
||||
//=-HexagoSelectCCInfo.td - Selectcc mappings ----------------*- tablegen -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
//
|
||||
// selectcc mappings.
|
||||
//
|
||||
def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETEQ)),
|
||||
(i32 (MUX_rr (i1 (CMPEQrr IntRegs:$lhs, IntRegs:$rhs)),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETNE)),
|
||||
(i32 (MUX_rr (i1 (NOT_Ps (CMPEQrr IntRegs:$lhs, IntRegs:$rhs))),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETGT)),
|
||||
(i32 (MUX_rr (i1 (CMPGTrr IntRegs:$lhs, IntRegs:$rhs)),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETUGT)),
|
||||
(i32 (MUX_rr (i1 (CMPGTUrr IntRegs:$lhs, IntRegs:$rhs)),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
|
||||
|
||||
def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETULT)),
|
||||
(i32 (MUX_rr (i1 (NOT_Ps (CMPGTUrr IntRegs:$lhs,
|
||||
(ADD_ri IntRegs:$rhs, -1)))),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETLT)),
|
||||
(i32 (MUX_rr (i1 (NOT_Ps (CMPGTrr IntRegs:$lhs,
|
||||
(ADD_ri IntRegs:$rhs, -1)))),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETLE)),
|
||||
(i32 (MUX_rr (i1 (NOT_Ps (CMPGTrr IntRegs:$lhs, IntRegs:$rhs))),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETULE)),
|
||||
(i32 (MUX_rr (i1 (NOT_Ps (CMPGTUrr IntRegs:$lhs, IntRegs:$rhs))),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
|
||||
//
|
||||
// selectcc mappings for greater-equal-to Rs => greater-than Rs-1.
|
||||
//
|
||||
def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETGE)),
|
||||
(i32 (MUX_rr (i1 (CMPGTrr IntRegs:$lhs, (ADD_ri IntRegs:$rhs, -1))),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
def : Pat <(i32 (selectcc IntRegs:$lhs, IntRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETUGE)),
|
||||
(i32 (MUX_rr (i1 (CMPGTUrr IntRegs:$lhs, (ADD_ri IntRegs:$rhs, -1))),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
|
||||
|
||||
//
|
||||
// selectcc mappings for predicate comparisons.
|
||||
//
|
||||
// Convert Rd = selectcc(p0, p1, true_val, false_val, SETEQ) into:
|
||||
// pt = not(p1 xor p2)
|
||||
// Rd = mux(pt, true_val, false_val)
|
||||
// and similarly for SETNE
|
||||
//
|
||||
def : Pat <(i32 (selectcc PredRegs:$lhs, PredRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETNE)),
|
||||
(i32 (MUX_rr (i1 (XOR_pp PredRegs:$lhs, PredRegs:$rhs)), IntRegs:$tval,
|
||||
IntRegs:$fval))>;
|
||||
|
||||
def : Pat <(i32 (selectcc PredRegs:$lhs, PredRegs:$rhs, IntRegs:$tval,
|
||||
IntRegs:$fval, SETEQ)),
|
||||
(i32 (MUX_rr (i1 (NOT_pp (XOR_pp PredRegs:$lhs, PredRegs:$rhs))),
|
||||
IntRegs:$tval, IntRegs:$fval))>;
|
||||
|
||||
|
||||
//
|
||||
// selectcc mappings for 64-bit operands are messy. Hexagon does not have a
|
||||
// MUX64 o, use this:
|
||||
// selectcc(Rss, Rdd, tval, fval, cond) ->
|
||||
// combine(mux(cmp_cond(Rss, Rdd), tval.hi, fval.hi),
|
||||
// mux(cmp_cond(Rss, Rdd), tval.lo, fval.lo))
|
||||
|
||||
// setgt-64.
|
||||
def : Pat<(i64 (selectcc DoubleRegs:$lhs, DoubleRegs:$rhs, DoubleRegs:$tval,
|
||||
DoubleRegs:$fval, SETGT)),
|
||||
(COMBINE_rr (MUX_rr (CMPGT64rr DoubleRegs:$lhs, DoubleRegs:$rhs),
|
||||
(EXTRACT_SUBREG DoubleRegs:$tval, subreg_hireg),
|
||||
(EXTRACT_SUBREG DoubleRegs:$fval, subreg_hireg)),
|
||||
(MUX_rr (CMPGT64rr DoubleRegs:$lhs, DoubleRegs:$rhs),
|
||||
(EXTRACT_SUBREG DoubleRegs:$tval, subreg_loreg),
|
||||
(EXTRACT_SUBREG DoubleRegs:$fval, subreg_loreg)))>;
|
||||
|
||||
|
||||
// setlt-64 -> setgt-64.
|
||||
def : Pat<(i64 (selectcc DoubleRegs:$lhs, DoubleRegs:$rhs, DoubleRegs:$tval,
|
||||
DoubleRegs:$fval, SETLT)),
|
||||
(COMBINE_rr (MUX_rr (CMPGT64rr DoubleRegs:$lhs,
|
||||
(ADD64_rr DoubleRegs:$rhs, (TFRI64 -1))),
|
||||
(EXTRACT_SUBREG DoubleRegs:$tval, subreg_hireg),
|
||||
(EXTRACT_SUBREG DoubleRegs:$fval, subreg_hireg)),
|
||||
(MUX_rr (CMPGT64rr DoubleRegs:$lhs,
|
||||
(ADD64_rr DoubleRegs:$rhs, (TFRI64 -1))),
|
||||
(EXTRACT_SUBREG DoubleRegs:$tval, subreg_loreg),
|
||||
(EXTRACT_SUBREG DoubleRegs:$fval, subreg_loreg)))>;
|
46
lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp
Normal file
46
lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
//===-- HexagonSelectionDAGInfo.cpp - Hexagon SelectionDAG Info -----------===//
|
||||
//
|
||||
// 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 HexagonSelectionDAGInfo class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "hexagon-selectiondag-info"
|
||||
#include "HexagonTargetMachine.h"
|
||||
using namespace llvm;
|
||||
|
||||
bool llvm::flag_aligned_memcpy;
|
||||
|
||||
HexagonSelectionDAGInfo::HexagonSelectionDAGInfo(const HexagonTargetMachine
|
||||
&TM)
|
||||
: TargetSelectionDAGInfo(TM) {
|
||||
}
|
||||
|
||||
HexagonSelectionDAGInfo::~HexagonSelectionDAGInfo() {
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonSelectionDAGInfo::
|
||||
EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, SDValue Chain,
|
||||
SDValue Dst, SDValue Src, SDValue Size, unsigned Align,
|
||||
bool isVolatile, bool AlwaysInline,
|
||||
MachinePointerInfo DstPtrInfo,
|
||||
MachinePointerInfo SrcPtrInfo) const {
|
||||
flag_aligned_memcpy = false;
|
||||
if ((Align & 0x3) == 0) {
|
||||
ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
|
||||
if (ConstantSize) {
|
||||
uint64_t SizeVal = ConstantSize->getZExtValue();
|
||||
if ((SizeVal > 32) && ((SizeVal % 8) == 0))
|
||||
flag_aligned_memcpy = true;
|
||||
}
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
}
|
40
lib/Target/Hexagon/HexagonSelectionDAGInfo.h
Normal file
40
lib/Target/Hexagon/HexagonSelectionDAGInfo.h
Normal file
@ -0,0 +1,40 @@
|
||||
//=-- HexagonSelectionDAGInfo.h - Hexagon SelectionDAG 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 defines the Hexagon subclass for TargetSelectionDAGInfo.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef HexagonSELECTIONDAGINFO_H
|
||||
#define HexagonSELECTIONDAGINFO_H
|
||||
|
||||
#include "llvm/Target/TargetSelectionDAGInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class HexagonTargetMachine;
|
||||
|
||||
class HexagonSelectionDAGInfo : public TargetSelectionDAGInfo {
|
||||
public:
|
||||
explicit HexagonSelectionDAGInfo(const HexagonTargetMachine &TM);
|
||||
~HexagonSelectionDAGInfo();
|
||||
|
||||
virtual
|
||||
SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
|
||||
SDValue Chain,
|
||||
SDValue Dst, SDValue Src,
|
||||
SDValue Size, unsigned Align,
|
||||
bool isVolatile, bool AlwaysInline,
|
||||
MachinePointerInfo DstPtrInfo,
|
||||
MachinePointerInfo SrcPtrInfo) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
136
lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp
Normal file
136
lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
//===---- HexagonSplitTFRCondSets.cpp - split TFR condsets into xfers -----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===////
|
||||
// This pass tries to provide opportunities for better optimization of muxes.
|
||||
// The default code generated for something like: flag = (a == b) ? 1 : 3;
|
||||
// would be:
|
||||
//
|
||||
// {p0 = cmp.eq(r0,r1)}
|
||||
// {r3 = mux(p0,#1,#3)}
|
||||
//
|
||||
// This requires two packets. If we use .new predicated immediate transfers,
|
||||
// then we can do this in a single packet, e.g.:
|
||||
//
|
||||
// {p0 = cmp.eq(r0,r1)
|
||||
// if (p0.new) r3 = #1
|
||||
// if (!p0.new) r3 = #3}
|
||||
//
|
||||
// Note that the conditional assignments are not generated in .new form here.
|
||||
// We assume opptimisically that they will be formed later.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "xfer"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/CodeGen/LatencyPriorityQueue.h"
|
||||
#include "llvm/CodeGen/SchedulerRegistry.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#define DEBUG_TYPE "xfer"
|
||||
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
||||
class HexagonSplitTFRCondSets : public MachineFunctionPass {
|
||||
HexagonTargetMachine& QTM;
|
||||
const HexagonSubtarget &QST;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
HexagonSplitTFRCondSets(HexagonTargetMachine& TM) :
|
||||
MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {}
|
||||
|
||||
const char *getPassName() const {
|
||||
return "Hexagon Split TFRCondSets";
|
||||
}
|
||||
bool runOnMachineFunction(MachineFunction &Fn);
|
||||
};
|
||||
|
||||
|
||||
char HexagonSplitTFRCondSets::ID = 0;
|
||||
|
||||
|
||||
bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) {
|
||||
|
||||
const TargetInstrInfo *TII = QTM.getInstrInfo();
|
||||
|
||||
// Loop over all of the basic blocks.
|
||||
for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
|
||||
MBBb != MBBe; ++MBBb) {
|
||||
MachineBasicBlock* MBB = MBBb;
|
||||
// Traverse the basic block.
|
||||
for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
|
||||
++MII) {
|
||||
MachineInstr *MI = MII;
|
||||
int Opc = MI->getOpcode();
|
||||
if (Opc == Hexagon::TFR_condset_rr) {
|
||||
|
||||
int DestReg = MI->getOperand(0).getReg();
|
||||
int SrcReg1 = MI->getOperand(2).getReg();
|
||||
int SrcReg2 = MI->getOperand(3).getReg();
|
||||
|
||||
// Minor optimization: do not emit the predicated copy if the source and
|
||||
// the destination is the same register
|
||||
if (DestReg != SrcReg1) {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_cPt),
|
||||
DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg1);
|
||||
}
|
||||
if (DestReg != SrcReg2) {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_cNotPt),
|
||||
DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg2);
|
||||
}
|
||||
MII = MBB->erase(MI);
|
||||
--MII;
|
||||
} else if (Opc == Hexagon::TFR_condset_ii) {
|
||||
int DestReg = MI->getOperand(0).getReg();
|
||||
int SrcReg1 = MI->getOperand(1).getReg();
|
||||
int Immed1 = MI->getOperand(2).getImm();
|
||||
int Immed2 = MI->getOperand(3).getImm();
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cPt),
|
||||
DestReg).addReg(SrcReg1).addImm(Immed1);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cNotPt),
|
||||
DestReg).addReg(SrcReg1).addImm(Immed2);
|
||||
MII = MBB->erase(MI);
|
||||
--MII;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Public Constructor Functions
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
FunctionPass *llvm::createHexagonSplitTFRCondSets(HexagonTargetMachine &TM) {
|
||||
return new HexagonSplitTFRCondSets(TM);
|
||||
}
|
60
lib/Target/Hexagon/HexagonSubtarget.cpp
Normal file
60
lib/Target/Hexagon/HexagonSubtarget.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
//===- HexagonSubtarget.cpp - Hexagon Subtarget Information ---------------===//
|
||||
//
|
||||
// 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 Hexagon specific subclass of TargetSubtarget.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "Hexagon.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
using namespace llvm;
|
||||
|
||||
#define GET_SUBTARGETINFO_MC_DESC
|
||||
#define GET_SUBTARGETINFO_CTOR
|
||||
#define GET_SUBTARGETINFO_TARGET_DESC
|
||||
#include "HexagonGenSubtargetInfo.inc"
|
||||
|
||||
static cl::opt<bool>
|
||||
EnableV3("enable-hexagon-v3", cl::Hidden,
|
||||
cl::desc("Enable Hexagon V3 instructions."));
|
||||
|
||||
static cl::opt<bool>
|
||||
EnableMemOps(
|
||||
"enable-hexagon-memops",
|
||||
cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed,
|
||||
cl::desc("Generate V4 MEMOP in code generation for Hexagon target"));
|
||||
|
||||
HexagonSubtarget::HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS):
|
||||
HexagonGenSubtargetInfo(TT, CPU, FS),
|
||||
HexagonArchVersion(V1),
|
||||
CPUString(CPU.str()) {
|
||||
ParseSubtargetFeatures(CPU, FS);
|
||||
|
||||
switch(HexagonArchVersion) {
|
||||
case HexagonSubtarget::V2:
|
||||
break;
|
||||
case HexagonSubtarget::V3:
|
||||
EnableV3 = true;
|
||||
break;
|
||||
case HexagonSubtarget::V4:
|
||||
break;
|
||||
default:
|
||||
llvm_unreachable("Unknown Architecture Version.");
|
||||
}
|
||||
|
||||
// Initialize scheduling itinerary for the specified CPU.
|
||||
InstrItins = getInstrItineraryForCPU(CPUString);
|
||||
|
||||
if (EnableMemOps)
|
||||
UseMemOps = true;
|
||||
else
|
||||
UseMemOps = false;
|
||||
}
|
74
lib/Target/Hexagon/HexagonSubtarget.h
Normal file
74
lib/Target/Hexagon/HexagonSubtarget.h
Normal file
@ -0,0 +1,74 @@
|
||||
//==-- HexagonSubtarget.h - Define Subtarget for the Hexagon ----*- 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 Hexagon specific subclass of TargetSubtarget.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef Hexagon_SUBTARGET_H
|
||||
#define Hexagon_SUBTARGET_H
|
||||
|
||||
#include "llvm/Target/TargetSubtargetInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include <string>
|
||||
|
||||
#define GET_SUBTARGETINFO_HEADER
|
||||
#include "HexagonGenSubtargetInfo.inc"
|
||||
|
||||
#define Hexagon_SMALL_DATA_THRESHOLD 8
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class HexagonSubtarget : public HexagonGenSubtargetInfo {
|
||||
|
||||
bool UseMemOps;
|
||||
|
||||
public:
|
||||
enum HexagonArchEnum {
|
||||
V1, V2, V3, V4
|
||||
};
|
||||
|
||||
HexagonArchEnum HexagonArchVersion;
|
||||
std::string CPUString;
|
||||
InstrItineraryData InstrItins;
|
||||
|
||||
public:
|
||||
HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS);
|
||||
|
||||
/// getInstrItins - Return the instruction itineraies based on subtarget
|
||||
/// selection.
|
||||
const InstrItineraryData &getInstrItineraryData() const { return InstrItins; }
|
||||
|
||||
|
||||
/// ParseSubtargetFeatures - Parses features string setting specified
|
||||
/// subtarget options. Definition of function is auto generated by tblgen.
|
||||
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
|
||||
|
||||
bool hasV2TOps () const { return HexagonArchVersion >= V2; }
|
||||
bool hasV2TOpsOnly () const { return HexagonArchVersion == V2; }
|
||||
bool hasV3TOps () const { return HexagonArchVersion >= V3; }
|
||||
bool hasV3TOpsOnly () const { return HexagonArchVersion == V3; }
|
||||
bool hasV4TOps () const { return HexagonArchVersion >= V4; }
|
||||
bool useMemOps () const { return HexagonArchVersion >= V4 && UseMemOps; }
|
||||
|
||||
bool isSubtargetV2() const { return HexagonArchVersion == V2;}
|
||||
const std::string &getCPUString () const { return CPUString; }
|
||||
|
||||
// Threshold for small data section
|
||||
unsigned getSmallDataThreshold() const {
|
||||
return Hexagon_SMALL_DATA_THRESHOLD;
|
||||
}
|
||||
const HexagonArchEnum &getHexagonArchVersion() const {
|
||||
return HexagonArchVersion;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
128
lib/Target/Hexagon/HexagonTargetMachine.cpp
Normal file
128
lib/Target/Hexagon/HexagonTargetMachine.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
//===-- HexagonTargetMachine.cpp - Define TargetMachine for Hexagon -------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "HexagonMCAsmInfo.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonISelLowering.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include <iostream>
|
||||
|
||||
#define GET_REGINFO_MC_DESC
|
||||
#define GET_REGINFO_TARGET_DESC
|
||||
#include "HexagonGenRegisterInfo.inc"
|
||||
|
||||
extern "C" void LLVMInitializeHexagonTargetMC() {}
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::
|
||||
opt<bool> DisableHardwareLoops(
|
||||
"disable-hexagon-hwloops", cl::Hidden,
|
||||
cl::desc("Disable Hardware Loops for Hexagon target"));
|
||||
|
||||
/// HexagonTargetMachineModule - Note that this is used on hosts that
|
||||
/// cannot link in a library unless there are references into the
|
||||
/// library. In particular, it seems that it is not possible to get
|
||||
/// things to work on Win32 without this. Though it is unused, do not
|
||||
/// remove it.
|
||||
extern "C" int HexagonTargetMachineModule;
|
||||
int HexagonTargetMachineModule = 0;
|
||||
|
||||
extern "C" void LLVMInitializeHexagonTarget() {
|
||||
// Register the target.
|
||||
RegisterTargetMachine<HexagonTargetMachine> X(TheHexagonTarget);
|
||||
|
||||
// Register the target asm info.
|
||||
RegisterMCAsmInfo<HexagonMCAsmInfo> A(TheHexagonTarget);
|
||||
}
|
||||
|
||||
|
||||
/// HexagonTargetMachine ctor - Create an ILP32 architecture model.
|
||||
///
|
||||
|
||||
/// Hexagon_TODO: Do I need an aggregate alignment?
|
||||
///
|
||||
HexagonTargetMachine::HexagonTargetMachine(const Target &T, StringRef TT,
|
||||
StringRef CPU, StringRef FS,
|
||||
TargetOptions Options,
|
||||
Reloc::Model RM,
|
||||
CodeModel::Model CM,
|
||||
CodeGenOpt::Level OL)
|
||||
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
|
||||
DataLayout("e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-a0:0") ,
|
||||
Subtarget(TT, CPU, FS), TLInfo(*this), InstrInfo(Subtarget),
|
||||
TSInfo(*this),
|
||||
FrameLowering(Subtarget),
|
||||
InstrItins(&Subtarget.getInstrItineraryData()) {
|
||||
setMCUseCFI(false);
|
||||
}
|
||||
|
||||
// addPassesForOptimizations - Allow the backend (target) to add Target
|
||||
// Independent Optimization passes to the Pass Manager.
|
||||
bool HexagonTargetMachine::addPassesForOptimizations(PassManagerBase &PM) {
|
||||
|
||||
PM.add(createConstantPropagationPass());
|
||||
PM.add(createLoopSimplifyPass());
|
||||
PM.add(createDeadCodeEliminationPass());
|
||||
PM.add(createConstantPropagationPass());
|
||||
PM.add(createLoopUnrollPass());
|
||||
PM.add(createLoopStrengthReducePass(getTargetLowering()));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HexagonTargetMachine::addInstSelector(PassManagerBase &PM) {
|
||||
PM.add(createHexagonRemoveExtendOps(*this));
|
||||
PM.add(createHexagonISelDag(*this));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonTargetMachine::addPreRegAlloc(PassManagerBase &PM) {
|
||||
if (!DisableHardwareLoops) {
|
||||
PM.add(createHexagonHardwareLoops());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HexagonTargetMachine::addPostRegAlloc(PassManagerBase &PM) {
|
||||
PM.add(createHexagonCFGOptimizer(*this));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonTargetMachine::addPreSched2(PassManagerBase &PM) {
|
||||
PM.add(createIfConverterPass());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HexagonTargetMachine::addPreEmitPass(PassManagerBase &PM) {
|
||||
|
||||
if (!DisableHardwareLoops) {
|
||||
PM.add(createHexagonFixupHwLoops());
|
||||
}
|
||||
|
||||
// Expand Spill code for predicate registers.
|
||||
PM.add(createHexagonExpandPredSpillCode(*this));
|
||||
|
||||
// Split up TFRcondsets into conditional transfers.
|
||||
PM.add(createHexagonSplitTFRCondSets(*this));
|
||||
|
||||
return false;
|
||||
}
|
86
lib/Target/Hexagon/HexagonTargetMachine.h
Normal file
86
lib/Target/Hexagon/HexagonTargetMachine.h
Normal file
@ -0,0 +1,86 @@
|
||||
//=-- HexagonTargetMachine.h - Define TargetMachine for Hexagon ---*- 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 Hexagon specific subclass of TargetMachine.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef HexagonTARGETMACHINE_H
|
||||
#define HexagonTARGETMACHINE_H
|
||||
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "HexagonInstrInfo.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonISelLowering.h"
|
||||
#include "HexagonSelectionDAGInfo.h"
|
||||
#include "HexagonFrameLowering.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Module;
|
||||
|
||||
class HexagonTargetMachine : public LLVMTargetMachine {
|
||||
const TargetData DataLayout; // Calculates type size & alignment.
|
||||
HexagonSubtarget Subtarget;
|
||||
HexagonTargetLowering TLInfo;
|
||||
HexagonInstrInfo InstrInfo;
|
||||
HexagonSelectionDAGInfo TSInfo;
|
||||
HexagonFrameLowering FrameLowering;
|
||||
const InstrItineraryData* InstrItins;
|
||||
|
||||
public:
|
||||
HexagonTargetMachine(const Target &T, StringRef TT,StringRef CPU,
|
||||
StringRef FS, TargetOptions Options, Reloc::Model RM,
|
||||
CodeModel::Model CM, CodeGenOpt::Level OL);
|
||||
|
||||
virtual const HexagonInstrInfo *getInstrInfo() const {
|
||||
return &InstrInfo;
|
||||
}
|
||||
virtual const HexagonSubtarget *getSubtargetImpl() const {
|
||||
return &Subtarget;
|
||||
}
|
||||
virtual const HexagonRegisterInfo *getRegisterInfo() const {
|
||||
return &InstrInfo.getRegisterInfo();
|
||||
}
|
||||
|
||||
virtual const InstrItineraryData* getInstrItineraryData() const {
|
||||
return InstrItins;
|
||||
}
|
||||
|
||||
|
||||
virtual const HexagonTargetLowering* getTargetLowering() const {
|
||||
return &TLInfo;
|
||||
}
|
||||
|
||||
virtual const HexagonFrameLowering* getFrameLowering() const {
|
||||
return &FrameLowering;
|
||||
}
|
||||
|
||||
virtual const HexagonSelectionDAGInfo* getSelectionDAGInfo() const {
|
||||
return &TSInfo;
|
||||
}
|
||||
|
||||
virtual const TargetData *getTargetData() const { return &DataLayout; }
|
||||
static unsigned getModuleMatchQuality(const Module &M);
|
||||
|
||||
// Pass Pipeline Configuration.
|
||||
virtual bool addPassesForOptimizations(PassManagerBase &PM);
|
||||
virtual bool addInstSelector(PassManagerBase &PM);
|
||||
virtual bool addPreEmitPass(PassManagerBase &PM);
|
||||
virtual bool addPreRegAlloc(llvm::PassManagerBase &PM);
|
||||
virtual bool addPostRegAlloc(PassManagerBase &PM);
|
||||
virtual bool addPreSched2(PassManagerBase &PM);
|
||||
};
|
||||
|
||||
extern bool flag_aligned_memcpy;
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
94
lib/Target/Hexagon/HexagonTargetObjectFile.cpp
Normal file
94
lib/Target/Hexagon/HexagonTargetObjectFile.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
//===-- HexagonTargetObjectFile.cpp - Hexagon 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 declarations of the HexagonTargetAsmInfo properties.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonTargetObjectFile.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<int> SmallDataThreshold("hexagon-small-data-threshold",
|
||||
cl::init(8), cl::Hidden);
|
||||
|
||||
void HexagonTargetObjectFile::Initialize(MCContext &Ctx,
|
||||
const TargetMachine &TM) {
|
||||
TargetLoweringObjectFileELF::Initialize(Ctx, TM);
|
||||
|
||||
|
||||
SmallDataSection =
|
||||
getContext().getELFSection(".sdata", ELF::SHT_PROGBITS,
|
||||
ELF::SHF_WRITE | ELF::SHF_ALLOC,
|
||||
SectionKind::getDataRel());
|
||||
SmallBSSSection =
|
||||
getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
|
||||
ELF::SHF_WRITE | ELF::SHF_ALLOC,
|
||||
SectionKind::getBSS());
|
||||
}
|
||||
|
||||
// sdata/sbss support taken largely from the MIPS Backend.
|
||||
static bool IsInSmallSection(uint64_t Size) {
|
||||
return Size > 0 && Size <= (uint64_t)SmallDataThreshold;
|
||||
}
|
||||
/// IsGlobalInSmallSection - Return true if this global value should be
|
||||
/// placed into small data/bss section.
|
||||
bool HexagonTargetObjectFile::IsGlobalInSmallSection(const GlobalValue *GV,
|
||||
const TargetMachine &TM) const {
|
||||
// If the primary definition of this global value is outside the current
|
||||
// translation unit or the global value is available for inspection but not
|
||||
// emission, then do nothing.
|
||||
if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage())
|
||||
return false;
|
||||
|
||||
// Otherwise, Check if GV should be in sdata/sbss, when normally it would end
|
||||
// up in getKindForGlobal(GV, TM).
|
||||
return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM));
|
||||
}
|
||||
|
||||
/// IsGlobalInSmallSection - Return true if this global value should be
|
||||
/// placed into small data/bss section.
|
||||
bool HexagonTargetObjectFile::
|
||||
IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM,
|
||||
SectionKind Kind) const {
|
||||
// Only global variables, not functions.
|
||||
const GlobalVariable *GVA = dyn_cast<GlobalVariable>(GV);
|
||||
if (!GVA)
|
||||
return false;
|
||||
|
||||
if (Kind.isBSS() || Kind.isDataNoRel() || Kind.isCommon()) {
|
||||
Type *Ty = GV->getType()->getElementType();
|
||||
return IsInSmallSection(TM.getTargetData()->getTypeAllocSize(Ty));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const MCSection *HexagonTargetObjectFile::
|
||||
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
|
||||
Mangler *Mang, const TargetMachine &TM) const {
|
||||
|
||||
// Handle Small Section classification here.
|
||||
if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind))
|
||||
return SmallBSSSection;
|
||||
if (Kind.isDataNoRel() && IsGlobalInSmallSection(GV, TM, Kind))
|
||||
return SmallDataSection;
|
||||
|
||||
// Otherwise, we work the same as ELF.
|
||||
return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM);
|
||||
}
|
40
lib/Target/Hexagon/HexagonTargetObjectFile.h
Normal file
40
lib/Target/Hexagon/HexagonTargetObjectFile.h
Normal file
@ -0,0 +1,40 @@
|
||||
//===-- HexagonTargetAsmInfo.h - Hexagon asm properties ---------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef HexagonTARGETOBJECTFILE_H
|
||||
#define HexagonTARGETOBJECTFILE_H
|
||||
|
||||
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class HexagonTargetObjectFile : public TargetLoweringObjectFileELF {
|
||||
const MCSectionELF *SmallDataSection;
|
||||
const MCSectionELF *SmallBSSSection;
|
||||
public:
|
||||
virtual void Initialize(MCContext &Ctx, const TargetMachine &TM);
|
||||
|
||||
/// IsGlobalInSmallSection - Return true if this global address should be
|
||||
/// placed into small data/bss section.
|
||||
bool IsGlobalInSmallSection(const GlobalValue *GV,
|
||||
const TargetMachine &TM,
|
||||
SectionKind Kind) const;
|
||||
bool IsGlobalInSmallSection(const GlobalValue *GV,
|
||||
const TargetMachine &TM) const;
|
||||
|
||||
const MCSection* SelectSectionForGlobal(const GlobalValue *GV,
|
||||
SectionKind Kind,
|
||||
Mangler *Mang,
|
||||
const TargetMachine &TM) const;
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
141
lib/Target/Hexagon/HexagonVarargsCallingConvention.h
Normal file
141
lib/Target/Hexagon/HexagonVarargsCallingConvention.h
Normal file
@ -0,0 +1,141 @@
|
||||
//==-- HexagonVarargsCallingConvention.h - Calling Conventions ---*- 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 functions that assign locations to outgoing function
|
||||
// arguments. Adapted from the target independent version but this handles
|
||||
// calls to varargs functions
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
static bool RetCC_Hexagon32_VarArgs(unsigned ValNo, EVT ValVT,
|
||||
EVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||
ISD::ArgFlagsTy ArgFlags,
|
||||
Hexagon_CCState &State,
|
||||
int NonVarArgsParams,
|
||||
int CurrentParam,
|
||||
bool ForceMem);
|
||||
|
||||
|
||||
static bool CC_Hexagon32_VarArgs(unsigned ValNo, EVT ValVT,
|
||||
EVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||
ISD::ArgFlagsTy ArgFlags,
|
||||
Hexagon_CCState &State,
|
||||
int NonVarArgsParams,
|
||||
int CurrentParam,
|
||||
bool ForceMem) {
|
||||
unsigned ByValSize = 0;
|
||||
if (ArgFlags.isByVal() &&
|
||||
((ByValSize = ArgFlags.getByValSize()) >
|
||||
(MVT(MVT::i64).getSizeInBits() / 8))) {
|
||||
ForceMem = true;
|
||||
}
|
||||
|
||||
|
||||
// Only assign registers for named (non varargs) arguments
|
||||
if ( !ForceMem && ((NonVarArgsParams == -1) || (CurrentParam <=
|
||||
NonVarArgsParams))) {
|
||||
|
||||
if (LocVT == MVT::i32 ||
|
||||
LocVT == MVT::i16 ||
|
||||
LocVT == MVT::i8 ||
|
||||
LocVT == MVT::f32) {
|
||||
static const unsigned RegList1[] = {
|
||||
Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
|
||||
Hexagon::R5
|
||||
};
|
||||
if (unsigned Reg = State.AllocateReg(RegList1, 6)) {
|
||||
State.addLoc(CCValAssign::getReg(ValNo, ValVT.getSimpleVT(), Reg,
|
||||
LocVT.getSimpleVT(), LocInfo));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (LocVT == MVT::i64 ||
|
||||
LocVT == MVT::f64) {
|
||||
static const unsigned RegList2[] = {
|
||||
Hexagon::D0, Hexagon::D1, Hexagon::D2
|
||||
};
|
||||
if (unsigned Reg = State.AllocateReg(RegList2, 3)) {
|
||||
State.addLoc(CCValAssign::getReg(ValNo, ValVT.getSimpleVT(), Reg,
|
||||
LocVT.getSimpleVT(), LocInfo));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Type* ArgTy = LocVT.getTypeForEVT(State.getContext());
|
||||
unsigned Alignment =
|
||||
State.getTarget().getTargetData()->getABITypeAlignment(ArgTy);
|
||||
unsigned Size =
|
||||
State.getTarget().getTargetData()->getTypeSizeInBits(ArgTy) / 8;
|
||||
|
||||
// If it's passed by value, then we need the size of the aggregate not of
|
||||
// the pointer.
|
||||
if (ArgFlags.isByVal()) {
|
||||
Size = ByValSize;
|
||||
|
||||
// Hexagon_TODO: Get the alignment of the contained type here.
|
||||
Alignment = 8;
|
||||
}
|
||||
|
||||
unsigned Offset3 = State.AllocateStack(Size, Alignment);
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset3,
|
||||
LocVT.getSimpleVT(), LocInfo));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool RetCC_Hexagon32_VarArgs(unsigned ValNo, EVT ValVT,
|
||||
EVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||
ISD::ArgFlagsTy ArgFlags,
|
||||
Hexagon_CCState &State,
|
||||
int NonVarArgsParams,
|
||||
int CurrentParam,
|
||||
bool ForceMem) {
|
||||
|
||||
if (LocVT == MVT::i32 ||
|
||||
LocVT == MVT::f32) {
|
||||
static const unsigned RegList1[] = {
|
||||
Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
|
||||
Hexagon::R5
|
||||
};
|
||||
if (unsigned Reg = State.AllocateReg(RegList1, 6)) {
|
||||
State.addLoc(CCValAssign::getReg(ValNo, ValVT.getSimpleVT(), Reg,
|
||||
LocVT.getSimpleVT(), LocInfo));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (LocVT == MVT::i64 ||
|
||||
LocVT == MVT::f64) {
|
||||
static const unsigned RegList2[] = {
|
||||
Hexagon::D0, Hexagon::D1, Hexagon::D2
|
||||
};
|
||||
if (unsigned Reg = State.AllocateReg(RegList2, 3)) {
|
||||
State.addLoc(CCValAssign::getReg(ValNo, ValVT.getSimpleVT(), Reg,
|
||||
LocVT.getSimpleVT(), LocInfo));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const Type* ArgTy = LocVT.getTypeForEVT(State.getContext());
|
||||
unsigned Alignment =
|
||||
State.getTarget().getTargetData()->getABITypeAlignment(ArgTy);
|
||||
unsigned Size =
|
||||
State.getTarget().getTargetData()->getTypeSizeInBits(ArgTy) / 8;
|
||||
|
||||
unsigned Offset3 = State.AllocateStack(Size, Alignment);
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT.getSimpleVT(), Offset3,
|
||||
LocVT.getSimpleVT(), LocInfo));
|
||||
return false;
|
||||
}
|
30
lib/Target/Hexagon/LLVMBuild.txt
Normal file
30
lib/Target/Hexagon/LLVMBuild.txt
Normal file
@ -0,0 +1,30 @@
|
||||
;===- ./lib/Target/Hexagon/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 = TargetGroup
|
||||
name = Hexagon
|
||||
parent = Target
|
||||
has_asmprinter = 1
|
||||
|
||||
[component_1]
|
||||
type = Library
|
||||
name = HexagonCodeGen
|
||||
parent = Hexagon
|
||||
required_libraries = AsmPrinter CodeGen Core HexagonInfo SelectionDAG Support Target MC
|
||||
add_to_library_groups = Hexagon
|
||||
|
23
lib/Target/Hexagon/Makefile
Normal file
23
lib/Target/Hexagon/Makefile
Normal file
@ -0,0 +1,23 @@
|
||||
##===- lib/Target/Hexagon/Makefile -------------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../..
|
||||
LIBRARYNAME = LLVMHexagonCodeGen
|
||||
TARGET = Hexagon
|
||||
|
||||
# Make sure that tblgen is run, first thing.
|
||||
BUILT_SOURCES = HexagonGenRegisterInfo.inc \
|
||||
HexagonGenInstrInfo.inc \
|
||||
HexagonGenAsmWriter.inc \
|
||||
HexagonGenDAGISel.inc HexagonGenSubtargetInfo.inc \
|
||||
HexagonGenCallingConv.inc \
|
||||
HexagonAsmPrinter.cpp
|
||||
|
||||
DIRS = TargetInfo
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
14
lib/Target/Hexagon/TargetInfo/CMakeLists.txt
Normal file
14
lib/Target/Hexagon/TargetInfo/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/.. )
|
||||
|
||||
add_llvm_library(LLVMHexagonInfo
|
||||
HexagonTargetInfo.cpp
|
||||
)
|
||||
|
||||
add_llvm_library_dependencies(LLVMHexagonInfo
|
||||
LLVMMC
|
||||
LLVMSupport
|
||||
LLVMTarget
|
||||
)
|
||||
|
||||
add_dependencies(LLVMHexagonInfo HexagonCommonTableGen)
|
19
lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp
Normal file
19
lib/Target/Hexagon/TargetInfo/HexagonTargetInfo.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
//===-- HexagonTargetInfo.cpp - Hexagon Target Implementation ------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "Hexagon.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
using namespace llvm;
|
||||
|
||||
Target llvm::TheHexagonTarget;
|
||||
|
||||
extern "C" void LLVMInitializeHexagonTargetInfo() {
|
||||
RegisterTarget<Triple::hexagon, /*HasJIT=*/false> X(TheHexagonTarget, "hexagon", "Hexagon");
|
||||
}
|
24
lib/Target/Hexagon/TargetInfo/LLVMBuild.txt
Normal file
24
lib/Target/Hexagon/TargetInfo/LLVMBuild.txt
Normal file
@ -0,0 +1,24 @@
|
||||
;===- ./lib/Target/Hexagon/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 = HexagonInfo
|
||||
parent = Hexagon
|
||||
required_libraries = MC Support
|
||||
add_to_library_groups = Hexagon
|
||||
|
15
lib/Target/Hexagon/TargetInfo/Makefile
Normal file
15
lib/Target/Hexagon/TargetInfo/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
##===- lib/Target/Hexagon/TargetInfo/Makefile ----------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../../..
|
||||
LIBRARYNAME = LLVMHexagonInfo
|
||||
|
||||
# Hack: we need to include 'main' target directory to grab private headers
|
||||
CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
@ -300,6 +300,7 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch],
|
||||
mips-*) llvm_cv_target_arch="Mips" ;;
|
||||
xcore-*) llvm_cv_target_arch="XCore" ;;
|
||||
msp430-*) llvm_cv_target_arch="MSP430" ;;
|
||||
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
|
||||
mblaze-*) llvm_cv_target_arch="MBlaze" ;;
|
||||
ptx-*) llvm_cv_target_arch="PTX" ;;
|
||||
*) llvm_cv_target_arch="Unknown" ;;
|
||||
@ -434,6 +435,7 @@ else
|
||||
Mips) AC_SUBST(TARGET_HAS_JIT,1) ;;
|
||||
XCore) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
MBlaze) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
PTX) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
*) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
@ -545,14 +547,14 @@ dnl Allow specific targets to be specified for building (or not)
|
||||
TARGETS_TO_BUILD=""
|
||||
AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets],
|
||||
[Build specific host targets: all or target1,target2,... Valid targets are:
|
||||
host, x86, x86_64, sparc, powerpc, arm, mips, spu,
|
||||
host, x86, x86_64, sparc, powerpc, arm, mips, spu, hexagon,
|
||||
xcore, msp430, ptx, cbe, and cpp (default=all)]),,
|
||||
enableval=all)
|
||||
if test "$enableval" = host-only ; then
|
||||
enableval=host
|
||||
fi
|
||||
case "$enableval" in
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX" ;;
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 Hexagon CBackend CppBackend MBlaze PTX" ;;
|
||||
*)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do
|
||||
case "$a_target" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
@ -564,6 +566,7 @@ case "$enableval" in
|
||||
spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;;
|
||||
xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||
msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;;
|
||||
cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;;
|
||||
mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
@ -579,6 +582,7 @@ case "$enableval" in
|
||||
CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;;
|
||||
XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||
MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
PTX) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;;
|
||||
*) AC_MSG_ERROR([Can not set target to build]) ;;
|
||||
esac ;;
|
||||
|
12
projects/sample/configure
vendored
12
projects/sample/configure
vendored
@ -1401,9 +1401,8 @@ Optional Features:
|
||||
(default is YES)
|
||||
--enable-targets Build specific host targets: all or
|
||||
target1,target2,... Valid targets are: host, x86,
|
||||
x86_64, sparc, powerpc, arm, mips, spu,
|
||||
xcore, msp430, ptx, cbe, and cpp
|
||||
(default=all)
|
||||
x86_64, sparc, powerpc, arm, mips, spu, hexagon,
|
||||
xcore, msp430, ptx, cbe, and cpp (default=all)
|
||||
--enable-cbe-printf-a Enable C Backend output with hex floating point via
|
||||
%a (default is YES)
|
||||
--enable-bindings Build specific language bindings:
|
||||
@ -3844,6 +3843,7 @@ else
|
||||
mips-*) llvm_cv_target_arch="Mips" ;;
|
||||
xcore-*) llvm_cv_target_arch="XCore" ;;
|
||||
msp430-*) llvm_cv_target_arch="MSP430" ;;
|
||||
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
|
||||
mblaze-*) llvm_cv_target_arch="MBlaze" ;;
|
||||
ptx-*) llvm_cv_target_arch="PTX" ;;
|
||||
*) llvm_cv_target_arch="Unknown" ;;
|
||||
@ -5044,6 +5044,8 @@ else
|
||||
XCore) TARGET_HAS_JIT=0
|
||||
;;
|
||||
MSP430) TARGET_HAS_JIT=0
|
||||
;;
|
||||
Hexagon) TARGET_HAS_JIT=0
|
||||
;;
|
||||
MBlaze) TARGET_HAS_JIT=0
|
||||
;;
|
||||
@ -5233,7 +5235,7 @@ if test "$enableval" = host-only ; then
|
||||
enableval=host
|
||||
fi
|
||||
case "$enableval" in
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX" ;;
|
||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 Hexagon CBackend CppBackend MBlaze PTX" ;;
|
||||
*)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do
|
||||
case "$a_target" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
@ -5245,6 +5247,7 @@ case "$enableval" in
|
||||
spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;;
|
||||
xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||
msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;;
|
||||
cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;;
|
||||
mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||
@ -5260,6 +5263,7 @@ case "$enableval" in
|
||||
CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;;
|
||||
XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||
MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
PTX) TARGETS_TO_BUILD="PTX $TARGETS_TO_BUILD" ;;
|
||||
*) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5
|
||||
echo "$as_me: error: Can not set target to build" >&2;}
|
||||
|
18
test/CodeGen/Hexagon/args.ll
Normal file
18
test/CodeGen/Hexagon/args.ll
Normal file
@ -0,0 +1,18 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; CHECK: r[[T0:[0-9]+]] = #7
|
||||
; CHECK: memw(r29 + #0) = r[[T0]]
|
||||
; CHECK: r0 = #1
|
||||
; CHECK: r1 = #2
|
||||
; CHECK: r2 = #3
|
||||
; CHECK: r3 = #4
|
||||
; CHECK: r4 = #5
|
||||
; CHECK: r5 = #6
|
||||
|
||||
|
||||
define void @foo() nounwind {
|
||||
entry:
|
||||
call void @bar(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @bar(i32, i32, i32, i32, i32, i32, i32)
|
17
test/CodeGen/Hexagon/combine.ll
Normal file
17
test/CodeGen/Hexagon/combine.ll
Normal file
@ -0,0 +1,17 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; CHECK: combine(r{{[0-9]+}}, r{{[0-9]+}})
|
||||
|
||||
@j = external global i32
|
||||
@k = external global i64
|
||||
|
||||
define void @foo() nounwind {
|
||||
entry:
|
||||
%0 = load i32* @j, align 4
|
||||
%1 = load i64* @k, align 8
|
||||
%conv = trunc i64 %1 to i32
|
||||
%2 = call i64 @llvm.hexagon.A2.combinew(i32 %0, i32 %conv)
|
||||
store i64 %2, i64* @k, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i64 @llvm.hexagon.A2.combinew(i32, i32) nounwind readnone
|
5
test/CodeGen/Hexagon/dg.exp
Normal file
5
test/CodeGen/Hexagon/dg.exp
Normal file
@ -0,0 +1,5 @@
|
||||
load_lib llvm.exp
|
||||
|
||||
if { [llvm_supports_target Hexagon] } {
|
||||
RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
|
||||
}
|
22
test/CodeGen/Hexagon/double.ll
Normal file
22
test/CodeGen/Hexagon/double.ll
Normal file
@ -0,0 +1,22 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; CHECK: __hexagon_adddf3
|
||||
; CHECK: __hexagon_subdf3
|
||||
|
||||
define void @foo(double* %acc, double %num, double %num2) nounwind {
|
||||
entry:
|
||||
%acc.addr = alloca double*, align 4
|
||||
%num.addr = alloca double, align 8
|
||||
%num2.addr = alloca double, align 8
|
||||
store double* %acc, double** %acc.addr, align 4
|
||||
store double %num, double* %num.addr, align 8
|
||||
store double %num2, double* %num2.addr, align 8
|
||||
%0 = load double** %acc.addr, align 4
|
||||
%1 = load double* %0
|
||||
%2 = load double* %num.addr, align 8
|
||||
%add = fadd double %1, %2
|
||||
%3 = load double* %num2.addr, align 8
|
||||
%sub = fsub double %add, %3
|
||||
%4 = load double** %acc.addr, align 4
|
||||
store double %sub, double* %4
|
||||
ret void
|
||||
}
|
22
test/CodeGen/Hexagon/float.ll
Normal file
22
test/CodeGen/Hexagon/float.ll
Normal file
@ -0,0 +1,22 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; CHECK: __hexagon_addsf3
|
||||
; CHECK: __hexagon_subsf3
|
||||
|
||||
define void @foo(float* %acc, float %num, float %num2) nounwind {
|
||||
entry:
|
||||
%acc.addr = alloca float*, align 4
|
||||
%num.addr = alloca float, align 4
|
||||
%num2.addr = alloca float, align 4
|
||||
store float* %acc, float** %acc.addr, align 4
|
||||
store float %num, float* %num.addr, align 4
|
||||
store float %num2, float* %num2.addr, align 4
|
||||
%0 = load float** %acc.addr, align 4
|
||||
%1 = load float* %0
|
||||
%2 = load float* %num.addr, align 4
|
||||
%add = fadd float %1, %2
|
||||
%3 = load float* %num2.addr, align 4
|
||||
%sub = fsub float %add, %3
|
||||
%4 = load float** %acc.addr, align 4
|
||||
store float %sub, float* %4
|
||||
ret void
|
||||
}
|
23
test/CodeGen/Hexagon/frame.ll
Normal file
23
test/CodeGen/Hexagon/frame.ll
Normal file
@ -0,0 +1,23 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
|
||||
@num = external global i32
|
||||
@acc = external global i32
|
||||
@num2 = external global i32
|
||||
|
||||
; CHECK: allocframe
|
||||
; CHECK: dealloc_return
|
||||
|
||||
define i32 @foo() nounwind {
|
||||
entry:
|
||||
%i = alloca i32, align 4
|
||||
%0 = load i32* @num, align 4
|
||||
store i32 %0, i32* %i, align 4
|
||||
%1 = load i32* %i, align 4
|
||||
%2 = load i32* @acc, align 4
|
||||
%mul = mul nsw i32 %1, %2
|
||||
%3 = load i32* @num2, align 4
|
||||
%add = add nsw i32 %mul, %3
|
||||
store i32 %add, i32* %i, align 4
|
||||
%4 = load i32* %i, align 4
|
||||
ret i32 %4
|
||||
}
|
19
test/CodeGen/Hexagon/mpy.ll
Normal file
19
test/CodeGen/Hexagon/mpy.ll
Normal file
@ -0,0 +1,19 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; CHECK: += mpyi
|
||||
|
||||
define void @foo(i32 %acc, i32 %num, i32 %num2) nounwind {
|
||||
entry:
|
||||
%acc.addr = alloca i32, align 4
|
||||
%num.addr = alloca i32, align 4
|
||||
%num2.addr = alloca i32, align 4
|
||||
store i32 %acc, i32* %acc.addr, align 4
|
||||
store i32 %num, i32* %num.addr, align 4
|
||||
store i32 %num2, i32* %num2.addr, align 4
|
||||
%0 = load i32* %num.addr, align 4
|
||||
%1 = load i32* %acc.addr, align 4
|
||||
%mul = mul nsw i32 %0, %1
|
||||
%2 = load i32* %num2.addr, align 4
|
||||
%add = add nsw i32 %mul, %2
|
||||
store i32 %add, i32* %num.addr, align 4
|
||||
ret void
|
||||
}
|
20
test/CodeGen/Hexagon/static.ll
Normal file
20
test/CodeGen/Hexagon/static.ll
Normal file
@ -0,0 +1,20 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
|
||||
@num = external global i32
|
||||
@acc = external global i32
|
||||
@val = external global i32
|
||||
|
||||
; CHECK: CONST32(#acc)
|
||||
; CHECK: CONST32(#val)
|
||||
; CHECK: CONST32(#num)
|
||||
|
||||
define void @foo() nounwind {
|
||||
entry:
|
||||
%0 = load i32* @num, align 4
|
||||
%1 = load i32* @acc, align 4
|
||||
%mul = mul nsw i32 %0, %1
|
||||
%2 = load i32* @val, align 4
|
||||
%add = add nsw i32 %mul, %2
|
||||
store i32 %add, i32* @num, align 4
|
||||
ret void
|
||||
}
|
15
test/CodeGen/Hexagon/struct_args.ll
Normal file
15
test/CodeGen/Hexagon/struct_args.ll
Normal file
@ -0,0 +1,15 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; CHECK: r1:0 = or(r{{[0-9]}}:{{[0-9]}}, r{{[0-9]}}:{{[0-9]}})
|
||||
|
||||
%struct.small = type { i32, i32 }
|
||||
|
||||
@s1 = common global %struct.small zeroinitializer, align 4
|
||||
|
||||
define void @foo() nounwind {
|
||||
entry:
|
||||
%0 = load i64* bitcast (%struct.small* @s1 to i64*), align 1
|
||||
call void @bar(i64 %0)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @bar(i64)
|
16
test/CodeGen/Hexagon/struct_args_large.ll
Normal file
16
test/CodeGen/Hexagon/struct_args_large.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; CHECK: r[[T0:[0-9]+]] = CONST32(#s2)
|
||||
; CHECK: r[[T1:[0-9]+]] = memw(r[[T0]] + #0)
|
||||
; CHECK: memw(r29 + #0) = r[[T1]]
|
||||
|
||||
%struct.large = type { i64, i64 }
|
||||
|
||||
@s2 = common global %struct.large zeroinitializer, align 8
|
||||
|
||||
define void @foo() nounwind {
|
||||
entry:
|
||||
call void @bar(%struct.large* byval @s2)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @bar(%struct.large* byval)
|
16
test/CodeGen/Hexagon/vaddh.ll
Normal file
16
test/CodeGen/Hexagon/vaddh.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; CHECK: vaddh(r{{[0-9]+}}, r{{[0-9]+}})
|
||||
|
||||
@j = external global i32
|
||||
@k = external global i32
|
||||
|
||||
define void @foo() nounwind {
|
||||
entry:
|
||||
%0 = load i32* @j, align 4
|
||||
%1 = load i32* @k, align 4
|
||||
%2 = call i32 @llvm.hexagon.A2.svaddh(i32 %0, i32 %1)
|
||||
store i32 %2, i32* @k, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i32 @llvm.hexagon.A2.svaddh(i32, i32) nounwind readnone
|
Loading…
x
Reference in New Issue
Block a user