diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2012-08-19 10:31:50 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2012-08-19 10:31:50 +0000 |
commit | 902a7b529820e6a0aa85f98f21afaeb1805a22f8 (patch) | |
tree | e7da40d2f6ef824f7371860826845870e6e1dcd5 | |
parent | 58b69754af0cbff56b1cfce9be9392e4451f6628 (diff) |
Notes
96 files changed, 3324 insertions, 1344 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b5240c7952e..fbf8e2bb90e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,10 +128,15 @@ if( LLVM_TARGETS_TO_BUILD STREQUAL "all" ) set( LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} ) endif() +set(LLVM_TARGETS_TO_BUILD + ${LLVM_TARGETS_TO_BUILD} + ${LLVM_EXPERIMENTAL_TARGETS_TO_BUILD}) + set(LLVM_ENUM_TARGETS "") foreach(c ${LLVM_TARGETS_TO_BUILD}) list(FIND LLVM_ALL_TARGETS ${c} idx) - if( idx LESS 0 ) + list(FIND LLVM_EXPERIMENTAL_TARGETS_TO_BUILD ${c} idy) + if( idx LESS 0 AND idy LESS 0 ) message(FATAL_ERROR "The target `${c}' does not exist. It should be one of\n${LLVM_ALL_TARGETS}") else() @@ -139,11 +144,6 @@ foreach(c ${LLVM_TARGETS_TO_BUILD}) endif() endforeach(c) -set(LLVM_TARGETS_TO_BUILD - ${LLVM_TARGETS_TO_BUILD} - ${LLVM_EXPERIMENTAL_TARGETS_TO_BUILD} - ) - set(llvm_builded_incs_dir ${LLVM_BINARY_DIR}/include/llvm) include(AddLLVMDefinitions) @@ -244,13 +244,13 @@ build-for-llvm-top: SVN = svn SVN-UPDATE-OPTIONS = AWK = awk -SUB-SVN-DIRS = $(AWK) '/\?\ \ \ \ \ \ / {print $$2}' \ +SUB-SVN-DIRS = $(AWK) '/I|\? / {print $$2}' \ | LC_ALL=C xargs $(SVN) info 2>/dev/null \ | $(AWK) '/^Path:\ / {print $$2}' update: $(SVN) $(SVN-UPDATE-OPTIONS) update $(LLVM_SRC_ROOT) - @ $(SVN) status $(LLVM_SRC_ROOT) | $(SUB-SVN-DIRS) | xargs $(SVN) $(SVN-UPDATE-OPTIONS) update + @ $(SVN) status --no-ignore $(LLVM_SRC_ROOT) | $(SUB-SVN-DIRS) | xargs $(SVN) $(SVN-UPDATE-OPTIONS) update happiness: update all check-all diff --git a/Makefile.config.in b/Makefile.config.in index 6d06f16b3575..e3bd2a207a50 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -258,6 +258,11 @@ ENABLE_WERROR = @ENABLE_WERROR@ #DEBUG_SYMBOLS = 1 @DEBUG_SYMBOLS@ +# When KEEP_SYMBOLS is enabled, installed executables will never have their +# symbols stripped. +#KEEP_SYMBOLS = 1 +@KEEP_SYMBOLS@ + # The compiler flags to use for optimized builds. OPTIMIZE_OPTION := @OPTIMIZE_OPTION@ diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 4dde3a6dfa39..7fa883e9cc50 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -542,6 +542,15 @@ else AC_SUBST(DEBUG_SYMBOLS,[[DEBUG_SYMBOLS=1]]) fi +dnl --enable-keep-symbols : do not strip installed executables +AC_ARG_ENABLE(keep-symbols, + AS_HELP_STRING(--enable-keep-symbols,[Do not strip installed executables)]),,enableval=no) +if test ${enableval} = "no" ; then + AC_SUBST(KEEP_SYMBOLS,[[]]) +else + AC_SUBST(KEEP_SYMBOLS,[[KEEP_SYMBOLS=1]]) +fi + dnl --enable-jit: check whether they want to enable the jit AC_ARG_ENABLE(jit, AS_HELP_STRING(--enable-jit, diff --git a/configure b/configure index 62a6478e0af0..6fbc47c72a7e 100755 --- a/configure +++ b/configure @@ -693,6 +693,7 @@ ENABLE_EXPENSIVE_CHECKS EXPENSIVE_CHECKS DEBUG_RUNTIME DEBUG_SYMBOLS +KEEP_SYMBOLS JIT TARGET_HAS_JIT ENABLE_DOCS @@ -1408,6 +1409,7 @@ Optional Features: NO) --enable-debug-symbols Build compiler with debug symbols (default is NO if optimization is on and YES if it's off) + --enable-keep-symbols Do not strip installed executables) --enable-jit Enable Just In Time Compiling (default is YES) --enable-docs Build documents (default is YES) --enable-doxygen Build doxygen documentation (default is NO) @@ -5158,6 +5160,21 @@ else fi +# Check whether --enable-keep-symbols was given. +if test "${enable_keep_symbols+set}" = set; then + enableval=$enable_keep_symbols; +else + enableval=no +fi + +if test ${enableval} = "no" ; then + KEEP_SYMBOLS= + +else + KEEP_SYMBOLS=KEEP_SYMBOLS=1 + +fi + # Check whether --enable-jit was given. if test "${enable_jit+set}" = set; then enableval=$enable_jit; @@ -10272,7 +10289,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF -#line 10275 "configure" +#line 10292 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -22150,12 +22167,12 @@ ENABLE_EXPENSIVE_CHECKS!$ENABLE_EXPENSIVE_CHECKS$ac_delim EXPENSIVE_CHECKS!$EXPENSIVE_CHECKS$ac_delim DEBUG_RUNTIME!$DEBUG_RUNTIME$ac_delim DEBUG_SYMBOLS!$DEBUG_SYMBOLS$ac_delim +KEEP_SYMBOLS!$KEEP_SYMBOLS$ac_delim JIT!$JIT$ac_delim TARGET_HAS_JIT!$TARGET_HAS_JIT$ac_delim ENABLE_DOCS!$ENABLE_DOCS$ac_delim ENABLE_DOXYGEN!$ENABLE_DOXYGEN$ac_delim LLVM_ENABLE_THREADS!$LLVM_ENABLE_THREADS$ac_delim -ENABLE_PTHREADS!$ENABLE_PTHREADS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -22197,6 +22214,7 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +ENABLE_PTHREADS!$ENABLE_PTHREADS$ac_delim ENABLE_PIC!$ENABLE_PIC$ac_delim ENABLE_SHARED!$ENABLE_SHARED$ac_delim ENABLE_EMBED_STDCXX!$ENABLE_EMBED_STDCXX$ac_delim @@ -22293,7 +22311,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 94; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 95; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 65a70fbfa6d0..f60d688c0dce 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -687,8 +687,7 @@ class SmallDenseMap /// A "union" of an inline bucket array and the struct representing /// a large bucket. This union will be discriminated by the 'Small' bit. - typename AlignedCharArray<BucketT[InlineBuckets], LargeRep>::union_type - storage; + AlignedCharArrayUnion<BucketT[InlineBuckets], LargeRep> storage; public: explicit SmallDenseMap(unsigned NumInitBuckets = 0) { @@ -834,8 +833,7 @@ public: return; // Nothing to do. // First move the inline buckets into a temporary storage. - typename AlignedCharArray<BucketT[InlineBuckets]>::union_type - TmpStorage; + AlignedCharArrayUnion<BucketT[InlineBuckets]> TmpStorage; BucketT *TmpBegin = reinterpret_cast<BucketT *>(TmpStorage.buffer); BucketT *TmpEnd = TmpBegin; diff --git a/include/llvm/ADT/VariadicFunction.h b/include/llvm/ADT/VariadicFunction.h index a9a0dc6b6e20..a7f83a6bca9d 100644 --- a/include/llvm/ADT/VariadicFunction.h +++ b/include/llvm/ADT/VariadicFunction.h @@ -206,7 +206,7 @@ struct VariadicFunction2 { ResultT operator()(Param0T P0, Param1T P1, \ LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \ const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \ - return Func(P0, P1, makeAraryRef(Args)); \ + return Func(P0, P1, makeArrayRef(Args)); \ } LLVM_DEFINE_OVERLOAD(1) LLVM_DEFINE_OVERLOAD(2) diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 2ced7967ed5b..006daa082946 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -122,6 +122,7 @@ private: bool calcLoopBranchHeuristics(BasicBlock *BB); bool calcZeroHeuristics(BasicBlock *BB); bool calcFloatingPointHeuristics(BasicBlock *BB); + bool calcInvokeHeuristics(BasicBlock *BB); }; } diff --git a/include/llvm/Analysis/Dominators.h b/include/llvm/Analysis/Dominators.h index 1289eddf51b9..a1cc196eae30 100644 --- a/include/llvm/Analysis/Dominators.h +++ b/include/llvm/Analysis/Dominators.h @@ -705,7 +705,20 @@ DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, const NodeT *B) { EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase<BasicBlock>); -class BasicBlockEdge; +class BasicBlockEdge { + const BasicBlock *Start; + const BasicBlock *End; +public: + BasicBlockEdge(const BasicBlock *Start_, const BasicBlock *End_) : + Start(Start_), End(End_) { } + const BasicBlock *getStart() const { + return Start; + } + const BasicBlock *getEnd() const { + return End; + } + bool isSingleEdge() const; +}; //===------------------------------------- /// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 4c5eb8b36f36..27756abf3f54 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -420,6 +420,12 @@ public: return hasProperty(MCID::Bitcast, Type); } + /// isSelect - Return true if this instruction is a select instruction. + /// + bool isSelect(QueryType Type = IgnoreBundle) const { + return hasProperty(MCID::Select, Type); + } + /// isNotDuplicable - Return true if this instruction cannot be safely /// duplicated. For example, if the instruction has a unique labels attached /// to it, duplicating it would cause multiple definition errors. diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 0dfb394d04a7..db361ee9b1bc 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -146,7 +146,8 @@ public: inline bool isMachineOpcode() const; inline unsigned getMachineOpcode() const; inline const DebugLoc getDebugLoc() const; - + inline void dump() const; + inline void dumpr() const; /// reachesChainWithoutSideEffects - Return true if this operand (which must /// be a chain) reaches the specified operand without crossing any @@ -806,7 +807,12 @@ inline bool SDValue::hasOneUse() const { inline const DebugLoc SDValue::getDebugLoc() const { return Node->getDebugLoc(); } - +inline void SDValue::dump() const { + return Node->dump(); +} +inline void SDValue::dumpr() const { + return Node->dumpr(); +} // Define inline functions from the SDUse class. inline void SDUse::set(const SDValue &V) { diff --git a/include/llvm/IntrinsicsHexagon.td b/include/llvm/IntrinsicsHexagon.td index efd04f309ae3..8a8872931f36 100644 --- a/include/llvm/IntrinsicsHexagon.td +++ b/include/llvm/IntrinsicsHexagon.td @@ -15,7 +15,7 @@ // // All Hexagon intrinsics start with "llvm.hexagon.". let TargetPrefix = "hexagon" in { - /// Hexagon_Intrinsic - Base class for all altivec intrinsics. + /// Hexagon_Intrinsic - Base class for all Hexagon intrinsics. class Hexagon_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types, list<LLVMType> param_types, list<IntrinsicProperty> properties> diff --git a/include/llvm/MC/MCFixedLenDisassembler.h b/include/llvm/MC/MCFixedLenDisassembler.h new file mode 100644 index 000000000000..22b3c32abde9 --- /dev/null +++ b/include/llvm/MC/MCFixedLenDisassembler.h @@ -0,0 +1,32 @@ +//===-- llvm/MC/MCFixedLenDisassembler.h - Decoder driver -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Fixed length disassembler decoder state machine driver. +//===----------------------------------------------------------------------===// +#ifndef MCFIXEDLENDISASSEMBLER_H +#define MCFIXEDLENDISASSEMBLER_H + +namespace llvm { + +namespace MCD { +// Disassembler state machine opcodes. +enum DecoderOps { + OPC_ExtractField = 1, // OPC_ExtractField(uint8_t Start, uint8_t Len) + OPC_FilterValue, // OPC_FilterValue(uleb128 Val, uint16_t NumToSkip) + OPC_CheckField, // OPC_CheckField(uint8_t Start, uint8_t Len, + // uleb128 Val, uint16_t NumToSkip) + OPC_CheckPredicate, // OPC_CheckPredicate(uleb128 PIdx, uint16_t NumToSkip) + OPC_Decode, // OPC_Decode(uleb128 Opcode, uleb128 DIdx) + OPC_SoftFail, // OPC_SoftFail(uleb128 PMask, uleb128 NMask) + OPC_Fail // OPC_Fail() +}; + +} // namespace MCDecode +} // namespace llvm + +#endif diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 186612d904d8..dbf16d870050 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -107,6 +107,7 @@ namespace MCID { Compare, MoveImm, Bitcast, + Select, DelaySlot, FoldableAsLoad, MayLoad, @@ -282,6 +283,12 @@ public: return Flags & (1 << MCID::Bitcast); } + /// isSelect - Return true if this is a select instruction. + /// + bool isSelect() const { + return Flags & (1 << MCID::Select); + } + /// isNotDuplicable - Return true if this instruction cannot be safely /// duplicated. For example, if the instruction has a unique labels attached /// to it, duplicating it would cause multiple definition errors. diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 85607c84482c..cf7125173ee1 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -107,8 +107,8 @@ LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192); // Any larger and MSVC complains. #undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT -/// \brief This class template exposes a typedef for type containing a suitable -/// aligned character array to hold elements of any of up to four types. +/// \brief This union template exposes a suitably aligned and sized character +/// array member which can hold elements of any of up to four types. /// /// These types may be arrays, structs, or any other types. The goal is to /// produce a union type containing a character array which, when used, forms @@ -116,7 +116,8 @@ LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192); /// than four types can be added at the cost of more boiler plate. template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char> -class AlignedCharArray { +union AlignedCharArrayUnion { +private: class AlignerImpl { T1 t1; T2 t2; T3 t3; T4 t4; @@ -127,6 +128,12 @@ class AlignedCharArray { }; public: + /// \brief The character array buffer for use by clients. + /// + /// No other member of this union should be referenced. The exist purely to + /// constrain the layout of this character array. + char buffer[sizeof(SizerImpl)]; + // Sadly, Clang and GCC both fail to align a character array properly even // with an explicit alignment attribute. To work around this, we union // the character array that will actually be used with a struct that contains @@ -134,16 +141,10 @@ public: // and GCC will properly register the alignment of a struct containing an // aligned member, and this alignment should carry over to the character // array in the union. - union union_type { - // This is the only member of the union which should be used by clients: - char buffer[sizeof(SizerImpl)]; - - // This member of the union only exists to force the alignment. - struct { - typename llvm::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment>::type - nonce_inner_member; - } nonce_member; - }; + struct { + typename llvm::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment>::type + nonce_inner_member; + } nonce_member; }; } // end namespace llvm diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 6c2ee08756e7..ba8adb018173 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -50,7 +50,7 @@ namespace COFF { }; enum MachineTypes { - MT_Invalid = -1, + MT_Invalid = 0xffff, IMAGE_FILE_MACHINE_UNKNOWN = 0x0, IMAGE_FILE_MACHINE_AM33 = 0x13, @@ -142,7 +142,7 @@ namespace COFF { /// Storage class tells where and what the symbol represents enum SymbolStorageClass { - SSC_Invalid = -1, + SSC_Invalid = 0xff, IMAGE_SYM_CLASS_END_OF_FUNCTION = -1, ///< Physical end of function IMAGE_SYM_CLASS_NULL = 0, ///< No symbol @@ -220,7 +220,7 @@ namespace COFF { }; enum SectionCharacteristics { - SC_Invalid = -1, + SC_Invalid = 0xffffffff, IMAGE_SCN_TYPE_NO_PAD = 0x00000008, IMAGE_SCN_CNT_CODE = 0x00000020, diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index f654f327a923..4469ae31de09 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -38,6 +38,25 @@ #define llvm_move(value) (value) #endif +/// LLVM_DELETED_FUNCTION - Expands to = delete if the compiler supports it. +/// Use to mark functions as uncallable. Member functions with this should +/// be declared private so that some behaivor is kept in C++03 mode. +/// +/// class DontCopy { +/// private: +/// DontCopy(const DontCopy&) LLVM_DELETED_FUNCTION; +/// DontCopy &operator =(const DontCopy&) LLVM_DELETED_FUNCTION; +/// public: +/// ... +/// }; +#if (__has_feature(cxx_deleted_functions) \ + || defined(__GXX_EXPERIMENTAL_CXX0X__)) + // No version of MSVC currently supports this. +#define LLVM_DELETED_FUNCTION = delete +#else +#define LLVM_DELETED_FUNCTION +#endif + /// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked /// into a shared library, then the class should be private to the library and /// not accessible from outside it. Can also be used to mark variables and diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index e0353f957a7c..f4a9aa0e8998 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -28,6 +28,7 @@ #define LLVM_SUPPORT_FILE_SYSTEM_H #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/DataTypes.h" @@ -576,6 +577,82 @@ error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); error_code GetMainExecutable(const char *argv0, void *MainAddr, SmallVectorImpl<char> &result); +/// This class represents a memory mapped file. It is based on +/// boost::iostreams::mapped_file. +class mapped_file_region { + mapped_file_region() LLVM_DELETED_FUNCTION; + mapped_file_region(mapped_file_region&) LLVM_DELETED_FUNCTION; + mapped_file_region &operator =(mapped_file_region&) LLVM_DELETED_FUNCTION; + +public: + enum mapmode { + readonly, //< May only access map via const_data as read only. + readwrite, //< May access map via data and modify it. Written to path. + priv //< May modify via data, but changes are lost on destruction. + }; + +private: + /// Platform specific mapping state. + mapmode Mode; + uint64_t Size; + void *Mapping; +#if LLVM_ON_WIN32 + int FileDescriptor; + void *FileHandle; + void *FileMappingHandle; +#endif + + error_code init(int FD, uint64_t Offset); + +public: + typedef char char_type; + +#if LLVM_USE_RVALUE_REFERENCES + mapped_file_region(mapped_file_region&&); + mapped_file_region &operator =(mapped_file_region&&); +#endif + + /// Construct a mapped_file_region at \a path starting at \a offset of length + /// \a length and with access \a mode. + /// + /// \param path Path to the file to map. If it does not exist it will be + /// created. + /// \param mode How to map the memory. + /// \param length Number of bytes to map in starting at \a offset. If the file + /// is shorter than this, it will be extended. If \a length is + /// 0, the entire file will be mapped. + /// \param offset Byte offset from the beginning of the file where the map + /// should begin. Must be a multiple of + /// mapped_file_region::alignment(). + /// \param ec This is set to errc::success if the map was constructed + /// sucessfully. Otherwise it is set to a platform dependent error. + mapped_file_region(const Twine &path, + mapmode mode, + uint64_t length, + uint64_t offset, + error_code &ec); + + /// \param fd An open file descriptor to map. mapped_file_region takes + /// ownership. It must have been opended in the correct mode. + mapped_file_region(int fd, + mapmode mode, + uint64_t length, + uint64_t offset, + error_code &ec); + + ~mapped_file_region(); + + mapmode flags() const; + uint64_t size() const; + char *data() const; + + /// Get a const view of the data. Modifying this memory has undefined + /// behaivor. + const char *const_data() const; + + /// \returns The minimum alignment offset must be. + static int alignment(); +}; /// @brief Memory maps the contents of a file /// diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index 00c7eeaebcbb..410edd4dc740 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -19,7 +19,7 @@ namespace llvm { -/// Utility function to encode a SLEB128 value. +/// Utility function to encode a SLEB128 value to an output stream. static inline void encodeSLEB128(int64_t Value, raw_ostream &OS) { bool More; do { @@ -34,7 +34,7 @@ static inline void encodeSLEB128(int64_t Value, raw_ostream &OS) { } while (More); } -/// Utility function to encode a ULEB128 value. +/// Utility function to encode a ULEB128 value to an output stream. static inline void encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned Padding = 0) { do { @@ -53,6 +53,43 @@ static inline void encodeULEB128(uint64_t Value, raw_ostream &OS, } } +/// Utility function to encode a ULEB128 value to a buffer. Returns +/// the length in bytes of the encoded value. +static inline unsigned encodeULEB128(uint64_t Value, uint8_t *p, + unsigned Padding = 0) { + uint8_t *orig_p = p; + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + if (Value != 0 || Padding != 0) + Byte |= 0x80; // Mark this byte that that more bytes will follow. + *p++ = Byte; + } while (Value != 0); + + // Pad with 0x80 and emit a null byte at the end. + if (Padding != 0) { + for (; Padding != 1; --Padding) + *p++ = '\x80'; + *p++ = '\x00'; + } + return (unsigned)(p - orig_p); +} + + +/// Utility function to decode a ULEB128 value. +static inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = 0) { + const uint8_t *orig_p = p; + uint64_t Value = 0; + unsigned Shift = 0; + do { + Value += (*p & 0x7f) << Shift; + Shift += 7; + } while (*p++ >= 128); + if (n) + *n = (unsigned)(p - orig_p); + return Value; +} + } // namespace llvm #endif // LLVM_SYSTEM_LEB128_H diff --git a/include/llvm/Support/NoFolder.h b/include/llvm/Support/NoFolder.h index 75c1a79265e2..8e41a64b1770 100644 --- a/include/llvm/Support/NoFolder.h +++ b/include/llvm/Support/NoFolder.h @@ -181,6 +181,12 @@ public: ArrayRef<Constant *> IdxList) const { return ConstantExpr::getGetElementPtr(C, IdxList); } + Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef<Constant *> or + // ArrayRef<Value *>. + return ConstantExpr::getGetElementPtr(C, Idx); + } Instruction *CreateGetElementPtr(Constant *C, ArrayRef<Value *> IdxList) const { return GetElementPtrInst::Create(C, IdxList); @@ -190,6 +196,12 @@ public: ArrayRef<Constant *> IdxList) const { return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); } + Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + // This form of the function only exists to avoid ambiguous overload + // warnings about whether to convert Idx to ArrayRef<Constant *> or + // ArrayRef<Value *>. + return ConstantExpr::getInBoundsGetElementPtr(C, Idx); + } Instruction *CreateInBoundsGetElementPtr(Constant *C, ArrayRef<Value *> IdxList) const { return GetElementPtrInst::CreateInBounds(C, IdxList); diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 24be2b10416c..1816445579ed 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -28,6 +28,24 @@ class SubRegIndex<list<SubRegIndex> comps = []> { // ComposedOf - A list of two SubRegIndex instances, [A, B]. // This indicates that this SubRegIndex is the result of composing A and B. list<SubRegIndex> ComposedOf = comps; + + // CoveringSubRegIndices - A list of two or more sub-register indexes that + // cover this sub-register. + // + // This field should normally be left blank as TableGen can infer it. + // + // TableGen automatically detects sub-registers that straddle the registers + // in the SubRegs field of a Register definition. For example: + // + // Q0 = dsub_0 -> D0, dsub_1 -> D1 + // Q1 = dsub_0 -> D2, dsub_1 -> D3 + // D1_D2 = dsub_0 -> D1, dsub_1 -> D2 + // QQ0 = qsub_0 -> Q0, qsub_1 -> Q1 + // + // TableGen will infer that D1_D2 is a sub-register of QQ0. It will be given + // the synthetic index dsub_1_dsub_2 unless some SubRegIndex is defined with + // CoveringSubRegIndices = [dsub_1, dsub_2]. + list<SubRegIndex> CoveringSubRegIndices = []; } // RegAltNameIndex - The alternate name set to use for register operands of @@ -321,6 +339,7 @@ class Instruction { bit isCompare = 0; // Is this instruction a comparison instruction? bit isMoveImm = 0; // Is this instruction a move immediate instruction? bit isBitcast = 0; // Is this instruction a bitcast instruction? + bit isSelect = 0; // Is this instruction a select instruction? bit isBarrier = 0; // Can control flow fall through this instruction? bit isCall = 0; // Is this instruction a call instruction? bit canFoldAsLoad = 0; // Can this be folded as a simple memory operand? diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index a18b0305a94b..da30ab82d6c2 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -413,6 +413,51 @@ public: llvm_unreachable("Target didn't implement TargetInstrInfo::insertSelect!"); } + /// analyzeSelect - Analyze the given select instruction, returning true if + /// it cannot be understood. It is assumed that MI->isSelect() is true. + /// + /// When successful, return the controlling condition and the operands that + /// determine the true and false result values. + /// + /// Result = SELECT Cond, TrueOp, FalseOp + /// + /// Some targets can optimize select instructions, for example by predicating + /// the instruction defining one of the operands. Such targets should set + /// Optimizable. + /// + /// @param MI Select instruction to analyze. + /// @param Cond Condition controlling the select. + /// @param TrueOp Operand number of the value selected when Cond is true. + /// @param FalseOp Operand number of the value selected when Cond is false. + /// @param Optimizable Returned as true if MI is optimizable. + /// @returns False on success. + virtual bool analyzeSelect(const MachineInstr *MI, + SmallVectorImpl<MachineOperand> &Cond, + unsigned &TrueOp, unsigned &FalseOp, + bool &Optimizable) const { + assert(MI && MI->isSelect() && "MI must be a select instruction"); + return true; + } + + /// optimizeSelect - Given a select instruction that was understood by + /// analyzeSelect and returned Optimizable = true, attempt to optimize MI by + /// merging it with one of its operands. Returns NULL on failure. + /// + /// When successful, returns the new select instruction. The client is + /// responsible for deleting MI. + /// + /// If both sides of the select can be optimized, PreferFalse is used to pick + /// a side. + /// + /// @param MI Optimizable select instruction. + /// @param PreferFalse Try to optimize FalseOp instead of TrueOp. + /// @returns Optimized instruction or NULL. + virtual MachineInstr *optimizeSelect(MachineInstr *MI, + bool PreferFalse = false) const { + // This function must be implemented if Optimizable is ever set. + llvm_unreachable("Target must implement TargetInstrInfo::optimizeSelect!"); + } + /// copyPhysReg - Emit instructions to copy a pair of physical registers. virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, DebugLoc DL, diff --git a/lib/Analysis/BranchProbabilityInfo.cpp b/lib/Analysis/BranchProbabilityInfo.cpp index 2730ce6c63bf..b255ce6dba51 100644 --- a/lib/Analysis/BranchProbabilityInfo.cpp +++ b/lib/Analysis/BranchProbabilityInfo.cpp @@ -1,4 +1,4 @@ -//===-- BranchProbabilityInfo.cpp - Branch Probability Analysis -*- C++ -*-===// +//===-- BranchProbabilityInfo.cpp - Branch Probability Analysis -----------===// // // The LLVM Compiler Infrastructure // @@ -78,6 +78,19 @@ static const uint32_t ZH_NONTAKEN_WEIGHT = 12; static const uint32_t FPH_TAKEN_WEIGHT = 20; static const uint32_t FPH_NONTAKEN_WEIGHT = 12; +/// \brief Invoke-terminating normal branch taken weight +/// +/// This is the weight for branching to the normal destination of an invoke +/// instruction. We expect this to happen most of the time. Set the weight to an +/// absurdly high value so that nested loops subsume it. +static const uint32_t IH_TAKEN_WEIGHT = 1024 * 1024 - 1; + +/// \brief Invoke-terminating normal branch not-taken weight. +/// +/// This is the weight for branching to the unwind destination of an invoke +/// instruction. This is essentially never taken. +static const uint32_t IH_NONTAKEN_WEIGHT = 1; + // Standard weight value. Used when none of the heuristics set weight for // the edge. static const uint32_t NORMAL_WEIGHT = 16; @@ -371,6 +384,19 @@ bool BranchProbabilityInfo::calcFloatingPointHeuristics(BasicBlock *BB) { return true; } +bool BranchProbabilityInfo::calcInvokeHeuristics(BasicBlock *BB) { + InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator()); + if (!II) + return false; + + BasicBlock *Normal = II->getNormalDest(); + BasicBlock *Unwind = II->getUnwindDest(); + + setEdgeWeight(BB, Normal, IH_TAKEN_WEIGHT); + setEdgeWeight(BB, Unwind, IH_NONTAKEN_WEIGHT); + return true; +} + void BranchProbabilityInfo::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<LoopInfo>(); AU.setPreservesAll(); @@ -397,7 +423,9 @@ bool BranchProbabilityInfo::runOnFunction(Function &F) { continue; if (calcZeroHeuristics(*I)) continue; - calcFloatingPointHeuristics(*I); + if (calcFloatingPointHeuristics(*I)) + continue; + calcInvokeHeuristics(*I); } PostDominatedByUnreachable.clear(); diff --git a/lib/Analysis/MemoryBuiltins.cpp b/lib/Analysis/MemoryBuiltins.cpp index c0cc27b6ec5e..e77d2ff9e44e 100644 --- a/lib/Analysis/MemoryBuiltins.cpp +++ b/lib/Analysis/MemoryBuiltins.cpp @@ -473,6 +473,10 @@ ObjectSizeOffsetVisitor::visitExtractValueInst(ExtractValueInst&) { } SizeOffsetType ObjectSizeOffsetVisitor::visitGEPOperator(GEPOperator &GEP) { + // Ignore self-referencing GEPs, they can occur in unreachable code. + if (&GEP == GEP.getPointerOperand()) + return unknown(); + SizeOffsetType PtrData = compute(GEP.getPointerOperand()); if (!bothKnown(PtrData) || !GEP.hasAllConstantIndices()) return unknown(); diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp index 172402e20d64..f745b41c16fe 100644 --- a/lib/CodeGen/MachineVerifier.cpp +++ b/lib/CodeGen/MachineVerifier.cpp @@ -681,10 +681,10 @@ void MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { const MachineInstr *MI = MO->getParent(); const MCInstrDesc &MCID = MI->getDesc(); - const MCOperandInfo &MCOI = MCID.OpInfo[MONum]; // The first MCID.NumDefs operands must be explicit register defines if (MONum < MCID.getNumDefs()) { + const MCOperandInfo &MCOI = MCID.OpInfo[MONum]; if (!MO->isReg()) report("Explicit definition must be a register", MO, MONum); else if (!MO->isDef() && !MCOI.isOptionalDef()) @@ -692,6 +692,7 @@ MachineVerifier::visitMachineOperand(const MachineOperand *MO, unsigned MONum) { else if (MO->isImplicit()) report("Explicit definition marked as implicit", MO, MONum); } else if (MONum < MCID.getNumOperands()) { + const MCOperandInfo &MCOI = MCID.OpInfo[MONum]; // Don't check if it's the last operand in a variadic instruction. See, // e.g., LDM_RET in the arm back end. if (MO->isReg() && diff --git a/lib/CodeGen/PeepholeOptimizer.cpp b/lib/CodeGen/PeepholeOptimizer.cpp index 6bc7e37e3d87..9099862bd312 100644 --- a/lib/CodeGen/PeepholeOptimizer.cpp +++ b/lib/CodeGen/PeepholeOptimizer.cpp @@ -79,6 +79,7 @@ STATISTIC(NumBitcasts, "Number of bitcasts eliminated"); STATISTIC(NumCmps, "Number of compares eliminated"); STATISTIC(NumImmFold, "Number of move immediate folded"); STATISTIC(NumLoadFold, "Number of loads folded"); +STATISTIC(NumSelects, "Number of selects optimized"); namespace { class PeepholeOptimizer : public MachineFunctionPass { @@ -109,6 +110,7 @@ namespace { bool optimizeCmpInstr(MachineInstr *MI, MachineBasicBlock *MBB); bool optimizeExtInstr(MachineInstr *MI, MachineBasicBlock *MBB, SmallPtrSet<MachineInstr*, 8> &LocalMIs); + bool optimizeSelect(MachineInstr *MI); bool isMoveImmediate(MachineInstr *MI, SmallSet<unsigned, 4> &ImmDefRegs, DenseMap<unsigned, MachineInstr*> &ImmDefMIs); @@ -386,6 +388,23 @@ bool PeepholeOptimizer::optimizeCmpInstr(MachineInstr *MI, return false; } +/// Optimize a select instruction. +bool PeepholeOptimizer::optimizeSelect(MachineInstr *MI) { + unsigned TrueOp = 0; + unsigned FalseOp = 0; + bool Optimizable = false; + SmallVector<MachineOperand, 4> Cond; + if (TII->analyzeSelect(MI, Cond, TrueOp, FalseOp, Optimizable)) + return false; + if (!Optimizable) + return false; + if (!TII->optimizeSelect(MI)) + return false; + MI->eraseFromParent(); + ++NumSelects; + return true; +} + /// isLoadFoldable - Check whether MI is a candidate for folding into a later /// instruction. We only fold loads to virtual registers and the virtual /// register defined has a single use. @@ -477,11 +496,11 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { ImmDefMIs.clear(); FoldAsLoadDefReg = 0; - bool First = true; - MachineBasicBlock::iterator PMII; for (MachineBasicBlock::iterator MII = I->begin(), MIE = I->end(); MII != MIE; ) { MachineInstr *MI = &*MII; + // We may be erasing MI below, increment MII now. + ++MII; LocalMIs.insert(MI); // If there exists an instruction which belongs to the following @@ -490,28 +509,18 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { MI->isKill() || MI->isInlineAsm() || MI->isDebugValue() || MI->hasUnmodeledSideEffects()) { FoldAsLoadDefReg = 0; - ++MII; continue; } if (MI->mayStore() || MI->isCall()) FoldAsLoadDefReg = 0; - if (MI->isBitcast()) { - if (optimizeBitcastInstr(MI, MBB)) { - // MI is deleted. - LocalMIs.erase(MI); - Changed = true; - MII = First ? I->begin() : llvm::next(PMII); - continue; - } - } else if (MI->isCompare()) { - if (optimizeCmpInstr(MI, MBB)) { - // MI is deleted. - LocalMIs.erase(MI); - Changed = true; - MII = First ? I->begin() : llvm::next(PMII); - continue; - } + if ((MI->isBitcast() && optimizeBitcastInstr(MI, MBB)) || + (MI->isCompare() && optimizeCmpInstr(MI, MBB)) || + (MI->isSelect() && optimizeSelect(MI))) { + // MI is deleted. + LocalMIs.erase(MI); + Changed = true; + continue; } if (isMoveImmediate(MI, ImmDefRegs, ImmDefMIs)) { @@ -542,14 +551,9 @@ bool PeepholeOptimizer::runOnMachineFunction(MachineFunction &MF) { // MI is replaced with FoldMI. Changed = true; - PMII = FoldMI; - MII = llvm::next(PMII); continue; } } - First = false; - PMII = MII; - ++MII; } } diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index f0c50c1ed3cd..6820175c1bed 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2303,7 +2303,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, N0.getOpcode() == ISD::AND) if (ConstantSDNode *AndRHS = dyn_cast<ConstantSDNode>(N0.getOperand(1))) { - EVT ShiftTy = DCI.isBeforeLegalize() ? + EVT ShiftTy = DCI.isBeforeLegalizeOps() ? getPointerTy() : getShiftAmountTy(N0.getValueType()); if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3 // Perform the xform if the AND RHS is a single bit. @@ -2333,7 +2333,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, const APInt &AndRHSC = AndRHS->getAPIntValue(); if ((-AndRHSC).isPowerOf2() && (AndRHSC & C1) == C1) { unsigned ShiftBits = AndRHSC.countTrailingZeros(); - EVT ShiftTy = DCI.isBeforeLegalize() ? + EVT ShiftTy = DCI.isBeforeLegalizeOps() ? getPointerTy() : getShiftAmountTy(N0.getValueType()); EVT CmpTy = N0.getValueType(); SDValue Shift = DAG.getNode(ISD::SRL, dl, CmpTy, N0.getOperand(0), @@ -2361,7 +2361,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, } NewC = NewC.lshr(ShiftBits); if (ShiftBits && isLegalICmpImmediate(NewC.getSExtValue())) { - EVT ShiftTy = DCI.isBeforeLegalize() ? + EVT ShiftTy = DCI.isBeforeLegalizeOps() ? getPointerTy() : getShiftAmountTy(N0.getValueType()); EVT CmpTy = N0.getValueType(); SDValue Shift = DAG.getNode(ISD::SRL, dl, CmpTy, N0, diff --git a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp index 7be6ef8cba93..61bc119d305b 100644 --- a/lib/ExecutionEngine/JIT/JITMemoryManager.cpp +++ b/lib/ExecutionEngine/JIT/JITMemoryManager.cpp @@ -461,6 +461,9 @@ namespace { /// allocateCodeSection - Allocate memory for a code section. uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) { + // Grow the required block size to account for the block header + Size += sizeof(*CurBlock); + // FIXME: Alignement handling. FreeRangeHeader* candidateBlock = FreeMemoryList; FreeRangeHeader* head = FreeMemoryList; diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 2139df56205b..ed261a4194c9 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -1770,23 +1770,41 @@ APFloat::opStatus APFloat::roundToIntegral(roundingMode rounding_mode) { opStatus fs; assertArithmeticOK(*semantics); + // If the exponent is large enough, we know that this value is already + // integral, and the arithmetic below would potentially cause it to saturate + // to +/-Inf. Bail out early instead. + if (exponent+1 >= (int)semanticsPrecision(*semantics)) + return opOK; + // The algorithm here is quite simple: we add 2^(p-1), where p is the // precision of our format, and then subtract it back off again. The choice // of rounding modes for the addition/subtraction determines the rounding mode // for our integral rounding as well. - APInt IntegerConstant(NextPowerOf2(semanticsPrecision(*semantics)), - 1 << (semanticsPrecision(*semantics)-1)); + // NOTE: When the input value is negative, we do subtraction followed by + // addition instead. + APInt IntegerConstant(NextPowerOf2(semanticsPrecision(*semantics)), 1); + IntegerConstant <<= semanticsPrecision(*semantics)-1; APFloat MagicConstant(*semantics); fs = MagicConstant.convertFromAPInt(IntegerConstant, false, rmNearestTiesToEven); + MagicConstant.copySign(*this); + if (fs != opOK) return fs; + // Preserve the input sign so that we can handle 0.0/-0.0 cases correctly. + bool inputSign = isNegative(); + fs = add(MagicConstant, rounding_mode); if (fs != opOK && fs != opInexact) return fs; fs = subtract(MagicConstant, rounding_mode); + + // Restore the input sign. + if (inputSign != isNegative()) + changeSign(); + return fs; } diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc index 99f8cd4cc370..d04f590f87ed 100644 --- a/lib/Support/Unix/PathV2.inc +++ b/lib/Support/Unix/PathV2.inc @@ -465,6 +465,118 @@ rety_open_create: return error_code::success(); } +error_code mapped_file_region::init(int fd, uint64_t offset) { + AutoFD FD(fd); + + // Figure out how large the file is. + struct stat FileInfo; + if (fstat(fd, &FileInfo) == -1) + return error_code(errno, system_category()); + uint64_t FileSize = FileInfo.st_size; + + if (Size == 0) + Size = FileSize; + else if (FileSize < Size) { + // We need to grow the file. + if (ftruncate(fd, Size) == -1) + return error_code(errno, system_category()); + } + + int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE; + int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE); +#ifdef MAP_FILE + flags |= MAP_FILE; +#endif + Mapping = ::mmap(0, Size, prot, flags, fd, offset); + if (Mapping == MAP_FAILED) + return error_code(errno, system_category()); + return error_code::success(); +} + +mapped_file_region::mapped_file_region(const Twine &path, + mapmode mode, + uint64_t length, + uint64_t offset, + error_code &ec) + : Mode(mode) + , Size(length) + , Mapping() { + // Make sure that the requested size fits within SIZE_T. + if (length > std::numeric_limits<size_t>::max()) { + ec = make_error_code(errc::invalid_argument); + return; + } + + SmallString<128> path_storage; + StringRef name = path.toNullTerminatedStringRef(path_storage); + int oflags = (mode == readonly) ? O_RDONLY : O_RDWR; + int ofd = ::open(name.begin(), oflags); + if (ofd == -1) { + ec = error_code(errno, system_category()); + return; + } + + ec = init(ofd, offset); + if (ec) + Mapping = 0; +} + +mapped_file_region::mapped_file_region(int fd, + mapmode mode, + uint64_t length, + uint64_t offset, + error_code &ec) + : Mode(mode) + , Size(length) + , Mapping() { + // Make sure that the requested size fits within SIZE_T. + if (length > std::numeric_limits<size_t>::max()) { + ec = make_error_code(errc::invalid_argument); + return; + } + + ec = init(fd, offset); + if (ec) + Mapping = 0; +} + +mapped_file_region::~mapped_file_region() { + if (Mapping) + ::munmap(Mapping, Size); +} + +#if LLVM_USE_RVALUE_REFERENCES +mapped_file_region::mapped_file_region(mapped_file_region &&other) + : Mode(other.Mode), Size(other.Size), Mapping(other.Mapping) { + other.Mapping = 0; +} +#endif + +mapped_file_region::mapmode mapped_file_region::flags() const { + assert(Mapping && "Mapping failed but used anyway!"); + return Mode; +} + +uint64_t mapped_file_region::size() const { + assert(Mapping && "Mapping failed but used anyway!"); + return Size; +} + +char *mapped_file_region::data() const { + assert(Mapping && "Mapping failed but used anyway!"); + assert(Mode != readonly && "Cannot get non const data for readonly mapping!"); + return reinterpret_cast<char*>(Mapping); +} + +const char *mapped_file_region::const_data() const { + assert(Mapping && "Mapping failed but used anyway!"); + return reinterpret_cast<const char*>(Mapping); +} + +int mapped_file_region::alignment() { + return Process::GetPageSize(); +} + error_code detail::directory_iterator_construct(detail::DirIterState &it, StringRef path){ SmallString<128> path_null(path); diff --git a/lib/Support/Windows/PathV2.inc b/lib/Support/Windows/PathV2.inc index 66eeab058f62..696768ba9dd1 100644 --- a/lib/Support/Windows/PathV2.inc +++ b/lib/Support/Windows/PathV2.inc @@ -22,6 +22,8 @@ #include <sys/stat.h> #include <sys/types.h> +#undef max + // MinGW doesn't define this. #ifndef _ERRNO_T_DEFINED #define _ERRNO_T_DEFINED @@ -703,6 +705,203 @@ error_code get_magic(const Twine &path, uint32_t len, return error_code::success(); } +error_code mapped_file_region::init(int FD, uint64_t Offset) { + FileDescriptor = FD; + // Make sure that the requested size fits within SIZE_T. + if (Size > std::numeric_limits<SIZE_T>::max()) { + if (FileDescriptor) + _close(FileDescriptor); + else + ::CloseHandle(FileHandle); + return make_error_code(errc::invalid_argument); + } + + DWORD flprotect; + switch (Mode) { + case readonly: flprotect = PAGE_READONLY; break; + case readwrite: flprotect = PAGE_READWRITE; break; + case priv: flprotect = PAGE_WRITECOPY; break; + default: llvm_unreachable("invalid mapping mode"); + } + + FileMappingHandle = ::CreateFileMapping(FileHandle, + 0, + flprotect, + Size >> 32, + Size & 0xffffffff, + 0); + if (FileMappingHandle == NULL) { + error_code ec = windows_error(GetLastError()); + if (FileDescriptor) + _close(FileDescriptor); + else + ::CloseHandle(FileHandle); + return ec; + } + + DWORD dwDesiredAccess; + switch (Mode) { + case readonly: dwDesiredAccess = FILE_MAP_READ; break; + case readwrite: dwDesiredAccess = FILE_MAP_WRITE; break; + case priv: dwDesiredAccess = FILE_MAP_COPY; break; + default: llvm_unreachable("invalid mapping mode"); + } + Mapping = ::MapViewOfFile(FileMappingHandle, + dwDesiredAccess, + Offset >> 32, + Offset & 0xffffffff, + Size); + if (Mapping == NULL) { + error_code ec = windows_error(GetLastError()); + ::CloseHandle(FileMappingHandle); + if (FileDescriptor) + _close(FileDescriptor); + else + ::CloseHandle(FileHandle); + return ec; + } + + if (Size == 0) { + MEMORY_BASIC_INFORMATION mbi; + SIZE_T Result = VirtualQuery(Mapping, &mbi, sizeof(mbi)); + if (Result == 0) { + error_code ec = windows_error(GetLastError()); + ::UnmapViewOfFile(Mapping); + ::CloseHandle(FileMappingHandle); + if (FileDescriptor) + _close(FileDescriptor); + else + ::CloseHandle(FileHandle); + return ec; + } + Size = mbi.RegionSize; + } + return error_code::success(); +} + +mapped_file_region::mapped_file_region(const Twine &path, + mapmode mode, + uint64_t length, + uint64_t offset, + error_code &ec) + : Mode(mode) + , Size(length) + , Mapping() + , FileDescriptor() + , FileHandle(INVALID_HANDLE_VALUE) + , FileMappingHandle() { + SmallString<128> path_storage; + SmallVector<wchar_t, 128> path_utf16; + + // Convert path to UTF-16. + if (ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16)) + return; + + // Get file handle for creating a file mapping. + FileHandle = ::CreateFileW(c_str(path_utf16), + Mode == readonly ? GENERIC_READ + : GENERIC_READ | GENERIC_WRITE, + Mode == readonly ? FILE_SHARE_READ + : 0, + 0, + Mode == readonly ? OPEN_EXISTING + : OPEN_ALWAYS, + Mode == readonly ? FILE_ATTRIBUTE_READONLY + : FILE_ATTRIBUTE_NORMAL, + 0); + if (FileHandle == INVALID_HANDLE_VALUE) { + ec = windows_error(::GetLastError()); + return; + } + + FileDescriptor = 0; + ec = init(FileDescriptor, offset); + if (ec) { + Mapping = FileMappingHandle = 0; + FileHandle = INVALID_HANDLE_VALUE; + FileDescriptor = 0; + } +} + +mapped_file_region::mapped_file_region(int fd, + mapmode mode, + uint64_t length, + uint64_t offset, + error_code &ec) + : Mode(mode) + , Size(length) + , Mapping() + , FileDescriptor(fd) + , FileHandle(INVALID_HANDLE_VALUE) + , FileMappingHandle() { + FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd)); + if (FileHandle == INVALID_HANDLE_VALUE) { + _close(FileDescriptor); + FileDescriptor = 0; + ec = make_error_code(errc::bad_file_descriptor); + return; + } + + ec = init(FileDescriptor, offset); + if (ec) { + Mapping = FileMappingHandle = 0; + FileHandle = INVALID_HANDLE_VALUE; + FileDescriptor = 0; + } +} + +mapped_file_region::~mapped_file_region() { + if (Mapping) + ::UnmapViewOfFile(Mapping); + if (FileMappingHandle) + ::CloseHandle(FileMappingHandle); + if (FileDescriptor) + _close(FileDescriptor); + else if (FileHandle != INVALID_HANDLE_VALUE) + ::CloseHandle(FileHandle); +} + +#if LLVM_USE_RVALUE_REFERENCES +mapped_file_region::mapped_file_region(mapped_file_region &&other) + : Mode(other.Mode) + , Size(other.Size) + , Mapping(other.Mapping) + , FileDescriptor(other.FileDescriptor) + , FileHandle(other.FileHandle) + , FileMappingHandle(other.FileMappingHandle) { + other.Mapping = other.FileMappingHandle = 0; + other.FileHandle = INVALID_HANDLE_VALUE; + other.FileDescriptor = 0; +} +#endif + +mapped_file_region::mapmode mapped_file_region::flags() const { + assert(Mapping && "Mapping failed but used anyway!"); + return Mode; +} + +uint64_t mapped_file_region::size() const { + assert(Mapping && "Mapping failed but used anyway!"); + return Size; +} + +char *mapped_file_region::data() const { + assert(Mode != readonly && "Cannot get non const data for readonly mapping!"); + assert(Mapping && "Mapping failed but used anyway!"); + return reinterpret_cast<char*>(Mapping); +} + +const char *mapped_file_region::const_data() const { + assert(Mapping && "Mapping failed but used anyway!"); + return reinterpret_cast<const char*>(Mapping); +} + +int mapped_file_region::alignment() { + SYSTEM_INFO SysInfo; + ::GetSystemInfo(&SysInfo); + return SysInfo.dwAllocationGranularity; +} + error_code detail::directory_iterator_construct(detail::DirIterState &it, StringRef path){ SmallVector<wchar_t, 128> path_utf16; diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 8536b94d716f..e9e2803ad579 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -532,7 +532,7 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, // This modifier is not yet supported. case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1. return true; - case 'H': // The highest-numbered register of a pair. + case 'H': { // The highest-numbered register of a pair. const MachineOperand &MO = MI->getOperand(OpNum); if (!MO.isReg()) return true; @@ -547,6 +547,7 @@ bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, O << ARMInstPrinter::getRegisterName(Reg); return false; } + } } printOperand(MI, OpNum, O); diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 057fd718fdb5..1cc5a17cb029 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -1568,6 +1568,136 @@ ARMBaseInstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const { return TargetInstrInfoImpl::commuteInstruction(MI, NewMI); } +/// Identify instructions that can be folded into a MOVCC instruction, and +/// return the corresponding opcode for the predicated pseudo-instruction. +static unsigned canFoldIntoMOVCC(unsigned Reg, MachineInstr *&MI, + const MachineRegisterInfo &MRI) { + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + return 0; + if (!MRI.hasOneNonDBGUse(Reg)) + return 0; + MI = MRI.getVRegDef(Reg); + if (!MI) + return 0; + // Check if MI has any non-dead defs or physreg uses. This also detects + // predicated instructions which will be reading CPSR. + for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) + return 0; + if (MO.isDef() && !MO.isDead()) + return 0; + } + switch (MI->getOpcode()) { + default: return 0; + case ARM::ANDri: return ARM::ANDCCri; + case ARM::ANDrr: return ARM::ANDCCrr; + case ARM::ANDrsi: return ARM::ANDCCrsi; + case ARM::ANDrsr: return ARM::ANDCCrsr; + case ARM::t2ANDri: return ARM::t2ANDCCri; + case ARM::t2ANDrr: return ARM::t2ANDCCrr; + case ARM::t2ANDrs: return ARM::t2ANDCCrs; + case ARM::EORri: return ARM::EORCCri; + case ARM::EORrr: return ARM::EORCCrr; + case ARM::EORrsi: return ARM::EORCCrsi; + case ARM::EORrsr: return ARM::EORCCrsr; + case ARM::t2EORri: return ARM::t2EORCCri; + case ARM::t2EORrr: return ARM::t2EORCCrr; + case ARM::t2EORrs: return ARM::t2EORCCrs; + case ARM::ORRri: return ARM::ORRCCri; + case ARM::ORRrr: return ARM::ORRCCrr; + case ARM::ORRrsi: return ARM::ORRCCrsi; + case ARM::ORRrsr: return ARM::ORRCCrsr; + case ARM::t2ORRri: return ARM::t2ORRCCri; + case ARM::t2ORRrr: return ARM::t2ORRCCrr; + case ARM::t2ORRrs: return ARM::t2ORRCCrs; + + // ARM ADD/SUB + case ARM::ADDri: return ARM::ADDCCri; + case ARM::ADDrr: return ARM::ADDCCrr; + case ARM::ADDrsi: return ARM::ADDCCrsi; + case ARM::ADDrsr: return ARM::ADDCCrsr; + case ARM::SUBri: return ARM::SUBCCri; + case ARM::SUBrr: return ARM::SUBCCrr; + case ARM::SUBrsi: return ARM::SUBCCrsi; + case ARM::SUBrsr: return ARM::SUBCCrsr; + + // Thumb2 ADD/SUB + case ARM::t2ADDri: return ARM::t2ADDCCri; + case ARM::t2ADDri12: return ARM::t2ADDCCri12; + case ARM::t2ADDrr: return ARM::t2ADDCCrr; + case ARM::t2ADDrs: return ARM::t2ADDCCrs; + case ARM::t2SUBri: return ARM::t2SUBCCri; + case ARM::t2SUBri12: return ARM::t2SUBCCri12; + case ARM::t2SUBrr: return ARM::t2SUBCCrr; + case ARM::t2SUBrs: return ARM::t2SUBCCrs; + } +} + +bool ARMBaseInstrInfo::analyzeSelect(const MachineInstr *MI, + SmallVectorImpl<MachineOperand> &Cond, + unsigned &TrueOp, unsigned &FalseOp, + bool &Optimizable) const { + assert((MI->getOpcode() == ARM::MOVCCr || MI->getOpcode() == ARM::t2MOVCCr) && + "Unknown select instruction"); + // MOVCC operands: + // 0: Def. + // 1: True use. + // 2: False use. + // 3: Condition code. + // 4: CPSR use. + TrueOp = 1; + FalseOp = 2; + Cond.push_back(MI->getOperand(3)); + Cond.push_back(MI->getOperand(4)); + // We can always fold a def. + Optimizable = true; + return false; +} + +MachineInstr *ARMBaseInstrInfo::optimizeSelect(MachineInstr *MI, + bool PreferFalse) const { + assert((MI->getOpcode() == ARM::MOVCCr || MI->getOpcode() == ARM::t2MOVCCr) && + "Unknown select instruction"); + const MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo(); + MachineInstr *DefMI = 0; + unsigned Opc = canFoldIntoMOVCC(MI->getOperand(2).getReg(), DefMI, MRI); + bool Invert = !Opc; + if (!Opc) + Opc = canFoldIntoMOVCC(MI->getOperand(1).getReg(), DefMI, MRI); + if (!Opc) + return 0; + + // Create a new predicated version of DefMI. + // Rfalse is the first use. + MachineInstrBuilder NewMI = BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), + get(Opc), MI->getOperand(0).getReg()) + .addOperand(MI->getOperand(Invert ? 2 : 1)); + + // Copy all the DefMI operands, excluding its (null) predicate. + const MCInstrDesc &DefDesc = DefMI->getDesc(); + for (unsigned i = 1, e = DefDesc.getNumOperands(); + i != e && !DefDesc.OpInfo[i].isPredicate(); ++i) + NewMI.addOperand(DefMI->getOperand(i)); + + unsigned CondCode = MI->getOperand(3).getImm(); + if (Invert) + NewMI.addImm(ARMCC::getOppositeCondition(ARMCC::CondCodes(CondCode))); + else + NewMI.addImm(CondCode); + NewMI.addOperand(MI->getOperand(4)); + + // DefMI is not the -S version that sets CPSR, so add an optional %noreg. + if (NewMI->hasOptionalDef()) + AddDefaultCC(NewMI); + + // The caller will erase MI, but not DefMI. + DefMI->eraseFromParent(); + return NewMI; +} + /// Map pseudo instructions that imply an 'S' bit onto real opcodes. Whether the /// instruction is encoded with an 'S' bit is determined by the optional CPSR /// def operand. @@ -3224,11 +3354,18 @@ enum ARMExeDomain { // std::pair<uint16_t, uint16_t> ARMBaseInstrInfo::getExecutionDomain(const MachineInstr *MI) const { - // VMOVD is a VFP instruction, but can be changed to NEON if it isn't - // predicated. + // VMOVD, VMOVRS and VMOVSR are VFP instructions, but can be changed to NEON + // if they are not predicated. if (MI->getOpcode() == ARM::VMOVD && !isPredicated(MI)) return std::make_pair(ExeVFP, (1<<ExeVFP) | (1<<ExeNEON)); + // Cortex-A9 is particularly picky about mixing the two and wants these + // converted. + if (Subtarget.isCortexA9() && !isPredicated(MI) && + (MI->getOpcode() == ARM::VMOVRS || + MI->getOpcode() == ARM::VMOVSR)) + return std::make_pair(ExeVFP, (1<<ExeVFP) | (1<<ExeNEON)); + // No other instructions can be swizzled, so just determine their domain. unsigned Domain = MI->getDesc().TSFlags & ARMII::DomainMask; @@ -3248,22 +3385,97 @@ ARMBaseInstrInfo::getExecutionDomain(const MachineInstr *MI) const { void ARMBaseInstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const { - // We only know how to change VMOVD into VORR. - assert(MI->getOpcode() == ARM::VMOVD && "Can only swizzle VMOVD"); - if (Domain != ExeNEON) - return; + unsigned DstReg, SrcReg, DReg; + unsigned Lane; + MachineInstrBuilder MIB(MI); + const TargetRegisterInfo *TRI = &getRegisterInfo(); + bool isKill; + switch (MI->getOpcode()) { + default: + llvm_unreachable("cannot handle opcode!"); + break; + case ARM::VMOVD: + if (Domain != ExeNEON) + break; + + // Zap the predicate operands. + assert(!isPredicated(MI) && "Cannot predicate a VORRd"); + MI->RemoveOperand(3); + MI->RemoveOperand(2); + + // Change to a VORRd which requires two identical use operands. + MI->setDesc(get(ARM::VORRd)); + + // Add the extra source operand and new predicates. + // This will go before any implicit ops. + AddDefaultPred(MachineInstrBuilder(MI).addOperand(MI->getOperand(1))); + break; + case ARM::VMOVRS: + if (Domain != ExeNEON) + break; + assert(!isPredicated(MI) && "Cannot predicate a VGETLN"); + + DstReg = MI->getOperand(0).getReg(); + SrcReg = MI->getOperand(1).getReg(); + + DReg = TRI->getMatchingSuperReg(SrcReg, ARM::ssub_0, &ARM::DPRRegClass); + Lane = 0; + if (DReg == ARM::NoRegister) { + DReg = TRI->getMatchingSuperReg(SrcReg, ARM::ssub_1, &ARM::DPRRegClass); + Lane = 1; + assert(DReg && "S-register with no D super-register?"); + } + + MI->RemoveOperand(3); + MI->RemoveOperand(2); + MI->RemoveOperand(1); - // Zap the predicate operands. - assert(!isPredicated(MI) && "Cannot predicate a VORRd"); - MI->RemoveOperand(3); - MI->RemoveOperand(2); + MI->setDesc(get(ARM::VGETLNi32)); + MIB.addReg(DReg); + MIB.addImm(Lane); - // Change to a VORRd which requires two identical use operands. - MI->setDesc(get(ARM::VORRd)); + MIB->getOperand(1).setIsUndef(); + MIB.addReg(SrcReg, RegState::Implicit); + + AddDefaultPred(MIB); + break; + case ARM::VMOVSR: + if (Domain != ExeNEON) + break; + assert(!isPredicated(MI) && "Cannot predicate a VSETLN"); + + DstReg = MI->getOperand(0).getReg(); + SrcReg = MI->getOperand(1).getReg(); + DReg = TRI->getMatchingSuperReg(DstReg, ARM::ssub_0, &ARM::DPRRegClass); + Lane = 0; + if (DReg == ARM::NoRegister) { + DReg = TRI->getMatchingSuperReg(DstReg, ARM::ssub_1, &ARM::DPRRegClass); + Lane = 1; + assert(DReg && "S-register with no D super-register?"); + } + isKill = MI->getOperand(0).isKill(); + + MI->RemoveOperand(3); + MI->RemoveOperand(2); + MI->RemoveOperand(1); + MI->RemoveOperand(0); + + MI->setDesc(get(ARM::VSETLNi32)); + MIB.addReg(DReg); + MIB.addReg(DReg); + MIB.addReg(SrcReg); + MIB.addImm(Lane); + + MIB->getOperand(1).setIsUndef(); + + if (isKill) + MIB->addRegisterKilled(DstReg, TRI, true); + MIB->addRegisterDefined(DstReg, TRI); + + AddDefaultPred(MIB); + break; + } - // Add the extra source operand and new predicates. - // This will go before any implicit ops. - AddDefaultPred(MachineInstrBuilder(MI).addOperand(MI->getOperand(1))); } bool ARMBaseInstrInfo::hasNOP() const { diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index 1a10a4ab1c52..92e5ee8dcbd3 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -202,6 +202,13 @@ public: unsigned SrcReg2, int CmpMask, int CmpValue, const MachineRegisterInfo *MRI) const; + virtual bool analyzeSelect(const MachineInstr *MI, + SmallVectorImpl<MachineOperand> &Cond, + unsigned &TrueOp, unsigned &FalseOp, + bool &Optimizable) const; + + virtual MachineInstr *optimizeSelect(MachineInstr *MI, bool) const; + /// FoldImmediate - 'Reg' is known to be defined by a move immediate /// instruction, try to fold the immediate into the use instruction. virtual bool FoldImmediate(MachineInstr *UseMI, MachineInstr *DefMI, @@ -352,6 +359,11 @@ ARMCC::CondCodes getInstrPredicate(const MachineInstr *MI, unsigned &PredReg); int getMatchingCondBranchOpcode(int Opc); +/// Determine if MI can be folded into an ARM MOVCC instruction, and return the +/// opcode of the SSA instruction representing the conditional MI. +unsigned canFoldARMInstrIntoMOVCC(unsigned Reg, + MachineInstr *&MI, + const MachineRegisterInfo &MRI); /// Map pseudo instructions that imply an 'S' bit onto real opcodes. Whether /// the instruction is encoded with an 'S' bit is determined by the optional diff --git a/lib/Target/ARM/ARMFastISel.cpp b/lib/Target/ARM/ARMFastISel.cpp index 57f811603945..bf9d16eea181 100644 --- a/lib/Target/ARM/ARMFastISel.cpp +++ b/lib/Target/ARM/ARMFastISel.cpp @@ -1821,9 +1821,12 @@ CCAssignFn *ARMFastISel::CCAssignFnForCall(CallingConv::ID CC, default: llvm_unreachable("Unsupported calling convention"); case CallingConv::Fast: - // Ignore fastcc. Silence compiler warnings. - (void)RetFastCC_ARM_APCS; - (void)FastCC_ARM_APCS; + if (Subtarget->hasVFP2() && !isVarArg) { + if (!Subtarget->isAAPCS_ABI()) + return (Return ? RetFastCC_ARM_APCS : FastCC_ARM_APCS); + // For AAPCS ABI targets, just use VFP variant of the calling convention. + return (Return ? RetCC_ARM_AAPCS_VFP : CC_ARM_AAPCS_VFP); + } // Fallthrough case CallingConv::C: // Use target triple & subtarget features to do actual dispatch. diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index ee349a753fef..a3a6c3176bea 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -2385,8 +2385,10 @@ SDNode *ARMDAGToDAGISel::SelectConditionalOp(SDNode *N) { case ARMISD::COR: Opc = ARM::t2ORRCCrs; break; case ARMISD::CXOR: Opc = ARM::t2EORCCrs; break; } - SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CC, CCR, Reg0, InFlag }; - return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 7); + SDValue Ops[] = { + FalseVal, FalseVal, CPTmp0, CPTmp1, CC, CCR, Reg0, InFlag + }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 8); } ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); @@ -2401,8 +2403,8 @@ SDNode *ARMDAGToDAGISel::SelectConditionalOp(SDNode *N) { case ARMISD::CXOR: Opc = ARM::t2EORCCri; break; } SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32); - SDValue Ops[] = { FalseVal, True, CC, CCR, Reg0, InFlag }; - return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 6); + SDValue Ops[] = { FalseVal, FalseVal, True, CC, CCR, Reg0, InFlag }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 7); } } @@ -2413,8 +2415,8 @@ SDNode *ARMDAGToDAGISel::SelectConditionalOp(SDNode *N) { case ARMISD::COR: Opc = ARM::t2ORRCCrr; break; case ARMISD::CXOR: Opc = ARM::t2EORCCrr; break; } - SDValue Ops[] = { FalseVal, TrueVal, CC, CCR, Reg0, InFlag }; - return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 6); + SDValue Ops[] = { FalseVal, FalseVal, TrueVal, CC, CCR, Reg0, InFlag }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 7); } SDValue CPTmp0; @@ -2428,8 +2430,10 @@ SDNode *ARMDAGToDAGISel::SelectConditionalOp(SDNode *N) { case ARMISD::COR: Opc = ARM::ORRCCrsi; break; case ARMISD::CXOR: Opc = ARM::EORCCrsi; break; } - SDValue Ops[] = { FalseVal, CPTmp0, CPTmp2, CC, CCR, Reg0, InFlag }; - return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 7); + SDValue Ops[] = { + FalseVal, FalseVal, CPTmp0, CPTmp2, CC, CCR, Reg0, InFlag + }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 8); } if (SelectRegShifterOperand(TrueVal, CPTmp0, CPTmp1, CPTmp2)) { @@ -2440,8 +2444,10 @@ SDNode *ARMDAGToDAGISel::SelectConditionalOp(SDNode *N) { case ARMISD::COR: Opc = ARM::ORRCCrsr; break; case ARMISD::CXOR: Opc = ARM::EORCCrsr; break; } - SDValue Ops[] = { FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, Reg0, InFlag }; - return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 8); + SDValue Ops[] = { + FalseVal, FalseVal, CPTmp0, CPTmp1, CPTmp2, CC, CCR, Reg0, InFlag + }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 9); } ConstantSDNode *T = dyn_cast<ConstantSDNode>(TrueVal); @@ -2456,8 +2462,8 @@ SDNode *ARMDAGToDAGISel::SelectConditionalOp(SDNode *N) { case ARMISD::CXOR: Opc = ARM::EORCCri; break; } SDValue True = CurDAG->getTargetConstant(TrueImm, MVT::i32); - SDValue Ops[] = { FalseVal, True, CC, CCR, Reg0, InFlag }; - return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 6); + SDValue Ops[] = { FalseVal, FalseVal, True, CC, CCR, Reg0, InFlag }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 7); } } @@ -2468,8 +2474,8 @@ SDNode *ARMDAGToDAGISel::SelectConditionalOp(SDNode *N) { case ARMISD::COR: Opc = ARM::ORRCCrr; break; case ARMISD::CXOR: Opc = ARM::EORCCrr; break; } - SDValue Ops[] = { FalseVal, TrueVal, CC, CCR, Reg0, InFlag }; - return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 6); + SDValue Ops[] = { FalseVal, FalseVal, TrueVal, CC, CCR, Reg0, InFlag }; + return CurDAG->SelectNodeTo(N, Opc, MVT::i32, Ops, 7); } /// Target-specific DAG combining for ISD::XOR. diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index c66618a8ef5f..190ca076dae5 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -6973,6 +6973,27 @@ void ARMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr *MI, // ARM Optimization Hooks //===----------------------------------------------------------------------===// +// Helper function that checks if N is a null or all ones constant. +static inline bool isZeroOrAllOnes(SDValue N, bool AllOnes) { + ConstantSDNode *C = dyn_cast<ConstantSDNode>(N); + if (!C) + return false; + return AllOnes ? C->isAllOnesValue() : C->isNullValue(); +} + +// Combine a constant select operand into its use: +// +// (add (select cc, 0, c), x) -> (select cc, x, (add, x, c)) +// (sub x, (select cc, 0, c)) -> (select cc, x, (sub, x, c)) +// +// The transform is rejected if the select doesn't have a constant operand that +// is null. +// +// @param N The node to transform. +// @param Slct The N operand that is a select. +// @param OtherOp The other N operand (x above). +// @param DCI Context. +// @returns The new node, or SDValue() on failure. static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, TargetLowering::DAGCombinerInfo &DCI) { @@ -6998,16 +7019,12 @@ SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, assert ((Opc == ISD::ADD || (Opc == ISD::SUB && Slct == N->getOperand(1))) && "Bad input!"); - if (LHS.getOpcode() == ISD::Constant && - cast<ConstantSDNode>(LHS)->isNullValue()) { + if (isZeroOrAllOnes(LHS, false)) { DoXform = true; - } else if (CC != ISD::SETCC_INVALID && - RHS.getOpcode() == ISD::Constant && - cast<ConstantSDNode>(RHS)->isNullValue()) { + } else if (CC != ISD::SETCC_INVALID && isZeroOrAllOnes(RHS, false)) { std::swap(LHS, RHS); SDValue Op0 = Slct.getOperand(0); - EVT OpVT = isSlctCC ? Op0.getValueType() : - Op0.getOperand(0).getValueType(); + EVT OpVT = isSlctCC ? Op0.getValueType() : Op0.getOperand(0).getValueType(); bool isInt = OpVT.isInteger(); CC = ISD::getSetCCInverse(CC, isInt); @@ -7018,19 +7035,19 @@ SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp, InvCC = true; } - if (DoXform) { - SDValue Result = DAG.getNode(Opc, RHS.getDebugLoc(), VT, OtherOp, RHS); - if (isSlctCC) - return DAG.getSelectCC(N->getDebugLoc(), OtherOp, Result, - Slct.getOperand(0), Slct.getOperand(1), CC); - SDValue CCOp = Slct.getOperand(0); - if (InvCC) - CCOp = DAG.getSetCC(Slct.getDebugLoc(), CCOp.getValueType(), - CCOp.getOperand(0), CCOp.getOperand(1), CC); - return DAG.getNode(ISD::SELECT, N->getDebugLoc(), VT, - CCOp, OtherOp, Result); - } - return SDValue(); + if (!DoXform) + return SDValue(); + + SDValue Result = DAG.getNode(Opc, RHS.getDebugLoc(), VT, OtherOp, RHS); + if (isSlctCC) + return DAG.getSelectCC(N->getDebugLoc(), OtherOp, Result, + Slct.getOperand(0), Slct.getOperand(1), CC); + SDValue CCOp = Slct.getOperand(0); + if (InvCC) + CCOp = DAG.getSetCC(Slct.getDebugLoc(), CCOp.getValueType(), + CCOp.getOperand(0), CCOp.getOperand(1), CC); + return DAG.getNode(ISD::SELECT, N->getDebugLoc(), VT, + CCOp, OtherOp, Result); } // AddCombineToVPADDL- For pair-wise add on neon, use the vpaddl instruction @@ -7297,16 +7314,8 @@ static SDValue PerformMULCombine(SDNode *N, } static bool isCMOVWithZeroOrAllOnesLHS(SDValue N, bool AllOnes) { - if (N.getOpcode() != ARMISD::CMOV || !N.getNode()->hasOneUse()) - return false; - - SDValue FalseVal = N.getOperand(0); - ConstantSDNode *C = dyn_cast<ConstantSDNode>(FalseVal); - if (!C) - return false; - if (AllOnes) - return C->isAllOnesValue(); - return C->isNullValue(); + return N.getOpcode() == ARMISD::CMOV && N.getNode()->hasOneUse() && + isZeroOrAllOnes(N.getOperand(0), AllOnes); } /// formConditionalOp - Combine an operation with a conditional move operand @@ -8808,6 +8817,8 @@ bool ARMTargetLowering::allowsUnalignedMemoryAccesses(EVT VT) const { case MVT::i16: case MVT::i32: return true; + case MVT::f64: + return Subtarget->hasNEON(); // FIXME: VLD1 etc with standard alignment is legal. } } diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 6340a58f1a0f..992aba5803f6 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -242,6 +242,9 @@ def UseFusedMAC : Predicate<"(TM.Options.AllowFPOpFusion ==" def DontUseFusedMAC : Predicate<"!Subtarget->hasVFP4() || " "Subtarget->isTargetDarwin()">; +def IsLE : Predicate<"TLI.isLittleEndian()">; +def IsBE : Predicate<"TLI.isBigEndian()">; + //===----------------------------------------------------------------------===// // ARM Flag Definitions. @@ -3936,7 +3939,7 @@ def BCCZi64 : PseudoInst<(outs), // a two-value operand where a dag node expects two operands. :( let neverHasSideEffects = 1 in { -let isCommutable = 1 in +let isCommutable = 1, isSelect = 1 in def MOVCCr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$false, GPR:$Rm, pred:$p), 4, IIC_iCMOVr, [/*(set GPR:$Rd, (ARMcmov GPR:$false, GPR:$Rm, imm:$cc, CCR:$ccr))*/]>, @@ -3989,25 +3992,29 @@ multiclass AsI1_bincc_irs<Instruction iri, Instruction irr, Instruction irsi, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis> { def ri : ARMPseudoExpand<(outs GPR:$Rd), - (ins GPR:$Rn, so_imm:$imm, pred:$p, cc_out:$s), + (ins GPR:$Rfalse, GPR:$Rn, so_imm:$imm, + pred:$p, cc_out:$s), 4, iii, [], (iri GPR:$Rd, GPR:$Rn, so_imm:$imm, pred:$p, cc_out:$s)>, - RegConstraint<"$Rn = $Rd">; + RegConstraint<"$Rfalse = $Rd">; def rr : ARMPseudoExpand<(outs GPR:$Rd), - (ins GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s), + (ins GPR:$Rfalse, GPR:$Rn, GPR:$Rm, + pred:$p, cc_out:$s), 4, iir, [], (irr GPR:$Rd, GPR:$Rn, GPR:$Rm, pred:$p, cc_out:$s)>, - RegConstraint<"$Rn = $Rd">; + RegConstraint<"$Rfalse = $Rd">; def rsi : ARMPseudoExpand<(outs GPR:$Rd), - (ins GPR:$Rn, so_reg_imm:$shift, pred:$p, cc_out:$s), + (ins GPR:$Rfalse, GPR:$Rn, so_reg_imm:$shift, + pred:$p, cc_out:$s), 4, iis, [], (irsi GPR:$Rd, GPR:$Rn, so_reg_imm:$shift, pred:$p, cc_out:$s)>, - RegConstraint<"$Rn = $Rd">; + RegConstraint<"$Rfalse = $Rd">; def rsr : ARMPseudoExpand<(outs GPRnopc:$Rd), - (ins GPRnopc:$Rn, so_reg_reg:$shift, pred:$p, cc_out:$s), + (ins GPRnopc:$Rfalse, GPRnopc:$Rn, so_reg_reg:$shift, + pred:$p, cc_out:$s), 4, iis, [], (irsr GPR:$Rd, GPR:$Rn, so_reg_reg:$shift, pred:$p, cc_out:$s)>, - RegConstraint<"$Rn = $Rd">; + RegConstraint<"$Rfalse = $Rd">; } defm ANDCC : AsI1_bincc_irs<ANDri, ANDrr, ANDrsi, ANDrsr, @@ -4016,6 +4023,10 @@ defm ORRCC : AsI1_bincc_irs<ORRri, ORRrr, ORRrsi, ORRrsr, IIC_iBITi, IIC_iBITr, IIC_iBITsr>; defm EORCC : AsI1_bincc_irs<EORri, EORrr, EORrsi, EORrsr, IIC_iBITi, IIC_iBITr, IIC_iBITsr>; +defm ADDCC : AsI1_bincc_irs<ADDri, ADDrr, ADDrsi, ADDrsr, + IIC_iBITi, IIC_iBITr, IIC_iBITsr>; +defm SUBCC : AsI1_bincc_irs<SUBri, SUBrr, SUBrsi, SUBrsr, + IIC_iBITi, IIC_iBITr, IIC_iBITsr>; } // neverHasSideEffects diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index 31340881920d..048d340df006 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -398,6 +398,27 @@ def VecListFourQWordIndexed : Operand<i32> { let MIOperandInfo = (ops DPR:$Vd, i32imm:$idx); } +def hword_alignedload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + return cast<LoadSDNode>(N)->getAlignment() == 2; +}]>; +def hword_alignedstore : PatFrag<(ops node:$val, node:$ptr), + (store node:$val, node:$ptr), [{ + return cast<StoreSDNode>(N)->getAlignment() == 2; +}]>; +def byte_alignedload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + return cast<LoadSDNode>(N)->getAlignment() == 1; +}]>; +def byte_alignedstore : PatFrag<(ops node:$val, node:$ptr), + (store node:$val, node:$ptr), [{ + return cast<StoreSDNode>(N)->getAlignment() == 1; +}]>; +def non_word_alignedload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + return cast<LoadSDNode>(N)->getAlignment() < 4; +}]>; +def non_word_alignedstore : PatFrag<(ops node:$val, node:$ptr), + (store node:$val, node:$ptr), [{ + return cast<StoreSDNode>(N)->getAlignment() < 4; +}]>; //===----------------------------------------------------------------------===// // NEON-specific DAG Nodes. @@ -2238,6 +2259,19 @@ def VST4LNq32Pseudo_UPD : VSTQQQQLNWBPseudo<IIC_VST4lnu>; } // mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 +// Use vld1/vst1 for unaligned f64 load / store +def : Pat<(f64 (hword_alignedload addrmode6:$addr)), + (VLD1d16 addrmode6:$addr)>, Requires<[IsLE]>; +def : Pat<(hword_alignedstore (f64 DPR:$value), addrmode6:$addr), + (VST1d16 addrmode6:$addr, DPR:$value)>, Requires<[IsLE]>; +def : Pat<(f64 (byte_alignedload addrmode6:$addr)), + (VLD1d8 addrmode6:$addr)>, Requires<[IsLE]>; +def : Pat<(byte_alignedstore (f64 DPR:$value), addrmode6:$addr), + (VST1d8 addrmode6:$addr, DPR:$value)>, Requires<[IsLE]>; +def : Pat<(f64 (non_word_alignedload addrmode6:$addr)), + (VLD1d64 addrmode6:$addr)>, Requires<[IsBE]>; +def : Pat<(non_word_alignedstore (f64 DPR:$value), addrmode6:$addr), + (VST1d64 addrmode6:$addr, DPR:$value)>, Requires<[IsBE]>; //===----------------------------------------------------------------------===// // NEON pattern fragments diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 307006f413a8..8ecf0091d8b6 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -757,6 +757,33 @@ multiclass T2I_bin_ii12rs<bits<3> op23_21, string opc, PatFrag opnode, let Inst{24} = 1; let Inst{23-21} = op23_21; } + + // Predicated versions. + def CCri : t2PseudoExpand<(outs GPRnopc:$Rd), + (ins GPRnopc:$Rfalse, GPRnopc:$Rn, t2_so_imm:$imm, + pred:$p, cc_out:$s), 4, IIC_iALUi, [], + (!cast<Instruction>(NAME#ri) GPRnopc:$Rd, + GPRnopc:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>, + RegConstraint<"$Rfalse = $Rd">; + def CCri12 : t2PseudoExpand<(outs GPRnopc:$Rd), + (ins GPRnopc:$Rfalse, GPR:$Rn, imm0_4095:$imm, + pred:$p), + 4, IIC_iALUi, [], + (!cast<Instruction>(NAME#ri12) GPRnopc:$Rd, + GPR:$Rn, imm0_4095:$imm, pred:$p)>, + RegConstraint<"$Rfalse = $Rd">; + def CCrr : t2PseudoExpand<(outs GPRnopc:$Rd), + (ins GPRnopc:$Rfalse, GPRnopc:$Rn, rGPR:$Rm, + pred:$p, cc_out:$s), 4, IIC_iALUr, [], + (!cast<Instruction>(NAME#rr) GPRnopc:$Rd, + GPRnopc:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>, + RegConstraint<"$Rfalse = $Rd">; + def CCrs : t2PseudoExpand<(outs GPRnopc:$Rd), + (ins GPRnopc:$Rfalse, GPRnopc:$Rn, t2_so_reg:$Rm, + pred:$p, cc_out:$s), 4, IIC_iALUsi, [], + (!cast<Instruction>(NAME#rs) GPRnopc:$Rd, + GPRnopc:$Rn, t2_so_reg:$Rm, pred:$p, cc_out:$s)>, + RegConstraint<"$Rfalse = $Rd">; } /// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns @@ -2938,7 +2965,7 @@ defm t2TEQ : T2I_cmp_irs<0b0100, "teq", // a two-value operand where a dag node expects two operands. :( let neverHasSideEffects = 1 in { -let isCommutable = 1 in +let isCommutable = 1, isSelect = 1 in def t2MOVCCr : t2PseudoInst<(outs rGPR:$Rd), (ins rGPR:$false, rGPR:$Rm, pred:$p), 4, IIC_iCMOVr, @@ -3026,22 +3053,25 @@ multiclass T2I_bincc_irs<Instruction iri, Instruction irr, Instruction irs, InstrItinClass iii, InstrItinClass iir, InstrItinClass iis> { // shifted imm def ri : t2PseudoExpand<(outs rGPR:$Rd), - (ins rGPR:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s), + (ins rGPR:$Rfalse, rGPR:$Rn, t2_so_imm:$imm, + pred:$p, cc_out:$s), 4, iii, [], (iri rGPR:$Rd, rGPR:$Rn, t2_so_imm:$imm, pred:$p, cc_out:$s)>, - RegConstraint<"$Rn = $Rd">; + RegConstraint<"$Rfalse = $Rd">; // register def rr : t2PseudoExpand<(outs rGPR:$Rd), - (ins rGPR:$Rn, rGPR:$Rm, pred:$p, cc_out:$s), + (ins rGPR:$Rfalse, rGPR:$Rn, rGPR:$Rm, + pred:$p, cc_out:$s), 4, iir, [], (irr rGPR:$Rd, rGPR:$Rn, rGPR:$Rm, pred:$p, cc_out:$s)>, - RegConstraint<"$Rn = $Rd">; + RegConstraint<"$Rfalse = $Rd">; // shifted register def rs : t2PseudoExpand<(outs rGPR:$Rd), - (ins rGPR:$Rn, t2_so_reg:$ShiftedRm, pred:$p, cc_out:$s), + (ins rGPR:$Rfalse, rGPR:$Rn, t2_so_reg:$ShiftedRm, + pred:$p, cc_out:$s), 4, iis, [], (irs rGPR:$Rd, rGPR:$Rn, t2_so_reg:$ShiftedRm, pred:$p, cc_out:$s)>, - RegConstraint<"$Rn = $Rd">; + RegConstraint<"$Rfalse = $Rd">; } // T2I_bincc_irs defm t2ANDCC : T2I_bincc_irs<t2ANDri, t2ANDrr, t2ANDrs, diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 23c132e4f6a8..eb7eaa6c9708 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -61,6 +61,15 @@ def vfp_f64imm : Operand<f64>, let ParserMatchClass = FPImmOperand; } +def alignedload32 : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + return cast<LoadSDNode>(N)->getAlignment() >= 4; +}]>; + +def alignedstore32 : PatFrag<(ops node:$val, node:$ptr), + (store node:$val, node:$ptr), [{ + return cast<StoreSDNode>(N)->getAlignment() >= 4; +}]>; + // The VCVT to/from fixed-point instructions encode the 'fbits' operand // (the number of fixed bits) differently than it appears in the assembly // source. It's encoded as "Size - fbits" where Size is the size of the @@ -86,7 +95,7 @@ let canFoldAsLoad = 1, isReMaterializable = 1 in { def VLDRD : ADI5<0b1101, 0b01, (outs DPR:$Dd), (ins addrmode5:$addr), IIC_fpLoad64, "vldr", "\t$Dd, $addr", - [(set DPR:$Dd, (f64 (load addrmode5:$addr)))]>; + [(set DPR:$Dd, (f64 (alignedload32 addrmode5:$addr)))]>; def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$Sd), (ins addrmode5:$addr), IIC_fpLoad32, "vldr", "\t$Sd, $addr", @@ -100,7 +109,7 @@ def VLDRS : ASI5<0b1101, 0b01, (outs SPR:$Sd), (ins addrmode5:$addr), def VSTRD : ADI5<0b1101, 0b00, (outs), (ins DPR:$Dd, addrmode5:$addr), IIC_fpStore64, "vstr", "\t$Dd, $addr", - [(store (f64 DPR:$Dd), addrmode5:$addr)]>; + [(alignedstore32 (f64 DPR:$Dd), addrmode5:$addr)]>; def VSTRS : ASI5<0b1101, 0b00, (outs), (ins SPR:$Sd, addrmode5:$addr), IIC_fpStore32, "vstr", "\t$Sd, $addr", @@ -433,25 +442,25 @@ def VCVTSD : VFPAI<(outs SPR:$Sd), (ins DPR:$Dm), VFPUnaryFrm, // Between half-precision and single-precision. For disassembly only. // FIXME: Verify encoding after integrated assembler is working. -def VCVTBSH: ASuI<0b11101, 0b11, 0b0010, 0b01, 0, (outs SPR:$Sd), (ins SPR:$Sm), +def VCVTBHS: ASuI<0b11101, 0b11, 0b0010, 0b01, 0, (outs SPR:$Sd), (ins SPR:$Sm), /* FIXME */ IIC_fpCVTSH, "vcvtb", ".f32.f16\t$Sd, $Sm", [/* For disassembly only; pattern left blank */]>; -def : ARMPat<(f32_to_f16 SPR:$a), - (i32 (COPY_TO_REGCLASS (VCVTBSH SPR:$a), GPR))>; - -def VCVTBHS: ASuI<0b11101, 0b11, 0b0011, 0b01, 0, (outs SPR:$Sd), (ins SPR:$Sm), +def VCVTBSH: ASuI<0b11101, 0b11, 0b0011, 0b01, 0, (outs SPR:$Sd), (ins SPR:$Sm), /* FIXME */ IIC_fpCVTHS, "vcvtb", ".f16.f32\t$Sd, $Sm", [/* For disassembly only; pattern left blank */]>; +def : ARMPat<(f32_to_f16 SPR:$a), + (i32 (COPY_TO_REGCLASS (VCVTBSH SPR:$a), GPR))>; + def : ARMPat<(f16_to_f32 GPR:$a), (VCVTBHS (COPY_TO_REGCLASS GPR:$a, SPR))>; -def VCVTTSH: ASuI<0b11101, 0b11, 0b0010, 0b11, 0, (outs SPR:$Sd), (ins SPR:$Sm), +def VCVTTHS: ASuI<0b11101, 0b11, 0b0010, 0b11, 0, (outs SPR:$Sd), (ins SPR:$Sm), /* FIXME */ IIC_fpCVTSH, "vcvtt", ".f32.f16\t$Sd, $Sm", [/* For disassembly only; pattern left blank */]>; -def VCVTTHS: ASuI<0b11101, 0b11, 0b0011, 0b11, 0, (outs SPR:$Sd), (ins SPR:$Sm), +def VCVTTSH: ASuI<0b11101, 0b11, 0b0011, 0b11, 0, (outs SPR:$Sd), (ins SPR:$Sm), /* FIXME */ IIC_fpCVTHS, "vcvtt", ".f16.f32\t$Sd, $Sm", [/* For disassembly only; pattern left blank */]>; diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index e47bf66e3afe..c90751d0b962 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -18,10 +18,12 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCFixedLenDisassembler.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include <vector> @@ -383,7 +385,6 @@ static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val, static DecodeStatus DecodeMRRC2(llvm::MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder); #include "ARMGenDisassemblerTables.inc" -#include "ARMGenInstrInfo.inc" #include "ARMGenEDInfo.inc" static MCDisassembler *createARMDisassembler(const Target &T, const MCSubtargetInfo &STI) { @@ -427,7 +428,8 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size, (bytes[0] << 0); // Calling the auto-generated decoder function. - DecodeStatus result = decodeARMInstruction32(MI, insn, Address, this, STI); + DecodeStatus result = decodeInstruction(DecoderTableARM32, MI, insn, + Address, this, STI); if (result != MCDisassembler::Fail) { Size = 4; return result; @@ -436,14 +438,15 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size, // VFP and NEON instructions, similarly, are shared between ARM // and Thumb modes. MI.clear(); - result = decodeVFPInstruction32(MI, insn, Address, this, STI); + result = decodeInstruction(DecoderTableVFP32, MI, insn, Address, this, STI); if (result != MCDisassembler::Fail) { Size = 4; return result; } MI.clear(); - result = decodeNEONDataInstruction32(MI, insn, Address, this, STI); + result = decodeInstruction(DecoderTableNEONData32, MI, insn, Address, + this, STI); if (result != MCDisassembler::Fail) { Size = 4; // Add a fake predicate operand, because we share these instruction @@ -454,7 +457,8 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size, } MI.clear(); - result = decodeNEONLoadStoreInstruction32(MI, insn, Address, this, STI); + result = decodeInstruction(DecoderTableNEONLoadStore32, MI, insn, Address, + this, STI); if (result != MCDisassembler::Fail) { Size = 4; // Add a fake predicate operand, because we share these instruction @@ -465,7 +469,8 @@ DecodeStatus ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size, } MI.clear(); - result = decodeNEONDupInstruction32(MI, insn, Address, this, STI); + result = decodeInstruction(DecoderTableNEONDup32, MI, insn, Address, + this, STI); if (result != MCDisassembler::Fail) { Size = 4; // Add a fake predicate operand, because we share these instruction @@ -765,7 +770,8 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, } uint16_t insn16 = (bytes[1] << 8) | bytes[0]; - DecodeStatus result = decodeThumbInstruction16(MI, insn16, Address, this, STI); + DecodeStatus result = decodeInstruction(DecoderTableThumb16, MI, insn16, + Address, this, STI); if (result != MCDisassembler::Fail) { Size = 2; Check(result, AddThumbPredicate(MI)); @@ -773,7 +779,8 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, } MI.clear(); - result = decodeThumbSBitInstruction16(MI, insn16, Address, this, STI); + result = decodeInstruction(DecoderTableThumbSBit16, MI, insn16, + Address, this, STI); if (result) { Size = 2; bool InITBlock = ITBlock.instrInITBlock(); @@ -783,7 +790,8 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, } MI.clear(); - result = decodeThumb2Instruction16(MI, insn16, Address, this, STI); + result = decodeInstruction(DecoderTableThumb216, MI, insn16, + Address, this, STI); if (result != MCDisassembler::Fail) { Size = 2; @@ -818,7 +826,8 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, (bytes[1] << 24) | (bytes[0] << 16); MI.clear(); - result = decodeThumbInstruction32(MI, insn32, Address, this, STI); + result = decodeInstruction(DecoderTableThumb32, MI, insn32, Address, + this, STI); if (result != MCDisassembler::Fail) { Size = 4; bool InITBlock = ITBlock.instrInITBlock(); @@ -828,7 +837,8 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, } MI.clear(); - result = decodeThumb2Instruction32(MI, insn32, Address, this, STI); + result = decodeInstruction(DecoderTableThumb232, MI, insn32, Address, + this, STI); if (result != MCDisassembler::Fail) { Size = 4; Check(result, AddThumbPredicate(MI)); @@ -836,7 +846,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, } MI.clear(); - result = decodeVFPInstruction32(MI, insn32, Address, this, STI); + result = decodeInstruction(DecoderTableVFP32, MI, insn32, Address, this, STI); if (result != MCDisassembler::Fail) { Size = 4; UpdateThumbVFPPredicate(MI); @@ -844,19 +854,21 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, } MI.clear(); - result = decodeNEONDupInstruction32(MI, insn32, Address, this, STI); + result = decodeInstruction(DecoderTableNEONDup32, MI, insn32, Address, + this, STI); if (result != MCDisassembler::Fail) { Size = 4; Check(result, AddThumbPredicate(MI)); return result; } - if (fieldFromInstruction32(insn32, 24, 8) == 0xF9) { + if (fieldFromInstruction(insn32, 24, 8) == 0xF9) { MI.clear(); uint32_t NEONLdStInsn = insn32; NEONLdStInsn &= 0xF0FFFFFF; NEONLdStInsn |= 0x04000000; - result = decodeNEONLoadStoreInstruction32(MI, NEONLdStInsn, Address, this, STI); + result = decodeInstruction(DecoderTableNEONLoadStore32, MI, NEONLdStInsn, + Address, this, STI); if (result != MCDisassembler::Fail) { Size = 4; Check(result, AddThumbPredicate(MI)); @@ -864,13 +876,14 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, } } - if (fieldFromInstruction32(insn32, 24, 4) == 0xF) { + if (fieldFromInstruction(insn32, 24, 4) == 0xF) { MI.clear(); uint32_t NEONDataInsn = insn32; NEONDataInsn &= 0xF0FFFFFF; // Clear bits 27-24 NEONDataInsn |= (NEONDataInsn & 0x10000000) >> 4; // Move bit 28 to bit 24 NEONDataInsn |= 0x12000000; // Set bits 28 and 25 - result = decodeNEONDataInstruction32(MI, NEONDataInsn, Address, this, STI); + result = decodeInstruction(DecoderTableNEONData32, MI, NEONDataInsn, + Address, this, STI); if (result != MCDisassembler::Fail) { Size = 4; Check(result, AddThumbPredicate(MI)); @@ -1117,9 +1130,9 @@ static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rm = fieldFromInstruction32(Val, 0, 4); - unsigned type = fieldFromInstruction32(Val, 5, 2); - unsigned imm = fieldFromInstruction32(Val, 7, 5); + unsigned Rm = fieldFromInstruction(Val, 0, 4); + unsigned type = fieldFromInstruction(Val, 5, 2); + unsigned imm = fieldFromInstruction(Val, 7, 5); // Register-immediate if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder))) @@ -1154,9 +1167,9 @@ static DecodeStatus DecodeSORegRegOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rm = fieldFromInstruction32(Val, 0, 4); - unsigned type = fieldFromInstruction32(Val, 5, 2); - unsigned Rs = fieldFromInstruction32(Val, 8, 4); + unsigned Rm = fieldFromInstruction(Val, 0, 4); + unsigned type = fieldFromInstruction(Val, 5, 2); + unsigned Rs = fieldFromInstruction(Val, 8, 4); // Register-register if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder))) @@ -1224,8 +1237,8 @@ static DecodeStatus DecodeSPRRegListOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Vd = fieldFromInstruction32(Val, 8, 5); - unsigned regs = fieldFromInstruction32(Val, 0, 8); + unsigned Vd = fieldFromInstruction(Val, 8, 5); + unsigned regs = fieldFromInstruction(Val, 0, 8); if (!Check(S, DecodeSPRRegisterClass(Inst, Vd, Address, Decoder))) return MCDisassembler::Fail; @@ -1241,8 +1254,8 @@ static DecodeStatus DecodeDPRRegListOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Vd = fieldFromInstruction32(Val, 8, 5); - unsigned regs = fieldFromInstruction32(Val, 0, 8); + unsigned Vd = fieldFromInstruction(Val, 8, 5); + unsigned regs = fieldFromInstruction(Val, 0, 8); regs = regs >> 1; @@ -1263,8 +1276,8 @@ static DecodeStatus DecodeBitfieldMaskOperand(MCInst &Inst, unsigned Val, // the mask of all bits LSB-and-lower, and then xor them to create // the mask of that's all ones on [msb, lsb]. Finally we not it to // create the final mask. - unsigned msb = fieldFromInstruction32(Val, 5, 5); - unsigned lsb = fieldFromInstruction32(Val, 0, 5); + unsigned msb = fieldFromInstruction(Val, 5, 5); + unsigned lsb = fieldFromInstruction(Val, 0, 5); DecodeStatus S = MCDisassembler::Success; if (lsb > msb) Check(S, MCDisassembler::SoftFail); @@ -1281,12 +1294,12 @@ static DecodeStatus DecodeCopMemInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned pred = fieldFromInstruction32(Insn, 28, 4); - unsigned CRd = fieldFromInstruction32(Insn, 12, 4); - unsigned coproc = fieldFromInstruction32(Insn, 8, 4); - unsigned imm = fieldFromInstruction32(Insn, 0, 8); - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned U = fieldFromInstruction32(Insn, 23, 1); + unsigned pred = fieldFromInstruction(Insn, 28, 4); + unsigned CRd = fieldFromInstruction(Insn, 12, 4); + unsigned coproc = fieldFromInstruction(Insn, 8, 4); + unsigned imm = fieldFromInstruction(Insn, 0, 8); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned U = fieldFromInstruction(Insn, 23, 1); switch (Inst.getOpcode()) { case ARM::LDC_OFFSET: @@ -1426,14 +1439,14 @@ DecodeAddrMode2IdxInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned imm = fieldFromInstruction32(Insn, 0, 12); - unsigned pred = fieldFromInstruction32(Insn, 28, 4); - unsigned reg = fieldFromInstruction32(Insn, 25, 1); - unsigned P = fieldFromInstruction32(Insn, 24, 1); - unsigned W = fieldFromInstruction32(Insn, 21, 1); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned imm = fieldFromInstruction(Insn, 0, 12); + unsigned pred = fieldFromInstruction(Insn, 28, 4); + unsigned reg = fieldFromInstruction(Insn, 25, 1); + unsigned P = fieldFromInstruction(Insn, 24, 1); + unsigned W = fieldFromInstruction(Insn, 21, 1); // On stores, the writeback operand precedes Rt. switch (Inst.getOpcode()) { @@ -1476,7 +1489,7 @@ DecodeAddrMode2IdxInstruction(MCInst &Inst, unsigned Insn, return MCDisassembler::Fail; ARM_AM::AddrOpc Op = ARM_AM::add; - if (!fieldFromInstruction32(Insn, 23, 1)) + if (!fieldFromInstruction(Insn, 23, 1)) Op = ARM_AM::sub; bool writeback = (P == 0) || (W == 1); @@ -1493,7 +1506,7 @@ DecodeAddrMode2IdxInstruction(MCInst &Inst, unsigned Insn, if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder))) return MCDisassembler::Fail; ARM_AM::ShiftOpc Opc = ARM_AM::lsl; - switch( fieldFromInstruction32(Insn, 5, 2)) { + switch( fieldFromInstruction(Insn, 5, 2)) { case 0: Opc = ARM_AM::lsl; break; @@ -1509,7 +1522,7 @@ DecodeAddrMode2IdxInstruction(MCInst &Inst, unsigned Insn, default: return MCDisassembler::Fail; } - unsigned amt = fieldFromInstruction32(Insn, 7, 5); + unsigned amt = fieldFromInstruction(Insn, 7, 5); unsigned imm = ARM_AM::getAM2Opc(Op, amt, Opc, idx_mode); Inst.addOperand(MCOperand::CreateImm(imm)); @@ -1529,11 +1542,11 @@ static DecodeStatus DecodeSORegMemOperand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Val, 13, 4); - unsigned Rm = fieldFromInstruction32(Val, 0, 4); - unsigned type = fieldFromInstruction32(Val, 5, 2); - unsigned imm = fieldFromInstruction32(Val, 7, 5); - unsigned U = fieldFromInstruction32(Val, 12, 1); + unsigned Rn = fieldFromInstruction(Val, 13, 4); + unsigned Rm = fieldFromInstruction(Val, 0, 4); + unsigned type = fieldFromInstruction(Val, 5, 2); + unsigned imm = fieldFromInstruction(Val, 7, 5); + unsigned U = fieldFromInstruction(Val, 12, 1); ARM_AM::ShiftOpc ShOp = ARM_AM::lsl; switch (type) { @@ -1570,15 +1583,15 @@ DecodeAddrMode3Instruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned type = fieldFromInstruction32(Insn, 22, 1); - unsigned imm = fieldFromInstruction32(Insn, 8, 4); - unsigned U = ((~fieldFromInstruction32(Insn, 23, 1)) & 1) << 8; - unsigned pred = fieldFromInstruction32(Insn, 28, 4); - unsigned W = fieldFromInstruction32(Insn, 21, 1); - unsigned P = fieldFromInstruction32(Insn, 24, 1); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned type = fieldFromInstruction(Insn, 22, 1); + unsigned imm = fieldFromInstruction(Insn, 8, 4); + unsigned U = ((~fieldFromInstruction(Insn, 23, 1)) & 1) << 8; + unsigned pred = fieldFromInstruction(Insn, 28, 4); + unsigned W = fieldFromInstruction(Insn, 21, 1); + unsigned P = fieldFromInstruction(Insn, 24, 1); unsigned Rt2 = Rt + 1; bool writeback = (W == 1) | (P == 0); @@ -1609,7 +1622,7 @@ DecodeAddrMode3Instruction(MCInst &Inst, unsigned Insn, S = MCDisassembler::SoftFail; if (Rt2 == 15) S = MCDisassembler::SoftFail; - if (!type && fieldFromInstruction32(Insn, 8, 4)) + if (!type && fieldFromInstruction(Insn, 8, 4)) S = MCDisassembler::SoftFail; break; case ARM::STRH: @@ -1761,8 +1774,8 @@ static DecodeStatus DecodeRFEInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned mode = fieldFromInstruction32(Insn, 23, 2); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned mode = fieldFromInstruction(Insn, 23, 2); switch (mode) { case 0: @@ -1791,9 +1804,9 @@ static DecodeStatus DecodeMemMultipleWritebackInstruction(MCInst &Inst, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned pred = fieldFromInstruction32(Insn, 28, 4); - unsigned reglist = fieldFromInstruction32(Insn, 0, 16); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned pred = fieldFromInstruction(Insn, 28, 4); + unsigned reglist = fieldFromInstruction(Insn, 0, 16); if (pred == 0xF) { switch (Inst.getOpcode()) { @@ -1850,9 +1863,9 @@ static DecodeStatus DecodeMemMultipleWritebackInstruction(MCInst &Inst, } // For stores (which become SRS's, the only operand is the mode. - if (fieldFromInstruction32(Insn, 20, 1) == 0) { + if (fieldFromInstruction(Insn, 20, 1) == 0) { Inst.addOperand( - MCOperand::CreateImm(fieldFromInstruction32(Insn, 0, 4))); + MCOperand::CreateImm(fieldFromInstruction(Insn, 0, 4))); return S; } @@ -1873,10 +1886,10 @@ static DecodeStatus DecodeMemMultipleWritebackInstruction(MCInst &Inst, static DecodeStatus DecodeCPSInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - unsigned imod = fieldFromInstruction32(Insn, 18, 2); - unsigned M = fieldFromInstruction32(Insn, 17, 1); - unsigned iflags = fieldFromInstruction32(Insn, 6, 3); - unsigned mode = fieldFromInstruction32(Insn, 0, 5); + unsigned imod = fieldFromInstruction(Insn, 18, 2); + unsigned M = fieldFromInstruction(Insn, 17, 1); + unsigned iflags = fieldFromInstruction(Insn, 6, 3); + unsigned mode = fieldFromInstruction(Insn, 0, 5); DecodeStatus S = MCDisassembler::Success; @@ -1913,10 +1926,10 @@ static DecodeStatus DecodeCPSInstruction(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeT2CPSInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - unsigned imod = fieldFromInstruction32(Insn, 9, 2); - unsigned M = fieldFromInstruction32(Insn, 8, 1); - unsigned iflags = fieldFromInstruction32(Insn, 5, 3); - unsigned mode = fieldFromInstruction32(Insn, 0, 5); + unsigned imod = fieldFromInstruction(Insn, 9, 2); + unsigned M = fieldFromInstruction(Insn, 8, 1); + unsigned iflags = fieldFromInstruction(Insn, 5, 3); + unsigned mode = fieldFromInstruction(Insn, 0, 5); DecodeStatus S = MCDisassembler::Success; @@ -1955,13 +1968,13 @@ static DecodeStatus DecodeT2MOVTWInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 8, 4); + unsigned Rd = fieldFromInstruction(Insn, 8, 4); unsigned imm = 0; - imm |= (fieldFromInstruction32(Insn, 0, 8) << 0); - imm |= (fieldFromInstruction32(Insn, 12, 3) << 8); - imm |= (fieldFromInstruction32(Insn, 16, 4) << 12); - imm |= (fieldFromInstruction32(Insn, 26, 1) << 11); + imm |= (fieldFromInstruction(Insn, 0, 8) << 0); + imm |= (fieldFromInstruction(Insn, 12, 3) << 8); + imm |= (fieldFromInstruction(Insn, 16, 4) << 12); + imm |= (fieldFromInstruction(Insn, 26, 1) << 11); if (Inst.getOpcode() == ARM::t2MOVTi16) if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder))) @@ -1979,12 +1992,12 @@ static DecodeStatus DecodeArmMOVTWInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + unsigned pred = fieldFromInstruction(Insn, 28, 4); unsigned imm = 0; - imm |= (fieldFromInstruction32(Insn, 0, 12) << 0); - imm |= (fieldFromInstruction32(Insn, 16, 4) << 12); + imm |= (fieldFromInstruction(Insn, 0, 12) << 0); + imm |= (fieldFromInstruction(Insn, 16, 4) << 12); if (Inst.getOpcode() == ARM::MOVTi16) if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder))) @@ -2005,11 +2018,11 @@ static DecodeStatus DecodeSMLAInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 16, 4); - unsigned Rn = fieldFromInstruction32(Insn, 0, 4); - unsigned Rm = fieldFromInstruction32(Insn, 8, 4); - unsigned Ra = fieldFromInstruction32(Insn, 12, 4); - unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned Rd = fieldFromInstruction(Insn, 16, 4); + unsigned Rn = fieldFromInstruction(Insn, 0, 4); + unsigned Rm = fieldFromInstruction(Insn, 8, 4); + unsigned Ra = fieldFromInstruction(Insn, 12, 4); + unsigned pred = fieldFromInstruction(Insn, 28, 4); if (pred == 0xF) return DecodeCPSInstruction(Inst, Insn, Address, Decoder); @@ -2033,9 +2046,9 @@ static DecodeStatus DecodeAddrModeImm12Operand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned add = fieldFromInstruction32(Val, 12, 1); - unsigned imm = fieldFromInstruction32(Val, 0, 12); - unsigned Rn = fieldFromInstruction32(Val, 13, 4); + unsigned add = fieldFromInstruction(Val, 12, 1); + unsigned imm = fieldFromInstruction(Val, 0, 12); + unsigned Rn = fieldFromInstruction(Val, 13, 4); if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; @@ -2053,9 +2066,9 @@ static DecodeStatus DecodeAddrMode5Operand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Val, 9, 4); - unsigned U = fieldFromInstruction32(Val, 8, 1); - unsigned imm = fieldFromInstruction32(Val, 0, 8); + unsigned Rn = fieldFromInstruction(Val, 9, 4); + unsigned U = fieldFromInstruction(Val, 8, 1); + unsigned imm = fieldFromInstruction(Val, 0, 8); if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; @@ -2077,11 +2090,11 @@ static DecodeStatus DecodeT2BInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned imm = (fieldFromInstruction32(Insn, 0, 11) << 0) | - (fieldFromInstruction32(Insn, 11, 1) << 18) | - (fieldFromInstruction32(Insn, 13, 1) << 17) | - (fieldFromInstruction32(Insn, 16, 6) << 11) | - (fieldFromInstruction32(Insn, 26, 1) << 19); + unsigned imm = (fieldFromInstruction(Insn, 0, 11) << 0) | + (fieldFromInstruction(Insn, 11, 1) << 18) | + (fieldFromInstruction(Insn, 13, 1) << 17) | + (fieldFromInstruction(Insn, 16, 6) << 11) | + (fieldFromInstruction(Insn, 26, 1) << 19); if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<20>(imm<<1) + 4, true, 4, Inst, Decoder)) Inst.addOperand(MCOperand::CreateImm(SignExtend32<20>(imm << 1))); @@ -2093,12 +2106,12 @@ DecodeBranchImmInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned pred = fieldFromInstruction32(Insn, 28, 4); - unsigned imm = fieldFromInstruction32(Insn, 0, 24) << 2; + unsigned pred = fieldFromInstruction(Insn, 28, 4); + unsigned imm = fieldFromInstruction(Insn, 0, 24) << 2; if (pred == 0xF) { Inst.setOpcode(ARM::BLXi); - imm |= fieldFromInstruction32(Insn, 24, 1) << 1; + imm |= fieldFromInstruction(Insn, 24, 1) << 1; if (!tryAddingSymbolicOperand(Address, Address + SignExtend32<26>(imm) + 8, true, 4, Inst, Decoder)) Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(imm))); @@ -2119,8 +2132,8 @@ static DecodeStatus DecodeAddrMode6Operand(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rm = fieldFromInstruction32(Val, 0, 4); - unsigned align = fieldFromInstruction32(Val, 4, 2); + unsigned Rm = fieldFromInstruction(Val, 0, 4); + unsigned align = fieldFromInstruction(Val, 4, 2); if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder))) return MCDisassembler::Fail; @@ -2136,12 +2149,12 @@ static DecodeStatus DecodeVLDInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned wb = fieldFromInstruction32(Insn, 16, 4); - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - Rn |= fieldFromInstruction32(Insn, 4, 2) << 4; - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned wb = fieldFromInstruction(Insn, 16, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + Rn |= fieldFromInstruction(Insn, 4, 2) << 4; + unsigned Rm = fieldFromInstruction(Insn, 0, 4); // First output register switch (Inst.getOpcode()) { @@ -2410,12 +2423,12 @@ static DecodeStatus DecodeVSTInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned wb = fieldFromInstruction32(Insn, 16, 4); - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - Rn |= fieldFromInstruction32(Insn, 4, 2) << 4; - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned wb = fieldFromInstruction(Insn, 16, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + Rn |= fieldFromInstruction(Insn, 4, 2) << 4; + unsigned Rm = fieldFromInstruction(Insn, 0, 4); // Writeback Operand switch (Inst.getOpcode()) { @@ -2681,12 +2694,12 @@ static DecodeStatus DecodeVLD1DupInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned align = fieldFromInstruction32(Insn, 4, 1); - unsigned size = fieldFromInstruction32(Insn, 6, 2); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned align = fieldFromInstruction(Insn, 4, 1); + unsigned size = fieldFromInstruction(Insn, 6, 2); align *= (1 << size); @@ -2726,12 +2739,12 @@ static DecodeStatus DecodeVLD2DupInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned align = fieldFromInstruction32(Insn, 4, 1); - unsigned size = 1 << fieldFromInstruction32(Insn, 6, 2); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned align = fieldFromInstruction(Insn, 4, 1); + unsigned size = 1 << fieldFromInstruction(Insn, 6, 2); align *= 2*size; switch (Inst.getOpcode()) { @@ -2774,11 +2787,11 @@ static DecodeStatus DecodeVLD3DupInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1; + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned inc = fieldFromInstruction(Insn, 5, 1) + 1; if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder))) return MCDisassembler::Fail; @@ -2809,13 +2822,13 @@ static DecodeStatus DecodeVLD4DupInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned size = fieldFromInstruction32(Insn, 6, 2); - unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1; - unsigned align = fieldFromInstruction32(Insn, 4, 1); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned size = fieldFromInstruction(Insn, 6, 2); + unsigned inc = fieldFromInstruction(Insn, 5, 1) + 1; + unsigned align = fieldFromInstruction(Insn, 4, 1); if (size == 0x3) { size = 4; @@ -2862,14 +2875,14 @@ DecodeNEONModImmInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned imm = fieldFromInstruction32(Insn, 0, 4); - imm |= fieldFromInstruction32(Insn, 16, 3) << 4; - imm |= fieldFromInstruction32(Insn, 24, 1) << 7; - imm |= fieldFromInstruction32(Insn, 8, 4) << 8; - imm |= fieldFromInstruction32(Insn, 5, 1) << 12; - unsigned Q = fieldFromInstruction32(Insn, 6, 1); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned imm = fieldFromInstruction(Insn, 0, 4); + imm |= fieldFromInstruction(Insn, 16, 3) << 4; + imm |= fieldFromInstruction(Insn, 24, 1) << 7; + imm |= fieldFromInstruction(Insn, 8, 4) << 8; + imm |= fieldFromInstruction(Insn, 5, 1) << 12; + unsigned Q = fieldFromInstruction(Insn, 6, 1); if (Q) { if (!Check(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder))) @@ -2907,11 +2920,11 @@ static DecodeStatus DecodeVSHLMaxInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - Rm |= fieldFromInstruction32(Insn, 5, 1) << 4; - unsigned size = fieldFromInstruction32(Insn, 18, 2); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + Rm |= fieldFromInstruction(Insn, 5, 1) << 4; + unsigned size = fieldFromInstruction(Insn, 18, 2); if (!Check(S, DecodeQPRRegisterClass(Inst, Rd, Address, Decoder))) return MCDisassembler::Fail; @@ -2950,13 +2963,13 @@ static DecodeStatus DecodeTBLInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - Rn |= fieldFromInstruction32(Insn, 7, 1) << 4; - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - Rm |= fieldFromInstruction32(Insn, 5, 1) << 4; - unsigned op = fieldFromInstruction32(Insn, 6, 1); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + Rn |= fieldFromInstruction(Insn, 7, 1) << 4; + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + Rm |= fieldFromInstruction(Insn, 5, 1) << 4; + unsigned op = fieldFromInstruction(Insn, 6, 1); if (!Check(S, DecodeDPRRegisterClass(Inst, Rd, Address, Decoder))) return MCDisassembler::Fail; @@ -2986,8 +2999,8 @@ static DecodeStatus DecodeThumbAddSpecialReg(MCInst &Inst, uint16_t Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned dst = fieldFromInstruction16(Insn, 8, 3); - unsigned imm = fieldFromInstruction16(Insn, 0, 8); + unsigned dst = fieldFromInstruction(Insn, 8, 3); + unsigned imm = fieldFromInstruction(Insn, 0, 8); if (!Check(S, DecodetGPRRegisterClass(Inst, dst, Address, Decoder))) return MCDisassembler::Fail; @@ -3034,8 +3047,8 @@ static DecodeStatus DecodeThumbAddrModeRR(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Val, 0, 3); - unsigned Rm = fieldFromInstruction32(Val, 3, 3); + unsigned Rn = fieldFromInstruction(Val, 0, 3); + unsigned Rm = fieldFromInstruction(Val, 3, 3); if (!Check(S, DecodetGPRRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; @@ -3049,8 +3062,8 @@ static DecodeStatus DecodeThumbAddrModeIS(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Val, 0, 3); - unsigned imm = fieldFromInstruction32(Val, 3, 5); + unsigned Rn = fieldFromInstruction(Val, 0, 3); + unsigned imm = fieldFromInstruction(Val, 3, 5); if (!Check(S, DecodetGPRRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; @@ -3081,9 +3094,9 @@ static DecodeStatus DecodeT2AddrModeSOReg(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Val, 6, 4); - unsigned Rm = fieldFromInstruction32(Val, 2, 4); - unsigned imm = fieldFromInstruction32(Val, 0, 2); + unsigned Rn = fieldFromInstruction(Val, 6, 4); + unsigned Rm = fieldFromInstruction(Val, 2, 4); + unsigned imm = fieldFromInstruction(Val, 0, 2); if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; @@ -3104,13 +3117,13 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn, case ARM::t2PLIs: break; default: { - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); if (!Check(S, DecoderGPRRegisterClass(Inst, Rt, Address, Decoder))) return MCDisassembler::Fail; } } - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); if (Rn == 0xF) { switch (Inst.getOpcode()) { case ARM::t2LDRBs: @@ -3133,16 +3146,16 @@ static DecodeStatus DecodeT2LoadShift(MCInst &Inst, unsigned Insn, return MCDisassembler::Fail; } - int imm = fieldFromInstruction32(Insn, 0, 12); - if (!fieldFromInstruction32(Insn, 23, 1)) imm *= -1; + int imm = fieldFromInstruction(Insn, 0, 12); + if (!fieldFromInstruction(Insn, 23, 1)) imm *= -1; Inst.addOperand(MCOperand::CreateImm(imm)); return S; } - unsigned addrmode = fieldFromInstruction32(Insn, 4, 2); - addrmode |= fieldFromInstruction32(Insn, 0, 4) << 2; - addrmode |= fieldFromInstruction32(Insn, 16, 4) << 6; + unsigned addrmode = fieldFromInstruction(Insn, 4, 2); + addrmode |= fieldFromInstruction(Insn, 0, 4) << 2; + addrmode |= fieldFromInstruction(Insn, 16, 4) << 6; if (!Check(S, DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder))) return MCDisassembler::Fail; @@ -3167,8 +3180,8 @@ static DecodeStatus DecodeT2AddrModeImm8s4(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Val, 9, 4); - unsigned imm = fieldFromInstruction32(Val, 0, 9); + unsigned Rn = fieldFromInstruction(Val, 9, 4); + unsigned imm = fieldFromInstruction(Val, 0, 9); if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; @@ -3182,8 +3195,8 @@ static DecodeStatus DecodeT2AddrModeImm0_1020s4(MCInst &Inst,unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Val, 8, 4); - unsigned imm = fieldFromInstruction32(Val, 0, 8); + unsigned Rn = fieldFromInstruction(Val, 8, 4); + unsigned imm = fieldFromInstruction(Val, 0, 8); if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; @@ -3210,8 +3223,8 @@ static DecodeStatus DecodeT2AddrModeImm8(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Val, 9, 4); - unsigned imm = fieldFromInstruction32(Val, 0, 9); + unsigned Rn = fieldFromInstruction(Val, 9, 4); + unsigned imm = fieldFromInstruction(Val, 0, 9); // Some instructions always use an additive offset. switch (Inst.getOpcode()) { @@ -3241,12 +3254,12 @@ static DecodeStatus DecodeT2LdStPre(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned addr = fieldFromInstruction32(Insn, 0, 8); - addr |= fieldFromInstruction32(Insn, 9, 1) << 8; + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned addr = fieldFromInstruction(Insn, 0, 8); + addr |= fieldFromInstruction(Insn, 9, 1) << 8; addr |= Rn << 9; - unsigned load = fieldFromInstruction32(Insn, 20, 1); + unsigned load = fieldFromInstruction(Insn, 20, 1); if (!load) { if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))) @@ -3271,8 +3284,8 @@ static DecodeStatus DecodeT2AddrModeImm12(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Val, 13, 4); - unsigned imm = fieldFromInstruction32(Val, 0, 12); + unsigned Rn = fieldFromInstruction(Val, 13, 4); + unsigned imm = fieldFromInstruction(Val, 0, 12); if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; @@ -3284,7 +3297,7 @@ static DecodeStatus DecodeT2AddrModeImm12(MCInst &Inst, unsigned Val, static DecodeStatus DecodeThumbAddSPImm(MCInst &Inst, uint16_t Insn, uint64_t Address, const void *Decoder) { - unsigned imm = fieldFromInstruction16(Insn, 0, 7); + unsigned imm = fieldFromInstruction(Insn, 0, 7); Inst.addOperand(MCOperand::CreateReg(ARM::SP)); Inst.addOperand(MCOperand::CreateReg(ARM::SP)); @@ -3298,8 +3311,8 @@ static DecodeStatus DecodeThumbAddSPReg(MCInst &Inst, uint16_t Insn, DecodeStatus S = MCDisassembler::Success; if (Inst.getOpcode() == ARM::tADDrSP) { - unsigned Rdm = fieldFromInstruction16(Insn, 0, 3); - Rdm |= fieldFromInstruction16(Insn, 7, 1) << 3; + unsigned Rdm = fieldFromInstruction(Insn, 0, 3); + Rdm |= fieldFromInstruction(Insn, 7, 1) << 3; if (!Check(S, DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder))) return MCDisassembler::Fail; @@ -3307,7 +3320,7 @@ static DecodeStatus DecodeThumbAddSPReg(MCInst &Inst, uint16_t Insn, if (!Check(S, DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder))) return MCDisassembler::Fail; } else if (Inst.getOpcode() == ARM::tADDspr) { - unsigned Rm = fieldFromInstruction16(Insn, 3, 4); + unsigned Rm = fieldFromInstruction(Insn, 3, 4); Inst.addOperand(MCOperand::CreateReg(ARM::SP)); Inst.addOperand(MCOperand::CreateReg(ARM::SP)); @@ -3320,8 +3333,8 @@ static DecodeStatus DecodeThumbAddSPReg(MCInst &Inst, uint16_t Insn, static DecodeStatus DecodeThumbCPS(MCInst &Inst, uint16_t Insn, uint64_t Address, const void *Decoder) { - unsigned imod = fieldFromInstruction16(Insn, 4, 1) | 0x2; - unsigned flags = fieldFromInstruction16(Insn, 0, 3); + unsigned imod = fieldFromInstruction(Insn, 4, 1) | 0x2; + unsigned flags = fieldFromInstruction(Insn, 0, 3); Inst.addOperand(MCOperand::CreateImm(imod)); Inst.addOperand(MCOperand::CreateImm(flags)); @@ -3332,8 +3345,8 @@ static DecodeStatus DecodeThumbCPS(MCInst &Inst, uint16_t Insn, static DecodeStatus DecodePostIdxReg(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned add = fieldFromInstruction32(Insn, 4, 1); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned add = fieldFromInstruction(Insn, 4, 1); if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder))) return MCDisassembler::Fail; @@ -3380,8 +3393,8 @@ DecodeThumbTableBranch(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); if (Rn == ARM::SP) S = MCDisassembler::SoftFail; if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))) @@ -3396,9 +3409,9 @@ DecodeThumb2BCCInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned pred = fieldFromInstruction32(Insn, 22, 4); + unsigned pred = fieldFromInstruction(Insn, 22, 4); if (pred == 0xE || pred == 0xF) { - unsigned opc = fieldFromInstruction32(Insn, 4, 28); + unsigned opc = fieldFromInstruction(Insn, 4, 28); switch (opc) { default: return MCDisassembler::Fail; @@ -3413,15 +3426,15 @@ DecodeThumb2BCCInstruction(MCInst &Inst, unsigned Insn, break; } - unsigned imm = fieldFromInstruction32(Insn, 0, 4); + unsigned imm = fieldFromInstruction(Insn, 0, 4); return DecodeMemBarrierOption(Inst, imm, Address, Decoder); } - unsigned brtarget = fieldFromInstruction32(Insn, 0, 11) << 1; - brtarget |= fieldFromInstruction32(Insn, 11, 1) << 19; - brtarget |= fieldFromInstruction32(Insn, 13, 1) << 18; - brtarget |= fieldFromInstruction32(Insn, 16, 6) << 12; - brtarget |= fieldFromInstruction32(Insn, 26, 1) << 20; + unsigned brtarget = fieldFromInstruction(Insn, 0, 11) << 1; + brtarget |= fieldFromInstruction(Insn, 11, 1) << 19; + brtarget |= fieldFromInstruction(Insn, 13, 1) << 18; + brtarget |= fieldFromInstruction(Insn, 16, 6) << 12; + brtarget |= fieldFromInstruction(Insn, 26, 1) << 20; if (!Check(S, DecodeT2BROperand(Inst, brtarget, Address, Decoder))) return MCDisassembler::Fail; @@ -3436,10 +3449,10 @@ DecodeThumb2BCCInstruction(MCInst &Inst, unsigned Insn, // a splat operation or a rotation. static DecodeStatus DecodeT2SOImm(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { - unsigned ctrl = fieldFromInstruction32(Val, 10, 2); + unsigned ctrl = fieldFromInstruction(Val, 10, 2); if (ctrl == 0) { - unsigned byte = fieldFromInstruction32(Val, 8, 2); - unsigned imm = fieldFromInstruction32(Val, 0, 8); + unsigned byte = fieldFromInstruction(Val, 8, 2); + unsigned imm = fieldFromInstruction(Val, 0, 8); switch (byte) { case 0: Inst.addOperand(MCOperand::CreateImm(imm)); @@ -3456,8 +3469,8 @@ static DecodeStatus DecodeT2SOImm(MCInst &Inst, unsigned Val, break; } } else { - unsigned unrot = fieldFromInstruction32(Val, 0, 7) | 0x80; - unsigned rot = fieldFromInstruction32(Val, 7, 5); + unsigned unrot = fieldFromInstruction(Val, 0, 7) | 0x80; + unsigned rot = fieldFromInstruction(Val, 7, 5); unsigned imm = (unrot >> rot) | (unrot << ((32-rot)&31)); Inst.addOperand(MCOperand::CreateImm(imm)); } @@ -3517,9 +3530,9 @@ static DecodeStatus DecodeDoubleRegLoad(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned pred = fieldFromInstruction(Insn, 28, 4); if ((Rt & 1) || Rt == 0xE || Rn == 0xF) return MCDisassembler::Fail; @@ -3540,10 +3553,10 @@ static DecodeStatus DecodeDoubleRegStore(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder){ DecodeStatus S = MCDisassembler::Success; - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - unsigned Rt = fieldFromInstruction32(Insn, 0, 4); - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + unsigned Rt = fieldFromInstruction(Insn, 0, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned pred = fieldFromInstruction(Insn, 28, 4); if (!Check(S, DecoderGPRRegisterClass(Inst, Rd, Address, Decoder))) return MCDisassembler::Fail; @@ -3567,12 +3580,12 @@ static DecodeStatus DecodeLDRPreImm(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned imm = fieldFromInstruction32(Insn, 0, 12); - imm |= fieldFromInstruction32(Insn, 16, 4) << 13; - imm |= fieldFromInstruction32(Insn, 23, 1) << 12; - unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned imm = fieldFromInstruction(Insn, 0, 12); + imm |= fieldFromInstruction(Insn, 16, 4) << 13; + imm |= fieldFromInstruction(Insn, 23, 1) << 12; + unsigned pred = fieldFromInstruction(Insn, 28, 4); if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail; @@ -3592,13 +3605,13 @@ static DecodeStatus DecodeLDRPreReg(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned imm = fieldFromInstruction32(Insn, 0, 12); - imm |= fieldFromInstruction32(Insn, 16, 4) << 13; - imm |= fieldFromInstruction32(Insn, 23, 1) << 12; - unsigned pred = fieldFromInstruction32(Insn, 28, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned imm = fieldFromInstruction(Insn, 0, 12); + imm |= fieldFromInstruction(Insn, 16, 4) << 13; + imm |= fieldFromInstruction(Insn, 23, 1) << 12; + unsigned pred = fieldFromInstruction(Insn, 28, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail; if (Rm == 0xF) S = MCDisassembler::SoftFail; @@ -3620,12 +3633,12 @@ static DecodeStatus DecodeSTRPreImm(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned imm = fieldFromInstruction32(Insn, 0, 12); - imm |= fieldFromInstruction32(Insn, 16, 4) << 13; - imm |= fieldFromInstruction32(Insn, 23, 1) << 12; - unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned imm = fieldFromInstruction(Insn, 0, 12); + imm |= fieldFromInstruction(Insn, 16, 4) << 13; + imm |= fieldFromInstruction(Insn, 23, 1) << 12; + unsigned pred = fieldFromInstruction(Insn, 28, 4); if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail; @@ -3645,12 +3658,12 @@ static DecodeStatus DecodeSTRPreReg(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned imm = fieldFromInstruction32(Insn, 0, 12); - imm |= fieldFromInstruction32(Insn, 16, 4) << 13; - imm |= fieldFromInstruction32(Insn, 23, 1) << 12; - unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned imm = fieldFromInstruction(Insn, 0, 12); + imm |= fieldFromInstruction(Insn, 16, 4) << 13; + imm |= fieldFromInstruction(Insn, 23, 1) << 12; + unsigned pred = fieldFromInstruction(Insn, 28, 4); if (Rn == 0xF || Rn == Rt) S = MCDisassembler::SoftFail; @@ -3670,11 +3683,11 @@ static DecodeStatus DecodeVLD1LN(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned size = fieldFromInstruction32(Insn, 10, 2); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned size = fieldFromInstruction(Insn, 10, 2); unsigned align = 0; unsigned index = 0; @@ -3682,22 +3695,22 @@ static DecodeStatus DecodeVLD1LN(MCInst &Inst, unsigned Insn, default: return MCDisassembler::Fail; case 0: - if (fieldFromInstruction32(Insn, 4, 1)) + if (fieldFromInstruction(Insn, 4, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 5, 3); + index = fieldFromInstruction(Insn, 5, 3); break; case 1: - if (fieldFromInstruction32(Insn, 5, 1)) + if (fieldFromInstruction(Insn, 5, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 6, 2); - if (fieldFromInstruction32(Insn, 4, 1)) + index = fieldFromInstruction(Insn, 6, 2); + if (fieldFromInstruction(Insn, 4, 1)) align = 2; break; case 2: - if (fieldFromInstruction32(Insn, 6, 1)) + if (fieldFromInstruction(Insn, 6, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 7, 1); - if (fieldFromInstruction32(Insn, 4, 2) != 0) + index = fieldFromInstruction(Insn, 7, 1); + if (fieldFromInstruction(Insn, 4, 2) != 0) align = 4; } @@ -3729,11 +3742,11 @@ static DecodeStatus DecodeVST1LN(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned size = fieldFromInstruction32(Insn, 10, 2); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned size = fieldFromInstruction(Insn, 10, 2); unsigned align = 0; unsigned index = 0; @@ -3741,22 +3754,22 @@ static DecodeStatus DecodeVST1LN(MCInst &Inst, unsigned Insn, default: return MCDisassembler::Fail; case 0: - if (fieldFromInstruction32(Insn, 4, 1)) + if (fieldFromInstruction(Insn, 4, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 5, 3); + index = fieldFromInstruction(Insn, 5, 3); break; case 1: - if (fieldFromInstruction32(Insn, 5, 1)) + if (fieldFromInstruction(Insn, 5, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 6, 2); - if (fieldFromInstruction32(Insn, 4, 1)) + index = fieldFromInstruction(Insn, 6, 2); + if (fieldFromInstruction(Insn, 4, 1)) align = 2; break; case 2: - if (fieldFromInstruction32(Insn, 6, 1)) + if (fieldFromInstruction(Insn, 6, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 7, 1); - if (fieldFromInstruction32(Insn, 4, 2) != 0) + index = fieldFromInstruction(Insn, 7, 1); + if (fieldFromInstruction(Insn, 4, 2) != 0) align = 4; } @@ -3787,11 +3800,11 @@ static DecodeStatus DecodeVLD2LN(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned size = fieldFromInstruction32(Insn, 10, 2); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned size = fieldFromInstruction(Insn, 10, 2); unsigned align = 0; unsigned index = 0; @@ -3800,24 +3813,24 @@ static DecodeStatus DecodeVLD2LN(MCInst &Inst, unsigned Insn, default: return MCDisassembler::Fail; case 0: - index = fieldFromInstruction32(Insn, 5, 3); - if (fieldFromInstruction32(Insn, 4, 1)) + index = fieldFromInstruction(Insn, 5, 3); + if (fieldFromInstruction(Insn, 4, 1)) align = 2; break; case 1: - index = fieldFromInstruction32(Insn, 6, 2); - if (fieldFromInstruction32(Insn, 4, 1)) + index = fieldFromInstruction(Insn, 6, 2); + if (fieldFromInstruction(Insn, 4, 1)) align = 4; - if (fieldFromInstruction32(Insn, 5, 1)) + if (fieldFromInstruction(Insn, 5, 1)) inc = 2; break; case 2: - if (fieldFromInstruction32(Insn, 5, 1)) + if (fieldFromInstruction(Insn, 5, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 7, 1); - if (fieldFromInstruction32(Insn, 4, 1) != 0) + index = fieldFromInstruction(Insn, 7, 1); + if (fieldFromInstruction(Insn, 4, 1) != 0) align = 8; - if (fieldFromInstruction32(Insn, 6, 1)) + if (fieldFromInstruction(Insn, 6, 1)) inc = 2; break; } @@ -3854,11 +3867,11 @@ static DecodeStatus DecodeVST2LN(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned size = fieldFromInstruction32(Insn, 10, 2); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned size = fieldFromInstruction(Insn, 10, 2); unsigned align = 0; unsigned index = 0; @@ -3867,24 +3880,24 @@ static DecodeStatus DecodeVST2LN(MCInst &Inst, unsigned Insn, default: return MCDisassembler::Fail; case 0: - index = fieldFromInstruction32(Insn, 5, 3); - if (fieldFromInstruction32(Insn, 4, 1)) + index = fieldFromInstruction(Insn, 5, 3); + if (fieldFromInstruction(Insn, 4, 1)) align = 2; break; case 1: - index = fieldFromInstruction32(Insn, 6, 2); - if (fieldFromInstruction32(Insn, 4, 1)) + index = fieldFromInstruction(Insn, 6, 2); + if (fieldFromInstruction(Insn, 4, 1)) align = 4; - if (fieldFromInstruction32(Insn, 5, 1)) + if (fieldFromInstruction(Insn, 5, 1)) inc = 2; break; case 2: - if (fieldFromInstruction32(Insn, 5, 1)) + if (fieldFromInstruction(Insn, 5, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 7, 1); - if (fieldFromInstruction32(Insn, 4, 1) != 0) + index = fieldFromInstruction(Insn, 7, 1); + if (fieldFromInstruction(Insn, 4, 1) != 0) align = 8; - if (fieldFromInstruction32(Insn, 6, 1)) + if (fieldFromInstruction(Insn, 6, 1)) inc = 2; break; } @@ -3918,11 +3931,11 @@ static DecodeStatus DecodeVLD3LN(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned size = fieldFromInstruction32(Insn, 10, 2); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned size = fieldFromInstruction(Insn, 10, 2); unsigned align = 0; unsigned index = 0; @@ -3931,22 +3944,22 @@ static DecodeStatus DecodeVLD3LN(MCInst &Inst, unsigned Insn, default: return MCDisassembler::Fail; case 0: - if (fieldFromInstruction32(Insn, 4, 1)) + if (fieldFromInstruction(Insn, 4, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 5, 3); + index = fieldFromInstruction(Insn, 5, 3); break; case 1: - if (fieldFromInstruction32(Insn, 4, 1)) + if (fieldFromInstruction(Insn, 4, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 6, 2); - if (fieldFromInstruction32(Insn, 5, 1)) + index = fieldFromInstruction(Insn, 6, 2); + if (fieldFromInstruction(Insn, 5, 1)) inc = 2; break; case 2: - if (fieldFromInstruction32(Insn, 4, 2)) + if (fieldFromInstruction(Insn, 4, 2)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 7, 1); - if (fieldFromInstruction32(Insn, 6, 1)) + index = fieldFromInstruction(Insn, 7, 1); + if (fieldFromInstruction(Insn, 6, 1)) inc = 2; break; } @@ -3988,11 +4001,11 @@ static DecodeStatus DecodeVST3LN(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned size = fieldFromInstruction32(Insn, 10, 2); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned size = fieldFromInstruction(Insn, 10, 2); unsigned align = 0; unsigned index = 0; @@ -4001,22 +4014,22 @@ static DecodeStatus DecodeVST3LN(MCInst &Inst, unsigned Insn, default: return MCDisassembler::Fail; case 0: - if (fieldFromInstruction32(Insn, 4, 1)) + if (fieldFromInstruction(Insn, 4, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 5, 3); + index = fieldFromInstruction(Insn, 5, 3); break; case 1: - if (fieldFromInstruction32(Insn, 4, 1)) + if (fieldFromInstruction(Insn, 4, 1)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 6, 2); - if (fieldFromInstruction32(Insn, 5, 1)) + index = fieldFromInstruction(Insn, 6, 2); + if (fieldFromInstruction(Insn, 5, 1)) inc = 2; break; case 2: - if (fieldFromInstruction32(Insn, 4, 2)) + if (fieldFromInstruction(Insn, 4, 2)) return MCDisassembler::Fail; // UNDEFINED - index = fieldFromInstruction32(Insn, 7, 1); - if (fieldFromInstruction32(Insn, 6, 1)) + index = fieldFromInstruction(Insn, 7, 1); + if (fieldFromInstruction(Insn, 6, 1)) inc = 2; break; } @@ -4052,11 +4065,11 @@ static DecodeStatus DecodeVLD4LN(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned size = fieldFromInstruction32(Insn, 10, 2); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned size = fieldFromInstruction(Insn, 10, 2); unsigned align = 0; unsigned index = 0; @@ -4065,22 +4078,22 @@ static DecodeStatus DecodeVLD4LN(MCInst &Inst, unsigned Insn, default: return MCDisassembler::Fail; case 0: - if (fieldFromInstruction32(Insn, 4, 1)) + if (fieldFromInstruction(Insn, 4, 1)) align = 4; - index = fieldFromInstruction32(Insn, 5, 3); + index = fieldFromInstruction(Insn, 5, 3); break; case 1: - if (fieldFromInstruction32(Insn, 4, 1)) + if (fieldFromInstruction(Insn, 4, 1)) align = 8; - index = fieldFromInstruction32(Insn, 6, 2); - if (fieldFromInstruction32(Insn, 5, 1)) + index = fieldFromInstruction(Insn, 6, 2); + if (fieldFromInstruction(Insn, 5, 1)) inc = 2; break; case 2: - if (fieldFromInstruction32(Insn, 4, 2)) - align = 4 << fieldFromInstruction32(Insn, 4, 2); - index = fieldFromInstruction32(Insn, 7, 1); - if (fieldFromInstruction32(Insn, 6, 1)) + if (fieldFromInstruction(Insn, 4, 2)) + align = 4 << fieldFromInstruction(Insn, 4, 2); + index = fieldFromInstruction(Insn, 7, 1); + if (fieldFromInstruction(Insn, 6, 1)) inc = 2; break; } @@ -4126,11 +4139,11 @@ static DecodeStatus DecodeVST4LN(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 0, 4); - unsigned Rd = fieldFromInstruction32(Insn, 12, 4); - Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; - unsigned size = fieldFromInstruction32(Insn, 10, 2); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 0, 4); + unsigned Rd = fieldFromInstruction(Insn, 12, 4); + Rd |= fieldFromInstruction(Insn, 22, 1) << 4; + unsigned size = fieldFromInstruction(Insn, 10, 2); unsigned align = 0; unsigned index = 0; @@ -4139,22 +4152,22 @@ static DecodeStatus DecodeVST4LN(MCInst &Inst, unsigned Insn, default: return MCDisassembler::Fail; case 0: - if (fieldFromInstruction32(Insn, 4, 1)) + if (fieldFromInstruction(Insn, 4, 1)) align = 4; - index = fieldFromInstruction32(Insn, 5, 3); + index = fieldFromInstruction(Insn, 5, 3); break; case 1: - if (fieldFromInstruction32(Insn, 4, 1)) + if (fieldFromInstruction(Insn, 4, 1)) align = 8; - index = fieldFromInstruction32(Insn, 6, 2); - if (fieldFromInstruction32(Insn, 5, 1)) + index = fieldFromInstruction(Insn, 6, 2); + if (fieldFromInstruction(Insn, 5, 1)) inc = 2; break; case 2: - if (fieldFromInstruction32(Insn, 4, 2)) - align = 4 << fieldFromInstruction32(Insn, 4, 2); - index = fieldFromInstruction32(Insn, 7, 1); - if (fieldFromInstruction32(Insn, 6, 1)) + if (fieldFromInstruction(Insn, 4, 2)) + align = 4 << fieldFromInstruction(Insn, 4, 2); + index = fieldFromInstruction(Insn, 7, 1); + if (fieldFromInstruction(Insn, 6, 1)) inc = 2; break; } @@ -4190,11 +4203,11 @@ static DecodeStatus DecodeVST4LN(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeVMOVSRR(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned Rt2 = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 5, 1); - unsigned pred = fieldFromInstruction32(Insn, 28, 4); - Rm |= fieldFromInstruction32(Insn, 0, 4) << 1; + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned Rt2 = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 5, 1); + unsigned pred = fieldFromInstruction(Insn, 28, 4); + Rm |= fieldFromInstruction(Insn, 0, 4) << 1; if (Rt == 0xF || Rt2 == 0xF || Rm == 0x1F) S = MCDisassembler::SoftFail; @@ -4216,11 +4229,11 @@ static DecodeStatus DecodeVMOVSRR(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeVMOVRRS(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned Rt2 = fieldFromInstruction32(Insn, 16, 4); - unsigned Rm = fieldFromInstruction32(Insn, 5, 1); - unsigned pred = fieldFromInstruction32(Insn, 28, 4); - Rm |= fieldFromInstruction32(Insn, 0, 4) << 1; + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned Rt2 = fieldFromInstruction(Insn, 16, 4); + unsigned Rm = fieldFromInstruction(Insn, 5, 1); + unsigned pred = fieldFromInstruction(Insn, 28, 4); + Rm |= fieldFromInstruction(Insn, 0, 4) << 1; if (Rt == 0xF || Rt2 == 0xF || Rm == 0x1F) S = MCDisassembler::SoftFail; @@ -4242,8 +4255,8 @@ static DecodeStatus DecodeVMOVRRS(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeIT(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned pred = fieldFromInstruction16(Insn, 4, 4); - unsigned mask = fieldFromInstruction16(Insn, 0, 4); + unsigned pred = fieldFromInstruction(Insn, 4, 4); + unsigned mask = fieldFromInstruction(Insn, 0, 4); if (pred == 0xF) { pred = 0xE; @@ -4265,13 +4278,13 @@ DecodeT2LDRDPreInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned Rt2 = fieldFromInstruction32(Insn, 8, 4); - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned addr = fieldFromInstruction32(Insn, 0, 8); - unsigned W = fieldFromInstruction32(Insn, 21, 1); - unsigned U = fieldFromInstruction32(Insn, 23, 1); - unsigned P = fieldFromInstruction32(Insn, 24, 1); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned Rt2 = fieldFromInstruction(Insn, 8, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned addr = fieldFromInstruction(Insn, 0, 8); + unsigned W = fieldFromInstruction(Insn, 21, 1); + unsigned U = fieldFromInstruction(Insn, 23, 1); + unsigned P = fieldFromInstruction(Insn, 24, 1); bool writeback = (W == 1) | (P == 0); addr |= (U << 8) | (Rn << 9); @@ -4302,13 +4315,13 @@ DecodeT2STRDPreInstruction(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned Rt2 = fieldFromInstruction32(Insn, 8, 4); - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned addr = fieldFromInstruction32(Insn, 0, 8); - unsigned W = fieldFromInstruction32(Insn, 21, 1); - unsigned U = fieldFromInstruction32(Insn, 23, 1); - unsigned P = fieldFromInstruction32(Insn, 24, 1); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned Rt2 = fieldFromInstruction(Insn, 8, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned addr = fieldFromInstruction(Insn, 0, 8); + unsigned W = fieldFromInstruction(Insn, 21, 1); + unsigned U = fieldFromInstruction(Insn, 23, 1); + unsigned P = fieldFromInstruction(Insn, 24, 1); bool writeback = (W == 1) | (P == 0); addr |= (U << 8) | (Rn << 9); @@ -4334,13 +4347,13 @@ DecodeT2STRDPreInstruction(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeT2Adr(MCInst &Inst, uint32_t Insn, uint64_t Address, const void *Decoder) { - unsigned sign1 = fieldFromInstruction32(Insn, 21, 1); - unsigned sign2 = fieldFromInstruction32(Insn, 23, 1); + unsigned sign1 = fieldFromInstruction(Insn, 21, 1); + unsigned sign2 = fieldFromInstruction(Insn, 23, 1); if (sign1 != sign2) return MCDisassembler::Fail; - unsigned Val = fieldFromInstruction32(Insn, 0, 8); - Val |= fieldFromInstruction32(Insn, 12, 3) << 8; - Val |= fieldFromInstruction32(Insn, 26, 1) << 11; + unsigned Val = fieldFromInstruction(Insn, 0, 8); + Val |= fieldFromInstruction(Insn, 12, 3) << 8; + Val |= fieldFromInstruction(Insn, 26, 1) << 11; Val |= sign1 << 12; Inst.addOperand(MCOperand::CreateImm(SignExtend32<13>(Val))); @@ -4360,10 +4373,10 @@ static DecodeStatus DecodeT2ShifterImmOperand(MCInst &Inst, uint32_t Val, static DecodeStatus DecodeSwap(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - unsigned Rt = fieldFromInstruction32(Insn, 12, 4); - unsigned Rt2 = fieldFromInstruction32(Insn, 0, 4); - unsigned Rn = fieldFromInstruction32(Insn, 16, 4); - unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned Rt = fieldFromInstruction(Insn, 12, 4); + unsigned Rt2 = fieldFromInstruction(Insn, 0, 4); + unsigned Rn = fieldFromInstruction(Insn, 16, 4); + unsigned pred = fieldFromInstruction(Insn, 28, 4); if (pred == 0xF) return DecodeCPSInstruction(Inst, Insn, Address, Decoder); @@ -4387,12 +4400,12 @@ static DecodeStatus DecodeSwap(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeVCVTD(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - unsigned Vd = (fieldFromInstruction32(Insn, 12, 4) << 0); - Vd |= (fieldFromInstruction32(Insn, 22, 1) << 4); - unsigned Vm = (fieldFromInstruction32(Insn, 0, 4) << 0); - Vm |= (fieldFromInstruction32(Insn, 5, 1) << 4); - unsigned imm = fieldFromInstruction32(Insn, 16, 6); - unsigned cmode = fieldFromInstruction32(Insn, 8, 4); + unsigned Vd = (fieldFromInstruction(Insn, 12, 4) << 0); + Vd |= (fieldFromInstruction(Insn, 22, 1) << 4); + unsigned Vm = (fieldFromInstruction(Insn, 0, 4) << 0); + Vm |= (fieldFromInstruction(Insn, 5, 1) << 4); + unsigned imm = fieldFromInstruction(Insn, 16, 6); + unsigned cmode = fieldFromInstruction(Insn, 8, 4); DecodeStatus S = MCDisassembler::Success; @@ -4415,12 +4428,12 @@ static DecodeStatus DecodeVCVTD(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeVCVTQ(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - unsigned Vd = (fieldFromInstruction32(Insn, 12, 4) << 0); - Vd |= (fieldFromInstruction32(Insn, 22, 1) << 4); - unsigned Vm = (fieldFromInstruction32(Insn, 0, 4) << 0); - Vm |= (fieldFromInstruction32(Insn, 5, 1) << 4); - unsigned imm = fieldFromInstruction32(Insn, 16, 6); - unsigned cmode = fieldFromInstruction32(Insn, 8, 4); + unsigned Vd = (fieldFromInstruction(Insn, 12, 4) << 0); + Vd |= (fieldFromInstruction(Insn, 22, 1) << 4); + unsigned Vm = (fieldFromInstruction(Insn, 0, 4) << 0); + Vm |= (fieldFromInstruction(Insn, 5, 1) << 4); + unsigned imm = fieldFromInstruction(Insn, 16, 6); + unsigned cmode = fieldFromInstruction(Insn, 8, 4); DecodeStatus S = MCDisassembler::Success; @@ -4445,13 +4458,13 @@ static DecodeStatus DecodeLDR(MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; - unsigned Rn = fieldFromInstruction32(Val, 16, 4); - unsigned Rt = fieldFromInstruction32(Val, 12, 4); - unsigned Rm = fieldFromInstruction32(Val, 0, 4); - Rm |= (fieldFromInstruction32(Val, 23, 1) << 4); - unsigned Cond = fieldFromInstruction32(Val, 28, 4); + unsigned Rn = fieldFromInstruction(Val, 16, 4); + unsigned Rt = fieldFromInstruction(Val, 12, 4); + unsigned Rm = fieldFromInstruction(Val, 0, 4); + Rm |= (fieldFromInstruction(Val, 23, 1) << 4); + unsigned Cond = fieldFromInstruction(Val, 28, 4); - if (fieldFromInstruction32(Val, 8, 4) != 0 || Rn == Rt) + if (fieldFromInstruction(Val, 8, 4) != 0 || Rn == Rt) S = MCDisassembler::SoftFail; if (!Check(S, DecodeGPRnopcRegisterClass(Inst, Rt, Address, Decoder))) @@ -4473,11 +4486,11 @@ static DecodeStatus DecodeMRRC2(llvm::MCInst &Inst, unsigned Val, DecodeStatus S = MCDisassembler::Success; - unsigned CRm = fieldFromInstruction32(Val, 0, 4); - unsigned opc1 = fieldFromInstruction32(Val, 4, 4); - unsigned cop = fieldFromInstruction32(Val, 8, 4); - unsigned Rt = fieldFromInstruction32(Val, 12, 4); - unsigned Rt2 = fieldFromInstruction32(Val, 16, 4); + unsigned CRm = fieldFromInstruction(Val, 0, 4); + unsigned opc1 = fieldFromInstruction(Val, 4, 4); + unsigned cop = fieldFromInstruction(Val, 8, 4); + unsigned Rt = fieldFromInstruction(Val, 12, 4); + unsigned Rt2 = fieldFromInstruction(Val, 16, 4); if ((cop & ~0x1) == 0xa) return MCDisassembler::Fail; diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 042b456538c3..aa5747209b79 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -16,6 +16,7 @@ #include "MipsRegisterInfo.h" #include "llvm/MC/EDInstInfo.h" #include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCFixedLenDisassembler.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -274,7 +275,8 @@ MipsDisassembler::getInstruction(MCInst &instr, return MCDisassembler::Fail; // Calling the auto-generated decoder function. - Result = decodeMipsInstruction32(instr, Insn, Address, this, STI); + Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address, + this, STI); if (Result != MCDisassembler::Fail) { Size = 4; return Result; @@ -298,13 +300,15 @@ Mips64Disassembler::getInstruction(MCInst &instr, return MCDisassembler::Fail; // Calling the auto-generated decoder function. - Result = decodeMips64Instruction32(instr, Insn, Address, this, STI); + Result = decodeInstruction(DecoderTableMips6432, instr, Insn, Address, + this, STI); if (Result != MCDisassembler::Fail) { Size = 4; return Result; } // If we fail to decode in Mips64 decoder space we can try in Mips32 - Result = decodeMipsInstruction32(instr, Insn, Address, this, STI); + Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address, + this, STI); if (Result != MCDisassembler::Fail) { Size = 4; return Result; @@ -379,8 +383,8 @@ static DecodeStatus DecodeMem(MCInst &Inst, uint64_t Address, const void *Decoder) { int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Reg = fieldFromInstruction32(Insn, 16, 5); - unsigned Base = fieldFromInstruction32(Insn, 21, 5); + unsigned Reg = fieldFromInstruction(Insn, 16, 5); + unsigned Base = fieldFromInstruction(Insn, 21, 5); Reg = getReg(Decoder, Mips::CPURegsRegClassID, Reg); Base = getReg(Decoder, Mips::CPURegsRegClassID, Base); @@ -401,8 +405,8 @@ static DecodeStatus DecodeFMem(MCInst &Inst, uint64_t Address, const void *Decoder) { int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Reg = fieldFromInstruction32(Insn, 16, 5); - unsigned Base = fieldFromInstruction32(Insn, 21, 5); + unsigned Reg = fieldFromInstruction(Insn, 16, 5); + unsigned Base = fieldFromInstruction(Insn, 21, 5); Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg); Base = getReg(Decoder, Mips::CPURegsRegClassID, Base); @@ -484,7 +488,7 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst, uint64_t Address, const void *Decoder) { - unsigned JumpOffset = fieldFromInstruction32(Insn, 0, 26) << 2; + unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 2; Inst.addOperand(MCOperand::CreateImm(JumpOffset)); return MCDisassembler::Success; } diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index 8548ae0b8b53..90f7942c5b4e 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -44,6 +44,8 @@ def FeatureN64 : SubtargetFeature<"n64", "MipsABI", "N64", "Enable n64 ABI">; def FeatureEABI : SubtargetFeature<"eabi", "MipsABI", "EABI", "Enable eabi ABI">; +def FeatureAndroid : SubtargetFeature<"android", "IsAndroid", "true", + "Target is android">; def FeatureVFPU : SubtargetFeature<"vfpu", "HasVFPU", "true", "Enable vector FPU instructions.">; def FeatureSEInReg : SubtargetFeature<"seinreg", "HasSEInReg", "true", diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 8aadefdcd141..19213fa67305 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -145,6 +145,17 @@ def RetCC_MipsEABI : CallingConv<[ ]>; //===----------------------------------------------------------------------===// +// Mips Android Calling Convention +//===----------------------------------------------------------------------===// + +def RetCC_MipsAndroid : CallingConv<[ + // f32 are returned in registers F0, F2, F1, F3 + CCIfType<[f32], CCAssignToReg<[F0, F2, F1, F3]>>, + + CCDelegateTo<RetCC_MipsO32> +]>; + +//===----------------------------------------------------------------------===// // Mips FastCC Calling Convention //===----------------------------------------------------------------------===// def CC_MipsO32_FastCC : CallingConv<[ @@ -210,6 +221,7 @@ def RetCC_Mips : CallingConv<[ CCIfSubtarget<"isABI_EABI()", CCDelegateTo<RetCC_MipsEABI>>, CCIfSubtarget<"isABI_N32()", CCDelegateTo<RetCC_MipsN>>, CCIfSubtarget<"isABI_N64()", CCDelegateTo<RetCC_MipsN>>, + CCIfSubtarget<"isAndroid()", CCDelegateTo<RetCC_MipsAndroid>>, CCDelegateTo<RetCC_MipsO32> ]>; diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 3215c44be0ef..ba15362f07b0 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -89,6 +89,9 @@ protected: // InMips16 -- can process Mips16 instructions bool InMips16Mode; + // IsAndroid -- target is android + bool IsAndroid; + InstrItineraryData InstrItins; public: @@ -128,6 +131,7 @@ public: bool isNotSingleFloat() const { return !IsSingleFloat; } bool hasVFPU() const { return HasVFPU; } bool inMips16Mode() const { return InMips16Mode; } + bool isAndroid() const { return IsAndroid; } bool isLinux() const { return IsLinux; } bool hasStandardEncoding() const { return !inMips16Mode(); } diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index aa819eeb30a2..61d44c52d438 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -106,7 +106,7 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) // from FP_ROUND: that rounds to nearest, this rounds to zero. setOperationAction(ISD::FP_ROUND_INREG, MVT::ppcf128, Custom); - // We do not currently implment this libm ops for PowerPC. + // We do not currently implement these libm ops for PowerPC. setOperationAction(ISD::FFLOOR, MVT::ppcf128, Expand); setOperationAction(ISD::FCEIL, MVT::ppcf128, Expand); setOperationAction(ISD::FTRUNC, MVT::ppcf128, Expand); diff --git a/lib/Target/X86/X86.td b/lib/Target/X86/X86.td index 6c1a816c9ff2..18e6b7c3d9b6 100644 --- a/lib/Target/X86/X86.td +++ b/lib/Target/X86/X86.td @@ -17,14 +17,14 @@ include "llvm/Target/Target.td" //===----------------------------------------------------------------------===// -// X86 Subtarget state. +// X86 Subtarget state // def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true", "64-bit mode (x86_64)">; //===----------------------------------------------------------------------===// -// X86 Subtarget features. +// X86 Subtarget features //===----------------------------------------------------------------------===// def FeatureCMOV : SubtargetFeature<"cmov","HasCMov", "true", @@ -97,7 +97,7 @@ def FeatureFMA4 : SubtargetFeature<"fma4", "HasFMA4", "true", [FeatureAVX, FeatureSSE4A]>; def FeatureXOP : SubtargetFeature<"xop", "HasXOP", "true", "Enable XOP instructions", - [FeatureAVX, FeatureSSE4A]>; + [FeatureFMA4]>; def FeatureVectorUAMem : SubtargetFeature<"vector-unaligned-mem", "HasVectorUAMem", "true", "Allow unaligned memory operands on vector/SIMD instructions">; @@ -226,7 +226,7 @@ def : Proc<"bdver1", [FeatureXOP, FeatureFMA4, FeatureCMPXCHG16B, def : Proc<"bdver2", [FeatureXOP, FeatureFMA4, FeatureCMPXCHG16B, FeatureAES, FeaturePCLMUL, FeatureF16C, FeatureLZCNT, - FeaturePOPCNT, FeatureBMI]>; + FeaturePOPCNT, FeatureBMI, FeatureFMA]>; def : Proc<"winchip-c6", [FeatureMMX]>; def : Proc<"winchip2", [Feature3DNow]>; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index ea66a6115d7e..c77355f91796 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -5114,6 +5114,82 @@ X86TargetLowering::LowerVectorBroadcast(SDValue &Op, SelectionDAG &DAG) const { return SDValue(); } +// LowerVectorFpExtend - Recognize the scalarized FP_EXTEND from v2f32 to v2f64 +// and convert it into X86ISD::VFPEXT due to the current ISD::FP_EXTEND has the +// constraint of matching input/output vector elements. +SDValue +X86TargetLowering::LowerVectorFpExtend(SDValue &Op, SelectionDAG &DAG) const { + DebugLoc DL = Op.getDebugLoc(); + SDNode *N = Op.getNode(); + EVT VT = Op.getValueType(); + unsigned NumElts = Op.getNumOperands(); + + // Check supported types and sub-targets. + // + // Only v2f32 -> v2f64 needs special handling. + if (VT != MVT::v2f64 || !Subtarget->hasSSE2()) + return SDValue(); + + SDValue VecIn; + EVT VecInVT; + SmallVector<int, 8> Mask; + EVT SrcVT = MVT::Other; + + // Check the patterns could be translated into X86vfpext. + for (unsigned i = 0; i < NumElts; ++i) { + SDValue In = N->getOperand(i); + unsigned Opcode = In.getOpcode(); + + // Skip if the element is undefined. + if (Opcode == ISD::UNDEF) { + Mask.push_back(-1); + continue; + } + + // Quit if one of the elements is not defined from 'fpext'. + if (Opcode != ISD::FP_EXTEND) + return SDValue(); + + // Check how the source of 'fpext' is defined. + SDValue L2In = In.getOperand(0); + EVT L2InVT = L2In.getValueType(); + + // Check the original type + if (SrcVT == MVT::Other) + SrcVT = L2InVT; + else if (SrcVT != L2InVT) // Quit if non-homogenous typed. + return SDValue(); + + // Check whether the value being 'fpext'ed is extracted from the same + // source. + Opcode = L2In.getOpcode(); + + // Quit if it's not extracted with a constant index. + if (Opcode != ISD::EXTRACT_VECTOR_ELT || + !isa<ConstantSDNode>(L2In.getOperand(1))) + return SDValue(); + + SDValue ExtractedFromVec = L2In.getOperand(0); + + if (VecIn.getNode() == 0) { + VecIn = ExtractedFromVec; + VecInVT = ExtractedFromVec.getValueType(); + } else if (VecIn != ExtractedFromVec) // Quit if built from more than 1 vec. + return SDValue(); + + Mask.push_back(cast<ConstantSDNode>(L2In.getOperand(1))->getZExtValue()); + } + + // Fill the remaining mask as undef. + for (unsigned i = NumElts; i < VecInVT.getVectorNumElements(); ++i) + Mask.push_back(-1); + + return DAG.getNode(X86ISD::VFPEXT, DL, VT, + DAG.getVectorShuffle(VecInVT, DL, + VecIn, DAG.getUNDEF(VecInVT), + &Mask[0])); +} + SDValue X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const { DebugLoc dl = Op.getDebugLoc(); @@ -5146,6 +5222,10 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const { if (Broadcast.getNode()) return Broadcast; + SDValue FpExt = LowerVectorFpExtend(Op, DAG); + if (FpExt.getNode()) + return FpExt; + unsigned EVTBits = ExtVT.getSizeInBits(); unsigned NumZero = 0; @@ -11122,9 +11202,9 @@ static void ReplaceATOMIC_LOAD(SDNode *Node, Results.push_back(Swap.getValue(1)); } -void X86TargetLowering:: +static void ReplaceATOMIC_BINARY_64(SDNode *Node, SmallVectorImpl<SDValue>&Results, - SelectionDAG &DAG, unsigned NewOp) const { + SelectionDAG &DAG, unsigned NewOp) { DebugLoc dl = Node->getDebugLoc(); assert (Node->getValueType(0) == MVT::i64 && "Only know how to expand i64 atomics"); @@ -11245,26 +11325,40 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N, return; } case ISD::ATOMIC_LOAD_ADD: - ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMADD64_DAG); - return; case ISD::ATOMIC_LOAD_AND: - ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMAND64_DAG); - return; case ISD::ATOMIC_LOAD_NAND: - ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMNAND64_DAG); - return; case ISD::ATOMIC_LOAD_OR: - ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMOR64_DAG); - return; case ISD::ATOMIC_LOAD_SUB: - ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMSUB64_DAG); - return; case ISD::ATOMIC_LOAD_XOR: - ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMXOR64_DAG); - return; - case ISD::ATOMIC_SWAP: - ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMSWAP64_DAG); + case ISD::ATOMIC_SWAP: { + unsigned Opc; + switch (N->getOpcode()) { + default: llvm_unreachable("Unexpected opcode"); + case ISD::ATOMIC_LOAD_ADD: + Opc = X86ISD::ATOMADD64_DAG; + break; + case ISD::ATOMIC_LOAD_AND: + Opc = X86ISD::ATOMAND64_DAG; + break; + case ISD::ATOMIC_LOAD_NAND: + Opc = X86ISD::ATOMNAND64_DAG; + break; + case ISD::ATOMIC_LOAD_OR: + Opc = X86ISD::ATOMOR64_DAG; + break; + case ISD::ATOMIC_LOAD_SUB: + Opc = X86ISD::ATOMSUB64_DAG; + break; + case ISD::ATOMIC_LOAD_XOR: + Opc = X86ISD::ATOMXOR64_DAG; + break; + case ISD::ATOMIC_SWAP: + Opc = X86ISD::ATOMSWAP64_DAG; + break; + } + ReplaceATOMIC_BINARY_64(N, Results, DAG, Opc); return; + } case ISD::ATOMIC_LOAD: ReplaceATOMIC_LOAD(N, Results, DAG); } @@ -11342,7 +11436,9 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::ATOMAND64_DAG: return "X86ISD::ATOMAND64_DAG"; case X86ISD::ATOMNAND64_DAG: return "X86ISD::ATOMNAND64_DAG"; case X86ISD::VZEXT_MOVL: return "X86ISD::VZEXT_MOVL"; + case X86ISD::VSEXT_MOVL: return "X86ISD::VSEXT_MOVL"; case X86ISD::VZEXT_LOAD: return "X86ISD::VZEXT_LOAD"; + case X86ISD::VFPEXT: return "X86ISD::VFPEXT"; case X86ISD::VSHLDQ: return "X86ISD::VSHLDQ"; case X86ISD::VSRLDQ: return "X86ISD::VSRLDQ"; case X86ISD::VSHL: return "X86ISD::VSHL"; @@ -12792,16 +12888,31 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, // String/text processing lowering. case X86::PCMPISTRM128REG: case X86::VPCMPISTRM128REG: - return EmitPCMP(MI, BB, 3, false /* in-mem */); case X86::PCMPISTRM128MEM: case X86::VPCMPISTRM128MEM: - return EmitPCMP(MI, BB, 3, true /* in-mem */); case X86::PCMPESTRM128REG: case X86::VPCMPESTRM128REG: - return EmitPCMP(MI, BB, 5, false /* in mem */); case X86::PCMPESTRM128MEM: - case X86::VPCMPESTRM128MEM: - return EmitPCMP(MI, BB, 5, true /* in mem */); + case X86::VPCMPESTRM128MEM: { + unsigned NumArgs; + bool MemArg; + switch (MI->getOpcode()) { + default: llvm_unreachable("illegal opcode!"); + case X86::PCMPISTRM128REG: + case X86::VPCMPISTRM128REG: + NumArgs = 3; MemArg = false; break; + case X86::PCMPISTRM128MEM: + case X86::VPCMPISTRM128MEM: + NumArgs = 3; MemArg = true; break; + case X86::PCMPESTRM128REG: + case X86::VPCMPESTRM128REG: + NumArgs = 5; MemArg = false; break; + case X86::PCMPESTRM128MEM: + case X86::VPCMPESTRM128MEM: + NumArgs = 5; MemArg = true; break; + } + return EmitPCMP(MI, BB, NumArgs, MemArg); + } // Thread synchronization. case X86::MONITOR: diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 9123ebd8ae49..896d067fda75 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -227,6 +227,9 @@ namespace llvm { // VSEXT_MOVL - Vector move low and sign extend. VSEXT_MOVL, + // VFPEXT - Vector FP extend. + VFPEXT, + // VSHL, VSRL - 128-bit vector logical left / right shift VSHLDQ, VSRLDQ, @@ -828,6 +831,8 @@ namespace llvm { SDValue LowerVectorBroadcast(SDValue &Op, SelectionDAG &DAG) const; SDValue NormalizeVectorShuffle(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerVectorFpExtend(SDValue &Op, SelectionDAG &DAG) const; + virtual SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, @@ -859,9 +864,6 @@ namespace llvm { const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const; - void ReplaceATOMIC_BINARY_64(SDNode *N, SmallVectorImpl<SDValue> &Results, - SelectionDAG &DAG, unsigned NewOp) const; - /// Utility function to emit string processing sse4.2 instructions /// that return in xmm0. /// This takes the instruction to expand, the associated machine basic diff --git a/lib/Target/X86/X86InstrFragmentsSIMD.td b/lib/Target/X86/X86InstrFragmentsSIMD.td index d13167bb05db..1db68c86b76d 100644 --- a/lib/Target/X86/X86InstrFragmentsSIMD.td +++ b/lib/Target/X86/X86InstrFragmentsSIMD.td @@ -81,6 +81,11 @@ def X86vsmovl : SDNode<"X86ISD::VSEXT_MOVL", def X86vzload : SDNode<"X86ISD::VZEXT_LOAD", SDTLoad, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; + +def X86vfpext : SDNode<"X86ISD::VFPEXT", + SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>, + SDTCisFP<0>, SDTCisFP<1>]>>; + def X86vshldq : SDNode<"X86ISD::VSHLDQ", SDTIntShiftOp>; def X86vshrdq : SDNode<"X86ISD::VSRLDQ", SDTIntShiftOp>; def X86cmpp : SDNode<"X86ISD::CMPP", SDTX86VFCMP>; diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index e4c35b9bc556..20dc81eb4a37 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -2101,12 +2101,20 @@ let Predicates = [HasAVX] in { def : Pat<(v4f32 (fround (loadv4f64 addr:$src))), (VCVTPD2PSYrm addr:$src)>; + def : Pat<(v2f64 (X86vfpext (v4f32 VR128:$src))), + (VCVTPS2PDrr VR128:$src)>; def : Pat<(v4f64 (fextend (v4f32 VR128:$src))), (VCVTPS2PDYrr VR128:$src)>; def : Pat<(v4f64 (fextend (loadv4f32 addr:$src))), (VCVTPS2PDYrm addr:$src)>; } +let Predicates = [HasSSE2] in { + // Match fextend for 128 conversions + def : Pat<(v2f64 (X86vfpext (v4f32 VR128:$src))), + (CVTPS2PDrr VR128:$src)>; +} + //===----------------------------------------------------------------------===// // SSE 1 & 2 - Compare Instructions //===----------------------------------------------------------------------===// diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index d34fab103fa3..cbe1ca4ddcec 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -51,8 +51,8 @@ Instruction *InstCombiner::SimplifyMemTransfer(MemIntrinsic *MI) { // if the size is something we can handle with a single primitive load/store. // A single load+store correctly handles overlapping memory in the memmove // case. - unsigned Size = MemOpLength->getZExtValue(); - if (Size == 0) return MI; // Delete this mem transfer. + uint64_t Size = MemOpLength->getLimitedValue(); + assert(Size && "0-sized memory transfering should be removed already."); if (Size > 8 || (Size&(Size-1))) return 0; // If not 1/2/4/8 bytes, exit. @@ -133,11 +133,9 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) { ConstantInt *FillC = dyn_cast<ConstantInt>(MI->getValue()); if (!LenC || !FillC || !FillC->getType()->isIntegerTy(8)) return 0; - uint64_t Len = LenC->getZExtValue(); + uint64_t Len = LenC->getLimitedValue(); Alignment = MI->getAlignment(); - - // If the length is zero, this is a no-op - if (Len == 0) return MI; // memset(d,c,0,a) -> noop + assert(Len && "0-sized memory setting should be removed already."); // memset(s,c,n) -> store s, c (for n=1,2,4,8) if (Len <= 8 && isPowerOf2_32((uint32_t)Len)) { diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/lib/Transforms/Instrumentation/AddressSanitizer.cpp index bf35eacd69fa..17b83ceee194 100644 --- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -86,6 +86,9 @@ static cl::opt<bool> ClInstrumentWrites("asan-instrument-writes", static cl::opt<bool> ClInstrumentAtomics("asan-instrument-atomics", cl::desc("instrument atomic instructions (rmw, cmpxchg)"), cl::Hidden, cl::init(true)); +static cl::opt<bool> ClAlwaysSlowPath("asan-always-slow-path", + cl::desc("use instrumentation with slow path for all accesses"), + cl::Hidden, cl::init(false)); // This flag limits the number of instructions to be instrumented // in any given BB. Normally, this should be set to unlimited (INT_MAX), // but due to http://llvm.org/bugs/show_bug.cgi?id=12652 we temporary @@ -159,7 +162,7 @@ struct AddressSanitizer : public ModulePass { Value *Addr, uint32_t TypeSize, bool IsWrite); Value *createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong, Value *ShadowValue, uint32_t TypeSize); - Instruction *generateCrashCode(BasicBlock *BB, Value *Addr, Value *PC, + Instruction *generateCrashCode(Instruction *InsertBefore, Value *Addr, bool IsWrite, size_t AccessSizeIndex); bool instrumentMemIntrinsic(AsanFunctionContext &AFC, MemIntrinsic *MI); void instrumentMemIntrinsicParam(AsanFunctionContext &AFC, @@ -251,24 +254,24 @@ static GlobalVariable *createPrivateGlobalForString(Module &M, StringRef Str) { // ThenBlock // Tail // -// If ThenBlock is zero, a new block is created and its terminator is returned. -// Otherwize 0 is returned. -static BranchInst *splitBlockAndInsertIfThen(Value *Cmp, - BasicBlock *ThenBlock = 0) { +// ThenBlock block is created and its terminator is returned. +// If Unreachable, ThenBlock is terminated with UnreachableInst, otherwise +// it is terminated with BranchInst to Tail. +static TerminatorInst *splitBlockAndInsertIfThen(Value *Cmp, bool Unreachable) { Instruction *SplitBefore = cast<Instruction>(Cmp)->getNextNode(); BasicBlock *Head = SplitBefore->getParent(); BasicBlock *Tail = Head->splitBasicBlock(SplitBefore); TerminatorInst *HeadOldTerm = Head->getTerminator(); - BranchInst *CheckTerm = 0; - if (!ThenBlock) { - LLVMContext &C = Head->getParent()->getParent()->getContext(); - ThenBlock = BasicBlock::Create(C, "", Head->getParent(), Tail); + LLVMContext &C = Head->getParent()->getParent()->getContext(); + BasicBlock *ThenBlock = BasicBlock::Create(C, "", Head->getParent(), Tail); + TerminatorInst *CheckTerm; + if (Unreachable) + CheckTerm = new UnreachableInst(C, ThenBlock); + else CheckTerm = BranchInst::Create(Tail, ThenBlock); - } BranchInst *HeadNewTerm = BranchInst::Create(/*ifTrue*/ThenBlock, /*ifFalse*/Tail, Cmp); ReplaceInstWithInst(HeadOldTerm, HeadNewTerm); - return CheckTerm; } @@ -320,7 +323,7 @@ bool AddressSanitizer::instrumentMemIntrinsic(AsanFunctionContext &AFC, Value *Cmp = IRB.CreateICmpNE(Length, Constant::getNullValue(Length->getType())); - InsertBefore = splitBlockAndInsertIfThen(Cmp); + InsertBefore = splitBlockAndInsertIfThen(Cmp, false); } instrumentMemIntrinsicParam(AFC, MI, Dst, Length, InsertBefore, true); @@ -391,15 +394,11 @@ Function *AddressSanitizer::checkInterfaceFunction(Constant *FuncOrBitcast) { } Instruction *AddressSanitizer::generateCrashCode( - BasicBlock *BB, Value *Addr, Value *PC, + Instruction *InsertBefore, Value *Addr, bool IsWrite, size_t AccessSizeIndex) { - IRBuilder<> IRB(BB->getFirstNonPHI()); - CallInst *Call; - if (PC) - Call = IRB.CreateCall2(AsanErrorCallback[IsWrite][AccessSizeIndex], - Addr, PC); - else - Call = IRB.CreateCall(AsanErrorCallback[IsWrite][AccessSizeIndex], Addr); + IRBuilder<> IRB(InsertBefore); + CallInst *Call = IRB.CreateCall(AsanErrorCallback[IsWrite][AccessSizeIndex], + Addr); // We don't do Call->setDoesNotReturn() because the BB already has // UnreachableInst at the end. // This EmptyAsm is required to avoid callback merge. @@ -420,7 +419,7 @@ Value *AddressSanitizer::createSlowPathCmp(IRBuilder<> &IRB, Value *AddrLong, LastAccessedByte, ConstantInt::get(IntptrTy, TypeSize / 8 - 1)); // (uint8_t) ((Addr & (Granularity-1)) + size - 1) LastAccessedByte = IRB.CreateIntCast( - LastAccessedByte, IRB.getInt8Ty(), false); + LastAccessedByte, ShadowValue->getType(), false); // ((uint8_t) ((Addr & (Granularity-1)) + size - 1)) >= ShadowValue return IRB.CreateICmpSGE(LastAccessedByte, ShadowValue); } @@ -440,26 +439,27 @@ void AddressSanitizer::instrumentAddress(AsanFunctionContext &AFC, IRB.CreateIntToPtr(ShadowPtr, ShadowPtrTy)); Value *Cmp = IRB.CreateICmpNE(ShadowValue, CmpVal); - - BasicBlock *CrashBlock = BasicBlock::Create(*C, "crash_bb", &AFC.F); - new UnreachableInst(*C, CrashBlock); size_t AccessSizeIndex = TypeSizeToSizeIndex(TypeSize); - Instruction *Crash = - generateCrashCode(CrashBlock, AddrLong, 0, IsWrite, AccessSizeIndex); - Crash->setDebugLoc(OrigIns->getDebugLoc()); - size_t Granularity = 1 << MappingScale; - if (TypeSize < 8 * Granularity) { - BranchInst *CheckTerm = splitBlockAndInsertIfThen(Cmp); - assert(CheckTerm->isUnconditional()); + TerminatorInst *CrashTerm = 0; + + if (ClAlwaysSlowPath || (TypeSize < 8 * Granularity)) { + TerminatorInst *CheckTerm = splitBlockAndInsertIfThen(Cmp, false); + assert(dyn_cast<BranchInst>(CheckTerm)->isUnconditional()); BasicBlock *NextBB = CheckTerm->getSuccessor(0); IRB.SetInsertPoint(CheckTerm); Value *Cmp2 = createSlowPathCmp(IRB, AddrLong, ShadowValue, TypeSize); + BasicBlock *CrashBlock = BasicBlock::Create(*C, "", &AFC.F, NextBB); + CrashTerm = new UnreachableInst(*C, CrashBlock); BranchInst *NewTerm = BranchInst::Create(CrashBlock, NextBB, Cmp2); ReplaceInstWithInst(CheckTerm, NewTerm); } else { - splitBlockAndInsertIfThen(Cmp, CrashBlock); + CrashTerm = splitBlockAndInsertIfThen(Cmp, true); } + + Instruction *Crash = + generateCrashCode(CrashTerm, AddrLong, IsWrite, AccessSizeIndex); + Crash->setDebugLoc(OrigIns->getDebugLoc()); } // This function replaces all global variables with new variables that have diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index bc87106b3d21..a3c426a714e0 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -66,11 +66,6 @@ static cl::opt<bool> DisableBranchOpts( "disable-cgp-branch-opts", cl::Hidden, cl::init(false), cl::desc("Disable branch optimizations in CodeGenPrepare")); -// FIXME: Remove this abomination once all of the tests pass without it! -static cl::opt<bool> DisableDeleteDeadBlocks( - "disable-cgp-delete-dead-blocks", cl::Hidden, cl::init(false), - cl::desc("Disable deleting dead blocks in CodeGenPrepare")); - static cl::opt<bool> DisableSelectToBranch( "disable-cgp-select2branch", cl::Hidden, cl::init(false), cl::desc("Disable select to branch conversion.")); @@ -188,10 +183,9 @@ bool CodeGenPrepare::runOnFunction(Function &F) { WorkList.insert(*II); } - if (!DisableDeleteDeadBlocks) - for (SmallPtrSet<BasicBlock*, 8>::iterator - I = WorkList.begin(), E = WorkList.end(); I != E; ++I) - DeleteDeadBlock(*I); + for (SmallPtrSet<BasicBlock*, 8>::iterator + I = WorkList.begin(), E = WorkList.end(); I != E; ++I) + DeleteDeadBlock(*I); // Merge pairs of basic blocks with unconditional branches, connected by // a single edge. diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 120175d5f7f2..4822fd09448c 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -613,8 +613,8 @@ namespace { void verifyRemoved(const Instruction *I) const; bool splitCriticalEdges(); unsigned replaceAllDominatedUsesWith(Value *From, Value *To, - const BasicBlock *Root); - bool propagateEquality(Value *LHS, Value *RHS, const BasicBlock *Root); + const BasicBlockEdge &Root); + bool propagateEquality(Value *LHS, Value *RHS, const BasicBlockEdge &Root); }; char GVN::ID = 0; @@ -2004,22 +2004,13 @@ Value *GVN::findLeader(const BasicBlock *BB, uint32_t num) { /// use is dominated by the given basic block. Returns the number of uses that /// were replaced. unsigned GVN::replaceAllDominatedUsesWith(Value *From, Value *To, - const BasicBlock *Root) { + const BasicBlockEdge &Root) { unsigned Count = 0; for (Value::use_iterator UI = From->use_begin(), UE = From->use_end(); UI != UE; ) { Use &U = (UI++).getUse(); - // If From occurs as a phi node operand then the use implicitly lives in the - // corresponding incoming block. Otherwise it is the block containing the - // user that must be dominated by Root. - BasicBlock *UsingBlock; - if (PHINode *PN = dyn_cast<PHINode>(U.getUser())) - UsingBlock = PN->getIncomingBlock(U); - else - UsingBlock = cast<Instruction>(U.getUser())->getParent(); - - if (DT->dominates(Root, UsingBlock)) { + if (DT->dominates(Root, U)) { U.set(To); ++Count; } @@ -2027,13 +2018,34 @@ unsigned GVN::replaceAllDominatedUsesWith(Value *From, Value *To, return Count; } +/// isOnlyReachableViaThisEdge - There is an edge from 'Src' to 'Dst'. Return +/// true if every path from the entry block to 'Dst' passes via this edge. In +/// particular 'Dst' must not be reachable via another edge from 'Src'. +static bool isOnlyReachableViaThisEdge(const BasicBlockEdge &E, + DominatorTree *DT) { + // While in theory it is interesting to consider the case in which Dst has + // more than one predecessor, because Dst might be part of a loop which is + // only reachable from Src, in practice it is pointless since at the time + // GVN runs all such loops have preheaders, which means that Dst will have + // been changed to have only one predecessor, namely Src. + const BasicBlock *Pred = E.getEnd()->getSinglePredecessor(); + const BasicBlock *Src = E.getStart(); + assert((!Pred || Pred == Src) && "No edge between these basic blocks!"); + (void)Src; + return Pred != 0; +} + /// propagateEquality - The given values are known to be equal in every block /// dominated by 'Root'. Exploit this, for example by replacing 'LHS' with /// 'RHS' everywhere in the scope. Returns whether a change was made. -bool GVN::propagateEquality(Value *LHS, Value *RHS, const BasicBlock *Root) { +bool GVN::propagateEquality(Value *LHS, Value *RHS, + const BasicBlockEdge &Root) { SmallVector<std::pair<Value*, Value*>, 4> Worklist; Worklist.push_back(std::make_pair(LHS, RHS)); bool Changed = false; + // For speed, compute a conservative fast approximation to + // DT->dominates(Root, Root.getEnd()); + bool RootDominatesEnd = isOnlyReachableViaThisEdge(Root, DT); while (!Worklist.empty()) { std::pair<Value*, Value*> Item = Worklist.pop_back_val(); @@ -2065,9 +2077,6 @@ bool GVN::propagateEquality(Value *LHS, Value *RHS, const BasicBlock *Root) { LVN = RVN; } } - assert((!isa<Instruction>(RHS) || - DT->properlyDominates(cast<Instruction>(RHS)->getParent(), Root)) && - "Instruction doesn't dominate scope!"); // If value numbering later sees that an instruction in the scope is equal // to 'LHS' then ensure it will be turned into 'RHS'. In order to preserve @@ -2076,8 +2085,10 @@ bool GVN::propagateEquality(Value *LHS, Value *RHS, const BasicBlock *Root) { // if RHS is an instruction (if an instruction in the scope is morphed into // LHS then it will be turned into RHS by the next GVN iteration anyway, so // using the leader table is about compiling faster, not optimizing better). - if (!isa<Instruction>(RHS)) - addToLeaderTable(LVN, RHS, Root); + // The leader table only tracks basic blocks, not edges. Only add to if we + // have the simple case where the edge dominates the end. + if (RootDominatesEnd && !isa<Instruction>(RHS)) + addToLeaderTable(LVN, RHS, Root.getEnd()); // Replace all occurrences of 'LHS' with 'RHS' everywhere in the scope. As // LHS always has at least one use that is not dominated by Root, this will @@ -2136,7 +2147,7 @@ bool GVN::propagateEquality(Value *LHS, Value *RHS, const BasicBlock *Root) { // If the number we were assigned was brand new then there is no point in // looking for an instruction realizing it: there cannot be one! if (Num < NextNum) { - Value *NotCmp = findLeader(Root, Num); + Value *NotCmp = findLeader(Root.getEnd(), Num); if (NotCmp && isa<Instruction>(NotCmp)) { unsigned NumReplacements = replaceAllDominatedUsesWith(NotCmp, NotVal, Root); @@ -2146,7 +2157,10 @@ bool GVN::propagateEquality(Value *LHS, Value *RHS, const BasicBlock *Root) { } // Ensure that any instruction in scope that gets the "A < B" value number // is replaced with false. - addToLeaderTable(Num, NotVal, Root); + // The leader table only tracks basic blocks, not edges. Only add to if we + // have the simple case where the edge dominates the end. + if (RootDominatesEnd) + addToLeaderTable(Num, NotVal, Root.getEnd()); continue; } @@ -2155,22 +2169,6 @@ bool GVN::propagateEquality(Value *LHS, Value *RHS, const BasicBlock *Root) { return Changed; } -/// isOnlyReachableViaThisEdge - There is an edge from 'Src' to 'Dst'. Return -/// true if every path from the entry block to 'Dst' passes via this edge. In -/// particular 'Dst' must not be reachable via another edge from 'Src'. -static bool isOnlyReachableViaThisEdge(BasicBlock *Src, BasicBlock *Dst, - DominatorTree *DT) { - // While in theory it is interesting to consider the case in which Dst has - // more than one predecessor, because Dst might be part of a loop which is - // only reachable from Src, in practice it is pointless since at the time - // GVN runs all such loops have preheaders, which means that Dst will have - // been changed to have only one predecessor, namely Src. - BasicBlock *Pred = Dst->getSinglePredecessor(); - assert((!Pred || Pred == Src) && "No edge between these basic blocks!"); - (void)Src; - return Pred != 0; -} - /// processInstruction - When calculating availability, handle an instruction /// by inserting it into the appropriate sets bool GVN::processInstruction(Instruction *I) { @@ -2210,18 +2208,20 @@ bool GVN::processInstruction(Instruction *I) { BasicBlock *TrueSucc = BI->getSuccessor(0); BasicBlock *FalseSucc = BI->getSuccessor(1); + // Avoid multiple edges early. + if (TrueSucc == FalseSucc) + return false; + BasicBlock *Parent = BI->getParent(); bool Changed = false; - if (isOnlyReachableViaThisEdge(Parent, TrueSucc, DT)) - Changed |= propagateEquality(BranchCond, - ConstantInt::getTrue(TrueSucc->getContext()), - TrueSucc); + Value *TrueVal = ConstantInt::getTrue(TrueSucc->getContext()); + BasicBlockEdge TrueE(Parent, TrueSucc); + Changed |= propagateEquality(BranchCond, TrueVal, TrueE); - if (isOnlyReachableViaThisEdge(Parent, FalseSucc, DT)) - Changed |= propagateEquality(BranchCond, - ConstantInt::getFalse(FalseSucc->getContext()), - FalseSucc); + Value *FalseVal = ConstantInt::getFalse(FalseSucc->getContext()); + BasicBlockEdge FalseE(Parent, FalseSucc); + Changed |= propagateEquality(BranchCond, FalseVal, FalseE); return Changed; } @@ -2234,8 +2234,9 @@ bool GVN::processInstruction(Instruction *I) { for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i) { BasicBlock *Dst = i.getCaseSuccessor(); - if (isOnlyReachableViaThisEdge(Parent, Dst, DT)) - Changed |= propagateEquality(SwitchCond, i.getCaseValue(), Dst); + BasicBlockEdge E(Parent, Dst); + if (E.isSingleEdge()) + Changed |= propagateEquality(SwitchCond, i.getCaseValue(), E); } return Changed; } diff --git a/lib/VMCore/Dominators.cpp b/lib/VMCore/Dominators.cpp index 682d928e4da3..60bdeac16b36 100644 --- a/lib/VMCore/Dominators.cpp +++ b/lib/VMCore/Dominators.cpp @@ -39,20 +39,17 @@ static cl::opt<bool,true> VerifyDomInfoX("verify-dom-info", cl::location(VerifyDomInfo), cl::desc("Verify dominator info (time consuming)")); -namespace llvm { - class BasicBlockEdge { - const BasicBlock *Start; - const BasicBlock *End; - public: - BasicBlockEdge(const BasicBlock *Start_, const BasicBlock *End_) : - Start(Start_), End(End_) { } - const BasicBlock *getStart() const { - return Start; - } - const BasicBlock *getEnd() const { - return End; - } - }; +bool BasicBlockEdge::isSingleEdge() const { + const TerminatorInst *TI = Start->getTerminator(); + unsigned NumEdgesToEnd = 0; + for (unsigned int i = 0, n = TI->getNumSuccessors(); i < n; ++i) { + if (TI->getSuccessor(i) == End) + ++NumEdgesToEnd; + if (NumEdgesToEnd >= 2) + return false; + } + assert(NumEdgesToEnd == 1); + return true; } //===----------------------------------------------------------------------===// diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 685124628198..38914b3fe7ec 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -1093,7 +1093,7 @@ void Verifier::visitBitCastInst(BitCastInst &I) { // BitCast implies a no-op cast of type only. No bits change. // However, you can't cast pointers to anything but pointers. - Assert1(DestTy->isPointerTy() == DestTy->isPointerTy(), + Assert1(SrcTy->isPointerTy() == DestTy->isPointerTy(), "Bitcast requires both operands to be pointer or neither", &I); Assert1(SrcBitSize == DestBitSize, "Bitcast requires types of same width",&I); diff --git a/test/Analysis/ScalarEvolution/2012-05-29-MulAddRec.ll b/test/Analysis/ScalarEvolution/2012-05-29-MulAddRec.ll index eee4ec4333c9..3f04e2e21c46 100644 --- a/test/Analysis/ScalarEvolution/2012-05-29-MulAddRec.ll +++ b/test/Analysis/ScalarEvolution/2012-05-29-MulAddRec.ll @@ -16,7 +16,7 @@ ; CHECK: for.body: ; CHECK: %inc.9 = add i8 %inc.8, 1 ; CHECK: %0 = add i8 %inc1, 10 -; CHEKC: br label %for.cond +; CHECK: br label %for.cond target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" define void @func() noreturn nounwind uwtable ssp { diff --git a/test/CodeGen/ARM/2011-03-15-LdStMultipleBug.ll b/test/CodeGen/ARM/2011-03-15-LdStMultipleBug.ll index 2faa04af8bac..e84ce0e2394d 100644 --- a/test/CodeGen/ARM/2011-03-15-LdStMultipleBug.ll +++ b/test/CodeGen/ARM/2011-03-15-LdStMultipleBug.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mtriple=thumbv7-apple-darwin10 -relocation-model=pic -disable-fp-elim -disable-cgp-delete-dead-blocks -mcpu=cortex-a8 | FileCheck %s +; RUN: llc < %s -mtriple=thumbv7-apple-darwin10 -relocation-model=pic -disable-fp-elim -mcpu=cortex-a8 | FileCheck %s ; Do not form Thumb2 ldrd / strd if the offset is not multiple of 4. ; rdar://9133587 @@ -21,12 +21,6 @@ for.body: ; preds = %_Z14printIsNotZeroi %x = getelementptr %struct.Outer* @oStruct, i32 0, i32 1, i32 %i.022, i32 0 %y = getelementptr %struct.Outer* @oStruct, i32 0, i32 1, i32 %i.022, i32 1 %inc = add i32 %i.022, 1 - br i1 %tmp3, label %_Z14printIsNotZeroi.exit, label %if.then.i - -if.then.i: ; preds = %for.body - unreachable - -_Z14printIsNotZeroi.exit: ; preds = %for.body %tmp8 = load i32* %x, align 4, !tbaa !0 %tmp11 = load i32* %y, align 4, !tbaa !0 %mul = mul nsw i32 %tmp11, %tmp8 @@ -37,7 +31,7 @@ if.then.i16: ; preds = %_Z14printIsNotZeroi unreachable _Z14printIsNotZeroi.exit17: ; preds = %_Z14printIsNotZeroi.exit - br i1 undef, label %_Z14printIsNotZeroi.exit17.for.body_crit_edge, label %for.end + br label %_Z14printIsNotZeroi.exit17.for.body_crit_edge _Z14printIsNotZeroi.exit17.for.body_crit_edge: ; preds = %_Z14printIsNotZeroi.exit17 %b.phi.trans.insert = getelementptr %struct.Outer* @oStruct, i32 0, i32 1, i32 %inc, i32 3 diff --git a/test/CodeGen/ARM/2011-11-29-128bitArithmetics.ll b/test/CodeGen/ARM/2011-11-29-128bitArithmetics.ll index 6fbae199aaed..89c01d58c398 100644 --- a/test/CodeGen/ARM/2011-11-29-128bitArithmetics.ll +++ b/test/CodeGen/ARM/2011-11-29-128bitArithmetics.ll @@ -33,16 +33,16 @@ define void @test_cos(<4 x float>* %X) nounwind { ; CHECK: movt [[reg0]], :upper16:{{.*}} ; CHECK: vldmia r{{[0-9][0-9]?}}, {{.*}} -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}cosf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}cosf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}cosf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}cosf ; CHECK: vstmia {{.*}} @@ -64,16 +64,16 @@ define void @test_exp(<4 x float>* %X) nounwind { ; CHECK: movt [[reg0]], :upper16:{{.*}} ; CHECK: vldmia r{{[0-9][0-9]?}}, {{.*}} -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}expf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}expf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}expf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}expf ; CHECK: vstmia {{.*}} @@ -95,16 +95,16 @@ define void @test_exp2(<4 x float>* %X) nounwind { ; CHECK: movt [[reg0]], :upper16:{{.*}} ; CHECK: vldmia r{{[0-9][0-9]?}}, {{.*}} -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}exp2f -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}exp2f -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}exp2f -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}exp2f ; CHECK: vstmia {{.*}} @@ -126,16 +126,16 @@ define void @test_log10(<4 x float>* %X) nounwind { ; CHECK: movt [[reg0]], :upper16:{{.*}} ; CHECK: vldmia r{{[0-9][0-9]?}}, {{.*}} -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}log10f -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}log10f -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}log10f -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}log10f ; CHECK: vstmia {{.*}} @@ -157,16 +157,16 @@ define void @test_log(<4 x float>* %X) nounwind { ; CHECK: movt [[reg0]], :upper16:{{.*}} ; CHECK: vldmia r{{[0-9][0-9]?}}, {{.*}} -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}logf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}logf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}logf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}logf ; CHECK: vstmia {{.*}} @@ -188,16 +188,16 @@ define void @test_log2(<4 x float>* %X) nounwind { ; CHECK: movt [[reg0]], :upper16:{{.*}} ; CHECK: vldmia r{{[0-9][0-9]?}}, {{.*}} -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}log2f -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}log2f -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}log2f -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}log2f ; CHECK: vstmia {{.*}} @@ -220,16 +220,16 @@ define void @test_pow(<4 x float>* %X) nounwind { ; CHECK: movt [[reg0]], :upper16:{{.*}} ; CHECK: vldmia r{{[0-9][0-9]?}}, {{.*}} -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}powf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}powf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}powf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}powf ; CHECK: vstmia {{.*}} @@ -277,16 +277,16 @@ define void @test_sin(<4 x float>* %X) nounwind { ; CHECK: movt [[reg0]], :upper16:{{.*}} ; CHECK: vldmia r{{[0-9][0-9]?}}, {{.*}} -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}sinf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}sinf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}sinf -; CHECK: {{[v]?mov}} r0, {{[r|s][0-9]+}} +; CHECK: {{[mov|vmov.32]}} r0, ; CHECK: bl {{.*}}sinf ; CHECK: vstmia {{.*}} diff --git a/test/CodeGen/ARM/fast-isel-call.ll b/test/CodeGen/ARM/fast-isel-call.ll index edc805a47d6a..b6c9098613fe 100644 --- a/test/CodeGen/ARM/fast-isel-call.ll +++ b/test/CodeGen/ARM/fast-isel-call.ll @@ -2,6 +2,8 @@ ; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios | FileCheck %s --check-prefix=THUMB ; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -arm-long-calls | FileCheck %s --check-prefix=ARM-LONG ; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -arm-long-calls | FileCheck %s --check-prefix=THUMB-LONG +; RUN: llc < %s -O0 -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -mattr=-vfp2 | FileCheck %s --check-prefix=ARM-NOVFP +; RUN: llc < %s -O0 -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -mattr=-vfp2 | FileCheck %s --check-prefix=THUMB-NOVFP define i32 @t0(i1 zeroext %a) nounwind { %1 = zext i1 %a to i32 @@ -221,3 +223,67 @@ entry: } declare i32 @CallVariadic(i32, ...) + +; Test fastcc + +define fastcc void @fast_callee(float %i) ssp { +entry: +; ARM: fast_callee +; ARM: vmov r0, s0 +; THUMB: fast_callee +; THUMB: vmov r0, s0 +; ARM-NOVFP: fast_callee +; ARM-NOVFP-NOT: s0 +; THUMB-NOVFP: fast_callee +; THUMB-NOVFP-NOT: s0 + call void @print(float %i) + ret void +} + +define void @fast_caller() ssp { +entry: +; ARM: fast_caller +; ARM: vldr s0, +; THUMB: fast_caller +; THUMB: vldr s0, +; ARM-NOVFP: fast_caller +; ARM-NOVFP: movw r0, #13107 +; ARM-NOVFP: movt r0, #16611 +; THUMB-NOVFP: fast_caller +; THUMB-NOVFP: movw r0, #13107 +; THUMB-NOVFP: movt r0, #16611 + call fastcc void @fast_callee(float 0x401C666660000000) + ret void +} + +define void @no_fast_callee(float %i) ssp { +entry: +; ARM: no_fast_callee +; ARM: vmov s0, r0 +; THUMB: no_fast_callee +; THUMB: vmov s0, r0 +; ARM-NOVFP: no_fast_callee +; ARM-NOVFP-NOT: s0 +; THUMB-NOVFP: no_fast_callee +; THUMB-NOVFP-NOT: s0 + call void @print(float %i) + ret void +} + +define void @no_fast_caller() ssp { +entry: +; ARM: no_fast_caller +; ARM: vmov r0, s0 +; THUMB: no_fast_caller +; THUMB: vmov r0, s0 +; ARM-NOVFP: no_fast_caller +; ARM-NOVFP: movw r0, #13107 +; ARM-NOVFP: movt r0, #16611 +; THUMB-NOVFP: no_fast_caller +; THUMB-NOVFP: movw r0, #13107 +; THUMB-NOVFP: movt r0, #16611 + call void @no_fast_callee(float 0x401C666660000000) + ret void +} + +declare void @print(float) diff --git a/test/CodeGen/ARM/fp16.ll b/test/CodeGen/ARM/fp16.ll index c5583b94befd..1261ea502129 100644 --- a/test/CodeGen/ARM/fp16.ll +++ b/test/CodeGen/ARM/fp16.ll @@ -15,14 +15,14 @@ entry: %1 = load i16* @y, align 2 %2 = tail call float @llvm.convert.from.fp16(i16 %0) ; CHECK: __gnu_h2f_ieee -; CHECK-FP16: vcvtb.f16.f32 +; CHECK-FP16: vcvtb.f32.f16 %3 = tail call float @llvm.convert.from.fp16(i16 %1) ; CHECK: __gnu_h2f_ieee -; CHECK-FP16: vcvtb.f16.f32 +; CHECK-FP16: vcvtb.f32.f16 %4 = fadd float %2, %3 %5 = tail call i16 @llvm.convert.to.fp16(float %4) ; CHECK: __gnu_f2h_ieee -; CHECK-FP16: vcvtb.f32.f16 +; CHECK-FP16: vcvtb.f16.f32 store i16 %5, i16* @x, align 2 ret void } diff --git a/test/CodeGen/ARM/select.ll b/test/CodeGen/ARM/select.ll index 418d4f31ee2b..557556662892 100644 --- a/test/CodeGen/ARM/select.ll +++ b/test/CodeGen/ARM/select.ll @@ -76,12 +76,11 @@ define double @f7(double %a, double %b) { ; block generated, odds are good that we have close to the ideal code for this: ; ; CHECK-NEON: _f8: +; CHECK-NEON: movw [[R3:r[0-9]+]], #1123 ; CHECK-NEON: adr [[R2:r[0-9]+]], LCPI7_0 -; CHECK-NEON-NEXT: movw [[R3:r[0-9]+]], #1123 -; CHECK-NEON-NEXT: adds {{r.*}}, [[R2]], #4 ; CHECK-NEON-NEXT: cmp r0, [[R3]] -; CHECK-NEON-NEXT: it ne -; CHECK-NEON-NEXT: movne {{r.*}}, [[R2]] +; CHECK-NEON-NEXT: it eq +; CHECK-NEON-NEXT: addeq.w {{r.*}}, [[R2]] ; CHECK-NEON-NEXT: ldr ; CHECK-NEON: bx diff --git a/test/CodeGen/ARM/select_xform.ll b/test/CodeGen/ARM/select_xform.ll index ca2e18a63949..26f7cb68901f 100644 --- a/test/CodeGen/ARM/select_xform.ll +++ b/test/CodeGen/ARM/select_xform.ll @@ -4,13 +4,13 @@ define i32 @t1(i32 %a, i32 %b, i32 %c) nounwind { ; ARM: t1: -; ARM: sub r0, r1, #-2147483647 -; ARM: movgt r0, r1 +; ARM: suble r1, r1, #-2147483647 +; ARM: mov r0, r1 ; T2: t1: ; T2: mvn r0, #-2147483648 -; T2: add r0, r1 -; T2: movgt r0, r1 +; T2: addle.w r1, r1 +; T2: mov r0, r1 %tmp1 = icmp sgt i32 %c, 10 %tmp2 = select i1 %tmp1, i32 0, i32 2147483647 %tmp3 = add i32 %tmp2, %b @@ -19,12 +19,12 @@ define i32 @t1(i32 %a, i32 %b, i32 %c) nounwind { define i32 @t2(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { ; ARM: t2: -; ARM: sub r0, r1, #10 -; ARM: movgt r0, r1 +; ARM: suble r1, r1, #10 +; ARM: mov r0, r1 ; T2: t2: -; T2: sub.w r0, r1, #10 -; T2: movgt r0, r1 +; T2: suble.w r1, r1, #10 +; T2: mov r0, r1 %tmp1 = icmp sgt i32 %c, 10 %tmp2 = select i1 %tmp1, i32 0, i32 10 %tmp3 = sub i32 %b, %tmp2 @@ -104,3 +104,78 @@ entry: ret i32 %tmp3 } +; Fold ORRri into movcc. +define i32 @t8(i32 %a, i32 %b) nounwind { +; ARM: t8: +; ARM: cmp r0, r1 +; ARM: orrge r0, r1, #1 + +; T2: t8: +; T2: cmp r0, r1 +; T2: orrge r0, r1, #1 + %x = or i32 %b, 1 + %cond = icmp slt i32 %a, %b + %tmp1 = select i1 %cond, i32 %a, i32 %x + ret i32 %tmp1 +} + +; Fold ANDrr into movcc. +define i32 @t9(i32 %a, i32 %b, i32 %c) nounwind { +; ARM: t9: +; ARM: cmp r0, r1 +; ARM: andge r0, r1, r2 + +; T2: t9: +; T2: cmp r0, r1 +; T2: andge.w r0, r1, r2 + %x = and i32 %b, %c + %cond = icmp slt i32 %a, %b + %tmp1 = select i1 %cond, i32 %a, i32 %x + ret i32 %tmp1 +} + +; Fold EORrs into movcc. +define i32 @t10(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { +; ARM: t10: +; ARM: cmp r0, r1 +; ARM: eorge r0, r1, r2, lsl #7 + +; T2: t10: +; T2: cmp r0, r1 +; T2: eorge.w r0, r1, r2, lsl #7 + %s = shl i32 %c, 7 + %x = xor i32 %b, %s + %cond = icmp slt i32 %a, %b + %tmp1 = select i1 %cond, i32 %a, i32 %x + ret i32 %tmp1 +} + +; Fold ORRri into movcc, reversing the condition. +define i32 @t11(i32 %a, i32 %b) nounwind { +; ARM: t11: +; ARM: cmp r0, r1 +; ARM: orrlt r0, r1, #1 + +; T2: t11: +; T2: cmp r0, r1 +; T2: orrlt r0, r1, #1 + %x = or i32 %b, 1 + %cond = icmp slt i32 %a, %b + %tmp1 = select i1 %cond, i32 %x, i32 %a + ret i32 %tmp1 +} + +; Fold ADDri12 into movcc +define i32 @t12(i32 %a, i32 %b) nounwind { +; ARM: t12: +; ARM: cmp r0, r1 +; ARM: addge r0, r1, + +; T2: t12: +; T2: cmp r0, r1 +; T2: addwge r0, r1, #3000 + %x = add i32 %b, 3000 + %cond = icmp slt i32 %a, %b + %tmp1 = select i1 %cond, i32 %a, i32 %x + ret i32 %tmp1 +} diff --git a/test/CodeGen/ARM/unaligned_load_store.ll b/test/CodeGen/ARM/unaligned_load_store.ll index a8237c60e4e0..869b92675def 100644 --- a/test/CodeGen/ARM/unaligned_load_store.ll +++ b/test/CodeGen/ARM/unaligned_load_store.ll @@ -1,25 +1,25 @@ -; RUN: llc < %s -march=arm -pre-RA-sched=source | FileCheck %s -check-prefix=GENERIC -; RUN: llc < %s -mtriple=armv6-apple-darwin | FileCheck %s -check-prefix=DARWIN_V6 -; RUN: llc < %s -mtriple=armv6-apple-darwin -arm-strict-align | FileCheck %s -check-prefix=GENERIC -; RUN: llc < %s -mtriple=armv6-linux | FileCheck %s -check-prefix=GENERIC +; RUN: llc < %s -march=arm -pre-RA-sched=source | FileCheck %s -check-prefix=EXPANDED +; RUN: llc < %s -mtriple=armv6-apple-darwin -mcpu=cortex-a8 -arm-strict-align -pre-RA-sched=source | FileCheck %s -check-prefix=EXPANDED +; RUN: llc < %s -mtriple=armv6-apple-darwin -mcpu=cortex-a8 | FileCheck %s -check-prefix=UNALIGNED ; rdar://7113725 +; rdar://12091029 define void @t(i8* nocapture %a, i8* nocapture %b) nounwind { entry: -; GENERIC: t: -; GENERIC: ldrb [[R2:r[0-9]+]] -; GENERIC: ldrb [[R3:r[0-9]+]] -; GENERIC: ldrb [[R12:r[0-9]+]] -; GENERIC: ldrb [[R1:r[0-9]+]] -; GENERIC: strb [[R1]] -; GENERIC: strb [[R12]] -; GENERIC: strb [[R3]] -; GENERIC: strb [[R2]] - -; DARWIN_V6: t: -; DARWIN_V6: ldr r1 -; DARWIN_V6: str r1 +; EXPANDED: t: +; EXPANDED: ldrb [[R2:r[0-9]+]] +; EXPANDED: ldrb [[R3:r[0-9]+]] +; EXPANDED: ldrb [[R12:r[0-9]+]] +; EXPANDED: ldrb [[R1:r[0-9]+]] +; EXPANDED: strb [[R1]] +; EXPANDED: strb [[R12]] +; EXPANDED: strb [[R3]] +; EXPANDED: strb [[R2]] + +; UNALIGNED: t: +; UNALIGNED: ldr r1 +; UNALIGNED: str r1 %__src1.i = bitcast i8* %b to i32* ; <i32*> [#uses=1] %__dest2.i = bitcast i8* %a to i32* ; <i32*> [#uses=1] @@ -27,3 +27,35 @@ entry: store i32 %tmp.i, i32* %__dest2.i, align 1 ret void } + +define void @hword(double* %a, double* %b) nounwind { +entry: +; EXPANDED: hword: +; EXPANDED-NOT: vld1 +; EXPANDED: ldrh +; EXPANDED-NOT: str1 +; EXPANDED: strh + +; UNALIGNED: hword: +; UNALIGNED: vld1.16 +; UNALIGNED: vst1.16 + %tmp = load double* %a, align 2 + store double %tmp, double* %b, align 2 + ret void +} + +define void @byte(double* %a, double* %b) nounwind { +entry: +; EXPANDED: byte: +; EXPANDED-NOT: vld1 +; EXPANDED: ldrb +; EXPANDED-NOT: str1 +; EXPANDED: strb + +; UNALIGNED: byte: +; UNALIGNED: vld1.8 +; UNALIGNED: vst1.8 + %tmp = load double* %a, align 1 + store double %tmp, double* %b, align 1 + ret void +} diff --git a/test/CodeGen/Generic/donothing.ll b/test/CodeGen/Generic/donothing.ll index d6ba138fc6da..3727b60a1a45 100644 --- a/test/CodeGen/Generic/donothing.ll +++ b/test/CodeGen/Generic/donothing.ll @@ -7,7 +7,7 @@ declare void @llvm.donothing() readnone ; CHECK: f1 define void @f1() nounwind uwtable ssp { entry: -; CHECK-NOT donothing +; CHECK-NOT: donothing invoke void @llvm.donothing() to label %invoke.cont unwind label %lpad @@ -25,7 +25,7 @@ lpad: ; CHECK: f2 define void @f2() nounwind { entry: -; CHECK-NOT donothing +; CHECK-NOT: donothing call void @llvm.donothing() ret void } diff --git a/test/CodeGen/Mips/return-vector-float4.ll b/test/CodeGen/Mips/return-vector-float4.ll new file mode 100644 index 000000000000..ae10f123e4d2 --- /dev/null +++ b/test/CodeGen/Mips/return-vector-float4.ll @@ -0,0 +1,12 @@ +; RUN: llc -march=mipsel -mattr=+android < %s | FileCheck %s + +define <4 x float> @retvec4() nounwind readnone { +entry: +; CHECK: lwc1 $f0 +; CHECK: lwc1 $f2 +; CHECK: lwc1 $f1 +; CHECK: lwc1 $f3 + + ret <4 x float> <float 1.000000e+00, float 2.000000e+00, float 3.000000e+00, float 4.000000e+00> +} + diff --git a/test/CodeGen/Thumb2/machine-licm.ll b/test/CodeGen/Thumb2/machine-licm.ll index 82857425a9d7..01df37323252 100644 --- a/test/CodeGen/Thumb2/machine-licm.ll +++ b/test/CodeGen/Thumb2/machine-licm.ll @@ -95,7 +95,7 @@ bb.nph: bb: ; preds = %bb, %bb.nph ; CHECK: bb ; CHECK: eor.w -; CHECK: eor.w {{(r[0-9])|(lr)}}, {{(r[0-9])|(lr)}}, [[REGISTER]] +; CHECK: eorne.w {{(r[0-9])|(lr)}}, {{(r[0-9])|(lr)}}, [[REGISTER]] ; CHECK-NOT: eor ; CHECK: and %data_addr.013 = phi i8 [ %data, %bb.nph ], [ %8, %bb ] ; <i8> [#uses=2] diff --git a/test/CodeGen/Thumb2/thumb2-select_xform.ll b/test/CodeGen/Thumb2/thumb2-select_xform.ll index 74729fd4150f..ead198f21624 100644 --- a/test/CodeGen/Thumb2/thumb2-select_xform.ll +++ b/test/CodeGen/Thumb2/thumb2-select_xform.ll @@ -4,9 +4,9 @@ define i32 @t1(i32 %a, i32 %b, i32 %c) nounwind { ; CHECK: t1 ; CHECK: mvn r0, #-2147483648 ; CHECK: cmp r2, #10 -; CHECK: add r0, r1 -; CHECK: it gt -; CHECK: movgt r0, r1 +; CHECK: it le +; CHECK: addle.w r1, r1, r0 +; CHECK: mov r0, r1 %tmp1 = icmp sgt i32 %c, 10 %tmp2 = select i1 %tmp1, i32 0, i32 2147483647 %tmp3 = add i32 %tmp2, %b @@ -15,10 +15,10 @@ define i32 @t1(i32 %a, i32 %b, i32 %c) nounwind { define i32 @t2(i32 %a, i32 %b, i32 %c) nounwind { ; CHECK: t2 -; CHECK: add.w r0, r1, #-2147483648 ; CHECK: cmp r2, #10 -; CHECK: it gt -; CHECK: movgt r0, r1 +; CHECK: it le +; CHECK: addle.w r1, r1, #-2147483648 +; CHECK: mov r0, r1 %tmp1 = icmp sgt i32 %c, 10 %tmp2 = select i1 %tmp1, i32 0, i32 2147483648 @@ -28,10 +28,10 @@ define i32 @t2(i32 %a, i32 %b, i32 %c) nounwind { define i32 @t3(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { ; CHECK: t3 -; CHECK: sub.w r0, r1, #10 ; CHECK: cmp r2, #10 -; CHECK: it gt -; CHECK: movgt r0, r1 +; CHECK: it le +; CHECK: suble.w r1, r1, #10 +; CHECK: mov r0, r1 %tmp1 = icmp sgt i32 %c, 10 %tmp2 = select i1 %tmp1, i32 0, i32 10 %tmp3 = sub i32 %b, %tmp2 diff --git a/test/CodeGen/X86/2011-08-29-InitOrder.ll b/test/CodeGen/X86/2011-08-29-InitOrder.ll index 4d5f8d7857c0..a95dcb580702 100644 --- a/test/CodeGen/X86/2011-08-29-InitOrder.ll +++ b/test/CodeGen/X86/2011-08-29-InitOrder.ll @@ -3,7 +3,7 @@ ; PR5329 @llvm.global_ctors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 2000, void ()* @construct_2 }, { i32, void ()* } { i32 3000, void ()* @construct_3 }, { i32, void ()* } { i32 1000, void ()* @construct_1 }] -; CHECK-DEFAULT .section .ctors.64535,"aw",@progbits +; CHECK-DEFAULT: .section .ctors.64535,"aw",@progbits ; CHECK-DEFAULT: .long construct_1 ; CHECK-DEFAULT: .section .ctors.63535,"aw",@progbits ; CHECK-DEFAULT: .long construct_2 diff --git a/test/CodeGen/X86/2012-08-17-legalizer-crash.ll b/test/CodeGen/X86/2012-08-17-legalizer-crash.ll new file mode 100644 index 000000000000..a65e6881540d --- /dev/null +++ b/test/CodeGen/X86/2012-08-17-legalizer-crash.ll @@ -0,0 +1,32 @@ +; RUN: llc < %s | FileCheck %s +; Check that an overly large immediate created by SROA doesn't crash the +; legalizer. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.8.0" + +%struct._GtkSheetRow = type { i32*, i32, i32, i32, %struct._GtkSheetButton, i32, i32 } +%struct._GtkSheetButton = type { i32, i32*, i32, i32*, i32 } + +@a = common global %struct._GtkSheetRow* null, align 8 + +define void @fn1() nounwind uwtable ssp { +entry: + %0 = load %struct._GtkSheetRow** @a, align 8 + %1 = bitcast %struct._GtkSheetRow* %0 to i576* + %srcval2 = load i576* %1, align 8 + %tobool = icmp ugt i576 %srcval2, 57586096570152913699974892898380567793532123114264532903689671329431521032595044740083720782129802971518987656109067457577065805510327036019308994315074097345724415 + br i1 %tobool, label %if.then, label %if.end + +if.then: ; preds = %entry + store i576 %srcval2, i576* %1, align 8 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void + +; CHECK: fn1: +; CHECK: shrq $32, [[REG:%.*]] +; CHECK: testq [[REG]], [[REG]] +; CHECK: je +} diff --git a/test/CodeGen/X86/fast-isel-x86.ll b/test/CodeGen/X86/fast-isel-x86.ll index 19f38882a6c6..4caa3a039d6a 100644 --- a/test/CodeGen/X86/fast-isel-x86.ll +++ b/test/CodeGen/X86/fast-isel-x86.ll @@ -57,6 +57,6 @@ entry: ; CHECK: subl $28 ; CHECK: leal (%esp), %ecx ; CHECK: calll _test4fastccsret -; CHECK addl $28 +; CHECK: addl $28 } declare fastcc void @test4fastccsret(%struct.a* sret) diff --git a/test/CodeGen/X86/full-lsr.ll b/test/CodeGen/X86/full-lsr.ll index 1344cdcd4320..0729dda4a12b 100644 --- a/test/CodeGen/X86/full-lsr.ll +++ b/test/CodeGen/X86/full-lsr.ll @@ -10,7 +10,7 @@ define void @foo(float* nocapture %A, float* nocapture %B, float* nocapture %C, ; CHECK: foo ; CHECK: addl ; CHECK: addl -; CEHCK: addl +; CHECK: addl entry: %0 = icmp sgt i32 %N, 0 ; <i1> [#uses=1] diff --git a/test/CodeGen/X86/memcpy.ll b/test/CodeGen/X86/memcpy.ll index 86c6862a53fc..39c7fbafd4c7 100644 --- a/test/CodeGen/X86/memcpy.ll +++ b/test/CodeGen/X86/memcpy.ll @@ -65,18 +65,18 @@ entry: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %A, i8* %B, i64 64, i32 1, i1 false) ret void ; LINUX: test4: -; LINUX movq -; LINUX movq -; LINUX movq -; LINUX movq -; LINUX movq -; LINUX movq -; LINUX movq -; LINUX movq -; LINUX movq -; LINUX movq -; LINUX movq -; LINUX movq +; LINUX: movq +; LINUX: movq +; LINUX: movq +; LINUX: movq +; LINUX: movq +; LINUX: movq +; LINUX: movq +; LINUX: movq +; LINUX: movq +; LINUX: movq +; LINUX: movq +; LINUX: movq } diff --git a/test/CodeGen/X86/pr11334.ll b/test/CodeGen/X86/pr11334.ll new file mode 100644 index 000000000000..5b7b5eab87ec --- /dev/null +++ b/test/CodeGen/X86/pr11334.ll @@ -0,0 +1,56 @@ +; RUN: llc < %s -mtriple=x86_64-pc-linux -mcpu=corei7 | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-pc-linux -mcpu=core-avx-i | FileCheck %s --check-prefix=AVX + +define <2 x double> @v2f2d_ext_vec(<2 x float> %v1) nounwind { +entry: +; CHECK: v2f2d_ext_vec +; CHECK: cvtps2pd +; AVX: v2f2d_ext_vec +; AVX: vcvtps2pd + %f1 = fpext <2 x float> %v1 to <2 x double> + ret <2 x double> %f1 +} + +define <3 x double> @v3f2d_ext_vec(<3 x float> %v1) nounwind { +entry: +; CHECK: v3f2d_ext_vec +; CHECK: cvtps2pd +; CHECK: movhlps +; CHECK: cvtps2pd +; AVX: v3f2d_ext_vec +; AVX: vcvtps2pd +; AVX: ret + %f1 = fpext <3 x float> %v1 to <3 x double> + ret <3 x double> %f1 +} + +define <4 x double> @v4f2d_ext_vec(<4 x float> %v1) nounwind { +entry: +; CHECK: v4f2d_ext_vec +; CHECK: cvtps2pd +; CHECK: movhlps +; CHECK: cvtps2pd +; AVX: v4f2d_ext_vec +; AVX: vcvtps2pd +; AVX: ret + %f1 = fpext <4 x float> %v1 to <4 x double> + ret <4 x double> %f1 +} + +define <8 x double> @v8f2d_ext_vec(<8 x float> %v1) nounwind { +entry: +; CHECK: v8f2d_ext_vec +; CHECK: cvtps2pd +; CHECK: cvtps2pd +; CHECK: movhlps +; CHECK: cvtps2pd +; CHECK: movhlps +; CHECK: cvtps2pd +; AVX: v8f2d_ext_vec +; AVX: vcvtps2pd +; AVX: vextractf128 +; AVX: vcvtps2pd +; AVX: ret + %f1 = fpext <8 x float> %v1 to <8 x double> + ret <8 x double> %f1 +} diff --git a/test/CodeGen/X86/unreachable-stack-protector.ll b/test/CodeGen/X86/unreachable-stack-protector.ll deleted file mode 100644 index b066297ff1b4..000000000000 --- a/test/CodeGen/X86/unreachable-stack-protector.ll +++ /dev/null @@ -1,19 +0,0 @@ -; RUN: llc < %s -disable-cgp-delete-dead-blocks | FileCheck %s -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" -target triple = "x86_64-apple-darwin10.0.0" - -declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readnone - -define void @test5() nounwind optsize noinline ssp { -entry: -; CHECK: movq ___stack_chk_guard@GOTPCREL(%rip) - %buf = alloca [64 x i8], align 16 - %0 = call i64 @llvm.objectsize.i64(i8* undef, i1 false) - br i1 false, label %if.end, label %if.then - -if.then: ; preds = %entry - unreachable - -if.end: ; preds = %entry - ret void -} diff --git a/test/Instrumentation/AddressSanitizer/basic.ll b/test/Instrumentation/AddressSanitizer/basic.ll index 294ca8ab7560..d19000187060 100644 --- a/test/Instrumentation/AddressSanitizer/basic.ll +++ b/test/Instrumentation/AddressSanitizer/basic.ll @@ -23,15 +23,14 @@ define i32 @test_load(i32* %a) address_safety { ; CHECK: icmp sge i8 %{{.*}}, %[[LOAD_SHADOW]] ; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} ; -; The actual load comes next because ASan adds the crash block -; to the end of the function. -; CHECK: %tmp1 = load i32* %a -; CHECK: ret i32 %tmp1 - ; The crash block reports the error. ; CHECK: call void @__asan_report_load4(i64 %[[LOAD_ADDR]]) ; CHECK: unreachable ; +; The actual load. +; CHECK: %tmp1 = load i32* %a +; CHECK: ret i32 %tmp1 + entry: @@ -57,15 +56,14 @@ define void @test_store(i32* %a) address_safety { ; CHECK: icmp sge i8 %{{.*}}, %[[STORE_SHADOW]] ; CHECK: br i1 %{{.*}}, label %{{.*}}, label %{{.*}} ; -; The actual load comes next because ASan adds the crash block -; to the end of the function. -; CHECK: store i32 42, i32* %a -; CHECK: ret void -; ; The crash block reports the error. ; CHECK: call void @__asan_report_store4(i64 %[[STORE_ADDR]]) ; CHECK: unreachable ; +; The actual load. +; CHECK: store i32 42, i32* %a +; CHECK: ret void +; entry: store i32 42, i32* %a diff --git a/test/Transforms/GVN/edge.ll b/test/Transforms/GVN/edge.ll new file mode 100644 index 000000000000..32392f3ab0c8 --- /dev/null +++ b/test/Transforms/GVN/edge.ll @@ -0,0 +1,60 @@ +; RUN: opt %s -gvn -S -o - | FileCheck %s + +define i32 @f1(i32 %x) { + ; CHECK: define i32 @f1( +bb0: + %cmp = icmp eq i32 %x, 0 + br i1 %cmp, label %bb2, label %bb1 +bb1: + br label %bb2 +bb2: + %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] + %foo = add i32 %cond, %x + ret i32 %foo + ; CHECK: bb2: + ; CHECK: ret i32 %x +} + +define i32 @f2(i32 %x) { + ; CHECK: define i32 @f2( +bb0: + %cmp = icmp ne i32 %x, 0 + br i1 %cmp, label %bb1, label %bb2 +bb1: + br label %bb2 +bb2: + %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] + %foo = add i32 %cond, %x + ret i32 %foo + ; CHECK: bb2: + ; CHECK: ret i32 %x +} + +define i32 @f3(i32 %x) { + ; CHECK: define i32 @f3( +bb0: + switch i32 %x, label %bb1 [ i32 0, label %bb2] +bb1: + br label %bb2 +bb2: + %cond = phi i32 [ %x, %bb0 ], [ 0, %bb1 ] + %foo = add i32 %cond, %x + ret i32 %foo + ; CHECK: bb2: + ; CHECK: ret i32 %x +} + +declare void @g(i1) +define void @f4(i8 * %x) { +; CHECK: define void @f4( +bb0: + %y = icmp eq i8* null, %x + br i1 %y, label %bb2, label %bb1 +bb1: + br label %bb2 +bb2: + %zed = icmp eq i8* null, %x + call void @g(i1 %zed) +; CHECK: call void @g(i1 %y) + ret void +} diff --git a/test/Transforms/GVN/rle.ll b/test/Transforms/GVN/rle.ll index 9e08004ea476..e7641691264c 100644 --- a/test/Transforms/GVN/rle.ll +++ b/test/Transforms/GVN/rle.ll @@ -620,7 +620,7 @@ entry: ; CHECK-NOT: load ; CHECK: load i16* ; CHECK-NOT: load -; CHECK-ret i32 +; CHECK: ret i32 } define i32 @test_widening2() nounwind ssp noredzone { @@ -644,7 +644,7 @@ entry: ; CHECK-NOT: load ; CHECK: load i32* ; CHECK-NOT: load -; CHECK-ret i32 +; CHECK: ret i32 } declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind diff --git a/test/Transforms/Inline/always-inline.ll b/test/Transforms/Inline/always-inline.ll index e0be41fa6657..c918bc9d5dbb 100644 --- a/test/Transforms/Inline/always-inline.ll +++ b/test/Transforms/Inline/always-inline.ll @@ -33,7 +33,6 @@ define void @outer2(i32 %N) { ; ; CHECK: @outer2 ; CHECK-NOT: call void @inner2 -; CHECK alloca i32, i32 %N ; CHECK-NOT: call void @inner2 ; CHECK: ret void diff --git a/test/Transforms/InstCombine/memcpy.ll b/test/Transforms/InstCombine/memcpy.ll index 8a2e3aaad027..3a68ff95af82 100644 --- a/test/Transforms/InstCombine/memcpy.ll +++ b/test/Transforms/InstCombine/memcpy.ll @@ -1,6 +1,7 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind define void @test1(i8* %a) { tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* %a, i8* %a, i32 100, i32 1, i1 false) @@ -17,3 +18,10 @@ define void @test2(i8* %a) { ; CHECK: define void @test2 ; CHECK-NEXT: call void @llvm.memcpy } + +define void @test3(i8* %d, i8* %s) { + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %d, i8* %s, i64 17179869184, i32 4, i1 false) + ret void +; CHECK: define void @test3 +; CHECK-NEXT: call void @llvm.memcpy +} diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll index dbb0ffcd6742..d7e292155cd7 100644 --- a/test/Transforms/InstCombine/objsize.ll +++ b/test/Transforms/InstCombine/objsize.ll @@ -238,3 +238,20 @@ xpto: return: ret i32 42 } + +; CHECK: @PR13621 +define i32 @PR13621(i1 %bool) nounwind { +entry: + %cond = or i1 %bool, true + br i1 %cond, label %return, label %xpto + +; technically reachable, but this malformed IR may appear as a result of constant propagation +xpto: + %gep = getelementptr i8* %gep, i32 1 + %o = call i32 @llvm.objectsize.i32(i8* %gep, i1 true) +; CHECK: ret i32 undef + ret i32 %o + +return: + ret i32 7 +} diff --git a/test/Transforms/ObjCARC/basic.ll b/test/Transforms/ObjCARC/basic.ll index d9bb3f25bd79..0a7ba5de71bc 100644 --- a/test/Transforms/ObjCARC/basic.ll +++ b/test/Transforms/ObjCARC/basic.ll @@ -1272,7 +1272,7 @@ g: ; Delete retain,release pairs around loops. ; CHECK: define void @test39( -; CHECK_NOT: @objc_ +; CHECK-NOT: @objc_ ; CHECK: } define void @test39(i8* %p) { entry: @@ -1290,7 +1290,7 @@ exit: ; preds = %loop ; Delete retain,release pairs around loops containing uses. ; CHECK: define void @test39b( -; CHECK_NOT: @objc_ +; CHECK-NOT: @objc_ ; CHECK: } define void @test39b(i8* %p) { entry: @@ -1309,7 +1309,7 @@ exit: ; preds = %loop ; Delete retain,release pairs around loops containing potential decrements. ; CHECK: define void @test39c( -; CHECK_NOT: @objc_ +; CHECK-NOT: @objc_ ; CHECK: } define void @test39c(i8* %p) { entry: @@ -1329,7 +1329,7 @@ exit: ; preds = %loop ; the successors are in a different order. ; CHECK: define void @test40( -; CHECK_NOT: @objc_ +; CHECK-NOT: @objc_ ; CHECK: } define void @test40(i8* %p) { entry: diff --git a/test/Transforms/ObjCARC/invoke.ll b/test/Transforms/ObjCARC/invoke.ll index 76e82a587b8d..1a58e34940e1 100644 --- a/test/Transforms/ObjCARC/invoke.ll +++ b/test/Transforms/ObjCARC/invoke.ll @@ -76,12 +76,12 @@ done: ; CHECK: define void @test2() { ; CHECK: invoke.cont: ; CHECK-NEXT: call i8* @objc_retain -; CHEK-NOT: @objc +; CHECK-NOT: @objc_r ; CHECK: finally.cont: ; CHECK-NEXT: call void @objc_release -; CHEK-NOT: @objc +; CHECK-NOT: @objc ; CHECK: finally.rethrow: -; CHEK-NOT: @objc +; CHECK-NOT: @objc ; CHECK: } define void @test2() { entry: diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index cc207f764da2..00b62feaeb15 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -648,6 +648,49 @@ TEST(APFloatTest, exactInverse) { EXPECT_FALSE(APFloat(1.40129846e-45f).getExactInverse(0)); } +TEST(APFloatTest, roundToIntegral) { + APFloat T(-0.5), S(3.14), R(APFloat::getLargest(APFloat::IEEEdouble)), P(0.0); + + P = T; + P.roundToIntegral(APFloat::rmTowardZero); + EXPECT_EQ(-0.0, P.convertToDouble()); + P = T; + P.roundToIntegral(APFloat::rmTowardNegative); + EXPECT_EQ(-1.0, P.convertToDouble()); + P = T; + P.roundToIntegral(APFloat::rmTowardPositive); + EXPECT_EQ(-0.0, P.convertToDouble()); + P = T; + P.roundToIntegral(APFloat::rmNearestTiesToEven); + EXPECT_EQ(-0.0, P.convertToDouble()); + + P = S; + P.roundToIntegral(APFloat::rmTowardZero); + EXPECT_EQ(3.0, P.convertToDouble()); + P = S; + P.roundToIntegral(APFloat::rmTowardNegative); + EXPECT_EQ(3.0, P.convertToDouble()); + P = S; + P.roundToIntegral(APFloat::rmTowardPositive); + EXPECT_EQ(4.0, P.convertToDouble()); + P = S; + P.roundToIntegral(APFloat::rmNearestTiesToEven); + EXPECT_EQ(3.0, P.convertToDouble()); + + P = R; + P.roundToIntegral(APFloat::rmTowardZero); + EXPECT_EQ(R.convertToDouble(), P.convertToDouble()); + P = R; + P.roundToIntegral(APFloat::rmTowardNegative); + EXPECT_EQ(R.convertToDouble(), P.convertToDouble()); + P = R; + P.roundToIntegral(APFloat::rmTowardPositive); + EXPECT_EQ(R.convertToDouble(), P.convertToDouble()); + P = R; + P.roundToIntegral(APFloat::rmNearestTiesToEven); + EXPECT_EQ(R.convertToDouble(), P.convertToDouble()); +} + TEST(APFloatTest, getLargest) { EXPECT_EQ(3.402823466e+38f, APFloat::getLargest(APFloat::IEEEsingle).convertToFloat()); EXPECT_EQ(1.7976931348623158e+308, APFloat::getLargest(APFloat::IEEEdouble).convertToDouble()); diff --git a/unittests/Support/AlignOfTest.cpp b/unittests/Support/AlignOfTest.cpp index c45db2cdc007..6f576681a3e2 100644 --- a/unittests/Support/AlignOfTest.cpp +++ b/unittests/Support/AlignOfTest.cpp @@ -178,150 +178,150 @@ TEST(AlignOfTest, BasicAlignedArray) { // types because of the bugs mentioned above where GCC and Clang both // disregard the arbitrary alignment specifier until the type is used to // declare a member of a struct. - EXPECT_LE(1u, alignOf<AlignedCharArray<SA1>::union_type>()); - EXPECT_LE(2u, alignOf<AlignedCharArray<SA2>::union_type>()); - EXPECT_LE(4u, alignOf<AlignedCharArray<SA4>::union_type>()); - EXPECT_LE(8u, alignOf<AlignedCharArray<SA8>::union_type>()); + EXPECT_LE(1u, alignOf<AlignedCharArrayUnion<SA1> >()); + EXPECT_LE(2u, alignOf<AlignedCharArrayUnion<SA2> >()); + EXPECT_LE(4u, alignOf<AlignedCharArrayUnion<SA4> >()); + EXPECT_LE(8u, alignOf<AlignedCharArrayUnion<SA8> >()); - EXPECT_LE(1u, sizeof(AlignedCharArray<SA1>::union_type)); - EXPECT_LE(2u, sizeof(AlignedCharArray<SA2>::union_type)); - EXPECT_LE(4u, sizeof(AlignedCharArray<SA4>::union_type)); - EXPECT_LE(8u, sizeof(AlignedCharArray<SA8>::union_type)); + EXPECT_LE(1u, sizeof(AlignedCharArrayUnion<SA1>)); + EXPECT_LE(2u, sizeof(AlignedCharArrayUnion<SA2>)); + EXPECT_LE(4u, sizeof(AlignedCharArrayUnion<SA4>)); + EXPECT_LE(8u, sizeof(AlignedCharArrayUnion<SA8>)); - EXPECT_EQ(1u, (alignOf<AlignedCharArray<SA1>::union_type>())); - EXPECT_EQ(2u, (alignOf<AlignedCharArray<SA1, SA2>::union_type>())); - EXPECT_EQ(4u, (alignOf<AlignedCharArray<SA1, SA2, SA4>::union_type>())); - EXPECT_EQ(8u, (alignOf<AlignedCharArray<SA1, SA2, SA4, SA8>::union_type>())); + EXPECT_EQ(1u, (alignOf<AlignedCharArrayUnion<SA1> >())); + EXPECT_EQ(2u, (alignOf<AlignedCharArrayUnion<SA1, SA2> >())); + EXPECT_EQ(4u, (alignOf<AlignedCharArrayUnion<SA1, SA2, SA4> >())); + EXPECT_EQ(8u, (alignOf<AlignedCharArrayUnion<SA1, SA2, SA4, SA8> >())); - EXPECT_EQ(1u, sizeof(AlignedCharArray<SA1>::union_type)); - EXPECT_EQ(2u, sizeof(AlignedCharArray<SA1, SA2>::union_type)); - EXPECT_EQ(4u, sizeof(AlignedCharArray<SA1, SA2, SA4>::union_type)); - EXPECT_EQ(8u, sizeof(AlignedCharArray<SA1, SA2, SA4, SA8>::union_type)); + EXPECT_EQ(1u, sizeof(AlignedCharArrayUnion<SA1>)); + EXPECT_EQ(2u, sizeof(AlignedCharArrayUnion<SA1, SA2>)); + EXPECT_EQ(4u, sizeof(AlignedCharArrayUnion<SA1, SA2, SA4>)); + EXPECT_EQ(8u, sizeof(AlignedCharArrayUnion<SA1, SA2, SA4, SA8>)); - EXPECT_EQ(1u, (alignOf<AlignedCharArray<SA1[1]>::union_type>())); - EXPECT_EQ(2u, (alignOf<AlignedCharArray<SA1[2], SA2[1]>::union_type>())); - EXPECT_EQ(4u, (alignOf<AlignedCharArray<SA1[42], SA2[55], - SA4[13]>::union_type>())); - EXPECT_EQ(8u, (alignOf<AlignedCharArray<SA1[2], SA2[1], - SA4, SA8>::union_type>())); + EXPECT_EQ(1u, (alignOf<AlignedCharArrayUnion<SA1[1]> >())); + EXPECT_EQ(2u, (alignOf<AlignedCharArrayUnion<SA1[2], SA2[1]> >())); + EXPECT_EQ(4u, (alignOf<AlignedCharArrayUnion<SA1[42], SA2[55], + SA4[13]> >())); + EXPECT_EQ(8u, (alignOf<AlignedCharArrayUnion<SA1[2], SA2[1], + SA4, SA8> >())); - EXPECT_EQ(1u, sizeof(AlignedCharArray<SA1[1]>::union_type)); - EXPECT_EQ(2u, sizeof(AlignedCharArray<SA1[2], SA2[1]>::union_type)); - EXPECT_EQ(4u, sizeof(AlignedCharArray<SA1[3], SA2[2], SA4>::union_type)); - EXPECT_EQ(16u, sizeof(AlignedCharArray<SA1, SA2[3], - SA4[3], SA8>::union_type)); + EXPECT_EQ(1u, sizeof(AlignedCharArrayUnion<SA1[1]>)); + EXPECT_EQ(2u, sizeof(AlignedCharArrayUnion<SA1[2], SA2[1]>)); + EXPECT_EQ(4u, sizeof(AlignedCharArrayUnion<SA1[3], SA2[2], SA4>)); + EXPECT_EQ(16u, sizeof(AlignedCharArrayUnion<SA1, SA2[3], + SA4[3], SA8>)); // For other tests we simply assert that the alignment of the union mathes // that of the fundamental type and hope that we have any weird type // productions that would trigger bugs. - EXPECT_EQ(alignOf<char>(), alignOf<AlignedCharArray<char>::union_type>()); - EXPECT_EQ(alignOf<short>(), alignOf<AlignedCharArray<short>::union_type>()); - EXPECT_EQ(alignOf<int>(), alignOf<AlignedCharArray<int>::union_type>()); - EXPECT_EQ(alignOf<long>(), alignOf<AlignedCharArray<long>::union_type>()); + EXPECT_EQ(alignOf<char>(), alignOf<AlignedCharArrayUnion<char> >()); + EXPECT_EQ(alignOf<short>(), alignOf<AlignedCharArrayUnion<short> >()); + EXPECT_EQ(alignOf<int>(), alignOf<AlignedCharArrayUnion<int> >()); + EXPECT_EQ(alignOf<long>(), alignOf<AlignedCharArrayUnion<long> >()); EXPECT_EQ(alignOf<long long>(), - alignOf<AlignedCharArray<long long>::union_type>()); - EXPECT_EQ(alignOf<float>(), alignOf<AlignedCharArray<float>::union_type>()); - EXPECT_EQ(alignOf<double>(), alignOf<AlignedCharArray<double>::union_type>()); + alignOf<AlignedCharArrayUnion<long long> >()); + EXPECT_EQ(alignOf<float>(), alignOf<AlignedCharArrayUnion<float> >()); + EXPECT_EQ(alignOf<double>(), alignOf<AlignedCharArrayUnion<double> >()); EXPECT_EQ(alignOf<long double>(), - alignOf<AlignedCharArray<long double>::union_type>()); - EXPECT_EQ(alignOf<void *>(), alignOf<AlignedCharArray<void *>::union_type>()); - EXPECT_EQ(alignOf<int *>(), alignOf<AlignedCharArray<int *>::union_type>()); + alignOf<AlignedCharArrayUnion<long double> >()); + EXPECT_EQ(alignOf<void *>(), alignOf<AlignedCharArrayUnion<void *> >()); + EXPECT_EQ(alignOf<int *>(), alignOf<AlignedCharArrayUnion<int *> >()); EXPECT_EQ(alignOf<double (*)(double)>(), - alignOf<AlignedCharArray<double (*)(double)>::union_type>()); + alignOf<AlignedCharArrayUnion<double (*)(double)> >()); EXPECT_EQ(alignOf<double (S6::*)()>(), - alignOf<AlignedCharArray<double (S6::*)()>::union_type>()); - EXPECT_EQ(alignOf<S1>(), alignOf<AlignedCharArray<S1>::union_type>()); - EXPECT_EQ(alignOf<S2>(), alignOf<AlignedCharArray<S2>::union_type>()); - EXPECT_EQ(alignOf<S3>(), alignOf<AlignedCharArray<S3>::union_type>()); - EXPECT_EQ(alignOf<S4>(), alignOf<AlignedCharArray<S4>::union_type>()); - EXPECT_EQ(alignOf<S5>(), alignOf<AlignedCharArray<S5>::union_type>()); - EXPECT_EQ(alignOf<S6>(), alignOf<AlignedCharArray<S6>::union_type>()); - EXPECT_EQ(alignOf<D1>(), alignOf<AlignedCharArray<D1>::union_type>()); - EXPECT_EQ(alignOf<D2>(), alignOf<AlignedCharArray<D2>::union_type>()); - EXPECT_EQ(alignOf<D3>(), alignOf<AlignedCharArray<D3>::union_type>()); - EXPECT_EQ(alignOf<D4>(), alignOf<AlignedCharArray<D4>::union_type>()); - EXPECT_EQ(alignOf<D5>(), alignOf<AlignedCharArray<D5>::union_type>()); - EXPECT_EQ(alignOf<D6>(), alignOf<AlignedCharArray<D6>::union_type>()); - EXPECT_EQ(alignOf<D7>(), alignOf<AlignedCharArray<D7>::union_type>()); - EXPECT_EQ(alignOf<D8>(), alignOf<AlignedCharArray<D8>::union_type>()); - EXPECT_EQ(alignOf<D9>(), alignOf<AlignedCharArray<D9>::union_type>()); - EXPECT_EQ(alignOf<V1>(), alignOf<AlignedCharArray<V1>::union_type>()); - EXPECT_EQ(alignOf<V2>(), alignOf<AlignedCharArray<V2>::union_type>()); - EXPECT_EQ(alignOf<V3>(), alignOf<AlignedCharArray<V3>::union_type>()); - EXPECT_EQ(alignOf<V4>(), alignOf<AlignedCharArray<V4>::union_type>()); - EXPECT_EQ(alignOf<V5>(), alignOf<AlignedCharArray<V5>::union_type>()); - EXPECT_EQ(alignOf<V6>(), alignOf<AlignedCharArray<V6>::union_type>()); - EXPECT_EQ(alignOf<V7>(), alignOf<AlignedCharArray<V7>::union_type>()); + alignOf<AlignedCharArrayUnion<double (S6::*)()> >()); + EXPECT_EQ(alignOf<S1>(), alignOf<AlignedCharArrayUnion<S1> >()); + EXPECT_EQ(alignOf<S2>(), alignOf<AlignedCharArrayUnion<S2> >()); + EXPECT_EQ(alignOf<S3>(), alignOf<AlignedCharArrayUnion<S3> >()); + EXPECT_EQ(alignOf<S4>(), alignOf<AlignedCharArrayUnion<S4> >()); + EXPECT_EQ(alignOf<S5>(), alignOf<AlignedCharArrayUnion<S5> >()); + EXPECT_EQ(alignOf<S6>(), alignOf<AlignedCharArrayUnion<S6> >()); + EXPECT_EQ(alignOf<D1>(), alignOf<AlignedCharArrayUnion<D1> >()); + EXPECT_EQ(alignOf<D2>(), alignOf<AlignedCharArrayUnion<D2> >()); + EXPECT_EQ(alignOf<D3>(), alignOf<AlignedCharArrayUnion<D3> >()); + EXPECT_EQ(alignOf<D4>(), alignOf<AlignedCharArrayUnion<D4> >()); + EXPECT_EQ(alignOf<D5>(), alignOf<AlignedCharArrayUnion<D5> >()); + EXPECT_EQ(alignOf<D6>(), alignOf<AlignedCharArrayUnion<D6> >()); + EXPECT_EQ(alignOf<D7>(), alignOf<AlignedCharArrayUnion<D7> >()); + EXPECT_EQ(alignOf<D8>(), alignOf<AlignedCharArrayUnion<D8> >()); + EXPECT_EQ(alignOf<D9>(), alignOf<AlignedCharArrayUnion<D9> >()); + EXPECT_EQ(alignOf<V1>(), alignOf<AlignedCharArrayUnion<V1> >()); + EXPECT_EQ(alignOf<V2>(), alignOf<AlignedCharArrayUnion<V2> >()); + EXPECT_EQ(alignOf<V3>(), alignOf<AlignedCharArrayUnion<V3> >()); + EXPECT_EQ(alignOf<V4>(), alignOf<AlignedCharArrayUnion<V4> >()); + EXPECT_EQ(alignOf<V5>(), alignOf<AlignedCharArrayUnion<V5> >()); + EXPECT_EQ(alignOf<V6>(), alignOf<AlignedCharArrayUnion<V6> >()); + EXPECT_EQ(alignOf<V7>(), alignOf<AlignedCharArrayUnion<V7> >()); // Some versions of MSVC get this wrong somewhat disturbingly. The failure // appears to be benign: alignOf<V8>() produces a preposterous value: 12 #ifndef _MSC_VER - EXPECT_EQ(alignOf<V8>(), alignOf<AlignedCharArray<V8>::union_type>()); + EXPECT_EQ(alignOf<V8>(), alignOf<AlignedCharArrayUnion<V8> >()); #endif - EXPECT_EQ(sizeof(char), sizeof(AlignedCharArray<char>::union_type)); - EXPECT_EQ(sizeof(char[1]), sizeof(AlignedCharArray<char[1]>::union_type)); - EXPECT_EQ(sizeof(char[2]), sizeof(AlignedCharArray<char[2]>::union_type)); - EXPECT_EQ(sizeof(char[3]), sizeof(AlignedCharArray<char[3]>::union_type)); - EXPECT_EQ(sizeof(char[4]), sizeof(AlignedCharArray<char[4]>::union_type)); - EXPECT_EQ(sizeof(char[5]), sizeof(AlignedCharArray<char[5]>::union_type)); - EXPECT_EQ(sizeof(char[8]), sizeof(AlignedCharArray<char[8]>::union_type)); - EXPECT_EQ(sizeof(char[13]), sizeof(AlignedCharArray<char[13]>::union_type)); - EXPECT_EQ(sizeof(char[16]), sizeof(AlignedCharArray<char[16]>::union_type)); - EXPECT_EQ(sizeof(char[21]), sizeof(AlignedCharArray<char[21]>::union_type)); - EXPECT_EQ(sizeof(char[32]), sizeof(AlignedCharArray<char[32]>::union_type)); - EXPECT_EQ(sizeof(short), sizeof(AlignedCharArray<short>::union_type)); - EXPECT_EQ(sizeof(int), sizeof(AlignedCharArray<int>::union_type)); - EXPECT_EQ(sizeof(long), sizeof(AlignedCharArray<long>::union_type)); + EXPECT_EQ(sizeof(char), sizeof(AlignedCharArrayUnion<char>)); + EXPECT_EQ(sizeof(char[1]), sizeof(AlignedCharArrayUnion<char[1]>)); + EXPECT_EQ(sizeof(char[2]), sizeof(AlignedCharArrayUnion<char[2]>)); + EXPECT_EQ(sizeof(char[3]), sizeof(AlignedCharArrayUnion<char[3]>)); + EXPECT_EQ(sizeof(char[4]), sizeof(AlignedCharArrayUnion<char[4]>)); + EXPECT_EQ(sizeof(char[5]), sizeof(AlignedCharArrayUnion<char[5]>)); + EXPECT_EQ(sizeof(char[8]), sizeof(AlignedCharArrayUnion<char[8]>)); + EXPECT_EQ(sizeof(char[13]), sizeof(AlignedCharArrayUnion<char[13]>)); + EXPECT_EQ(sizeof(char[16]), sizeof(AlignedCharArrayUnion<char[16]>)); + EXPECT_EQ(sizeof(char[21]), sizeof(AlignedCharArrayUnion<char[21]>)); + EXPECT_EQ(sizeof(char[32]), sizeof(AlignedCharArrayUnion<char[32]>)); + EXPECT_EQ(sizeof(short), sizeof(AlignedCharArrayUnion<short>)); + EXPECT_EQ(sizeof(int), sizeof(AlignedCharArrayUnion<int>)); + EXPECT_EQ(sizeof(long), sizeof(AlignedCharArrayUnion<long>)); EXPECT_EQ(sizeof(long long), - sizeof(AlignedCharArray<long long>::union_type)); - EXPECT_EQ(sizeof(float), sizeof(AlignedCharArray<float>::union_type)); - EXPECT_EQ(sizeof(double), sizeof(AlignedCharArray<double>::union_type)); + sizeof(AlignedCharArrayUnion<long long>)); + EXPECT_EQ(sizeof(float), sizeof(AlignedCharArrayUnion<float>)); + EXPECT_EQ(sizeof(double), sizeof(AlignedCharArrayUnion<double>)); EXPECT_EQ(sizeof(long double), - sizeof(AlignedCharArray<long double>::union_type)); - EXPECT_EQ(sizeof(void *), sizeof(AlignedCharArray<void *>::union_type)); - EXPECT_EQ(sizeof(int *), sizeof(AlignedCharArray<int *>::union_type)); + sizeof(AlignedCharArrayUnion<long double>)); + EXPECT_EQ(sizeof(void *), sizeof(AlignedCharArrayUnion<void *>)); + EXPECT_EQ(sizeof(int *), sizeof(AlignedCharArrayUnion<int *>)); EXPECT_EQ(sizeof(double (*)(double)), - sizeof(AlignedCharArray<double (*)(double)>::union_type)); + sizeof(AlignedCharArrayUnion<double (*)(double)>)); EXPECT_EQ(sizeof(double (S6::*)()), - sizeof(AlignedCharArray<double (S6::*)()>::union_type)); - EXPECT_EQ(sizeof(S1), sizeof(AlignedCharArray<S1>::union_type)); - EXPECT_EQ(sizeof(S2), sizeof(AlignedCharArray<S2>::union_type)); - EXPECT_EQ(sizeof(S3), sizeof(AlignedCharArray<S3>::union_type)); - EXPECT_EQ(sizeof(S4), sizeof(AlignedCharArray<S4>::union_type)); - EXPECT_EQ(sizeof(S5), sizeof(AlignedCharArray<S5>::union_type)); - EXPECT_EQ(sizeof(S6), sizeof(AlignedCharArray<S6>::union_type)); - EXPECT_EQ(sizeof(D1), sizeof(AlignedCharArray<D1>::union_type)); - EXPECT_EQ(sizeof(D2), sizeof(AlignedCharArray<D2>::union_type)); - EXPECT_EQ(sizeof(D3), sizeof(AlignedCharArray<D3>::union_type)); - EXPECT_EQ(sizeof(D4), sizeof(AlignedCharArray<D4>::union_type)); - EXPECT_EQ(sizeof(D5), sizeof(AlignedCharArray<D5>::union_type)); - EXPECT_EQ(sizeof(D6), sizeof(AlignedCharArray<D6>::union_type)); - EXPECT_EQ(sizeof(D7), sizeof(AlignedCharArray<D7>::union_type)); - EXPECT_EQ(sizeof(D8), sizeof(AlignedCharArray<D8>::union_type)); - EXPECT_EQ(sizeof(D9), sizeof(AlignedCharArray<D9>::union_type)); - EXPECT_EQ(sizeof(D9[1]), sizeof(AlignedCharArray<D9[1]>::union_type)); - EXPECT_EQ(sizeof(D9[2]), sizeof(AlignedCharArray<D9[2]>::union_type)); - EXPECT_EQ(sizeof(D9[3]), sizeof(AlignedCharArray<D9[3]>::union_type)); - EXPECT_EQ(sizeof(D9[4]), sizeof(AlignedCharArray<D9[4]>::union_type)); - EXPECT_EQ(sizeof(D9[5]), sizeof(AlignedCharArray<D9[5]>::union_type)); - EXPECT_EQ(sizeof(D9[8]), sizeof(AlignedCharArray<D9[8]>::union_type)); - EXPECT_EQ(sizeof(D9[13]), sizeof(AlignedCharArray<D9[13]>::union_type)); - EXPECT_EQ(sizeof(D9[16]), sizeof(AlignedCharArray<D9[16]>::union_type)); - EXPECT_EQ(sizeof(D9[21]), sizeof(AlignedCharArray<D9[21]>::union_type)); - EXPECT_EQ(sizeof(D9[32]), sizeof(AlignedCharArray<D9[32]>::union_type)); - EXPECT_EQ(sizeof(V1), sizeof(AlignedCharArray<V1>::union_type)); - EXPECT_EQ(sizeof(V2), sizeof(AlignedCharArray<V2>::union_type)); - EXPECT_EQ(sizeof(V3), sizeof(AlignedCharArray<V3>::union_type)); - EXPECT_EQ(sizeof(V4), sizeof(AlignedCharArray<V4>::union_type)); - EXPECT_EQ(sizeof(V5), sizeof(AlignedCharArray<V5>::union_type)); - EXPECT_EQ(sizeof(V6), sizeof(AlignedCharArray<V6>::union_type)); - EXPECT_EQ(sizeof(V7), sizeof(AlignedCharArray<V7>::union_type)); + sizeof(AlignedCharArrayUnion<double (S6::*)()>)); + EXPECT_EQ(sizeof(S1), sizeof(AlignedCharArrayUnion<S1>)); + EXPECT_EQ(sizeof(S2), sizeof(AlignedCharArrayUnion<S2>)); + EXPECT_EQ(sizeof(S3), sizeof(AlignedCharArrayUnion<S3>)); + EXPECT_EQ(sizeof(S4), sizeof(AlignedCharArrayUnion<S4>)); + EXPECT_EQ(sizeof(S5), sizeof(AlignedCharArrayUnion<S5>)); + EXPECT_EQ(sizeof(S6), sizeof(AlignedCharArrayUnion<S6>)); + EXPECT_EQ(sizeof(D1), sizeof(AlignedCharArrayUnion<D1>)); + EXPECT_EQ(sizeof(D2), sizeof(AlignedCharArrayUnion<D2>)); + EXPECT_EQ(sizeof(D3), sizeof(AlignedCharArrayUnion<D3>)); + EXPECT_EQ(sizeof(D4), sizeof(AlignedCharArrayUnion<D4>)); + EXPECT_EQ(sizeof(D5), sizeof(AlignedCharArrayUnion<D5>)); + EXPECT_EQ(sizeof(D6), sizeof(AlignedCharArrayUnion<D6>)); + EXPECT_EQ(sizeof(D7), sizeof(AlignedCharArrayUnion<D7>)); + EXPECT_EQ(sizeof(D8), sizeof(AlignedCharArrayUnion<D8>)); + EXPECT_EQ(sizeof(D9), sizeof(AlignedCharArrayUnion<D9>)); + EXPECT_EQ(sizeof(D9[1]), sizeof(AlignedCharArrayUnion<D9[1]>)); + EXPECT_EQ(sizeof(D9[2]), sizeof(AlignedCharArrayUnion<D9[2]>)); + EXPECT_EQ(sizeof(D9[3]), sizeof(AlignedCharArrayUnion<D9[3]>)); + EXPECT_EQ(sizeof(D9[4]), sizeof(AlignedCharArrayUnion<D9[4]>)); + EXPECT_EQ(sizeof(D9[5]), sizeof(AlignedCharArrayUnion<D9[5]>)); + EXPECT_EQ(sizeof(D9[8]), sizeof(AlignedCharArrayUnion<D9[8]>)); + EXPECT_EQ(sizeof(D9[13]), sizeof(AlignedCharArrayUnion<D9[13]>)); + EXPECT_EQ(sizeof(D9[16]), sizeof(AlignedCharArrayUnion<D9[16]>)); + EXPECT_EQ(sizeof(D9[21]), sizeof(AlignedCharArrayUnion<D9[21]>)); + EXPECT_EQ(sizeof(D9[32]), sizeof(AlignedCharArrayUnion<D9[32]>)); + EXPECT_EQ(sizeof(V1), sizeof(AlignedCharArrayUnion<V1>)); + EXPECT_EQ(sizeof(V2), sizeof(AlignedCharArrayUnion<V2>)); + EXPECT_EQ(sizeof(V3), sizeof(AlignedCharArrayUnion<V3>)); + EXPECT_EQ(sizeof(V4), sizeof(AlignedCharArrayUnion<V4>)); + EXPECT_EQ(sizeof(V5), sizeof(AlignedCharArrayUnion<V5>)); + EXPECT_EQ(sizeof(V6), sizeof(AlignedCharArrayUnion<V6>)); + EXPECT_EQ(sizeof(V7), sizeof(AlignedCharArrayUnion<V7>)); // Some versions of MSVC also get this wrong. The failure again appears to be // benign: sizeof(V8) is only 52 bytes, but our array reserves 56. #ifndef _MSC_VER - EXPECT_EQ(sizeof(V8), sizeof(AlignedCharArray<V8>::union_type)); + EXPECT_EQ(sizeof(V8), sizeof(AlignedCharArrayUnion<V8>)); #endif } diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index a071a5a8d694..63c9ae059157 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -340,44 +340,51 @@ TEST_F(FileSystemTest, Permissions) { } #endif -#if !defined(_WIN32) // FIXME: temporary suppressed. TEST_F(FileSystemTest, FileMapping) { // Create a temp file. int FileDescriptor; SmallString<64> TempPath; ASSERT_NO_ERROR( fs::unique_file("%%-%%-%%-%%.temp", FileDescriptor, TempPath)); - - // Grow temp file to be 4096 bytes - ASSERT_NO_ERROR(sys::fs::resize_file(Twine(TempPath), 4096)); - // Map in temp file and add some content - void* MappedMemory; - ASSERT_NO_ERROR(fs::map_file_pages(Twine(TempPath), 0, 4096, - true /*writable*/, MappedMemory)); - char* Memory = reinterpret_cast<char*>(MappedMemory); - strcpy(Memory, "hello there"); - - // Unmap temp file - ASSERT_NO_ERROR(fs::unmap_file_pages(MappedMemory, 4096)); - MappedMemory = NULL; - Memory = NULL; + error_code EC; + StringRef Val("hello there"); + { + fs::mapped_file_region mfr(FileDescriptor, + fs::mapped_file_region::readwrite, + 4096, + 0, + EC); + ASSERT_NO_ERROR(EC); + std::copy(Val.begin(), Val.end(), mfr.data()); + // Explicitly add a 0. + mfr.data()[Val.size()] = 0; + // Unmap temp file + } // Map it back in read-only - ASSERT_NO_ERROR(fs::map_file_pages(Twine(TempPath), 0, 4096, - false /*read-only*/, MappedMemory)); + fs::mapped_file_region mfr(Twine(TempPath), + fs::mapped_file_region::readonly, + 0, + 0, + EC); + ASSERT_NO_ERROR(EC); // Verify content - Memory = reinterpret_cast<char*>(MappedMemory); - bool SAME = (strcmp(Memory, "hello there") == 0); - EXPECT_TRUE(SAME); + EXPECT_EQ(StringRef(mfr.const_data()), Val); // Unmap temp file - ASSERT_NO_ERROR(fs::unmap_file_pages(MappedMemory, 4096)); - MappedMemory = NULL; - Memory = NULL; -} -#endif - +#if LLVM_USE_RVALUE_REFERENCES + fs::mapped_file_region m(Twine(TempPath), + fs::mapped_file_region::readonly, + 0, + 0, + EC); + ASSERT_NO_ERROR(EC); + const char *Data = m.const_data(); + fs::mapped_file_region mfrrv(llvm_move(m)); + EXPECT_EQ(mfrrv.const_data(), Data); +#endif +} } // anonymous namespace diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 33381e956905..12e153a66514 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -297,6 +297,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) { isCompare = R->getValueAsBit("isCompare"); isMoveImm = R->getValueAsBit("isMoveImm"); isBitcast = R->getValueAsBit("isBitcast"); + isSelect = R->getValueAsBit("isSelect"); isBarrier = R->getValueAsBit("isBarrier"); isCall = R->getValueAsBit("isCall"); canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 3ba9f24daaed..95b572d2d08c 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -222,6 +222,7 @@ namespace llvm { bool isCompare; bool isMoveImm; bool isBitcast; + bool isSelect; bool isBarrier; bool isCall; bool canFoldAsLoad; diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index ff3ad7283939..011f4b79386f 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -28,19 +28,15 @@ using namespace llvm; //===----------------------------------------------------------------------===// CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) - : TheDef(R), - EnumValue(Enum) -{} - -std::string CodeGenSubRegIndex::getNamespace() const { - if (TheDef->getValue("Namespace")) - return TheDef->getValueAsString("Namespace"); - else - return ""; + : TheDef(R), EnumValue(Enum) { + Name = R->getName(); + if (R->getValue("Namespace")) + Namespace = R->getValueAsString("Namespace"); } -const std::string &CodeGenSubRegIndex::getName() const { - return TheDef->getName(); +CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace, + unsigned Enum) + : TheDef(0), Name(N), Namespace(Nspace), EnumValue(Enum) { } std::string CodeGenSubRegIndex::getQualifiedName() const { @@ -52,16 +48,31 @@ std::string CodeGenSubRegIndex::getQualifiedName() const { } void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { - std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf"); - if (Comps.empty()) + if (!TheDef) return; - if (Comps.size() != 2) - throw TGError(TheDef->getLoc(), "ComposedOf must have exactly two entries"); - CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]); - CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]); - CodeGenSubRegIndex *X = A->addComposite(B, this); - if (X) - throw TGError(TheDef->getLoc(), "Ambiguous ComposedOf entries"); + + std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf"); + if (!Comps.empty()) { + if (Comps.size() != 2) + throw TGError(TheDef->getLoc(), "ComposedOf must have exactly two entries"); + CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]); + CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]); + CodeGenSubRegIndex *X = A->addComposite(B, this); + if (X) + throw TGError(TheDef->getLoc(), "Ambiguous ComposedOf entries"); + } + + std::vector<Record*> Parts = + TheDef->getValueAsListOfDefs("CoveringSubRegIndices"); + if (!Parts.empty()) { + if (Parts.size() < 2) + throw TGError(TheDef->getLoc(), + "CoveredBySubRegs must have two or more entries"); + SmallVector<CodeGenSubRegIndex*, 8> IdxParts; + for (unsigned i = 0, e = Parts.size(); i != e; ++i) + IdxParts.push_back(RegBank.getSubRegIdx(Parts[i])); + RegBank.addConcatSubRegIndex(IdxParts, this); + } } void CodeGenSubRegIndex::cleanComposites() { @@ -937,7 +948,7 @@ void CodeGenRegisterClass::buildRegUnitSet( // CodeGenRegBank //===----------------------------------------------------------------------===// -CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { +CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { // Configure register Sets to understand register classes and tuples. Sets.addFieldExpander("RegisterClass", "MemberList"); Sets.addFieldExpander("CalleeSavedRegs", "SaveList"); @@ -947,7 +958,6 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { // More indices will be synthesized later. std::vector<Record*> SRIs = Records.getAllDerivedDefinitions("SubRegIndex"); std::sort(SRIs.begin(), SRIs.end(), LessRecord()); - NumNamedIndices = SRIs.size(); for (unsigned i = 0, e = SRIs.size(); i != e; ++i) getSubRegIdx(SRIs[i]); // Build composite maps from ComposedOf fields. @@ -1015,6 +1025,15 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) : Records(Records) { CodeGenRegisterClass::computeSubClasses(*this); } +// Create a synthetic CodeGenSubRegIndex without a corresponding Record. +CodeGenSubRegIndex* +CodeGenRegBank::createSubRegIndex(StringRef Name, StringRef Namespace) { + CodeGenSubRegIndex *Idx = new CodeGenSubRegIndex(Name, Namespace, + SubRegIndices.size() + 1); + SubRegIndices.push_back(Idx); + return Idx; +} + CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) { CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def]; if (Idx) @@ -1079,7 +1098,7 @@ CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A, // None exists, synthesize one. std::string Name = A->getName() + "_then_" + B->getName(); - Comp = getSubRegIdx(new Record(Name, SMLoc(), Records)); + Comp = createSubRegIndex(Name, A->getNamespace()); A->addComposite(B, Comp); return Comp; } @@ -1099,7 +1118,7 @@ getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex*, 8> &Parts) { Name += '_'; Name += Parts[i]->getName(); } - return Idx = getSubRegIdx(new Record(Name, SMLoc(), Records)); + return Idx = createSubRegIndex(Name, Parts.front()->getNamespace()); } void CodeGenRegBank::computeComposites() { diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index eb6724ea1ac5..827063e47017 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -35,14 +35,17 @@ namespace llvm { /// CodeGenSubRegIndex - Represents a sub-register index. class CodeGenSubRegIndex { Record *const TheDef; + std::string Name; + std::string Namespace; public: const unsigned EnumValue; CodeGenSubRegIndex(Record *R, unsigned Enum); + CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum); - const std::string &getName() const; - std::string getNamespace() const; + const std::string &getName() const { return Name; } + const std::string &getNamespace() const { return Namespace; } std::string getQualifiedName() const; // Order CodeGenSubRegIndex pointers by EnumValue. @@ -422,13 +425,13 @@ namespace llvm { // CodeGenRegBank - Represent a target's registers and the relations between // them. class CodeGenRegBank { - RecordKeeper &Records; SetTheory Sets; // SubRegIndices. std::vector<CodeGenSubRegIndex*> SubRegIndices; DenseMap<Record*, CodeGenSubRegIndex*> Def2SubRegIdx; - unsigned NumNamedIndices; + + CodeGenSubRegIndex *createSubRegIndex(StringRef Name, StringRef NameSpace); typedef std::map<SmallVector<CodeGenSubRegIndex*, 8>, CodeGenSubRegIndex*> ConcatIdxMap; @@ -495,7 +498,6 @@ namespace llvm { // in the .td files. The rest are synthesized such that all sub-registers // have a unique name. ArrayRef<CodeGenSubRegIndex*> getSubRegIndices() { return SubRegIndices; } - unsigned getNumNamedIndices() { return NumNamedIndices; } // Find a SubRegIndex form its Record def. CodeGenSubRegIndex *getSubRegIdx(Record*); diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index 2cdde5500954..e89c393b6a9b 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -17,9 +17,15 @@ #include "CodeGenTarget.h" #include "llvm/TableGen/Record.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/MC/MCFixedLenDisassembler.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TableGen/TableGenBackend.h" @@ -35,9 +41,7 @@ struct EncodingField { EncodingField(unsigned B, unsigned W, unsigned O) : Base(B), Width(W), Offset(O) { } }; -} // End anonymous namespace -namespace { struct OperandInfo { std::vector<EncodingField> Fields; std::string Decoder; @@ -56,10 +60,25 @@ struct OperandInfo { const_iterator begin() const { return Fields.begin(); } const_iterator end() const { return Fields.end(); } }; + +typedef std::vector<uint8_t> DecoderTable; +typedef uint32_t DecoderFixup; +typedef std::vector<DecoderFixup> FixupList; +typedef std::vector<FixupList> FixupScopeList; +typedef SetVector<std::string> PredicateSet; +typedef SetVector<std::string> DecoderSet; +struct DecoderTableInfo { + DecoderTable Table; + FixupScopeList FixupStack; + PredicateSet Predicates; + DecoderSet Decoders; +}; + } // End anonymous namespace namespace { class FixedLenDecoderEmitter { + const std::vector<const CodeGenInstruction*> *NumberedInstructions; public: // Defaults preserved here for documentation, even though they aren't @@ -77,6 +96,17 @@ public: GuardPrefix(GPrefix), GuardPostfix(GPostfix), ReturnOK(ROK), ReturnFail(RFail), Locals(L) {} + // Emit the decoder state machine table. + void emitTable(formatted_raw_ostream &o, DecoderTable &Table, + unsigned Indentation, unsigned BitWidth, + StringRef Namespace) const; + void emitPredicateFunction(formatted_raw_ostream &OS, + PredicateSet &Predicates, + unsigned Indentation) const; + void emitDecoderFunction(formatted_raw_ostream &OS, + DecoderSet &Decoders, + unsigned Indentation) const; + // run - Output the code emitter void run(raw_ostream &o); @@ -120,9 +150,7 @@ static bit_value_t bitFromBits(const BitsInit &bits, unsigned index) { } // Prints the bit value for each position. static void dumpBits(raw_ostream &o, const BitsInit &bits) { - unsigned index; - - for (index = bits.getNumBits(); index > 0; index--) { + for (unsigned index = bits.getNumBits(); index > 0; --index) { switch (bitFromBits(bits, index - 1)) { case BIT_TRUE: o << "1"; @@ -238,8 +266,9 @@ public: // match the remaining undecoded encoding bits against the singleton. void recurse(); - // Emit code to decode instructions given a segment or segments of bits. - void emit(raw_ostream &o, unsigned &Indentation) const; + // Emit table entries to decode instructions given a segment or segments of + // bits. + void emitTableEntry(DecoderTableInfo &TableInfo) const; // Returns the number of fanout produced by the filter. More fanout implies // the filter distinguishes more categories of instructions. @@ -338,12 +367,7 @@ public: doFilter(); } - // The top level filter chooser has NULL as its parent. - bool isTopLevel() const { return Parent == NULL; } - - // Emit the top level typedef and decodeInstruction() function. - void emitTop(raw_ostream &o, unsigned Indentation, - const std::string &Namespace) const; + unsigned getBitWidth() const { return BitWidth; } protected: // Populates the insn given the uid. @@ -414,21 +438,28 @@ protected: bool emitPredicateMatch(raw_ostream &o, unsigned &Indentation, unsigned Opc) const; - void emitSoftFailCheck(raw_ostream &o, unsigned Indentation, - unsigned Opc) const; + bool doesOpcodeNeedPredicate(unsigned Opc) const; + unsigned getPredicateIndex(DecoderTableInfo &TableInfo, StringRef P) const; + void emitPredicateTableEntry(DecoderTableInfo &TableInfo, + unsigned Opc) const; + + void emitSoftFailTableEntry(DecoderTableInfo &TableInfo, + unsigned Opc) const; - // Emits code to decode the singleton. Return true if we have matched all the - // well-known bits. - bool emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, - unsigned Opc) const; + // Emits table entries to decode the singleton. + void emitSingletonTableEntry(DecoderTableInfo &TableInfo, + unsigned Opc) const; // Emits code to decode the singleton, and then to decode the rest. - void emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, - const Filter &Best) const; + void emitSingletonTableEntry(DecoderTableInfo &TableInfo, + const Filter &Best) const; - void emitBinaryParser(raw_ostream &o , unsigned &Indentation, + void emitBinaryParser(raw_ostream &o, unsigned &Indentation, const OperandInfo &OpInfo) const; + void emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc) const; + unsigned getDecoderIndex(DecoderSet &Decoders, unsigned Opc) const; + // Assign a single filter and run with it. void runSingleFilter(unsigned startBit, unsigned numBit, bool mixed); @@ -447,10 +478,10 @@ protected: // dump the conflict set to the standard error. void doFilter(); - // Emits code to decode our share of instructions. Returns true if the - // emitted code causes a return, which occurs if we know how to decode - // the instruction at this level or the instruction is not decodeable. - bool emit(raw_ostream &o, unsigned &Indentation) const; +public: + // emitTableEntries - Emit state machine entries to decode our share of + // instructions. + void emitTableEntries(DecoderTableInfo &TableInfo) const; }; } // End anonymous namespace @@ -524,11 +555,9 @@ void Filter::recurse() { // Starts by inheriting our parent filter chooser's filter bit values. std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues); - unsigned bitIndex; - if (VariableInstructions.size()) { // Conservatively marks each segment position as BIT_UNSET. - for (bitIndex = 0; bitIndex < NumBits; bitIndex++) + for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) BitValueArray[StartBit + bitIndex] = BIT_UNSET; // Delegates to an inferior filter chooser for further processing on this @@ -544,7 +573,7 @@ void Filter::recurse() { } // No need to recurse for a singleton filtered instruction. - // See also Filter::emit(). + // See also Filter::emit*(). if (getNumFiltered() == 1) { //Owner->SingletonExists(LastOpcFiltered); assert(FilterChooserMap.size() == 1); @@ -557,7 +586,7 @@ void Filter::recurse() { mapIterator++) { // Marks all the segment positions with either BIT_TRUE or BIT_FALSE. - for (bitIndex = 0; bitIndex < NumBits; bitIndex++) { + for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) { if (mapIterator->first & (1ULL << bitIndex)) BitValueArray[StartBit + bitIndex] = BIT_TRUE; else @@ -577,64 +606,100 @@ void Filter::recurse() { } } -// Emit code to decode instructions given a segment or segments of bits. -void Filter::emit(raw_ostream &o, unsigned &Indentation) const { - o.indent(Indentation) << "// Check Inst{"; - - if (NumBits > 1) - o << (StartBit + NumBits - 1) << '-'; +static void resolveTableFixups(DecoderTable &Table, const FixupList &Fixups, + uint32_t DestIdx) { + // Any NumToSkip fixups in the current scope can resolve to the + // current location. + for (FixupList::const_reverse_iterator I = Fixups.rbegin(), + E = Fixups.rend(); + I != E; ++I) { + // Calculate the distance from the byte following the fixup entry byte + // to the destination. The Target is calculated from after the 16-bit + // NumToSkip entry itself, so subtract two from the displacement here + // to account for that. + uint32_t FixupIdx = *I; + uint32_t Delta = DestIdx - FixupIdx - 2; + // Our NumToSkip entries are 16-bits. Make sure our table isn't too + // big. + assert(Delta < 65536U && "disassembler decoding table too large!"); + Table[FixupIdx] = (uint8_t)Delta; + Table[FixupIdx + 1] = (uint8_t)(Delta >> 8); + } +} - o << StartBit << "} ...\n"; +// Emit table entries to decode instructions given a segment or segments +// of bits. +void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { + TableInfo.Table.push_back(MCD::OPC_ExtractField); + TableInfo.Table.push_back(StartBit); + TableInfo.Table.push_back(NumBits); - o.indent(Indentation) << "switch (fieldFromInstruction" << Owner->BitWidth - << "(insn, " << StartBit << ", " - << NumBits << ")) {\n"; + // A new filter entry begins a new scope for fixup resolution. + TableInfo.FixupStack.push_back(FixupList()); std::map<unsigned, const FilterChooser*>::const_iterator filterIterator; - bool DefaultCase = false; + DecoderTable &Table = TableInfo.Table; + + size_t PrevFilter = 0; + bool HasFallthrough = false; for (filterIterator = FilterChooserMap.begin(); filterIterator != FilterChooserMap.end(); filterIterator++) { - // Field value -1 implies a non-empty set of variable instructions. // See also recurse(). if (filterIterator->first == (unsigned)-1) { - DefaultCase = true; - - o.indent(Indentation) << "default:\n"; - o.indent(Indentation) << " break; // fallthrough\n"; - - // Closing curly brace for the switch statement. - // This is unconventional because we want the default processing to be - // performed for the fallthrough cases as well, i.e., when the "cases" - // did not prove a decoded instruction. - o.indent(Indentation) << "}\n"; - - } else - o.indent(Indentation) << "case " << filterIterator->first << ":\n"; + HasFallthrough = true; + + // Each scope should always have at least one filter value to check + // for. + assert(PrevFilter != 0 && "empty filter set!"); + FixupList &CurScope = TableInfo.FixupStack.back(); + // Resolve any NumToSkip fixups in the current scope. + resolveTableFixups(Table, CurScope, Table.size()); + CurScope.clear(); + PrevFilter = 0; // Don't re-process the filter's fallthrough. + } else { + Table.push_back(MCD::OPC_FilterValue); + // Encode and emit the value to filter against. + uint8_t Buffer[8]; + unsigned Len = encodeULEB128(filterIterator->first, Buffer); + Table.insert(Table.end(), Buffer, Buffer + Len); + // Reserve space for the NumToSkip entry. We'll backpatch the value + // later. + PrevFilter = Table.size(); + Table.push_back(0); + Table.push_back(0); + } // We arrive at a category of instructions with the same segment value. // Now delegate to the sub filter chooser for further decodings. // The case may fallthrough, which happens if the remaining well-known // encoding bits do not match exactly. - if (!DefaultCase) { ++Indentation; ++Indentation; } - - filterIterator->second->emit(o, Indentation); - // For top level default case, there's no need for a break statement. - if (Owner->isTopLevel() && DefaultCase) - break; - - o.indent(Indentation) << "break;\n"; - - if (!DefaultCase) { --Indentation; --Indentation; } + filterIterator->second->emitTableEntries(TableInfo); + + // Now that we've emitted the body of the handler, update the NumToSkip + // of the filter itself to be able to skip forward when false. Subtract + // two as to account for the width of the NumToSkip field itself. + if (PrevFilter) { + uint32_t NumToSkip = Table.size() - PrevFilter - 2; + assert(NumToSkip < 65536U && "disassembler decoding table too large!"); + Table[PrevFilter] = (uint8_t)NumToSkip; + Table[PrevFilter + 1] = (uint8_t)(NumToSkip >> 8); + } } - // If there is no default case, we still need to supply a closing brace. - if (!DefaultCase) { - // Closing curly brace for the switch statement. - o.indent(Indentation) << "}\n"; - } + // Any remaining unresolved fixups bubble up to the parent fixup scope. + assert(TableInfo.FixupStack.size() > 1 && "fixup stack underflow!"); + FixupScopeList::iterator Source = TableInfo.FixupStack.end() - 1; + FixupScopeList::iterator Dest = Source - 1; + Dest->insert(Dest->end(), Source->begin(), Source->end()); + TableInfo.FixupStack.pop_back(); + + // If there is no fallthrough, then the final filter should get fixed + // up according to the enclosing scope rather than the current position. + if (!HasFallthrough) + TableInfo.FixupStack.back().push_back(PrevFilter); } // Returns the number of fanout produced by the filter. More fanout implies @@ -652,31 +717,205 @@ unsigned Filter::usefulness() const { // // ////////////////////////////////// -// Emit the top level typedef and decodeInstruction() function. -void FilterChooser::emitTop(raw_ostream &o, unsigned Indentation, - const std::string &Namespace) const { - o.indent(Indentation) << - "static MCDisassembler::DecodeStatus decode" << Namespace << "Instruction" - << BitWidth << "(MCInst &MI, uint" << BitWidth - << "_t insn, uint64_t Address, " - << "const void *Decoder, const MCSubtargetInfo &STI) {\n"; - o.indent(Indentation) << " unsigned tmp = 0;\n"; - o.indent(Indentation) << " (void)tmp;\n"; - o.indent(Indentation) << Emitter->Locals << "\n"; - o.indent(Indentation) << " uint64_t Bits = STI.getFeatureBits();\n"; - o.indent(Indentation) << " (void)Bits;\n"; - - ++Indentation; ++Indentation; - // Emits code to decode the instructions. - emit(o, Indentation); - - o << '\n'; - o.indent(Indentation) << "return " << Emitter->ReturnFail << ";\n"; - --Indentation; --Indentation; - - o.indent(Indentation) << "}\n"; - - o << '\n'; +// Emit the decoder state machine table. +void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS, + DecoderTable &Table, + unsigned Indentation, + unsigned BitWidth, + StringRef Namespace) const { + OS.indent(Indentation) << "static const uint8_t DecoderTable" << Namespace + << BitWidth << "[] = {\n"; + + Indentation += 2; + + // FIXME: We may be able to use the NumToSkip values to recover + // appropriate indentation levels. + DecoderTable::const_iterator I = Table.begin(); + DecoderTable::const_iterator E = Table.end(); + while (I != E) { + assert (I < E && "incomplete decode table entry!"); + + uint64_t Pos = I - Table.begin(); + OS << "/* " << Pos << " */"; + OS.PadToColumn(12); + + switch (*I) { + default: + throw "invalid decode table opcode"; + case MCD::OPC_ExtractField: { + ++I; + unsigned Start = *I++; + unsigned Len = *I++; + OS.indent(Indentation) << "MCD::OPC_ExtractField, " << Start << ", " + << Len << ", // Inst{"; + if (Len > 1) + OS << (Start + Len - 1) << "-"; + OS << Start << "} ...\n"; + break; + } + case MCD::OPC_FilterValue: { + ++I; + OS.indent(Indentation) << "MCD::OPC_FilterValue, "; + // The filter value is ULEB128 encoded. + while (*I >= 128) + OS << utostr(*I++) << ", "; + OS << utostr(*I++) << ", "; + + // 16-bit numtoskip value. + uint8_t Byte = *I++; + uint32_t NumToSkip = Byte; + OS << utostr(Byte) << ", "; + Byte = *I++; + OS << utostr(Byte) << ", "; + NumToSkip |= Byte << 8; + OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; + break; + } + case MCD::OPC_CheckField: { + ++I; + unsigned Start = *I++; + unsigned Len = *I++; + OS.indent(Indentation) << "MCD::OPC_CheckField, " << Start << ", " + << Len << ", ";// << Val << ", " << NumToSkip << ",\n"; + // ULEB128 encoded field value. + for (; *I >= 128; ++I) + OS << utostr(*I) << ", "; + OS << utostr(*I++) << ", "; + // 16-bit numtoskip value. + uint8_t Byte = *I++; + uint32_t NumToSkip = Byte; + OS << utostr(Byte) << ", "; + Byte = *I++; + OS << utostr(Byte) << ", "; + NumToSkip |= Byte << 8; + OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; + break; + } + case MCD::OPC_CheckPredicate: { + ++I; + OS.indent(Indentation) << "MCD::OPC_CheckPredicate, "; + for (; *I >= 128; ++I) + OS << utostr(*I) << ", "; + OS << utostr(*I++) << ", "; + + // 16-bit numtoskip value. + uint8_t Byte = *I++; + uint32_t NumToSkip = Byte; + OS << utostr(Byte) << ", "; + Byte = *I++; + OS << utostr(Byte) << ", "; + NumToSkip |= Byte << 8; + OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n"; + break; + } + case MCD::OPC_Decode: { + ++I; + // Extract the ULEB128 encoded Opcode to a buffer. + uint8_t Buffer[8], *p = Buffer; + while ((*p++ = *I++) >= 128) + assert((p - Buffer) <= (ptrdiff_t)sizeof(Buffer) + && "ULEB128 value too large!"); + // Decode the Opcode value. + unsigned Opc = decodeULEB128(Buffer); + OS.indent(Indentation) << "MCD::OPC_Decode, "; + for (p = Buffer; *p >= 128; ++p) + OS << utostr(*p) << ", "; + OS << utostr(*p) << ", "; + + // Decoder index. + for (; *I >= 128; ++I) + OS << utostr(*I) << ", "; + OS << utostr(*I++) << ", "; + + OS << "// Opcode: " + << NumberedInstructions->at(Opc)->TheDef->getName() << "\n"; + break; + } + case MCD::OPC_SoftFail: { + ++I; + OS.indent(Indentation) << "MCD::OPC_SoftFail"; + // Positive mask + uint64_t Value = 0; + unsigned Shift = 0; + do { + OS << ", " << utostr(*I); + Value += (*I & 0x7f) << Shift; + Shift += 7; + } while (*I++ >= 128); + if (Value > 127) + OS << " /* 0x" << utohexstr(Value) << " */"; + // Negative mask + Value = 0; + Shift = 0; + do { + OS << ", " << utostr(*I); + Value += (*I & 0x7f) << Shift; + Shift += 7; + } while (*I++ >= 128); + if (Value > 127) + OS << " /* 0x" << utohexstr(Value) << " */"; + OS << ",\n"; + break; + } + case MCD::OPC_Fail: { + ++I; + OS.indent(Indentation) << "MCD::OPC_Fail,\n"; + break; + } + } + } + OS.indent(Indentation) << "0\n"; + + Indentation -= 2; + + OS.indent(Indentation) << "};\n\n"; +} + +void FixedLenDecoderEmitter:: +emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates, + unsigned Indentation) const { + // The predicate function is just a big switch statement based on the + // input predicate index. + OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, " + << "uint64_t Bits) {\n"; + Indentation += 2; + OS.indent(Indentation) << "switch (Idx) {\n"; + OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n"; + unsigned Index = 0; + for (PredicateSet::const_iterator I = Predicates.begin(), E = Predicates.end(); + I != E; ++I, ++Index) { + OS.indent(Indentation) << "case " << Index << ":\n"; + OS.indent(Indentation+2) << "return (" << *I << ");\n"; + } + OS.indent(Indentation) << "}\n"; + Indentation -= 2; + OS.indent(Indentation) << "}\n\n"; +} + +void FixedLenDecoderEmitter:: +emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders, + unsigned Indentation) const { + // The decoder function is just a big switch statement based on the + // input decoder index. + OS.indent(Indentation) << "template<typename InsnType>\n"; + OS.indent(Indentation) << "static DecodeStatus decodeToMCInst(DecodeStatus S," + << " unsigned Idx, InsnType insn, MCInst &MI,\n"; + OS.indent(Indentation) << " uint64_t " + << "Address, const void *Decoder) {\n"; + Indentation += 2; + OS.indent(Indentation) << "InsnType tmp;\n"; + OS.indent(Indentation) << "switch (Idx) {\n"; + OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n"; + unsigned Index = 0; + for (DecoderSet::const_iterator I = Decoders.begin(), E = Decoders.end(); + I != E; ++I, ++Index) { + OS.indent(Indentation) << "case " << Index << ":\n"; + OS << *I; + OS.indent(Indentation+2) << "return S;\n"; + } + OS.indent(Indentation) << "}\n"; + Indentation -= 2; + OS.indent(Indentation) << "}\n\n"; } // Populates the field of the insn given the start position and the number of @@ -703,9 +942,7 @@ bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn, /// filter array as a series of chars. void FilterChooser::dumpFilterArray(raw_ostream &o, const std::vector<bit_value_t> &filter) const { - unsigned bitIndex; - - for (bitIndex = BitWidth; bitIndex > 0; bitIndex--) { + for (unsigned bitIndex = BitWidth; bitIndex > 0; bitIndex--) { switch (filter[bitIndex - 1]) { case BIT_UNFILTERED: o << "."; @@ -827,26 +1064,71 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, if (OpInfo.numFields() == 1) { OperandInfo::const_iterator OI = OpInfo.begin(); - o.indent(Indentation) << " tmp = fieldFromInstruction" << BitWidth - << "(insn, " << OI->Base << ", " << OI->Width - << ");\n"; + o.indent(Indentation) << "tmp = fieldFromInstruction" + << "(insn, " << OI->Base << ", " << OI->Width + << ");\n"; } else { - o.indent(Indentation) << " tmp = 0;\n"; + o.indent(Indentation) << "tmp = 0;\n"; for (OperandInfo::const_iterator OI = OpInfo.begin(), OE = OpInfo.end(); OI != OE; ++OI) { - o.indent(Indentation) << " tmp |= (fieldFromInstruction" << BitWidth + o.indent(Indentation) << "tmp |= (fieldFromInstruction" << "(insn, " << OI->Base << ", " << OI->Width << ") << " << OI->Offset << ");\n"; } } if (Decoder != "") - o.indent(Indentation) << " " << Emitter->GuardPrefix << Decoder + o.indent(Indentation) << Emitter->GuardPrefix << Decoder << "(MI, tmp, Address, Decoder)" << Emitter->GuardPostfix << "\n"; else - o.indent(Indentation) << " MI.addOperand(MCOperand::CreateImm(tmp));\n"; + o.indent(Indentation) << "MI.addOperand(MCOperand::CreateImm(tmp));\n"; + +} + +void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation, + unsigned Opc) const { + std::map<unsigned, std::vector<OperandInfo> >::const_iterator OpIter = + Operands.find(Opc); + const std::vector<OperandInfo>& InsnOperands = OpIter->second; + for (std::vector<OperandInfo>::const_iterator + I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { + // If a custom instruction decoder was specified, use that. + if (I->numFields() == 0 && I->Decoder.size()) { + OS.indent(Indentation) << Emitter->GuardPrefix << I->Decoder + << "(MI, insn, Address, Decoder)" + << Emitter->GuardPostfix << "\n"; + break; + } + emitBinaryParser(OS, Indentation, *I); + } +} + +unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders, + unsigned Opc) const { + // Build up the predicate string. + SmallString<256> Decoder; + // FIXME: emitDecoder() function can take a buffer directly rather than + // a stream. + raw_svector_ostream S(Decoder); + unsigned I = 4; + emitDecoder(S, I, Opc); + S.flush(); + + // Using the full decoder string as the key value here is a bit + // heavyweight, but is effective. If the string comparisons become a + // performance concern, we can implement a mangling of the predicate + // data easilly enough with a map back to the actual string. That's + // overkill for now, though. + + // Make sure the predicate is in the table. + Decoders.insert(Decoder.str()); + // Now figure out the index for when we write out the table. + DecoderSet::const_iterator P = std::find(Decoders.begin(), + Decoders.end(), + Decoder.str()); + return (unsigned)(P - Decoders.begin()); } static void emitSinglePredicateMatch(raw_ostream &o, StringRef str, @@ -887,8 +1169,74 @@ bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation, return Predicates->getSize() > 0; } -void FilterChooser::emitSoftFailCheck(raw_ostream &o, unsigned Indentation, - unsigned Opc) const { +bool FilterChooser::doesOpcodeNeedPredicate(unsigned Opc) const { + ListInit *Predicates = + AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates"); + for (unsigned i = 0; i < Predicates->getSize(); ++i) { + Record *Pred = Predicates->getElementAsRecord(i); + if (!Pred->getValue("AssemblerMatcherPredicate")) + continue; + + std::string P = Pred->getValueAsString("AssemblerCondString"); + + if (!P.length()) + continue; + + return true; + } + return false; +} + +unsigned FilterChooser::getPredicateIndex(DecoderTableInfo &TableInfo, + StringRef Predicate) const { + // Using the full predicate string as the key value here is a bit + // heavyweight, but is effective. If the string comparisons become a + // performance concern, we can implement a mangling of the predicate + // data easilly enough with a map back to the actual string. That's + // overkill for now, though. + + // Make sure the predicate is in the table. + TableInfo.Predicates.insert(Predicate.str()); + // Now figure out the index for when we write out the table. + PredicateSet::const_iterator P = std::find(TableInfo.Predicates.begin(), + TableInfo.Predicates.end(), + Predicate.str()); + return (unsigned)(P - TableInfo.Predicates.begin()); +} + +void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo, + unsigned Opc) const { + if (!doesOpcodeNeedPredicate(Opc)) + return; + + // Build up the predicate string. + SmallString<256> Predicate; + // FIXME: emitPredicateMatch() functions can take a buffer directly rather + // than a stream. + raw_svector_ostream PS(Predicate); + unsigned I = 0; + emitPredicateMatch(PS, I, Opc); + + // Figure out the index into the predicate table for the predicate just + // computed. + unsigned PIdx = getPredicateIndex(TableInfo, PS.str()); + SmallString<16> PBytes; + raw_svector_ostream S(PBytes); + encodeULEB128(PIdx, S); + S.flush(); + + TableInfo.Table.push_back(MCD::OPC_CheckPredicate); + // Predicate index + for (unsigned i = 0, e = PBytes.size(); i != e; ++i) + TableInfo.Table.push_back(PBytes[i]); + // Push location for NumToSkip backpatching. + TableInfo.FixupStack.back().push_back(TableInfo.Table.size()); + TableInfo.Table.push_back(0); + TableInfo.Table.push_back(0); +} + +void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo, + unsigned Opc) const { BitsInit *SFBits = AllInstructions[Opc]->TheDef->getValueAsBitsInit("SoftFail"); if (!SFBits) return; @@ -914,13 +1262,11 @@ void FilterChooser::emitSoftFailCheck(raw_ostream &o, unsigned Indentation, default: // The bit is not set; this must be an error! StringRef Name = AllInstructions[Opc]->TheDef->getName(); - errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in " - << Name - << " is set but Inst{" << i <<"} is unset!\n" + errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in " << Name + << " is set but Inst{" << i << "} is unset!\n" << " - You can only mark a bit as SoftFail if it is fully defined" << " (1/0 - not '?') in Inst\n"; - o << "#error SoftFail Conflict, " << Name << "::SoftFail{" << i - << "} set but Inst{" << i << "} undefined!\n"; + return; } } @@ -930,27 +1276,31 @@ void FilterChooser::emitSoftFailCheck(raw_ostream &o, unsigned Indentation, if (!NeedPositiveMask && !NeedNegativeMask) return; - std::string PositiveMaskStr = PositiveMask.toString(16, /*signed=*/false); - std::string NegativeMaskStr = NegativeMask.toString(16, /*signed=*/false); - StringRef BitExt = ""; - if (BitWidth > 32) - BitExt = "ULL"; - - o.indent(Indentation) << "if ("; - if (NeedPositiveMask) - o << "insn & 0x" << PositiveMaskStr << BitExt; - if (NeedPositiveMask && NeedNegativeMask) - o << " || "; - if (NeedNegativeMask) - o << "~insn & 0x" << NegativeMaskStr << BitExt; - o << ")\n"; - o.indent(Indentation+2) << "S = MCDisassembler::SoftFail;\n"; + TableInfo.Table.push_back(MCD::OPC_SoftFail); + + SmallString<16> MaskBytes; + raw_svector_ostream S(MaskBytes); + if (NeedPositiveMask) { + encodeULEB128(PositiveMask.getZExtValue(), S); + S.flush(); + for (unsigned i = 0, e = MaskBytes.size(); i != e; ++i) + TableInfo.Table.push_back(MaskBytes[i]); + } else + TableInfo.Table.push_back(0); + if (NeedNegativeMask) { + MaskBytes.clear(); + S.resync(); + encodeULEB128(NegativeMask.getZExtValue(), S); + S.flush(); + for (unsigned i = 0, e = MaskBytes.size(); i != e; ++i) + TableInfo.Table.push_back(MaskBytes[i]); + } else + TableInfo.Table.push_back(0); } -// Emits code to decode the singleton. Return true if we have matched all the -// well-known bits. -bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, - unsigned Opc) const { +// Emits table entries to decode the singleton. +void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, + unsigned Opc) const { std::vector<unsigned> StartBits; std::vector<unsigned> EndBits; std::vector<uint64_t> FieldVals; @@ -961,107 +1311,70 @@ bool FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, getIslands(StartBits, EndBits, FieldVals, Insn); unsigned Size = StartBits.size(); - unsigned I, NumBits; - // If we have matched all the well-known bits, just issue a return. - if (Size == 0) { - o.indent(Indentation) << "if ("; - if (!emitPredicateMatch(o, Indentation, Opc)) - o << "1"; - o << ") {\n"; - emitSoftFailCheck(o, Indentation+2, Opc); - o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n"; - std::map<unsigned, std::vector<OperandInfo> >::const_iterator OpIter = - Operands.find(Opc); - const std::vector<OperandInfo>& InsnOperands = OpIter->second; - for (std::vector<OperandInfo>::const_iterator - I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { - // If a custom instruction decoder was specified, use that. - if (I->numFields() == 0 && I->Decoder.size()) { - o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder - << "(MI, insn, Address, Decoder)" - << Emitter->GuardPostfix << "\n"; - break; - } - - emitBinaryParser(o, Indentation, *I); - } - - o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " - << nameWithID(Opc) << '\n'; - o.indent(Indentation) << "}\n"; // Closing predicate block. - return true; - } - - // Otherwise, there are more decodings to be done! - - // Emit code to match the island(s) for the singleton. - o.indent(Indentation) << "// Check "; - - for (I = Size; I != 0; --I) { - o << "Inst{" << EndBits[I-1] << '-' << StartBits[I-1] << "} "; - if (I > 1) - o << " && "; - else - o << "for singleton decoding...\n"; - } - - o.indent(Indentation) << "if ("; - if (emitPredicateMatch(o, Indentation, Opc)) { - o << " &&\n"; - o.indent(Indentation+4); + // Emit the predicate table entry if one is needed. + emitPredicateTableEntry(TableInfo, Opc); + + // Check any additional encoding fields needed. + for (unsigned I = Size; I != 0; --I) { + unsigned NumBits = EndBits[I-1] - StartBits[I-1] + 1; + TableInfo.Table.push_back(MCD::OPC_CheckField); + TableInfo.Table.push_back(StartBits[I-1]); + TableInfo.Table.push_back(NumBits); + uint8_t Buffer[8], *p; + encodeULEB128(FieldVals[I-1], Buffer); + for (p = Buffer; *p >= 128 ; ++p) + TableInfo.Table.push_back(*p); + TableInfo.Table.push_back(*p); + // Push location for NumToSkip backpatching. + TableInfo.FixupStack.back().push_back(TableInfo.Table.size()); + // The fixup is always 16-bits, so go ahead and allocate the space + // in the table so all our relative position calculations work OK even + // before we fully resolve the real value here. + TableInfo.Table.push_back(0); + TableInfo.Table.push_back(0); } - for (I = Size; I != 0; --I) { - NumBits = EndBits[I-1] - StartBits[I-1] + 1; - o << "fieldFromInstruction" << BitWidth << "(insn, " - << StartBits[I-1] << ", " << NumBits - << ") == " << FieldVals[I-1]; - if (I > 1) - o << " && "; - else - o << ") {\n"; - } - emitSoftFailCheck(o, Indentation+2, Opc); - o.indent(Indentation) << " MI.setOpcode(" << Opc << ");\n"; - std::map<unsigned, std::vector<OperandInfo> >::const_iterator OpIter = - Operands.find(Opc); - const std::vector<OperandInfo>& InsnOperands = OpIter->second; - for (std::vector<OperandInfo>::const_iterator - I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { - // If a custom instruction decoder was specified, use that. - if (I->numFields() == 0 && I->Decoder.size()) { - o.indent(Indentation) << " " << Emitter->GuardPrefix << I->Decoder - << "(MI, insn, Address, Decoder)" - << Emitter->GuardPostfix << "\n"; - break; - } - - emitBinaryParser(o, Indentation, *I); - } - o.indent(Indentation) << " return " << Emitter->ReturnOK << "; // " - << nameWithID(Opc) << '\n'; - o.indent(Indentation) << "}\n"; - - return false; + // Check for soft failure of the match. + emitSoftFailTableEntry(TableInfo, Opc); + + TableInfo.Table.push_back(MCD::OPC_Decode); + uint8_t Buffer[8], *p; + encodeULEB128(Opc, Buffer); + for (p = Buffer; *p >= 128 ; ++p) + TableInfo.Table.push_back(*p); + TableInfo.Table.push_back(*p); + + unsigned DIdx = getDecoderIndex(TableInfo.Decoders, Opc); + SmallString<16> Bytes; + raw_svector_ostream S(Bytes); + encodeULEB128(DIdx, S); + S.flush(); + + // Decoder index + for (unsigned i = 0, e = Bytes.size(); i != e; ++i) + TableInfo.Table.push_back(Bytes[i]); } -// Emits code to decode the singleton, and then to decode the rest. -void FilterChooser::emitSingletonDecoder(raw_ostream &o, unsigned &Indentation, - const Filter &Best) const { - +// Emits table entries to decode the singleton, and then to decode the rest. +void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, + const Filter &Best) const { unsigned Opc = Best.getSingletonOpc(); - emitSingletonDecoder(o, Indentation, Opc); + // complex singletons need predicate checks from the first singleton + // to refer forward to the variable filterchooser that follows. + TableInfo.FixupStack.push_back(FixupList()); - // Emit code for the rest. - o.indent(Indentation) << "else\n"; + emitSingletonTableEntry(TableInfo, Opc); - Indentation += 2; - Best.getVariableFC().emit(o, Indentation); - Indentation -= 2; + resolveTableFixups(TableInfo.Table, TableInfo.FixupStack.back(), + TableInfo.Table.size()); + TableInfo.FixupStack.pop_back(); + + Best.getVariableFC().emitTableEntries(TableInfo); } + // Assign a single filter and run with it. Top level API client can initialize // with a single filter to start the filtering process. void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit, @@ -1119,7 +1432,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { } } - unsigned BitIndex, InsnIndex; + unsigned BitIndex; // We maintain BIT_WIDTH copies of the bitAttrs automaton. // The automaton consumes the corresponding bit from each @@ -1149,7 +1462,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { else bitAttrs.push_back(ATTR_NONE); - for (InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) { + for (unsigned InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) { insn_t insn; insnWithID(insn, Opcodes[InsnIndex]); @@ -1200,7 +1513,7 @@ bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) { bitAttr_t RA = ATTR_NONE; unsigned StartBit = 0; - for (BitIndex = 0; BitIndex < BitWidth; BitIndex++) { + for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) { bitAttr_t bitAttr = bitAttrs[BitIndex]; assert(bitAttr != ATTR_NONE && "Bit without attributes"); @@ -1341,36 +1654,29 @@ void FilterChooser::doFilter() { BestIndex = -1; } -// Emits code to decode our share of instructions. Returns true if the -// emitted code causes a return, which occurs if we know how to decode -// the instruction at this level or the instruction is not decodeable. -bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) const { - if (Opcodes.size() == 1) +// emitTableEntries - Emit state machine entries to decode our share of +// instructions. +void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const { + if (Opcodes.size() == 1) { // There is only one instruction in the set, which is great! // Call emitSingletonDecoder() to see whether there are any remaining // encodings bits. - return emitSingletonDecoder(o, Indentation, Opcodes[0]); + emitSingletonTableEntry(TableInfo, Opcodes[0]); + return; + } // Choose the best filter to do the decodings! if (BestIndex != -1) { const Filter &Best = Filters[BestIndex]; if (Best.getNumFiltered() == 1) - emitSingletonDecoder(o, Indentation, Best); + emitSingletonTableEntry(TableInfo, Best); else - Best.emit(o, Indentation); - return false; + Best.emitTableEntry(TableInfo); + return; } - // We don't know how to decode these instructions! Return 0 and dump the - // conflict set! - o.indent(Indentation) << "return 0;" << " // Conflict set: "; - for (int i = 0, N = Opcodes.size(); i < N; ++i) { - o << nameWithID(Opcodes[i]); - if (i < (N - 1)) - o << ", "; - else - o << '\n'; - } + // We don't know how to decode these instructions! Dump the + // conflict set and bail. // Print out useful conflict information for postmortem analysis. errs() << "Decoding Conflict:\n"; @@ -1385,8 +1691,6 @@ bool FilterChooser::emit(raw_ostream &o, unsigned &Indentation) const { getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst")); errs() << '\n'; } - - return true; } static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc, @@ -1549,62 +1853,168 @@ static bool populateInstruction(const CodeGenInstruction &CGI, unsigned Opc, return true; } -static void emitHelper(llvm::raw_ostream &o, unsigned BitWidth) { - unsigned Indentation = 0; - std::string WidthStr = "uint" + utostr(BitWidth) + "_t"; - - o << '\n'; - - o.indent(Indentation) << "static " << WidthStr << - " fieldFromInstruction" << BitWidth << - "(" << WidthStr <<" insn, unsigned startBit, unsigned numBits)\n"; - - o.indent(Indentation) << "{\n"; - - ++Indentation; ++Indentation; - o.indent(Indentation) << "assert(startBit + numBits <= " << BitWidth - << " && \"Instruction field out of bounds!\");\n"; - o << '\n'; - o.indent(Indentation) << WidthStr << " fieldMask;\n"; - o << '\n'; - o.indent(Indentation) << "if (numBits == " << BitWidth << ")\n"; - - ++Indentation; ++Indentation; - o.indent(Indentation) << "fieldMask = (" << WidthStr << ")-1;\n"; - --Indentation; --Indentation; - - o.indent(Indentation) << "else\n"; - - ++Indentation; ++Indentation; - o.indent(Indentation) << "fieldMask = ((1 << numBits) - 1) << startBit;\n"; - --Indentation; --Indentation; - - o << '\n'; - o.indent(Indentation) << "return (insn & fieldMask) >> startBit;\n"; - --Indentation; --Indentation; - - o.indent(Indentation) << "}\n"; +// emitFieldFromInstruction - Emit the templated helper function +// fieldFromInstruction(). +static void emitFieldFromInstruction(formatted_raw_ostream &OS) { + OS << "// Helper function for extracting fields from encoded instructions.\n" + << "template<typename InsnType>\n" + << "static InsnType fieldFromInstruction(InsnType insn, unsigned startBit,\n" + << " unsigned numBits) {\n" + << " assert(startBit + numBits <= (sizeof(InsnType)*8) &&\n" + << " \"Instruction field out of bounds!\");\n" + << " InsnType fieldMask;\n" + << " if (numBits == sizeof(InsnType)*8)\n" + << " fieldMask = (InsnType)(-1LL);\n" + << " else\n" + << " fieldMask = ((1 << numBits) - 1) << startBit;\n" + << " return (insn & fieldMask) >> startBit;\n" + << "}\n\n"; +} - o << '\n'; +// emitDecodeInstruction - Emit the templated helper function +// decodeInstruction(). +static void emitDecodeInstruction(formatted_raw_ostream &OS) { + OS << "template<typename InsnType>\n" + << "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,\n" + << " InsnType insn, uint64_t Address,\n" + << " const void *DisAsm,\n" + << " const MCSubtargetInfo &STI) {\n" + << " uint64_t Bits = STI.getFeatureBits();\n" + << "\n" + << " const uint8_t *Ptr = DecodeTable;\n" + << " uint32_t CurFieldValue;\n" + << " DecodeStatus S = MCDisassembler::Success;\n" + << " for (;;) {\n" + << " ptrdiff_t Loc = Ptr - DecodeTable;\n" + << " switch (*Ptr) {\n" + << " default:\n" + << " errs() << Loc << \": Unexpected decode table opcode!\\n\";\n" + << " return MCDisassembler::Fail;\n" + << " case MCD::OPC_ExtractField: {\n" + << " unsigned Start = *++Ptr;\n" + << " unsigned Len = *++Ptr;\n" + << " ++Ptr;\n" + << " CurFieldValue = fieldFromInstruction(insn, Start, Len);\n" + << " DEBUG(dbgs() << Loc << \": OPC_ExtractField(\" << Start << \", \"\n" + << " << Len << \"): \" << CurFieldValue << \"\\n\");\n" + << " break;\n" + << " }\n" + << " case MCD::OPC_FilterValue: {\n" + << " // Decode the field value.\n" + << " unsigned Len;\n" + << " InsnType Val = decodeULEB128(++Ptr, &Len);\n" + << " Ptr += Len;\n" + << " // NumToSkip is a plain 16-bit integer.\n" + << " unsigned NumToSkip = *Ptr++;\n" + << " NumToSkip |= (*Ptr++) << 8;\n" + << "\n" + << " // Perform the filter operation.\n" + << " if (Val != CurFieldValue)\n" + << " Ptr += NumToSkip;\n" + << " DEBUG(dbgs() << Loc << \": OPC_FilterValue(\" << Val << \", \" << NumToSkip\n" + << " << \"): \" << ((Val != CurFieldValue) ? \"FAIL:\" : \"PASS:\")\n" + << " << \" continuing at \" << (Ptr - DecodeTable) << \"\\n\");\n" + << "\n" + << " break;\n" + << " }\n" + << " case MCD::OPC_CheckField: {\n" + << " unsigned Start = *++Ptr;\n" + << " unsigned Len = *++Ptr;\n" + << " InsnType FieldValue = fieldFromInstruction(insn, Start, Len);\n" + << " // Decode the field value.\n" + << " uint32_t ExpectedValue = decodeULEB128(++Ptr, &Len);\n" + << " Ptr += Len;\n" + << " // NumToSkip is a plain 16-bit integer.\n" + << " unsigned NumToSkip = *Ptr++;\n" + << " NumToSkip |= (*Ptr++) << 8;\n" + << "\n" + << " // If the actual and expected values don't match, skip.\n" + << " if (ExpectedValue != FieldValue)\n" + << " Ptr += NumToSkip;\n" + << " DEBUG(dbgs() << Loc << \": OPC_CheckField(\" << Start << \", \"\n" + << " << Len << \", \" << ExpectedValue << \", \" << NumToSkip\n" + << " << \"): FieldValue = \" << FieldValue << \", ExpectedValue = \"\n" + << " << ExpectedValue << \": \"\n" + << " << ((ExpectedValue == FieldValue) ? \"PASS\\n\" : \"FAIL\\n\"));\n" + << " break;\n" + << " }\n" + << " case MCD::OPC_CheckPredicate: {\n" + << " unsigned Len;\n" + << " // Decode the Predicate Index value.\n" + << " unsigned PIdx = decodeULEB128(++Ptr, &Len);\n" + << " Ptr += Len;\n" + << " // NumToSkip is a plain 16-bit integer.\n" + << " unsigned NumToSkip = *Ptr++;\n" + << " NumToSkip |= (*Ptr++) << 8;\n" + << " // Check the predicate.\n" + << " bool Pred;\n" + << " if (!(Pred = checkDecoderPredicate(PIdx, Bits)))\n" + << " Ptr += NumToSkip;\n" + << " (void)Pred;\n" + << " DEBUG(dbgs() << Loc << \": OPC_CheckPredicate(\" << PIdx << \"): \"\n" + << " << (Pred ? \"PASS\\n\" : \"FAIL\\n\"));\n" + << "\n" + << " break;\n" + << " }\n" + << " case MCD::OPC_Decode: {\n" + << " unsigned Len;\n" + << " // Decode the Opcode value.\n" + << " unsigned Opc = decodeULEB128(++Ptr, &Len);\n" + << " Ptr += Len;\n" + << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n" + << " Ptr += Len;\n" + << " DEBUG(dbgs() << Loc << \": OPC_Decode: opcode \" << Opc\n" + << " << \", using decoder \" << DecodeIdx << \"\\n\" );\n" + << " DEBUG(dbgs() << \"----- DECODE SUCCESSFUL -----\\n\");\n" + << "\n" + << " MI.setOpcode(Opc);\n" + << " return decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm);\n" + << " }\n" + << " case MCD::OPC_SoftFail: {\n" + << " // Decode the mask values.\n" + << " unsigned Len;\n" + << " InsnType PositiveMask = decodeULEB128(++Ptr, &Len);\n" + << " Ptr += Len;\n" + << " InsnType NegativeMask = decodeULEB128(Ptr, &Len);\n" + << " Ptr += Len;\n" + << " bool Fail = (insn & PositiveMask) || (~insn & NegativeMask);\n" + << " if (Fail)\n" + << " S = MCDisassembler::SoftFail;\n" + << " DEBUG(dbgs() << Loc << \": OPC_SoftFail: \" << (Fail ? \"FAIL\\n\":\"PASS\\n\"));\n" + << " break;\n" + << " }\n" + << " case MCD::OPC_Fail: {\n" + << " DEBUG(dbgs() << Loc << \": OPC_Fail\\n\");\n" + << " return MCDisassembler::Fail;\n" + << " }\n" + << " }\n" + << " }\n" + << " llvm_unreachable(\"bogosity detected in disassembler state machine!\");\n" + << "}\n\n"; } // Emits disassembler code for instruction decoding. void FixedLenDecoderEmitter::run(raw_ostream &o) { - o << "#include \"llvm/MC/MCInst.h\"\n"; - o << "#include \"llvm/Support/DataTypes.h\"\n"; - o << "#include <assert.h>\n"; - o << '\n'; - o << "namespace llvm {\n\n"; + formatted_raw_ostream OS(o); + OS << "#include \"llvm/MC/MCInst.h\"\n"; + OS << "#include \"llvm/Support/Debug.h\"\n"; + OS << "#include \"llvm/Support/DataTypes.h\"\n"; + OS << "#include \"llvm/Support/LEB128.h\"\n"; + OS << "#include \"llvm/Support/raw_ostream.h\"\n"; + OS << "#include <assert.h>\n"; + OS << '\n'; + OS << "namespace llvm {\n\n"; + + emitFieldFromInstruction(OS); // Parameterize the decoders based on namespace and instruction width. - const std::vector<const CodeGenInstruction*> &NumberedInstructions = - Target.getInstructionsByEnumValue(); + NumberedInstructions = &Target.getInstructionsByEnumValue(); std::map<std::pair<std::string, unsigned>, std::vector<unsigned> > OpcMap; std::map<unsigned, std::vector<OperandInfo> > Operands; - for (unsigned i = 0; i < NumberedInstructions.size(); ++i) { - const CodeGenInstruction *Inst = NumberedInstructions[i]; + for (unsigned i = 0; i < NumberedInstructions->size(); ++i) { + const CodeGenInstruction *Inst = NumberedInstructions->at(i); const Record *Def = Inst->TheDef; unsigned Size = Def->getValueAsInt("Size"); if (Def->getValueAsString("Namespace") == "TargetOpcode" || @@ -1622,24 +2032,48 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { } } + DecoderTableInfo TableInfo; std::set<unsigned> Sizes; for (std::map<std::pair<std::string, unsigned>, std::vector<unsigned> >::const_iterator I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) { - // If we haven't visited this instruction width before, emit the - // helper method to extract fields. - if (!Sizes.count(I->first.second)) { - emitHelper(o, 8*I->first.second); - Sizes.insert(I->first.second); - } - // Emit the decoder for this namespace+width combination. - FilterChooser FC(NumberedInstructions, I->second, Operands, + FilterChooser FC(*NumberedInstructions, I->second, Operands, 8*I->first.second, this); - FC.emitTop(o, 0, I->first.first); + + // The decode table is cleared for each top level decoder function. The + // predicates and decoders themselves, however, are shared across all + // decoders to give more opportunities for uniqueing. + TableInfo.Table.clear(); + TableInfo.FixupStack.clear(); + TableInfo.Table.reserve(16384); + TableInfo.FixupStack.push_back(FixupList()); + FC.emitTableEntries(TableInfo); + // Any NumToSkip fixups in the top level scope can resolve to the + // OPC_Fail at the end of the table. + assert(TableInfo.FixupStack.size() == 1 && "fixup stack phasing error!"); + // Resolve any NumToSkip fixups in the current scope. + resolveTableFixups(TableInfo.Table, TableInfo.FixupStack.back(), + TableInfo.Table.size()); + TableInfo.FixupStack.clear(); + + TableInfo.Table.push_back(MCD::OPC_Fail); + + // Print the table to the output stream. + emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), I->first.first); + OS.flush(); } - o << "\n} // End llvm namespace \n"; + // Emit the predicate function. + emitPredicateFunction(OS, TableInfo.Predicates, 0); + + // Emit the decoder function. + emitDecoderFunction(OS, TableInfo.Decoders, 0); + + // Emit the main entry point for the decoder, decodeInstruction(). + emitDecodeInstruction(OS); + + OS << "\n} // End llvm namespace\n"; } namespace llvm { diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 3adb8694d9ab..b41ad94aca39 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -319,6 +319,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num, if (Inst.isCompare) OS << "|(1<<MCID::Compare)"; if (Inst.isMoveImm) OS << "|(1<<MCID::MoveImm)"; if (Inst.isBitcast) OS << "|(1<<MCID::Bitcast)"; + if (Inst.isSelect) OS << "|(1<<MCID::Select)"; if (Inst.isBarrier) OS << "|(1<<MCID::Barrier)"; if (Inst.hasDelaySlot) OS << "|(1<<MCID::DelaySlot)"; if (Inst.isCall) OS << "|(1<<MCID::Call)"; diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index b9138780aa8d..02546dfca715 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -145,9 +145,9 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; OS << "enum {\n NoSubRegister,\n"; - for (unsigned i = 0, e = Bank.getNumNamedIndices(); i != e; ++i) + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; - OS << " NUM_TARGET_NAMED_SUBREGS\n};\n"; + OS << " NUM_TARGET_SUBREGS\n};\n"; if (!Namespace.empty()) OS << "}\n"; } @@ -885,17 +885,6 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "\" };\n\n"; - // Emit names of the anonymous subreg indices. - unsigned NamedIndices = RegBank.getNumNamedIndices(); - if (SubRegIndices.size() > NamedIndices) { - OS << " enum {"; - for (unsigned i = NamedIndices, e = SubRegIndices.size(); i != e; ++i) { - OS << "\n " << SubRegIndices[i]->getName() << " = " << i+1; - if (i+1 != e) - OS << ','; - } - OS << "\n };\n\n"; - } OS << "\n"; // Now that all of the structs have been emitted, emit the instances. diff --git a/utils/lit/lit/main.py b/utils/lit/lit/main.py index 039868da7860..25bbcbd9f275 100755 --- a/utils/lit/lit/main.py +++ b/utils/lit/lit/main.py @@ -566,6 +566,9 @@ def main(builtinParameters = {}): # Bump the GIL check interval, its more imp if opts.maxTests is not None: tests = tests[:opts.maxTests] + # Don't create more threads than tests. + opts.numThreads = min(len(tests), opts.numThreads) + extra = '' if len(tests) != numTotalTests: extra = ' of %d' % numTotalTests @@ -589,9 +592,6 @@ def main(builtinParameters = {}): # Bump the GIL check interval, its more imp else: print header - # Don't create more threads than tests. - opts.numThreads = min(len(tests), opts.numThreads) - startTime = time.time() display = TestingProgressDisplay(opts, len(tests), progressBar) provider = TestProvider(tests, opts.maxTime) |