Update LLVM to r108428.

This commit is contained in:
Roman Divacky 2010-07-15 17:06:11 +00:00
parent 66e41e3c6e
commit f3d15b0b37
127 changed files with 2487 additions and 877 deletions

View file

@ -42,7 +42,7 @@ VPATH=$(PROJ_SRC_DIR)
# Reset the list of suffixes we know how to build.
#--------------------------------------------------------------------
.SUFFIXES:
.SUFFIXES: .c .cpp .cc .h .hpp .o .a .bc .td .ps .dot .ll
.SUFFIXES: .c .cpp .cc .h .hpp .o .a .bc .td .ps .dot .ll .m .mm
.SUFFIXES: $(SHLIBEXT) $(SUFFIXES)
#--------------------------------------------------------------------
@ -632,7 +632,12 @@ ifdef TOOLNAME
endif
endif
endif
else
ifneq ($(DARWIN_MAJVERS),4)
LD.Flags += $(RPATH) -Wl,@executable_path/../lib
endif
endif
#----------------------------------------------------------
# Options To Invoke Tools
@ -1442,6 +1447,11 @@ $(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_SRC_DIR)/Makefile
$(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \
$(DEPEND_MOVEFILE)
$(ObjDir)/%.o: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_SRC_DIR)/Makefile
$(Echo) "Compiling $*.mm for $(BuildMode) build" $(PIC_FLAG)
$(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \
$(DEPEND_MOVEFILE)
$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_SRC_DIR)/Makefile
$(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG)
$(Verb) if $(Compile.CXX) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \
@ -1452,6 +1462,11 @@ $(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_SRC_DIR)/Makefile
$(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \
$(DEPEND_MOVEFILE)
$(ObjDir)/%.o: %.m $(ObjDir)/.dir $(BUILT_SOURCES) $(PROJ_SRC_DIR)/Makefile
$(Echo) "Compiling $*.m for $(BuildMode) build" $(PIC_FLAG)
$(Verb) if $(Compile.C) $(DEPEND_OPTIONS) $< -o $(ObjDir)/$*.o ; \
$(DEPEND_MOVEFILE)
#---------------------------------------------------------
# Create .bc files in the ObjDir directory from .cpp .cc and .c files...
#---------------------------------------------------------
@ -1470,6 +1485,12 @@ $(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX)
$< -o $(ObjDir)/$*.ll -S -emit-llvm ; \
$(BC_DEPEND_MOVEFILE)
$(ObjDir)/%.ll: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX)
$(Echo) "Compiling $*.mm for $(BuildMode) build (bytecode)"
$(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \
$< -o $(ObjDir)/$*.ll -S -emit-llvm ; \
$(BC_DEPEND_MOVEFILE)
$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX)
$(Echo) "Compiling $*.cc for $(BuildMode) build (bytecode)"
$(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \
@ -1482,6 +1503,12 @@ $(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC)
$< -o $(ObjDir)/$*.ll -S -emit-llvm ; \
$(BC_DEPEND_MOVEFILE)
$(ObjDir)/%.ll: %.m $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC)
$(Echo) "Compiling $*.m for $(BuildMode) build (bytecode)"
$(Verb) if $(BCCompile.C) $(BC_DEPEND_OPTIONS) \
$< -o $(ObjDir)/$*.ll -S -emit-llvm ; \
$(BC_DEPEND_MOVEFILE)
# Provide alternate rule sets if dependencies are disabled
else
@ -1489,6 +1516,10 @@ $(ObjDir)/%.o: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.cpp for $(BuildMode) build" $(PIC_FLAG)
$(Compile.CXX) $< -o $@
$(ObjDir)/%.o: %.mm $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.mm for $(BuildMode) build" $(PIC_FLAG)
$(Compile.CXX) $< -o $@
$(ObjDir)/%.o: %.cc $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.cc for $(BuildMode) build" $(PIC_FLAG)
$(Compile.CXX) $< -o $@
@ -1497,10 +1528,18 @@ $(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG)
$(Compile.C) $< -o $@
$(ObjDir)/%.o: %.m $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.m for $(BuildMode) build" $(PIC_FLAG)
$(Compile.C) $< -o $@
$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX)
$(Echo) "Compiling $*.cpp for $(BuildMode) build (bytecode)"
$(BCCompile.CXX) $< -o $@ -S -emit-llvm
$(ObjDir)/%.ll: %.mm $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX)
$(Echo) "Compiling $*.mm for $(BuildMode) build (bytecode)"
$(BCCompile.CXX) $< -o $@ -S -emit-llvm
$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX)
$(Echo) "Compiling $*.cc for $(BuildMode) build (bytecode)"
$(BCCompile.CXX) $< -o $@ -S -emit-llvm
@ -1509,6 +1548,10 @@ $(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC)
$(Echo) "Compiling $*.c for $(BuildMode) build (bytecode)"
$(BCCompile.C) $< -o $@ -S -emit-llvm
$(ObjDir)/%.ll: %.m $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC)
$(Echo) "Compiling $*.m for $(BuildMode) build (bytecode)"
$(BCCompile.C) $< -o $@ -S -emit-llvm
endif
@ -1517,6 +1560,10 @@ $(BuildMode)/%.ii: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.cpp for $(BuildMode) build to .ii file"
$(Verb) $(Preprocess.CXX) $< -o $@
$(BuildMode)/%.ii: %.mm $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.mm for $(BuildMode) build to .ii file"
$(Verb) $(Preprocess.CXX) $< -o $@
$(BuildMode)/%.ii: %.cc $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.cc for $(BuildMode) build to .ii file"
$(Verb) $(Preprocess.CXX) $< -o $@
@ -1525,11 +1572,19 @@ $(BuildMode)/%.i: %.c $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.c for $(BuildMode) build to .i file"
$(Verb) $(Preprocess.C) $< -o $@
$(BuildMode)/%.i: %.m $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.m for $(BuildMode) build to .i file"
$(Verb) $(Preprocess.C) $< -o $@
$(ObjDir)/%.s: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.cpp to asm for $(BuildMode) build" $(PIC_FLAG)
$(Compile.CXX) $< -o $@ -S
$(ObjDir)/%.s: %.mm $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.mm to asm for $(BuildMode) build" $(PIC_FLAG)
$(Compile.CXX) $< -o $@ -S
$(ObjDir)/%.s: %.cc $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.cc to asm for $(BuildMode) build" $(PIC_FLAG)
$(Compile.CXX) $< -o $@ -S
@ -1538,6 +1593,10 @@ $(ObjDir)/%.s: %.c $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.c to asm for $(BuildMode) build" $(PIC_FLAG)
$(Compile.C) $< -o $@ -S
$(ObjDir)/%.s: %.m $(ObjDir)/.dir $(BUILT_SOURCES)
$(Echo) "Compiling $*.m to asm for $(BuildMode) build" $(PIC_FLAG)
$(Compile.C) $< -o $@ -S
# make the C and C++ compilers strip debug info out of bytecode libraries.
ifdef DEBUG_RUNTIME
@ -1750,7 +1809,7 @@ ifndef DISABLE_AUTO_DEPENDENCIES
ifndef IS_CLEANING_TARGET
# Get the list of dependency files
DependSourceFiles := $(basename $(filter %.cpp %.c %.cc, $(Sources)))
DependSourceFiles := $(basename $(filter %.cpp %.c %.cc %.m %.mm, $(Sources)))
DependFiles := $(DependSourceFiles:%=$(PROJ_OBJ_DIR)/$(BuildMode)/%.d)
# Include bitcode dependency files if using bitcode libraries

View file

@ -954,7 +954,9 @@ define [<a href="#linkage">linkage</a>] [<a href="#visibility">visibility</a>]
<h5>Syntax:</h5>
<pre class="doc_code">
; An unnamed metadata node, which is referenced by the named metadata.
!1 = metadata !{metadata !"one"}
; A named metadata.
!name = !{null, !1}
</pre>
@ -7744,7 +7746,7 @@ LLVM</a>.</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
Last modified: $Date: 2010-07-13 14:26:09 +0200 (Tue, 13 Jul 2010) $
Last modified: $Date: 2010-07-13 21:48:13 +0200 (Tue, 13 Jul 2010) $
</address>
</body>

View file

@ -457,8 +457,8 @@ StringMap class which is used extensively in LLVM and Clang.</p>
may have embedded null characters. Therefore, they cannot simply take
a <tt>const char *</tt>, and taking a <tt>const std::string&amp;</tt> requires
clients to perform a heap allocation which is usually unnecessary. Instead,
many LLVM APIs use a <tt>const StringRef&amp;</tt> or a <tt>const
Twine&amp;</tt> for passing strings efficiently.</p>
many LLVM APIs use a <tt>StringRef</tt> or a <tt>const Twine&amp;</tt> for
passing strings efficiently.</p>
</div>
@ -477,19 +477,17 @@ on <tt>std:string</tt>, but does not require heap allocation.</p>
an <tt>std::string</tt>, or explicitly with a character pointer and length.
For example, the <tt>StringRef</tt> find function is declared as:</p>
<div class="doc_code">
iterator find(const StringRef &amp;Key);
</div>
<pre class="doc_code">
iterator find(StringRef Key);
</pre>
<p>and clients can call it using any one of:</p>
<div class="doc_code">
<pre>
<pre class="doc_code">
Map.find("foo"); <i>// Lookup "foo"</i>
Map.find(std::string("bar")); <i>// Lookup "bar"</i>
Map.find(StringRef("\0baz", 4)); <i>// Lookup "\0baz"</i>
</pre>
</div>
<p>Similarly, APIs which need to return a string may return a <tt>StringRef</tt>
instance, which can be used directly or converted to an <tt>std::string</tt>
@ -499,7 +497,8 @@ for more information.</p>
<p>You should rarely use the <tt>StringRef</tt> class directly, because it contains
pointers to external memory it is not generally safe to store an instance of the
class (unless you know that the external storage will not be freed).</p>
class (unless you know that the external storage will not be freed). StringRef is
small and pervasive enough in LLVM that it should always be passed by value.</p>
</div>
@ -3943,7 +3942,7 @@ arguments. An argument has a pointer to the parent Function.</p>
<a href="mailto:dhurjati@cs.uiuc.edu">Dinakar Dhurjati</a> and
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
Last modified: $Date: 2010-07-15 00:38:02 +0200 (Thu, 15 Jul 2010) $
</address>
</body>

View file

@ -1058,7 +1058,7 @@ int main(int argc, char *argv[]) {
i32 524329, ;; Tag
metadata !"MySource.cpp",
metadata !"/Users/mine/sources",
metadata !3 ;; Compile unit
metadata !2 ;; Compile unit
}
;;
@ -1068,7 +1068,7 @@ int main(int argc, char *argv[]) {
i32 524329, ;; Tag
metadata !"Myheader.h"
metadata !"/Users/mine/sources",
metadata !3 ;; Compile unit
metadata !2 ;; Compile unit
}
...
@ -1780,7 +1780,7 @@ enum Trees {
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
Last modified: $Date: 2010-06-05 00:49:55 +0200 (Sat, 05 Jun 2010) $
Last modified: $Date: 2010-07-13 18:53:20 +0200 (Tue, 13 Jul 2010) $
</address>
</body>

View file

@ -179,7 +179,7 @@ namespace llvm {
// Constructors.
APFloat(const fltSemantics &); // Default construct to 0.0
APFloat(const fltSemantics &, const StringRef &);
APFloat(const fltSemantics &, StringRef);
APFloat(const fltSemantics &, integerPart);
APFloat(const fltSemantics &, fltCategory, bool negative);
APFloat(const fltSemantics &, uninitializedTag);
@ -282,7 +282,7 @@ namespace llvm {
bool, roundingMode);
opStatus convertFromZeroExtendedInteger(const integerPart *, unsigned int,
bool, roundingMode);
opStatus convertFromString(const StringRef&, roundingMode);
opStatus convertFromString(StringRef, roundingMode);
APInt bitcastToAPInt() const;
double convertToDouble() const;
float convertToFloat() const;
@ -386,8 +386,8 @@ namespace llvm {
roundingMode, bool *) const;
opStatus convertFromUnsignedParts(const integerPart *, unsigned int,
roundingMode);
opStatus convertFromHexadecimalString(const StringRef&, roundingMode);
opStatus convertFromDecimalString (const StringRef&, roundingMode);
opStatus convertFromHexadecimalString(StringRef, roundingMode);
opStatus convertFromDecimalString(StringRef, roundingMode);
char *convertNormalToHexString(char *, unsigned int, bool,
roundingMode) const;
opStatus roundSignificandWithExponent(const integerPart *, unsigned int,

View file

@ -162,7 +162,7 @@ class APInt {
///
/// @param radix 2, 8, 10, or 16
/// @brief Convert a char array into an APInt
void fromString(unsigned numBits, const StringRef &str, uint8_t radix);
void fromString(unsigned numBits, StringRef str, uint8_t radix);
/// This is used by the toString method to divide by the radix. It simply
/// provides a more convenient form of divide for internal use since KnuthDiv
@ -248,7 +248,7 @@ public:
/// @param str the string to be interpreted
/// @param radix the radix to use for the conversion
/// @brief Construct an APInt from a string representation.
APInt(unsigned numBits, const StringRef &str, uint8_t radix);
APInt(unsigned numBits, StringRef str, uint8_t radix);
/// Simply makes *this a copy of that.
/// @brief Copy Constructor.
@ -1153,7 +1153,7 @@ public:
/// This method determines how many bits are required to hold the APInt
/// equivalent of the string given by \arg str.
/// @brief Get bits required for string value.
static unsigned getBitsNeeded(const StringRef& str, uint8_t radix);
static unsigned getBitsNeeded(StringRef str, uint8_t radix);
/// countLeadingZeros - This function is an APInt version of the
/// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number

View file

@ -106,12 +106,17 @@ public:
/// into the current block.
void recomputeInsertPt();
struct SavePoint {
MachineBasicBlock::iterator InsertPt;
DebugLoc DL;
};
/// enterLocalValueArea - Prepare InsertPt to begin inserting instructions
/// into the local value area and return the old insert position.
MachineBasicBlock::iterator enterLocalValueArea();
SavePoint enterLocalValueArea();
/// leaveLocalValueArea - Reset InsertPt to the given old insert position
void leaveLocalValueArea(MachineBasicBlock::iterator OldInsertPt);
/// leaveLocalValueArea - Reset InsertPt to the given old insert position.
void leaveLocalValueArea(SavePoint Old);
virtual ~FastISel();
@ -302,8 +307,6 @@ protected:
}
private:
bool SelectLoad(const User *I);
bool SelectBinaryOp(const User *I, unsigned ISDOpcode);
bool SelectFNeg(const User *I);

View file

@ -272,10 +272,6 @@ namespace llvm {
unsigned getNumConflictsWithPhysReg(const LiveInterval &li,
unsigned PhysReg) const;
/// processImplicitDefs - Process IMPLICIT_DEF instructions. Add isUndef
/// marker to implicit_def defs and their uses.
void processImplicitDefs();
/// intervalIsInOneMBB - Returns true if the specified interval is entirely
/// within a single basic block.
bool intervalIsInOneMBB(const LiveInterval &li) const;

View file

@ -344,7 +344,7 @@ public:
VariableDbgInfo.push_back(std::make_pair(N, std::make_pair(Slot, Loc)));
}
VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfo; }
VariableDbgInfoMapTy &getVariableDbgInfo();
}; // End class MachineModuleInfo

View file

@ -12,6 +12,7 @@
#define LLVM_CODEGEN_PROCESSIMPLICITDEFS_H
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/ADT/SmallSet.h"
namespace llvm {
@ -24,7 +25,8 @@ namespace llvm {
private:
bool CanTurnIntoImplicitDef(MachineInstr *MI, unsigned Reg,
unsigned OpIdx, const TargetInstrInfo *tii_);
unsigned OpIdx, const TargetInstrInfo *tii_,
SmallSet<unsigned, 8> &ImpDefRegs);
public:
static char ID;

View file

@ -107,7 +107,7 @@ private:
void EatToEndOfStatement();
bool ParseAssignment(const StringRef &Name);
bool ParseAssignment(StringRef Name);
bool ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc);
bool ParseBinOpRHS(unsigned Precedence, const MCExpr *&Res, SMLoc &EndLoc);

View file

@ -10,12 +10,12 @@
// This file contains an definitions used in Windows COFF Files.
//
// Structures and enums defined within this file where created using
// information from Microsofts publicly available PE/COFF format document:
// information from Microsoft's publicly available PE/COFF format document:
//
// Microsoft Portable Executable and Common Object File Format Specification
// Revision 8.1 - February 15, 2008
//
// As of 5/2/2010, hosted by microsoft at:
// As of 5/2/2010, hosted by Microsoft at:
// http://www.microsoft.com/whdc/system/platform/firmware/pecoff.mspx
//
//===----------------------------------------------------------------------===//
@ -57,7 +57,7 @@ namespace COFF {
uint8_t NumberOfAuxSymbols;
};
enum symbol_flags {
enum SymbolFlags {
SF_TypeMask = 0x0000FFFF,
SF_TypeShift = 0,
@ -67,36 +67,70 @@ namespace COFF {
SF_WeakReference = 0x01000000
};
enum symbol_storage_class {
IMAGE_SYM_CLASS_END_OF_FUNCTION = -1,
IMAGE_SYM_CLASS_NULL = 0,
IMAGE_SYM_CLASS_AUTOMATIC = 1,
IMAGE_SYM_CLASS_EXTERNAL = 2,
IMAGE_SYM_CLASS_STATIC = 3,
IMAGE_SYM_CLASS_REGISTER = 4,
IMAGE_SYM_CLASS_EXTERNAL_DEF = 5,
IMAGE_SYM_CLASS_LABEL = 6,
IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7,
IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8,
IMAGE_SYM_CLASS_ARGUMENT = 9,
IMAGE_SYM_CLASS_STRUCT_TAG = 10,
IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11,
IMAGE_SYM_CLASS_UNION_TAG = 12,
IMAGE_SYM_CLASS_TYPE_DEFINITION = 13,
IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14,
IMAGE_SYM_CLASS_ENUM_TAG = 15,
IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16,
IMAGE_SYM_CLASS_REGISTER_PARAM = 17,
IMAGE_SYM_CLASS_BIT_FIELD = 18,
/// Storage class tells where and what the symbol represents
enum SymbolStorageClass {
IMAGE_SYM_CLASS_END_OF_FUNCTION = -1, ///< Physical end of function
IMAGE_SYM_CLASS_NULL = 0, ///< No symbol
IMAGE_SYM_CLASS_AUTOMATIC = 1, ///< Stack variable
IMAGE_SYM_CLASS_EXTERNAL = 2, ///< External symbol
IMAGE_SYM_CLASS_STATIC = 3, ///< Static
IMAGE_SYM_CLASS_REGISTER = 4, ///< Register variable
IMAGE_SYM_CLASS_EXTERNAL_DEF = 5, ///< External definition
IMAGE_SYM_CLASS_LABEL = 6, ///< Label
IMAGE_SYM_CLASS_UNDEFINED_LABEL = 7, ///< Undefined label
IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 8, ///< Member of structure
IMAGE_SYM_CLASS_ARGUMENT = 9, ///< Function argument
IMAGE_SYM_CLASS_STRUCT_TAG = 10, ///< Structure tag
IMAGE_SYM_CLASS_MEMBER_OF_UNION = 11, ///< Member of union
IMAGE_SYM_CLASS_UNION_TAG = 12, ///< Union tag
IMAGE_SYM_CLASS_TYPE_DEFINITION = 13, ///< Type definition
IMAGE_SYM_CLASS_UNDEFINED_STATIC = 14, ///< Undefined static
IMAGE_SYM_CLASS_ENUM_TAG = 15, ///< Enumeration tag
IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 16, ///< Member of enumeration
IMAGE_SYM_CLASS_REGISTER_PARAM = 17, ///< Register parameter
IMAGE_SYM_CLASS_BIT_FIELD = 18, ///< Bit field
/// ".bb" or ".eb" - beginning or end of block
IMAGE_SYM_CLASS_BLOCK = 100,
/// ".bf" or ".ef" - beginning or end of function
IMAGE_SYM_CLASS_FUNCTION = 101,
IMAGE_SYM_CLASS_END_OF_STRUCT = 102,
IMAGE_SYM_CLASS_FILE = 103,
IMAGE_SYM_CLASS_END_OF_STRUCT = 102, ///< End of structure
IMAGE_SYM_CLASS_FILE = 103, ///< File name
/// Line number, reformatted as symbol
IMAGE_SYM_CLASS_SECTION = 104,
IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105,
IMAGE_SYM_CLASS_WEAK_EXTERNAL = 105, ///< Duplicate tag
/// External symbol in dmert public lib
IMAGE_SYM_CLASS_CLR_TOKEN = 107
};
enum SymbolBaseType {
IMAGE_SYM_TYPE_NULL = 0, ///< No type information or unknown base type.
IMAGE_SYM_TYPE_VOID = 1, ///< Used with void pointers and functions.
IMAGE_SYM_TYPE_CHAR = 2, ///< A character (signed byte).
IMAGE_SYM_TYPE_SHORT = 3, ///< A 2-byte signed integer.
IMAGE_SYM_TYPE_INT = 4, ///< A natural integer type on the target.
IMAGE_SYM_TYPE_LONG = 5, ///< A 4-byte signed integer.
IMAGE_SYM_TYPE_FLOAT = 6, ///< A 4-byte floating-point number.
IMAGE_SYM_TYPE_DOUBLE = 7, ///< An 8-byte floating-point number.
IMAGE_SYM_TYPE_STRUCT = 8, ///< A structure.
IMAGE_SYM_TYPE_UNION = 9, ///< An union.
IMAGE_SYM_TYPE_ENUM = 10, ///< An enumerated type.
IMAGE_SYM_TYPE_MOE = 11, ///< A member of enumeration (a specific value).
IMAGE_SYM_TYPE_BYTE = 12, ///< A byte; unsigned 1-byte integer.
IMAGE_SYM_TYPE_WORD = 13, ///< A word; unsigned 2-byte integer.
IMAGE_SYM_TYPE_UINT = 14, ///< An unsigned integer of natural size.
IMAGE_SYM_TYPE_DWORD = 15 ///< An unsigned 4-byte integer.
};
enum SymbolComplexType {
IMAGE_SYM_DTYPE_NULL = 0, ///< No complex type; simple scalar variable.
IMAGE_SYM_DTYPE_POINTER = 1, ///< A pointer to base type.
IMAGE_SYM_DTYPE_FUNCTION = 2, ///< A function that returns a base type.
IMAGE_SYM_DTYPE_ARRAY = 3, ///< An array of base type.
/// Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
SCT_COMPLEX_TYPE_SHIFT = 4
};
struct section {
char Name[NameSize];
uint32_t VirtualSize;
@ -110,7 +144,7 @@ namespace COFF {
uint32_t Characteristics;
};
enum section_characteristics {
enum SectionCharacteristics {
IMAGE_SCN_TYPE_NO_PAD = 0x00000008,
IMAGE_SCN_CNT_CODE = 0x00000020,
IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040,
@ -154,7 +188,7 @@ namespace COFF {
uint16_t Type;
};
enum relocation_type_x86 {
enum RelocationTypeX86 {
IMAGE_REL_I386_ABSOLUTE = 0x0000,
IMAGE_REL_I386_DIR16 = 0x0001,
IMAGE_REL_I386_REL16 = 0x0002,

View file

@ -36,7 +36,7 @@ namespace llvm {
/// Compiles the given POSIX Extended Regular Expression \arg Regex.
/// This implementation supports regexes and matching strings with embedded
/// NUL characters.
Regex(const StringRef &Regex, unsigned Flags = NoFlags);
Regex(StringRef Regex, unsigned Flags = NoFlags);
~Regex();
/// isValid - returns the error encountered during regex compilation, or
@ -55,7 +55,7 @@ namespace llvm {
/// the first group is always the entire pattern.
///
/// This returns true on a successful match.
bool match(const StringRef &String, SmallVectorImpl<StringRef> *Matches=0);
bool match(StringRef String, SmallVectorImpl<StringRef> *Matches = 0);
/// sub - Return the result of replacing the first match of the regex in
/// \arg String with the \arg Repl string. Backreferences like "\0" in the

View file

@ -64,7 +64,7 @@ namespace llvm {
/// intern - Adds a string to the pool and returns a reference-counted
/// pointer to it. No additional memory is allocated if the string already
/// exists in the pool.
PooledStringPtr intern(const StringRef &Str);
PooledStringPtr intern(StringRef Str);
/// empty - Checks whether the pool is empty. Returns true if so.
///

View file

@ -49,7 +49,7 @@ public:
/// \param Operands [out] - The list of parsed operands, this returns
/// ownership of them to the caller.
/// \return True on failure.
virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc,
virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0;
/// ParseDirective - Parse a target specific assembler directive

View file

@ -371,7 +371,7 @@ public:
unsigned SrcReg, bool isKill, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
assert(0 && "Target didn't implement TargetInstrInfo::storeRegToStackSlot!");
assert(0 && "Target didn't implement TargetInstrInfo::storeRegToStackSlot!");
}
/// loadRegFromStackSlot - Load the specified register of the given register
@ -383,7 +383,7 @@ public:
unsigned DestReg, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const {
assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!");
assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!");
}
/// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee
@ -392,7 +392,7 @@ public:
/// storeRegToStackSlot(). Returns false otherwise.
virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
const std::vector<CalleeSavedInfo> &CSI,
const TargetRegisterInfo *TRI) const {
return false;
}
@ -457,7 +457,7 @@ protected:
/// take care of adding a MachineMemOperand to the newly created instruction.
virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF,
MachineInstr* MI,
const SmallVectorImpl<unsigned> &Ops,
const SmallVectorImpl<unsigned> &Ops,
MachineInstr* LoadMI) const {
return 0;
}
@ -501,7 +501,7 @@ public:
/// only differences between the two addresses are the offset. It also returns
/// the offsets by reference.
virtual bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2,
int64_t &Offset1, int64_t &Offset2) const {
int64_t &Offset1, int64_t &Offset2) const {
return false;
}

View file

@ -68,7 +68,7 @@ namespace llvm {
/// this flag is off (the default), the code generator is not allowed to
/// produce results that are "less precise" than IEEE allows. This includes
/// use of X86 instructions like FSIN and FCOS instead of libcalls.
/// UnsafeFPMath implies FiniteOnlyFPMath and LessPreciseFPMAD.
/// UnsafeFPMath implies LessPreciseFPMAD.
extern bool UnsafeFPMath;
/// FiniteOnlyFPMath - This returns true when the -enable-finite-only-fp-math

View file

@ -266,6 +266,10 @@ public:
SubclassOptionalData &= V->SubclassOptionalData;
}
/// hasValueHandle - Return true if there is a value handle associated with
/// this value.
bool hasValueHandle() const { return HasValueHandle; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const Value *) {
return true; // Values are always values.

View file

@ -440,27 +440,47 @@ void llvm::ReplaceAndSimplifyAllUses(Instruction *From, Value *To,
const TargetData *TD) {
assert(From != To && "ReplaceAndSimplifyAllUses(X,X) is not valid!");
// FromHandle - This keeps a weakvh on the from value so that we can know if
// it gets deleted out from under us in a recursive simplification.
// FromHandle/ToHandle - This keeps a WeakVH on the from/to values so that
// we can know if it gets deleted out from under us or replaced in a
// recursive simplification.
WeakVH FromHandle(From);
WeakVH ToHandle(To);
while (!From->use_empty()) {
// Update the instruction to use the new value.
Use &U = From->use_begin().getUse();
Instruction *User = cast<Instruction>(U.getUser());
U = To;
Use &TheUse = From->use_begin().getUse();
Instruction *User = cast<Instruction>(TheUse.getUser());
TheUse = To;
// Check to see if the instruction can be folded due to the operand
// replacement. For example changing (or X, Y) into (or X, -1) can replace
// the 'or' with -1.
Value *SimplifiedVal;
{
// Sanity check to make sure 'User' doesn't dangle across
// SimplifyInstruction.
AssertingVH<> UserHandle(User);
// See if we can simplify it.
if (Value *V = SimplifyInstruction(User, TD)) {
// Recursively simplify this.
ReplaceAndSimplifyAllUses(User, V, TD);
// If the recursive simplification ended up revisiting and deleting 'From'
// then we're done.
if (FromHandle == 0)
return;
SimplifiedVal = SimplifyInstruction(User, TD);
if (SimplifiedVal == 0) continue;
}
// Recursively simplify this user to the new value.
ReplaceAndSimplifyAllUses(User, SimplifiedVal, TD);
From = dyn_cast_or_null<Instruction>((Value*)FromHandle);
To = ToHandle;
assert(ToHandle && "To value deleted by recursive simplification?");
// If the recursive simplification ended up revisiting and deleting
// 'From' then we're done.
if (From == 0)
return;
}
// If 'From' has value handles referring to it, do a real RAUW to update them.
From->replaceAllUsesWith(To);
From->eraseFromParent();
}

View file

@ -71,22 +71,24 @@ ProfileInfoT<Function,BasicBlock>::getExecutionCount(const BasicBlock *BB) {
// Are there zero predecessors of this block?
if (PI == PE) {
Edge e = getEdge(0,BB);
Edge e = getEdge(0, BB);
Count = getEdgeWeight(e);
} else {
// Otherwise, if there are predecessors, the execution count of this block is
// the sum of the edge frequencies from the incoming edges.
std::set<const BasicBlock*> ProcessedPreds;
Count = 0;
for (; PI != PE; ++PI)
if (ProcessedPreds.insert(*PI).second) {
double w = getEdgeWeight(getEdge(*PI, BB));
for (; PI != PE; ++PI) {
const BasicBlock *P = *PI;
if (ProcessedPreds.insert(P).second) {
double w = getEdgeWeight(getEdge(P, BB));
if (w == MissingValue) {
Count = MissingValue;
break;
}
Count += w;
}
}
}
// If the predecessors did not suffice to get block weight, try successors.

View file

@ -544,20 +544,21 @@ bool LLParser::ParseNamedMetadata() {
return true;
SmallVector<MDNode *, 8> Elts;
do {
// Null is a special case since it is typeless.
if (EatIfPresent(lltok::kw_null)) {
Elts.push_back(0);
continue;
}
if (Lex.getKind() != lltok::rbrace)
do {
// Null is a special case since it is typeless.
if (EatIfPresent(lltok::kw_null)) {
Elts.push_back(0);
continue;
}
if (ParseToken(lltok::exclaim, "Expected '!' here"))
return true;
if (ParseToken(lltok::exclaim, "Expected '!' here"))
return true;
MDNode *N = 0;
if (ParseMDNodeID(N)) return true;
Elts.push_back(N);
} while (EatIfPresent(lltok::comma));
MDNode *N = 0;
if (ParseMDNodeID(N)) return true;
Elts.push_back(N);
} while (EatIfPresent(lltok::comma));
if (ParseToken(lltok::rbrace, "expected end of metadata node"))
return true;
@ -2021,33 +2022,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) {
ID.StrVal = Lex.getStrVal();
ID.Kind = ValID::t_LocalName;
break;
case lltok::exclaim: // !{...} MDNode, !"foo" MDString
Lex.Lex();
if (EatIfPresent(lltok::lbrace)) {
SmallVector<Value*, 16> Elts;
if (ParseMDNodeVector(Elts, PFS) ||
ParseToken(lltok::rbrace, "expected end of metadata node"))
return true;
ID.MDNodeVal = MDNode::get(Context, Elts.data(), Elts.size());
ID.Kind = ValID::t_MDNode;
return false;
}
// Standalone metadata reference
// !{ ..., !42, ... }
if (Lex.getKind() == lltok::APSInt) {
if (ParseMDNodeID(ID.MDNodeVal)) return true;
ID.Kind = ValID::t_MDNode;
return false;
}
// MDString:
// ::= '!' STRINGCONSTANT
if (ParseMDString(ID.MDStringVal)) return true;
ID.Kind = ValID::t_MDString;
return false;
case lltok::exclaim: // !42, !{...}, or !"foo"
return ParseMetadataValue(ID, PFS);
case lltok::APSInt:
ID.APSIntVal = Lex.getAPSIntVal();
ID.Kind = ValID::t_APSInt;
@ -2528,6 +2504,42 @@ bool LLParser::ParseGlobalValueVector(SmallVectorImpl<Constant*> &Elts) {
return false;
}
/// ParseMetadataValue
/// ::= !42
/// ::= !{...}
/// ::= !"string"
bool LLParser::ParseMetadataValue(ValID &ID, PerFunctionState *PFS) {
assert(Lex.getKind() == lltok::exclaim);
Lex.Lex();
// MDNode:
// !{ ... }
if (EatIfPresent(lltok::lbrace)) {
SmallVector<Value*, 16> Elts;
if (ParseMDNodeVector(Elts, PFS) ||
ParseToken(lltok::rbrace, "expected end of metadata node"))
return true;
ID.MDNodeVal = MDNode::get(Context, Elts.data(), Elts.size());
ID.Kind = ValID::t_MDNode;
return false;
}
// Standalone metadata reference
// !42
if (Lex.getKind() == lltok::APSInt) {
if (ParseMDNodeID(ID.MDNodeVal)) return true;
ID.Kind = ValID::t_MDNode;
return false;
}
// MDString:
// ::= '!' STRINGCONSTANT
if (ParseMDString(ID.MDStringVal)) return true;
ID.Kind = ValID::t_MDString;
return false;
}
//===----------------------------------------------------------------------===//
// Function Parsing.
@ -3983,6 +3995,10 @@ int LLParser::ParseInsertValue(Instruction *&Inst, PerFunctionState &PFS) {
/// ::= 'null' | TypeAndValue
bool LLParser::ParseMDNodeVector(SmallVectorImpl<Value*> &Elts,
PerFunctionState *PFS) {
// Check for an empty list.
if (Lex.getKind() == lltok::rbrace)
return false;
do {
// Null is a special case since it is typeless.
if (EatIfPresent(lltok::kw_null)) {

View file

@ -308,6 +308,7 @@ namespace llvm {
bool ParseGlobalValue(const Type *Ty, Constant *&V);
bool ParseGlobalTypeAndValue(Constant *&V);
bool ParseGlobalValueVector(SmallVectorImpl<Constant*> &Elts);
bool ParseMetadataValue(ValID &ID, PerFunctionState *PFS);
bool ParseMDNodeVector(SmallVectorImpl<Value*> &, PerFunctionState *PFS);
// Function Parsing.

View file

@ -820,7 +820,7 @@ bool BitcodeReader::ParseMetadata() {
IsFunctionLocal = true;
// fall-through
case bitc::METADATA_NODE: {
if (Record.empty() || Record.size() % 2 == 1)
if (Record.size() % 2 == 1)
return Error("Invalid METADATA_NODE record");
unsigned Size = Record.size();
@ -834,7 +834,8 @@ bool BitcodeReader::ParseMetadata() {
else
Elts.push_back(NULL);
}
Value *V = MDNode::getWhenValsUnresolved(Context, &Elts[0], Elts.size(),
Value *V = MDNode::getWhenValsUnresolved(Context,
Elts.data(), Elts.size(),
IsFunctionLocal);
IsFunctionLocal = false;
MDValueList.AssignValue(V, NextMDValueNo++);

View file

@ -178,7 +178,7 @@ bool AsmPrinter::doInitialization(Module &M) {
if (!M.getModuleInlineAsm().empty()) {
OutStreamer.AddComment("Start of file scope inline assembly");
OutStreamer.AddBlankLine();
EmitInlineAsm(M.getModuleInlineAsm(), 0/*no loc cookie*/);
EmitInlineAsm(M.getModuleInlineAsm()+"\n", 0/*no loc cookie*/);
OutStreamer.AddComment("End of file scope inline assembly");
OutStreamer.AddBlankLine();
}

View file

@ -53,17 +53,6 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, unsigned LocCookie) const {
}
SourceMgr SrcMgr;
// Ensure the buffer is newline terminated.
char *TmpString = 0;
if (Str.back() != '\n') {
TmpString = new char[Str.size() + 2];
memcpy(TmpString, Str.data(), Str.size());
TmpString[Str.size()] = '\n';
TmpString[Str.size() + 1] = 0;
isNullTerminated = true;
Str = TmpString;
}
// If the current LLVMContext has an inline asm handler, set it in SourceMgr.
LLVMContext &LLVMCtx = MMI->getModule()->getContext();
@ -95,9 +84,6 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, unsigned LocCookie) const {
/*NoFinalize*/ true);
if (Res && !HasDiagHandler)
report_fatal_error("Error parsing inline asm\n");
if (TmpString)
delete[] TmpString;
}

View file

@ -119,6 +119,7 @@ bool LiveInterval::killedInRange(SlotIndex Start, SlotIndex End) const {
//
bool LiveInterval::overlapsFrom(const LiveInterval& other,
const_iterator StartPos) const {
assert(!empty() && "empty interval");
const_iterator i = begin();
const_iterator ie = end();
const_iterator j = StartPos;
@ -161,16 +162,8 @@ bool LiveInterval::overlapsFrom(const LiveInterval& other,
/// by [Start, End).
bool LiveInterval::overlaps(SlotIndex Start, SlotIndex End) const {
assert(Start < End && "Invalid range");
const_iterator I = begin();
const_iterator E = end();
const_iterator si = std::upper_bound(I, E, Start);
const_iterator ei = std::upper_bound(I, E, End);
if (si != ei)
return true;
if (si == I)
return false;
--si;
return si->contains(Start);
const_iterator I = std::lower_bound(begin(), end(), End);
return I != begin() && (--I)->end > Start;
}
/// extendIntervalEndTo - This method is used when we want to extend the range
@ -868,6 +861,10 @@ void LiveInterval::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const {
OS << "?";
else
OS << vni->def;
if (vni->hasPHIKill())
OS << "-phikill";
if (vni->hasRedefByEC())
OS << "-ec";
}
}
}

View file

@ -497,11 +497,6 @@ void MachineLICM::HoistRegion(MachineDomTreeNode *N) {
/// candidate for LICM. e.g. If the instruction is a call, then it's obviously
/// not safe to hoist it.
bool MachineLICM::IsLICMCandidate(MachineInstr &I) {
// It is not profitable to hoist implicitdefs. FIXME: Why not? what if they
// are an argument to some other otherwise-hoistable instruction?
if (I.isImplicitDef())
return false;
// Check if it's safe to move the instruction.
bool DontMoveAcrossStore = true;
if (!I.isSafeToMove(TII, AA, DontMoveAcrossStore))
@ -717,7 +712,9 @@ MachineLICM::LookForDuplicate(const MachineInstr *MI,
bool MachineLICM::EliminateCSE(MachineInstr *MI,
DenseMap<unsigned, std::vector<const MachineInstr*> >::iterator &CI) {
if (CI == CSEMap.end())
// Do not CSE implicit_def so ProcessImplicitDefs can properly propagate
// the undef property onto uses.
if (CI == CSEMap.end() || MI->isImplicitDef())
return false;
if (const MachineInstr *Dup = LookForDuplicate(MI, CI->second)) {

View file

@ -563,3 +563,26 @@ unsigned MachineModuleInfo::getPersonalityIndex() const {
return 0;
}
namespace {
/// VariableDebugSorter - Comparison to sort the VariableDbgInfo map
/// by source location, to avoid depending on the arbitrary order that
/// instruction selection visits variables in.
struct VariableDebugSorter {
bool operator()(const MachineModuleInfo::VariableDbgInfoMapTy::value_type &A,
const MachineModuleInfo::VariableDbgInfoMapTy::value_type &B)
const {
if (A.second.second.getLine() != B.second.second.getLine())
return A.second.second.getLine() < B.second.second.getLine();
if (A.second.second.getCol() != B.second.second.getCol())
return A.second.second.getCol() < B.second.second.getCol();
return false;
}
};
}
MachineModuleInfo::VariableDbgInfoMapTy &
MachineModuleInfo::getVariableDbgInfo() {
std::stable_sort(VariableDbgInfo.begin(), VariableDbgInfo.end(),
VariableDebugSorter());
return VariableDbgInfo;
}

View file

@ -41,21 +41,51 @@ void ProcessImplicitDefs::getAnalysisUsage(AnalysisUsage &AU) const {
MachineFunctionPass::getAnalysisUsage(AU);
}
bool ProcessImplicitDefs::CanTurnIntoImplicitDef(MachineInstr *MI,
unsigned Reg, unsigned OpIdx,
const TargetInstrInfo *tii_) {
bool
ProcessImplicitDefs::CanTurnIntoImplicitDef(MachineInstr *MI,
unsigned Reg, unsigned OpIdx,
const TargetInstrInfo *tii_,
SmallSet<unsigned, 8> &ImpDefRegs) {
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
Reg == SrcReg && DstSubReg == 0)
Reg == SrcReg &&
(DstSubReg == 0 || ImpDefRegs.count(DstReg)))
return true;
switch(OpIdx) {
case 1: return MI->isCopy() && MI->getOperand(0).getSubReg() == 0;
case 2: return MI->isSubregToReg() && MI->getOperand(0).getSubReg() == 0;
default: return false;
case 1:
return MI->isCopy() && (MI->getOperand(0).getSubReg() == 0 ||
ImpDefRegs.count(MI->getOperand(0).getReg()));
case 2:
return MI->isSubregToReg() && (MI->getOperand(0).getSubReg() == 0 ||
ImpDefRegs.count(MI->getOperand(0).getReg()));
default: return false;
}
}
static bool isUndefCopy(MachineInstr *MI, unsigned Reg,
const TargetInstrInfo *tii_,
SmallSet<unsigned, 8> &ImpDefRegs) {
if (MI->isCopy()) {
MachineOperand &MO0 = MI->getOperand(0);
MachineOperand &MO1 = MI->getOperand(1);
if (MO1.getReg() != Reg)
return false;
if (!MO0.getSubReg() || ImpDefRegs.count(MO0.getReg()))
return true;
return false;
}
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubReg, DstSubReg)) {
if (Reg != SrcReg)
return false;
if (DstSubReg == 0 || ImpDefRegs.count(DstReg))
return true;
}
return false;
}
/// processImplicitDefs - Process IMPLICIT_DEF instructions and make sure
/// there is one implicit_def for each use. Add isUndef marker to
/// implicit_def defs and their uses.
@ -104,7 +134,7 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) {
// Eliminate %reg1032:sub<def> = COPY undef.
if (MI->isCopy() && MI->getOperand(0).getSubReg()) {
MachineOperand &MO = MI->getOperand(1);
if (ImpDefRegs.count(MO.getReg())) {
if (MO.isUndef() || ImpDefRegs.count(MO.getReg())) {
if (MO.isKill()) {
LiveVariables::VarInfo& vi = lv_->getVarInfo(MO.getReg());
vi.removeKill(MI);
@ -126,7 +156,7 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) {
if (!ImpDefRegs.count(Reg))
continue;
// Use is a copy, just turn it into an implicit_def.
if (CanTurnIntoImplicitDef(MI, Reg, i, tii_)) {
if (CanTurnIntoImplicitDef(MI, Reg, i, tii_, ImpDefRegs)) {
bool isKill = MO.isKill();
MI->setDesc(tii_->get(TargetOpcode::IMPLICIT_DEF));
for (int j = MI->getNumOperands() - 1, ee = 0; j > ee; --j)
@ -223,11 +253,7 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) {
MachineInstr *RMI = RUses[i];
// Turn a copy use into an implicit_def.
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if ((RMI->isCopy() && RMI->getOperand(1).getReg() == Reg &&
RMI->getOperand(0).getSubReg() == 0) ||
(tii_->isMoveInstr(*RMI, SrcReg, DstReg, SrcSubReg, DstSubReg) &&
Reg == SrcReg && DstSubReg == 0)) {
if (isUndefCopy(RMI, Reg, tii_, ImpDefRegs)) {
RMI->setDesc(tii_->get(TargetOpcode::IMPLICIT_DEF));
bool isKill = false;

View file

@ -135,7 +135,7 @@ unsigned FastISel::getRegForValue(const Value *V) {
!FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(V))))
return FuncInfo.InitializeRegForValue(V);
MachineBasicBlock::iterator SaveInsertPt = enterLocalValueArea();
SavePoint SaveInsertPt = enterLocalValueArea();
// Materialize the value in a register. Emit any instructions in the
// local value area.
@ -286,18 +286,22 @@ void FastISel::recomputeInsertPt() {
++FuncInfo.InsertPt;
}
MachineBasicBlock::iterator FastISel::enterLocalValueArea() {
FastISel::SavePoint FastISel::enterLocalValueArea() {
MachineBasicBlock::iterator OldInsertPt = FuncInfo.InsertPt;
DebugLoc OldDL = DL;
recomputeInsertPt();
return OldInsertPt;
DL = DebugLoc();
SavePoint SP = { OldInsertPt, OldDL };
return SP;
}
void FastISel::leaveLocalValueArea(MachineBasicBlock::iterator OldInsertPt) {
void FastISel::leaveLocalValueArea(SavePoint OldInsertPt) {
if (FuncInfo.InsertPt != FuncInfo.MBB->begin())
LastLocalValue = llvm::prior(FuncInfo.InsertPt);
// Restore the previous insert position.
FuncInfo.InsertPt = OldInsertPt;
FuncInfo.InsertPt = OldInsertPt.InsertPt;
DL = OldInsertPt.DL;
}
/// SelectBinaryOp - Select and emit code for a binary operator instruction,
@ -778,40 +782,9 @@ FastISel::SelectFNeg(const User *I) {
return true;
}
bool
FastISel::SelectLoad(const User *I) {
LoadInst *LI = const_cast<LoadInst *>(cast<LoadInst>(I));
// For a load from an alloca, make a limited effort to find the value
// already available in a register, avoiding redundant loads.
if (!LI->isVolatile() && isa<AllocaInst>(LI->getPointerOperand())) {
BasicBlock::iterator ScanFrom = LI;
if (const Value *V = FindAvailableLoadedValue(LI->getPointerOperand(),
LI->getParent(), ScanFrom)) {
if (!V->use_empty() &&
(!isa<Instruction>(V) ||
cast<Instruction>(V)->getParent() == LI->getParent() ||
(isa<AllocaInst>(V) &&
FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(V)))) &&
(!isa<Argument>(V) ||
LI->getParent() == &LI->getParent()->getParent()->getEntryBlock())) {
unsigned ResultReg = getRegForValue(V);
if (ResultReg != 0) {
UpdateValueMap(I, ResultReg);
return true;
}
}
}
}
return false;
}
bool
FastISel::SelectOperator(const User *I, unsigned Opcode) {
switch (Opcode) {
case Instruction::Load:
return SelectLoad(I);
case Instruction::Add:
return SelectBinaryOp(I, ISD::ADD);
case Instruction::FAdd:

View file

@ -820,7 +820,7 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) {
unsigned InReg = It->second;
RegsForValue RFV(*DAG.getContext(), TLI, InReg, V->getType());
SDValue Chain = DAG.getEntryNode();
return N = RFV.getCopyFromRegs(DAG, FuncInfo, getCurDebugLoc(), Chain, NULL);
return N = RFV.getCopyFromRegs(DAG, FuncInfo, getCurDebugLoc(), Chain,NULL);
}
// Otherwise create a new SDValue and remember it.
@ -3955,7 +3955,8 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
if (AA->alias(I.getArgOperand(0), Size, I.getArgOperand(1), Size) ==
AliasAnalysis::NoAlias) {
DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, isVol,
false, I.getArgOperand(0), 0, I.getArgOperand(1), 0));
false, I.getArgOperand(0), 0,
I.getArgOperand(1), 0));
return 0;
}
@ -5522,10 +5523,12 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) {
break;
}
if (OpInfo.ConstraintType == TargetLowering::C_Other) {
assert(!OpInfo.isIndirect &&
"Don't know how to handle indirect other inputs yet!");
// Treat indirect 'X' constraint as memory.
if (OpInfo.ConstraintType == TargetLowering::C_Other &&
OpInfo.isIndirect)
OpInfo.ConstraintType = TargetLowering::C_Memory;
if (OpInfo.ConstraintType == TargetLowering::C_Other) {
std::vector<SDValue> Ops;
TLI.LowerAsmOperandForConstraint(InOperandVal, OpInfo.ConstraintCode[0],
Ops, DAG);

View file

@ -712,7 +712,7 @@ bool AsmParser::ParseStatement() {
return HadError;
}
bool AsmParser::ParseAssignment(const StringRef &Name) {
bool AsmParser::ParseAssignment(StringRef Name) {
// FIXME: Use better location, we should use proper tokens.
SMLoc EqualLoc = Lexer.getLoc();

View file

@ -761,7 +761,7 @@ APFloat::APFloat(const fltSemantics &ourSemantics,
makeNaN();
}
APFloat::APFloat(const fltSemantics &ourSemantics, const StringRef& text)
APFloat::APFloat(const fltSemantics &ourSemantics, StringRef text)
{
assertArithmeticOK(ourSemantics);
initialize(&ourSemantics);
@ -2185,8 +2185,7 @@ APFloat::convertFromZeroExtendedInteger(const integerPart *parts,
}
APFloat::opStatus
APFloat::convertFromHexadecimalString(const StringRef &s,
roundingMode rounding_mode)
APFloat::convertFromHexadecimalString(StringRef s, roundingMode rounding_mode)
{
lostFraction lost_fraction = lfExactlyZero;
integerPart *significand;
@ -2361,7 +2360,7 @@ APFloat::roundSignificandWithExponent(const integerPart *decSigParts,
}
APFloat::opStatus
APFloat::convertFromDecimalString(const StringRef &str, roundingMode rounding_mode)
APFloat::convertFromDecimalString(StringRef str, roundingMode rounding_mode)
{
decimalInfo D;
opStatus fs;
@ -2471,7 +2470,7 @@ APFloat::convertFromDecimalString(const StringRef &str, roundingMode rounding_mo
}
APFloat::opStatus
APFloat::convertFromString(const StringRef &str, roundingMode rounding_mode)
APFloat::convertFromString(StringRef str, roundingMode rounding_mode)
{
assertArithmeticOK(*semantics);
assert(!str.empty() && "Invalid string length");

View file

@ -102,7 +102,7 @@ APInt::APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[])
clearUnusedBits();
}
APInt::APInt(unsigned numbits, const StringRef& Str, uint8_t radix)
APInt::APInt(unsigned numbits, StringRef Str, uint8_t radix)
: BitWidth(numbits), VAL(0) {
assert(BitWidth && "Bitwidth too small");
fromString(numbits, Str, radix);
@ -613,7 +613,7 @@ APInt& APInt::flip(unsigned bitPosition) {
return *this;
}
unsigned APInt::getBitsNeeded(const StringRef& str, uint8_t radix) {
unsigned APInt::getBitsNeeded(StringRef str, uint8_t radix) {
assert(!str.empty() && "Invalid string length");
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&
"Radix should be 2, 8, 10, or 16!");
@ -2046,7 +2046,7 @@ void APInt::udivrem(const APInt &LHS, const APInt &RHS,
divide(LHS, lhsWords, RHS, rhsWords, &Quotient, &Remainder);
}
void APInt::fromString(unsigned numbits, const StringRef& str, uint8_t radix) {
void APInt::fromString(unsigned numbits, StringRef str, uint8_t radix) {
// Check our assumptions here
assert(!str.empty() && "Invalid string length");
assert((radix == 10 || radix == 8 || radix == 16 || radix == 2) &&

View file

@ -19,7 +19,7 @@
#include <string>
using namespace llvm;
Regex::Regex(const StringRef &regex, unsigned Flags) {
Regex::Regex(StringRef regex, unsigned Flags) {
unsigned flags = 0;
preg = new llvm_regex();
preg->re_endp = regex.end();
@ -52,7 +52,7 @@ unsigned Regex::getNumMatches() const {
return preg->re_nsub;
}
bool Regex::match(const StringRef &String, SmallVectorImpl<StringRef> *Matches){
bool Regex::match(StringRef String, SmallVectorImpl<StringRef> *Matches){
unsigned nmatch = Matches ? preg->re_nsub+1 : 0;
// pmatch needs to have at least one element.

View file

@ -22,7 +22,7 @@ StringPool::~StringPool() {
assert(InternTable.empty() && "PooledStringPtr leaked!");
}
PooledStringPtr StringPool::intern(const StringRef &Key) {
PooledStringPtr StringPool::intern(StringRef Key) {
table_t::iterator I = InternTable.find(Key);
if (I != InternTable.end())
return PooledStringPtr(&*I);

View file

@ -310,12 +310,9 @@ Program::Wait(unsigned secondsToWait,
// fact of having a handler at all causes the wait below to return with EINTR,
// unlike if we used SIG_IGN.
if (secondsToWait) {
#if !defined(__HAIKU__) && !defined(__minix)
Act.sa_sigaction = 0;
#endif
memset(&Act, 0, sizeof(Act));
Act.sa_handler = TimeOutHandler;
sigemptyset(&Act.sa_mask);
Act.sa_flags = 0;
sigaction(SIGALRM, &Act, &Old);
alarm(secondsToWait);
}

View file

@ -48,6 +48,8 @@ def FeatureHWDiv : SubtargetFeature<"hwdiv", "HasHardwareDivide", "true",
"Enable divide instructions">;
def FeatureT2ExtractPack: SubtargetFeature<"t2xtpk", "HasT2ExtractPack", "true",
"Enable Thumb2 extract and pack instructions">;
def FeatureSlowFPBrcc : SubtargetFeature<"slow-fp-brcc", "SlowFPBrcc", "true",
"FP compare + branch is slow">;
// Some processors have multiply-accumulate instructions that don't
// play nicely with other VFP instructions, and it's generally better
@ -129,7 +131,7 @@ def : Processor<"arm1156t2f-s", ARMV6Itineraries,
// V7 Processors.
def : Processor<"cortex-a8", CortexA8Itineraries,
[ArchV7A, FeatureThumb2, FeatureNEON, FeatureHasSlowVMLx,
FeatureNEONForFP, FeatureT2ExtractPack]>;
FeatureSlowFPBrcc, FeatureNEONForFP, FeatureT2ExtractPack]>;
def : Processor<"cortex-a9", CortexA9Itineraries,
[ArchV7A, FeatureThumb2, FeatureNEON, FeatureT2ExtractPack]>;
def : ProcNoItin<"cortex-m3", [ArchV7M, FeatureThumb2, FeatureHWDiv]>;

View file

@ -519,9 +519,8 @@ namespace ARM_AM {
//
// This is stored in two operands [regaddr, align]. The first is the
// address register. The second operand is the value of the alignment
// specifier to use or zero if no explicit alignment.
// Valid alignments are: 0, 8, 16, and 32 bytes, depending on the specific
// instruction.
// specifier in bytes or zero if no explicit alignment.
// Valid alignments depend on the specific instruction.
//===--------------------------------------------------------------------===//
// NEON Modified Immediates

View file

@ -565,6 +565,7 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
case ARMISD::CMPZ: return "ARMISD::CMPZ";
case ARMISD::CMPFP: return "ARMISD::CMPFP";
case ARMISD::CMPFPw0: return "ARMISD::CMPFPw0";
case ARMISD::BCC_i64: return "ARMISD::BCC_i64";
case ARMISD::FMSTAT: return "ARMISD::FMSTAT";
case ARMISD::CMOV: return "ARMISD::CMOV";
case ARMISD::CNEG: return "ARMISD::CNEG";
@ -623,6 +624,8 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
case ARMISD::VQRSHRNsu: return "ARMISD::VQRSHRNsu";
case ARMISD::VGETLANEu: return "ARMISD::VGETLANEu";
case ARMISD::VGETLANEs: return "ARMISD::VGETLANEs";
case ARMISD::VMOVIMM: return "ARMISD::VMOVIMM";
case ARMISD::VMVNIMM: return "ARMISD::VMVNIMM";
case ARMISD::VDUP: return "ARMISD::VDUP";
case ARMISD::VDUPLANE: return "ARMISD::VDUPLANE";
case ARMISD::VEXT: return "ARMISD::VEXT";
@ -2216,7 +2219,7 @@ static bool isFloatingPointZero(SDValue Op) {
/// the given operands.
SDValue
ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
SDValue &ARMCC, SelectionDAG &DAG,
SDValue &ARMcc, SelectionDAG &DAG,
DebugLoc dl) const {
if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(RHS.getNode())) {
unsigned C = RHSC->getZExtValue();
@ -2268,48 +2271,14 @@ ARMTargetLowering::getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
CompareType = ARMISD::CMPZ;
break;
}
ARMCC = DAG.getConstant(CondCode, MVT::i32);
ARMcc = DAG.getConstant(CondCode, MVT::i32);
return DAG.getNode(CompareType, dl, MVT::Flag, LHS, RHS);
}
static bool canBitcastToInt(SDNode *Op) {
return Op->hasOneUse() &&
ISD::isNormalLoad(Op) &&
Op->getValueType(0) == MVT::f32;
}
static SDValue bitcastToInt(SDValue Op, SelectionDAG &DAG) {
if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Op))
return DAG.getLoad(MVT::i32, Op.getDebugLoc(),
Ld->getChain(), Ld->getBasePtr(),
Ld->getSrcValue(), Ld->getSrcValueOffset(),
Ld->isVolatile(), Ld->isNonTemporal(),
Ld->getAlignment());
llvm_unreachable("Unknown VFP cmp argument!");
}
/// Returns a appropriate VFP CMP (fcmp{s|d}+fmstat) for the given operands.
SDValue
ARMTargetLowering::getVFPCmp(SDValue &LHS, SDValue &RHS, ISD::CondCode CC,
SDValue &ARMCC, SelectionDAG &DAG,
ARMTargetLowering::getVFPCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG,
DebugLoc dl) const {
if (UnsafeFPMath && FiniteOnlyFPMath() &&
(CC == ISD::SETEQ || CC == ISD::SETOEQ ||
CC == ISD::SETNE || CC == ISD::SETUNE) &&
canBitcastToInt(LHS.getNode()) && canBitcastToInt(RHS.getNode())) {
// If unsafe fp math optimization is enabled and there are no othter uses of
// the CMP operands, and the condition code is EQ oe NE, we can optimize it
// to an integer comparison.
if (CC == ISD::SETOEQ)
CC = ISD::SETEQ;
else if (CC == ISD::SETUNE)
CC = ISD::SETNE;
LHS = bitcastToInt(LHS, DAG);
RHS = bitcastToInt(RHS, DAG);
return getARMCmp(LHS, RHS, CC, ARMCC, DAG, dl);
}
SDValue Cmp;
if (!isFloatingPointZero(RHS))
Cmp = DAG.getNode(ARMISD::CMPFP, dl, MVT::Flag, LHS, RHS);
@ -2328,59 +2297,184 @@ SDValue ARMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
DebugLoc dl = Op.getDebugLoc();
if (LHS.getValueType() == MVT::i32) {
SDValue ARMCC;
SDValue ARMcc;
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMCC, DAG, dl);
return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMCC, CCR,Cmp);
SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl);
return DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc, CCR,Cmp);
}
ARMCC::CondCodes CondCode, CondCode2;
FPCCToARMCC(CC, CondCode, CondCode2);
SDValue ARMCC = DAG.getConstant(CondCode, MVT::i32);
SDValue ARMcc = DAG.getConstant(CondCode, MVT::i32);
SDValue Cmp = getVFPCmp(LHS, RHS, DAG, dl);
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
SDValue Cmp = getVFPCmp(LHS, RHS, CC, ARMCC, DAG, dl);
SDValue Result = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal,
ARMCC, CCR, Cmp);
ARMcc, CCR, Cmp);
if (CondCode2 != ARMCC::AL) {
SDValue ARMCC2 = DAG.getConstant(CondCode2, MVT::i32);
SDValue ARMcc2 = DAG.getConstant(CondCode2, MVT::i32);
// FIXME: Needs another CMP because flag can have but one use.
SDValue Cmp2 = getVFPCmp(LHS, RHS, CC, ARMCC2, DAG, dl);
SDValue Cmp2 = getVFPCmp(LHS, RHS, DAG, dl);
Result = DAG.getNode(ARMISD::CMOV, dl, VT,
Result, TrueVal, ARMCC2, CCR, Cmp2);
Result, TrueVal, ARMcc2, CCR, Cmp2);
}
return Result;
}
SDValue ARMTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
SDValue Chain = Op.getOperand(0);
/// canChangeToInt - Given the fp compare operand, return true if it is suitable
/// to morph to an integer compare sequence.
static bool canChangeToInt(SDValue Op, bool &SeenZero,
const ARMSubtarget *Subtarget) {
SDNode *N = Op.getNode();
if (!N->hasOneUse())
// Otherwise it requires moving the value from fp to integer registers.
return false;
if (!N->getNumValues())
return false;
EVT VT = Op.getValueType();
if (VT != MVT::f32 && !Subtarget->isFPBrccSlow())
// f32 case is generally profitable. f64 case only makes sense when vcmpe +
// vmrs are very slow, e.g. cortex-a8.
return false;
if (isFloatingPointZero(Op)) {
SeenZero = true;
return true;
}
return ISD::isNormalLoad(N);
}
static SDValue bitcastf32Toi32(SDValue Op, SelectionDAG &DAG) {
if (isFloatingPointZero(Op))
return DAG.getConstant(0, MVT::i32);
if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Op))
return DAG.getLoad(MVT::i32, Op.getDebugLoc(),
Ld->getChain(), Ld->getBasePtr(),
Ld->getSrcValue(), Ld->getSrcValueOffset(),
Ld->isVolatile(), Ld->isNonTemporal(),
Ld->getAlignment());
llvm_unreachable("Unknown VFP cmp argument!");
}
static void expandf64Toi32(SDValue Op, SelectionDAG &DAG,
SDValue &RetVal1, SDValue &RetVal2) {
if (isFloatingPointZero(Op)) {
RetVal1 = DAG.getConstant(0, MVT::i32);
RetVal2 = DAG.getConstant(0, MVT::i32);
return;
}
if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Op)) {
SDValue Ptr = Ld->getBasePtr();
RetVal1 = DAG.getLoad(MVT::i32, Op.getDebugLoc(),
Ld->getChain(), Ptr,
Ld->getSrcValue(), Ld->getSrcValueOffset(),
Ld->isVolatile(), Ld->isNonTemporal(),
Ld->getAlignment());
EVT PtrType = Ptr.getValueType();
unsigned NewAlign = MinAlign(Ld->getAlignment(), 4);
SDValue NewPtr = DAG.getNode(ISD::ADD, Op.getDebugLoc(),
PtrType, Ptr, DAG.getConstant(4, PtrType));
RetVal2 = DAG.getLoad(MVT::i32, Op.getDebugLoc(),
Ld->getChain(), NewPtr,
Ld->getSrcValue(), Ld->getSrcValueOffset() + 4,
Ld->isVolatile(), Ld->isNonTemporal(),
NewAlign);
return;
}
llvm_unreachable("Unknown VFP cmp argument!");
}
/// OptimizeVFPBrcond - With -enable-unsafe-fp-math, it's legal to optimize some
/// f32 and even f64 comparisons to integer ones.
SDValue
ARMTargetLowering::OptimizeVFPBrcond(SDValue Op, SelectionDAG &DAG) const {
SDValue Chain = Op.getOperand(0);
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
SDValue LHS = Op.getOperand(2);
SDValue RHS = Op.getOperand(3);
SDValue Dest = Op.getOperand(4);
SDValue LHS = Op.getOperand(2);
SDValue RHS = Op.getOperand(3);
SDValue Dest = Op.getOperand(4);
DebugLoc dl = Op.getDebugLoc();
bool SeenZero = false;
if (canChangeToInt(LHS, SeenZero, Subtarget) &&
canChangeToInt(RHS, SeenZero, Subtarget) &&
// If one of the operand is zero, it's safe to ignore the NaN case.
(FiniteOnlyFPMath() || SeenZero)) {
// If unsafe fp math optimization is enabled and there are no othter uses of
// the CMP operands, and the condition code is EQ oe NE, we can optimize it
// to an integer comparison.
if (CC == ISD::SETOEQ)
CC = ISD::SETEQ;
else if (CC == ISD::SETUNE)
CC = ISD::SETNE;
SDValue ARMcc;
if (LHS.getValueType() == MVT::f32) {
LHS = bitcastf32Toi32(LHS, DAG);
RHS = bitcastf32Toi32(RHS, DAG);
SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl);
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
return DAG.getNode(ARMISD::BRCOND, dl, MVT::Other,
Chain, Dest, ARMcc, CCR, Cmp);
}
SDValue LHS1, LHS2;
SDValue RHS1, RHS2;
expandf64Toi32(LHS, DAG, LHS1, LHS2);
expandf64Toi32(RHS, DAG, RHS1, RHS2);
ARMCC::CondCodes CondCode = IntCCToARMCC(CC);
ARMcc = DAG.getConstant(CondCode, MVT::i32);
SDVTList VTList = DAG.getVTList(MVT::Other, MVT::Flag);
SDValue Ops[] = { Chain, ARMcc, LHS1, LHS2, RHS1, RHS2, Dest };
return DAG.getNode(ARMISD::BCC_i64, dl, VTList, Ops, 7);
}
return SDValue();
}
SDValue ARMTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
SDValue Chain = Op.getOperand(0);
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
SDValue LHS = Op.getOperand(2);
SDValue RHS = Op.getOperand(3);
SDValue Dest = Op.getOperand(4);
DebugLoc dl = Op.getDebugLoc();
if (LHS.getValueType() == MVT::i32) {
SDValue ARMCC;
SDValue ARMcc;
SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMcc, DAG, dl);
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
SDValue Cmp = getARMCmp(LHS, RHS, CC, ARMCC, DAG, dl);
return DAG.getNode(ARMISD::BRCOND, dl, MVT::Other,
Chain, Dest, ARMCC, CCR,Cmp);
Chain, Dest, ARMcc, CCR, Cmp);
}
assert(LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64);
if (UnsafeFPMath &&
(CC == ISD::SETEQ || CC == ISD::SETOEQ ||
CC == ISD::SETNE || CC == ISD::SETUNE)) {
SDValue Result = OptimizeVFPBrcond(Op, DAG);
if (Result.getNode())
return Result;
}
ARMCC::CondCodes CondCode, CondCode2;
FPCCToARMCC(CC, CondCode, CondCode2);
SDValue ARMCC = DAG.getConstant(CondCode, MVT::i32);
SDValue Cmp = getVFPCmp(LHS, RHS, CC, ARMCC, DAG, dl);
SDValue ARMcc = DAG.getConstant(CondCode, MVT::i32);
SDValue Cmp = getVFPCmp(LHS, RHS, DAG, dl);
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
SDVTList VTList = DAG.getVTList(MVT::Other, MVT::Flag);
SDValue Ops[] = { Chain, Dest, ARMCC, CCR, Cmp };
SDValue Ops[] = { Chain, Dest, ARMcc, CCR, Cmp };
SDValue Res = DAG.getNode(ARMISD::BRCOND, dl, VTList, Ops, 5);
if (CondCode2 != ARMCC::AL) {
ARMCC = DAG.getConstant(CondCode2, MVT::i32);
SDValue Ops[] = { Res, Dest, ARMCC, CCR, Res.getValue(1) };
ARMcc = DAG.getConstant(CondCode2, MVT::i32);
SDValue Ops[] = { Res, Dest, ARMcc, CCR, Res.getValue(1) };
Res = DAG.getNode(ARMISD::BRCOND, dl, VTList, Ops, 5);
}
return Res;
@ -2469,12 +2563,11 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
EVT VT = Op.getValueType();
EVT SrcVT = Tmp1.getValueType();
SDValue AbsVal = DAG.getNode(ISD::FABS, dl, VT, Tmp0);
SDValue ARMCC = DAG.getConstant(ARMCC::LT, MVT::i32);
SDValue ARMcc = DAG.getConstant(ARMCC::LT, MVT::i32);
SDValue FP0 = DAG.getConstantFP(0.0, SrcVT);
SDValue Cmp = getVFPCmp(Tmp1, FP0,
ISD::SETLT, ARMCC, DAG, dl);
SDValue Cmp = getVFPCmp(Tmp1, FP0, DAG, dl);
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
return DAG.getNode(ARMISD::CNEG, dl, VT, AbsVal, AbsVal, ARMCC, CCR, Cmp);
return DAG.getNode(ARMISD::CNEG, dl, VT, AbsVal, AbsVal, ARMcc, CCR, Cmp);
}
SDValue ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const{
@ -2553,51 +2646,18 @@ static SDValue ExpandBIT_CONVERT(SDNode *N, SelectionDAG &DAG) {
}
/// getZeroVector - Returns a vector of specified type with all zero elements.
///
/// Zero vectors are used to represent vector negation and in those cases
/// will be implemented with the NEON VNEG instruction. However, VNEG does
/// not support i64 elements, so sometimes the zero vectors will need to be
/// explicitly constructed. Regardless, use a canonical VMOV to create the
/// zero vector.
static SDValue getZeroVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) {
assert(VT.isVector() && "Expected a vector type");
// Zero vectors are used to represent vector negation and in those cases
// will be implemented with the NEON VNEG instruction. However, VNEG does
// not support i64 elements, so sometimes the zero vectors will need to be
// explicitly constructed. For those cases, and potentially other uses in
// the future, always build zero vectors as <16 x i8> or <8 x i8> bitcasted
// to their dest type. This ensures they get CSE'd.
SDValue Vec;
SDValue Cst = DAG.getTargetConstant(0, MVT::i8);
SmallVector<SDValue, 8> Ops;
MVT TVT;
if (VT.getSizeInBits() == 64) {
Ops.assign(8, Cst); TVT = MVT::v8i8;
} else {
Ops.assign(16, Cst); TVT = MVT::v16i8;
}
Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, TVT, &Ops[0], Ops.size());
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vec);
}
/// getOnesVector - Returns a vector of specified type with all bits set.
///
static SDValue getOnesVector(EVT VT, SelectionDAG &DAG, DebugLoc dl) {
assert(VT.isVector() && "Expected a vector type");
// Always build ones vectors as <16 x i8> or <8 x i8> bitcasted to their
// dest type. This ensures they get CSE'd.
SDValue Vec;
SDValue Cst = DAG.getTargetConstant(0xFF, MVT::i8);
SmallVector<SDValue, 8> Ops;
MVT TVT;
if (VT.getSizeInBits() == 64) {
Ops.assign(8, Cst); TVT = MVT::v8i8;
} else {
Ops.assign(16, Cst); TVT = MVT::v16i8;
}
Vec = DAG.getNode(ISD::BUILD_VECTOR, dl, TVT, &Ops[0], Ops.size());
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vec);
// The canonical modified immediate encoding of a zero vector is....0!
SDValue EncodedVal = DAG.getTargetConstant(0, MVT::i32);
EVT VmovVT = VT.is128BitVector() ? MVT::v4i32 : MVT::v2i32;
SDValue Vmov = DAG.getNode(ARMISD::VMOVIMM, dl, VmovVT, EncodedVal);
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vmov);
}
/// LowerShiftRightParts - Lower SRA_PARTS, which returns two
@ -2611,7 +2671,7 @@ SDValue ARMTargetLowering::LowerShiftRightParts(SDValue Op,
SDValue ShOpLo = Op.getOperand(0);
SDValue ShOpHi = Op.getOperand(1);
SDValue ShAmt = Op.getOperand(2);
SDValue ARMCC;
SDValue ARMcc;
unsigned Opc = (Op.getOpcode() == ISD::SRA_PARTS) ? ISD::SRA : ISD::SRL;
assert(Op.getOpcode() == ISD::SRA_PARTS || Op.getOpcode() == ISD::SRL_PARTS);
@ -2627,9 +2687,9 @@ SDValue ARMTargetLowering::LowerShiftRightParts(SDValue Op,
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
SDValue Cmp = getARMCmp(ExtraShAmt, DAG.getConstant(0, MVT::i32), ISD::SETGE,
ARMCC, DAG, dl);
ARMcc, DAG, dl);
SDValue Hi = DAG.getNode(Opc, dl, VT, ShOpHi, ShAmt);
SDValue Lo = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMCC,
SDValue Lo = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, TrueVal, ARMcc,
CCR, Cmp);
SDValue Ops[2] = { Lo, Hi };
@ -2647,7 +2707,7 @@ SDValue ARMTargetLowering::LowerShiftLeftParts(SDValue Op,
SDValue ShOpLo = Op.getOperand(0);
SDValue ShOpHi = Op.getOperand(1);
SDValue ShAmt = Op.getOperand(2);
SDValue ARMCC;
SDValue ARMcc;
assert(Op.getOpcode() == ISD::SHL_PARTS);
SDValue RevShAmt = DAG.getNode(ISD::SUB, dl, MVT::i32,
@ -2661,9 +2721,9 @@ SDValue ARMTargetLowering::LowerShiftLeftParts(SDValue Op,
SDValue FalseVal = DAG.getNode(ISD::OR, dl, VT, Tmp1, Tmp2);
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
SDValue Cmp = getARMCmp(ExtraShAmt, DAG.getConstant(0, MVT::i32), ISD::SETGE,
ARMCC, DAG, dl);
ARMcc, DAG, dl);
SDValue Lo = DAG.getNode(ISD::SHL, dl, VT, ShOpLo, ShAmt);
SDValue Hi = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, Tmp3, ARMCC,
SDValue Hi = DAG.getNode(ARMISD::CMOV, dl, VT, FalseVal, Tmp3, ARMcc,
CCR, Cmp);
SDValue Ops[2] = { Lo, Hi };
@ -2850,13 +2910,11 @@ static SDValue LowerVSETCC(SDValue Op, SelectionDAG &DAG) {
/// isNEONModifiedImm - Check if the specified splat value corresponds to a
/// valid vector constant for a NEON instruction with a "modified immediate"
/// operand (e.g., VMOV). If so, return either the constant being
/// splatted or the encoded value, depending on the DoEncode parameter.
/// operand (e.g., VMOV). If so, return the encoded value.
static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
unsigned SplatBitSize, SelectionDAG &DAG,
bool isVMOV, bool DoEncode) {
EVT &VT, bool is128Bits, bool isVMOV) {
unsigned OpCmode, Imm;
EVT VT;
// SplatBitSize is set to the smallest size that splats the vector, so a
// zero vector will always have SplatBitSize == 8. However, NEON modified
@ -2868,16 +2926,18 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
switch (SplatBitSize) {
case 8:
if (!isVMOV)
return SDValue();
// Any 1-byte value is OK. Op=0, Cmode=1110.
assert((SplatBits & ~0xff) == 0 && "one byte splat value is too big");
OpCmode = 0xe;
Imm = SplatBits;
VT = MVT::i8;
VT = is128Bits ? MVT::v16i8 : MVT::v8i8;
break;
case 16:
// NEON's 16-bit VMOV supports splat values where only one byte is nonzero.
VT = MVT::i16;
VT = is128Bits ? MVT::v8i16 : MVT::v4i16;
if ((SplatBits & ~0xff) == 0) {
// Value = 0x00nn: Op=x, Cmode=100x.
OpCmode = 0x8;
@ -2897,7 +2957,7 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
// * only one byte is nonzero, or
// * the least significant byte is 0xff and the second byte is nonzero, or
// * the least significant 2 bytes are 0xff and the third is nonzero.
VT = MVT::i32;
VT = is128Bits ? MVT::v4i32 : MVT::v2i32;
if ((SplatBits & ~0xff) == 0) {
// Value = 0x000000nn: Op=x, Cmode=000x.
OpCmode = 0;
@ -2949,9 +3009,9 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
return SDValue();
case 64: {
// NEON has a 64-bit VMOV splat where each byte is either 0 or 0xff.
if (!isVMOV)
return SDValue();
// NEON has a 64-bit VMOV splat where each byte is either 0 or 0xff.
uint64_t BitMask = 0xff;
uint64_t Val = 0;
unsigned ImmMask = 1;
@ -2969,7 +3029,7 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
// Op=1, Cmode=1110.
OpCmode = 0x1e;
SplatBits = Val;
VT = MVT::i64;
VT = is128Bits ? MVT::v2i64 : MVT::v1i64;
break;
}
@ -2978,32 +3038,8 @@ static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef,
return SDValue();
}
if (DoEncode) {
unsigned EncodedVal = ARM_AM::createNEONModImm(OpCmode, Imm);
return DAG.getTargetConstant(EncodedVal, MVT::i32);
}
return DAG.getTargetConstant(SplatBits, VT);
}
/// getNEONModImm - If this is a valid vector constant for a NEON instruction
/// with a "modified immediate" operand (e.g., VMOV) of the specified element
/// size, return the encoded value for that immediate. The ByteSize field
/// indicates the number of bytes of each element [1248].
SDValue ARM::getNEONModImm(SDNode *N, unsigned ByteSize, bool isVMOV,
SelectionDAG &DAG) {
BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(N);
APInt SplatBits, SplatUndef;
unsigned SplatBitSize;
bool HasAnyUndefs;
if (! BVN || ! BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize,
HasAnyUndefs, ByteSize * 8))
return SDValue();
if (SplatBitSize > ByteSize * 8)
return SDValue();
return isNEONModifiedImm(SplatBits.getZExtValue(), SplatUndef.getZExtValue(),
SplatBitSize, DAG, isVMOV, true);
unsigned EncodedVal = ARM_AM::createNEONModImm(OpCmode, Imm);
return DAG.getTargetConstant(EncodedVal, MVT::i32);
}
static bool isVEXTMask(const SmallVectorImpl<int> &M, EVT VT,
@ -3194,43 +3230,6 @@ static bool isVZIP_v_undef_Mask(const SmallVectorImpl<int> &M, EVT VT,
return true;
}
static SDValue BuildSplat(SDValue Val, EVT VT, SelectionDAG &DAG, DebugLoc dl) {
// Canonicalize all-zeros and all-ones vectors.
ConstantSDNode *ConstVal = cast<ConstantSDNode>(Val.getNode());
if (ConstVal->isNullValue())
return getZeroVector(VT, DAG, dl);
if (ConstVal->isAllOnesValue())
return getOnesVector(VT, DAG, dl);
EVT CanonicalVT;
if (VT.is64BitVector()) {
switch (Val.getValueType().getSizeInBits()) {
case 8: CanonicalVT = MVT::v8i8; break;
case 16: CanonicalVT = MVT::v4i16; break;
case 32: CanonicalVT = MVT::v2i32; break;
case 64: CanonicalVT = MVT::v1i64; break;
default: llvm_unreachable("unexpected splat element type"); break;
}
} else {
assert(VT.is128BitVector() && "unknown splat vector size");
switch (Val.getValueType().getSizeInBits()) {
case 8: CanonicalVT = MVT::v16i8; break;
case 16: CanonicalVT = MVT::v8i16; break;
case 32: CanonicalVT = MVT::v4i32; break;
case 64: CanonicalVT = MVT::v2i64; break;
default: llvm_unreachable("unexpected splat element type"); break;
}
}
// Build a canonical splat for this value.
SmallVector<SDValue, 8> Ops;
Ops.assign(CanonicalVT.getVectorNumElements(), Val);
SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, dl, CanonicalVT, &Ops[0],
Ops.size());
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Res);
}
// If this is a case we can't handle, return null and let the default
// expansion code take care of it.
static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
@ -3244,11 +3243,25 @@ static SDValue LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
if (BVN->isConstantSplat(SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs)) {
if (SplatBitSize <= 64) {
// Check if an immediate VMOV works.
EVT VmovVT;
SDValue Val = isNEONModifiedImm(SplatBits.getZExtValue(),
SplatUndef.getZExtValue(),
SplatBitSize, DAG, true, false);
if (Val.getNode())
return BuildSplat(Val, VT, DAG, dl);
SplatUndef.getZExtValue(), SplatBitSize,
DAG, VmovVT, VT.is128BitVector(), true);
if (Val.getNode()) {
SDValue Vmov = DAG.getNode(ARMISD::VMOVIMM, dl, VmovVT, Val);
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vmov);
}
// Try an immediate VMVN.
uint64_t NegatedImm = (SplatBits.getZExtValue() ^
((1LL << SplatBitSize) - 1));
Val = isNEONModifiedImm(NegatedImm,
SplatUndef.getZExtValue(), SplatBitSize,
DAG, VmovVT, VT.is128BitVector(), false);
if (Val.getNode()) {
SDValue Vmov = DAG.getNode(ARMISD::VMVNIMM, dl, VmovVT, Val);
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Vmov);
}
}
}
@ -3825,6 +3838,15 @@ ARMTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
return BB;
}
static
MachineBasicBlock *OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ) {
for (MachineBasicBlock::succ_iterator I = MBB->succ_begin(),
E = MBB->succ_end(); I != E; ++I)
if (*I != Succ)
return *I;
llvm_unreachable("Expecting a BB with two successors!");
}
MachineBasicBlock *
ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const {
@ -3941,6 +3963,46 @@ ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
return BB;
}
case ARM::BCCi64:
case ARM::BCCZi64: {
// Compare both parts that make up the double comparison separately for
// equality.
bool RHSisZero = MI->getOpcode() == ARM::BCCZi64;
unsigned LHS1 = MI->getOperand(1).getReg();
unsigned LHS2 = MI->getOperand(2).getReg();
if (RHSisZero) {
AddDefaultPred(BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
.addReg(LHS1).addImm(0));
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPri : ARM::CMPri))
.addReg(LHS2).addImm(0)
.addImm(ARMCC::EQ).addReg(ARM::CPSR);
} else {
unsigned RHS1 = MI->getOperand(3).getReg();
unsigned RHS2 = MI->getOperand(4).getReg();
AddDefaultPred(BuildMI(BB, dl,
TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
.addReg(LHS1).addReg(RHS1));
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2CMPrr : ARM::CMPrr))
.addReg(LHS2).addReg(RHS2)
.addImm(ARMCC::EQ).addReg(ARM::CPSR);
}
MachineBasicBlock *destMBB = MI->getOperand(RHSisZero ? 3 : 5).getMBB();
MachineBasicBlock *exitMBB = OtherSucc(BB, destMBB);
if (MI->getOperand(0).getImm() == ARMCC::NE)
std::swap(destMBB, exitMBB);
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2Bcc : ARM::Bcc))
.addMBB(destMBB).addImm(ARMCC::EQ).addReg(ARM::CPSR);
BuildMI(BB, dl, TII->get(isThumb2 ? ARM::t2B : ARM::B))
.addMBB(exitMBB);
MI->eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
case ARM::tANDsp:
case ARM::tADDspr_:
case ARM::tSUBspi_:
@ -4180,6 +4242,35 @@ static SDValue PerformVMOVRRDCombine(SDNode *N,
return SDValue();
}
/// PerformVDUPLANECombine - Target-specific dag combine xforms for
/// ARMISD::VDUPLANE.
static SDValue PerformVDUPLANECombine(SDNode *N,
TargetLowering::DAGCombinerInfo &DCI) {
// If the source is already a VMOVIMM or VMVNIMM splat, the VDUPLANE is
// redundant.
SDValue Op = N->getOperand(0);
EVT VT = N->getValueType(0);
// Ignore bit_converts.
while (Op.getOpcode() == ISD::BIT_CONVERT)
Op = Op.getOperand(0);
if (Op.getOpcode() != ARMISD::VMOVIMM && Op.getOpcode() != ARMISD::VMVNIMM)
return SDValue();
// Make sure the VMOV element size is not bigger than the VDUPLANE elements.
unsigned EltSize = Op.getValueType().getVectorElementType().getSizeInBits();
// The canonical VMOV for a zero vector uses a 32-bit element size.
unsigned Imm = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
unsigned EltBits;
if (ARM_AM::decodeNEONModImm(Imm, EltBits) == 0)
EltSize = 8;
if (EltSize > VT.getVectorElementType().getSizeInBits())
return SDValue();
SDValue Res = DCI.DAG.getNode(ISD::BIT_CONVERT, N->getDebugLoc(), VT, Op);
return DCI.CombineTo(N, Res, false);
}
/// getVShiftImm - Check if this is a valid build_vector for the immediate
/// operand of a vector shift operation, where all the elements of the
/// build_vector must have the same constant integer value.
@ -4558,6 +4649,7 @@ SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N,
case ISD::SUB: return PerformSUBCombine(N, DCI);
case ISD::MUL: return PerformMULCombine(N, DCI, Subtarget);
case ARMISD::VMOVRRD: return PerformVMOVRRDCombine(N, DCI);
case ARMISD::VDUPLANE: return PerformVDUPLANECombine(N, DCI);
case ISD::INTRINSIC_WO_CHAIN: return PerformIntrinsicCombine(N, DCI.DAG);
case ISD::SHL:
case ISD::SRA:

View file

@ -53,6 +53,8 @@ namespace llvm {
CMOV, // ARM conditional move instructions.
CNEG, // ARM conditional negate instructions.
BCC_i64,
RBIT, // ARM bitreverse instruction
FTOSI, // FP to sint within a FP register.
@ -122,6 +124,10 @@ namespace llvm {
VGETLANEu, // zero-extend vector extract element
VGETLANEs, // sign-extend vector extract element
// Vector move immediate and move negated immediate:
VMOVIMM,
VMVNIMM,
// Vector duplicate:
VDUP,
VDUPLANE,
@ -150,13 +156,6 @@ namespace llvm {
/// Define some predicates that are used for node matching.
namespace ARM {
/// getNEONModImm - If this is a valid vector constant for a NEON
/// instruction with a "modified immediate" operand (e.g., VMOV) of the
/// specified element size, return the encoded value for that immediate.
/// The ByteSize field indicates the number of bytes of each element [1248].
SDValue getNEONModImm(SDNode *N, unsigned ByteSize, bool isVMOV,
SelectionDAG &DAG);
/// getVFPf32Imm / getVFPf64Imm - If the given fp immediate can be
/// materialized with a VMOV.f32 / VMOV.f64 (i.e. fconsts / fconstd)
/// instruction, returns its 8-bit integer representation. Otherwise,
@ -363,9 +362,11 @@ namespace llvm {
DebugLoc dl, SelectionDAG &DAG) const;
SDValue getARMCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
SDValue &ARMCC, SelectionDAG &DAG, DebugLoc dl) const;
SDValue getVFPCmp(SDValue &LHS, SDValue &RHS, ISD::CondCode CC,
SDValue &ARMCC, SelectionDAG &DAG, DebugLoc dl) const;
SDValue &ARMcc, SelectionDAG &DAG, DebugLoc dl) const;
SDValue getVFPCmp(SDValue LHS, SDValue RHS,
SelectionDAG &DAG, DebugLoc dl) const;
SDValue OptimizeVFPBrcond(SDValue Op, SelectionDAG &DAG) const;
MachineBasicBlock *EmitAtomicCmpSwap(MachineInstr *MI,
MachineBasicBlock *BB,

View file

@ -38,6 +38,12 @@ def SDT_ARMBr2JT : SDTypeProfile<0, 4,
[SDTCisPtrTy<0>, SDTCisVT<1, i32>,
SDTCisVT<2, i32>, SDTCisVT<3, i32>]>;
def SDT_ARMBCC_i64 : SDTypeProfile<0, 6,
[SDTCisVT<0, i32>,
SDTCisVT<1, i32>, SDTCisVT<2, i32>,
SDTCisVT<3, i32>, SDTCisVT<4, i32>,
SDTCisVT<5, OtherVT>]>;
def SDT_ARMCmp : SDTypeProfile<0, 2, [SDTCisSameAs<0, 1>]>;
def SDT_ARMPICAdd : SDTypeProfile<1, 2, [SDTCisSameAs<0, 1>,
@ -90,6 +96,9 @@ def ARMbrjt : SDNode<"ARMISD::BR_JT", SDT_ARMBrJT,
def ARMbr2jt : SDNode<"ARMISD::BR2_JT", SDT_ARMBr2JT,
[SDNPHasChain]>;
def ARMBcci64 : SDNode<"ARMISD::BCC_i64", SDT_ARMBCC_i64,
[SDNPHasChain]>;
def ARMcmp : SDNode<"ARMISD::CMP", SDT_ARMCmp,
[SDNPOutFlag]>;
@ -1685,13 +1694,19 @@ def RSCSrs : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b),
}
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
// The assume-no-carry-in form uses the negation of the input since add/sub
// assume opposite meanings of the carry flag (i.e., carry == !borrow).
// See the definition of AddWithCarry() in the ARM ARM A2.2.1 for the gory
// details.
def : ARMPat<(add GPR:$src, so_imm_neg:$imm),
(SUBri GPR:$src, so_imm_neg:$imm)>;
//def : ARMPat<(addc GPR:$src, so_imm_neg:$imm),
// (SUBSri GPR:$src, so_imm_neg:$imm)>;
//def : ARMPat<(adde GPR:$src, so_imm_neg:$imm),
// (SBCri GPR:$src, so_imm_neg:$imm)>;
def : ARMPat<(addc GPR:$src, so_imm_neg:$imm),
(SUBSri GPR:$src, so_imm_neg:$imm)>;
// The with-carry-in form matches bitwise not instead of the negation.
// Effectively, the inverse interpretation of the carry flag already accounts
// for part of the negation.
def : ARMPat<(adde GPR:$src, so_imm_not:$imm),
(SBCri GPR:$src, so_imm_not:$imm)>;
// Note: These are implemented in C++ code, because they have to generate
// ADD/SUBrs instructions, which use a complex pattern that a xform function
@ -2279,6 +2294,22 @@ defm CMNz : AI1_cmp_irs<0b1011, "cmn",
def : ARMPat<(ARMcmpZ GPR:$src, so_imm_neg:$imm),
(CMNzri GPR:$src, so_imm_neg:$imm)>;
// Pseudo i64 compares for some floating point compares.
let usesCustomInserter = 1, isBranch = 1, isTerminator = 1,
Defs = [CPSR] in {
def BCCi64 : PseudoInst<(outs),
(ins i32imm:$cc, GPR:$lhs1, GPR:$lhs2, GPR:$rhs1, GPR:$rhs2, brtarget:$dst),
IIC_Br,
"${:comment} B\t$dst GPR:$lhs1, GPR:$lhs2, GPR:$rhs1, GPR:$rhs2, imm:$cc",
[(ARMBcci64 imm:$cc, GPR:$lhs1, GPR:$lhs2, GPR:$rhs1, GPR:$rhs2, bb:$dst)]>;
def BCCZi64 : PseudoInst<(outs),
(ins i32imm:$cc, GPR:$lhs1, GPR:$lhs2, brtarget:$dst),
IIC_Br,
"${:comment} B\t$dst GPR:$lhs1, GPR:$lhs2, 0, 0, imm:$cc",
[(ARMBcci64 imm:$cc, GPR:$lhs1, GPR:$lhs2, 0, 0, bb:$dst)]>;
} // usesCustomInserter
// Conditional moves
// FIXME: should be able to write a pattern for ARMcmov, but can't use

View file

@ -65,6 +65,10 @@ def SDTARMVGETLN : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisInt<1>,
def NEONvgetlaneu : SDNode<"ARMISD::VGETLANEu", SDTARMVGETLN>;
def NEONvgetlanes : SDNode<"ARMISD::VGETLANEs", SDTARMVGETLN>;
def SDTARMVMOVIMM : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVT<1, i32>]>;
def NEONvmovImm : SDNode<"ARMISD::VMOVIMM", SDTARMVMOVIMM>;
def NEONvmvnImm : SDNode<"ARMISD::VMVNIMM", SDTARMVMOVIMM>;
def NEONvdup : SDNode<"ARMISD::VDUP", SDTypeProfile<1, 1, [SDTCisVec<0>]>>;
// VDUPLANE can produce a quad-register result from a double-register source,
@ -94,6 +98,20 @@ def SDTARMFMAX : SDTypeProfile<1, 2, [SDTCisVT<0, f32>, SDTCisSameAs<0, 1>,
def NEONfmax : SDNode<"ARMISD::FMAX", SDTARMFMAX>;
def NEONfmin : SDNode<"ARMISD::FMIN", SDTARMFMAX>;
def NEONimmAllZerosV: PatLeaf<(NEONvmovImm (i32 timm)), [{
ConstantSDNode *ConstVal = cast<ConstantSDNode>(N->getOperand(0));
unsigned EltBits;
uint64_t EltVal = ARM_AM::decodeNEONModImm(ConstVal->getZExtValue(), EltBits);
return (EltBits == 32 && EltVal == 0);
}]>;
def NEONimmAllOnesV: PatLeaf<(NEONvmovImm (i32 timm)), [{
ConstantSDNode *ConstVal = cast<ConstantSDNode>(N->getOperand(0));
unsigned EltBits;
uint64_t EltVal = ARM_AM::decodeNEONModImm(ConstVal->getZExtValue(), EltBits);
return (EltBits == 8 && EltVal == 0xff);
}]>;
//===----------------------------------------------------------------------===//
// NEON operand definitions
//===----------------------------------------------------------------------===//
@ -2318,10 +2336,10 @@ defm VTST : N3V_QHS<0, 0, 0b1000, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q,
// Vector Bitwise Operations.
def vnot8 : PatFrag<(ops node:$in),
(xor node:$in, (bitconvert (v8i8 immAllOnesV)))>;
def vnot16 : PatFrag<(ops node:$in),
(xor node:$in, (bitconvert (v16i8 immAllOnesV)))>;
def vnotd : PatFrag<(ops node:$in),
(xor node:$in, (bitconvert (v8i8 NEONimmAllOnesV)))>;
def vnotq : PatFrag<(ops node:$in),
(xor node:$in, (bitconvert (v16i8 NEONimmAllOnesV)))>;
// VAND : Vector Bitwise AND
@ -2347,36 +2365,58 @@ def VBICd : N3VX<0, 0, 0b01, 0b0001, 0, 1, (outs DPR:$dst),
(ins DPR:$src1, DPR:$src2), N3RegFrm, IIC_VBINiD,
"vbic", "$dst, $src1, $src2", "",
[(set DPR:$dst, (v2i32 (and DPR:$src1,
(vnot8 DPR:$src2))))]>;
(vnotd DPR:$src2))))]>;
def VBICq : N3VX<0, 0, 0b01, 0b0001, 1, 1, (outs QPR:$dst),
(ins QPR:$src1, QPR:$src2), N3RegFrm, IIC_VBINiQ,
"vbic", "$dst, $src1, $src2", "",
[(set QPR:$dst, (v4i32 (and QPR:$src1,
(vnot16 QPR:$src2))))]>;
(vnotq QPR:$src2))))]>;
// VORN : Vector Bitwise OR NOT
def VORNd : N3VX<0, 0, 0b11, 0b0001, 0, 1, (outs DPR:$dst),
(ins DPR:$src1, DPR:$src2), N3RegFrm, IIC_VBINiD,
"vorn", "$dst, $src1, $src2", "",
[(set DPR:$dst, (v2i32 (or DPR:$src1,
(vnot8 DPR:$src2))))]>;
(vnotd DPR:$src2))))]>;
def VORNq : N3VX<0, 0, 0b11, 0b0001, 1, 1, (outs QPR:$dst),
(ins QPR:$src1, QPR:$src2), N3RegFrm, IIC_VBINiQ,
"vorn", "$dst, $src1, $src2", "",
[(set QPR:$dst, (v4i32 (or QPR:$src1,
(vnot16 QPR:$src2))))]>;
(vnotq QPR:$src2))))]>;
// VMVN : Vector Bitwise NOT (Immediate)
let isReMaterializable = 1 in {
def VMVNv4i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 0, 1, 1, (outs DPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmvn", "i16", "$dst, $SIMM", "",
[(set DPR:$dst, (v4i16 (NEONvmvnImm timm:$SIMM)))]>;
def VMVNv8i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 1, 1, 1, (outs QPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmvn", "i16", "$dst, $SIMM", "",
[(set QPR:$dst, (v8i16 (NEONvmvnImm timm:$SIMM)))]>;
def VMVNv2i32 : N1ModImm<1, 0b000, {?,?,?,?}, 0, 0, 1, 1, (outs DPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmvn", "i32", "$dst, $SIMM", "",
[(set DPR:$dst, (v2i32 (NEONvmvnImm timm:$SIMM)))]>;
def VMVNv4i32 : N1ModImm<1, 0b000, {?,?,?,?}, 0, 1, 1, 1, (outs QPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmvn", "i32", "$dst, $SIMM", "",
[(set QPR:$dst, (v4i32 (NEONvmvnImm timm:$SIMM)))]>;
}
// VMVN : Vector Bitwise NOT
def VMVNd : N2VX<0b11, 0b11, 0b00, 0b00, 0b01011, 0, 0,
(outs DPR:$dst), (ins DPR:$src), IIC_VSUBiD,
"vmvn", "$dst, $src", "",
[(set DPR:$dst, (v2i32 (vnot8 DPR:$src)))]>;
[(set DPR:$dst, (v2i32 (vnotd DPR:$src)))]>;
def VMVNq : N2VX<0b11, 0b11, 0b00, 0b00, 0b01011, 1, 0,
(outs QPR:$dst), (ins QPR:$src), IIC_VSUBiD,
"vmvn", "$dst, $src", "",
[(set QPR:$dst, (v4i32 (vnot16 QPR:$src)))]>;
def : Pat<(v2i32 (vnot8 DPR:$src)), (VMVNd DPR:$src)>;
def : Pat<(v4i32 (vnot16 QPR:$src)), (VMVNq QPR:$src)>;
[(set QPR:$dst, (v4i32 (vnotq QPR:$src)))]>;
def : Pat<(v2i32 (vnotd DPR:$src)), (VMVNd DPR:$src)>;
def : Pat<(v4i32 (vnotq QPR:$src)), (VMVNq QPR:$src)>;
// VBSL : Vector Bitwise Select
def VBSLd : N3VX<1, 0, 0b01, 0b0001, 0, 1, (outs DPR:$dst),
@ -2385,14 +2425,14 @@ def VBSLd : N3VX<1, 0, 0b01, 0b0001, 0, 1, (outs DPR:$dst),
"vbsl", "$dst, $src2, $src3", "$src1 = $dst",
[(set DPR:$dst,
(v2i32 (or (and DPR:$src2, DPR:$src1),
(and DPR:$src3, (vnot8 DPR:$src1)))))]>;
(and DPR:$src3, (vnotd DPR:$src1)))))]>;
def VBSLq : N3VX<1, 0, 0b01, 0b0001, 1, 1, (outs QPR:$dst),
(ins QPR:$src1, QPR:$src2, QPR:$src3),
N3RegFrm, IIC_VCNTiQ,
"vbsl", "$dst, $src2, $src3", "$src1 = $dst",
[(set QPR:$dst,
(v4i32 (or (and QPR:$src2, QPR:$src1),
(and QPR:$src3, (vnot16 QPR:$src1)))))]>;
(and QPR:$src3, (vnotq QPR:$src1)))))]>;
// VBIF : Vector Bitwise Insert if False
// like VBSL but with: "vbif $dst, $src3, $src1", "$src2 = $dst",
@ -2726,20 +2766,19 @@ defm VQABS : N2VInt_QHS<0b11, 0b11, 0b00, 0b01110, 0,
// Vector Negate.
def vneg : PatFrag<(ops node:$in), (sub immAllZerosV, node:$in)>;
def vneg8 : PatFrag<(ops node:$in),
(sub (bitconvert (v8i8 immAllZerosV)), node:$in)>;
def vneg16 : PatFrag<(ops node:$in),
(sub (bitconvert (v16i8 immAllZerosV)), node:$in)>;
def vnegd : PatFrag<(ops node:$in),
(sub (bitconvert (v2i32 NEONimmAllZerosV)), node:$in)>;
def vnegq : PatFrag<(ops node:$in),
(sub (bitconvert (v4i32 NEONimmAllZerosV)), node:$in)>;
class VNEGD<bits<2> size, string OpcodeStr, string Dt, ValueType Ty>
: N2V<0b11, 0b11, size, 0b01, 0b00111, 0, 0, (outs DPR:$dst), (ins DPR:$src),
IIC_VSHLiD, OpcodeStr, Dt, "$dst, $src", "",
[(set DPR:$dst, (Ty (vneg8 DPR:$src)))]>;
[(set DPR:$dst, (Ty (vnegd DPR:$src)))]>;
class VNEGQ<bits<2> size, string OpcodeStr, string Dt, ValueType Ty>
: N2V<0b11, 0b11, size, 0b01, 0b00111, 1, 0, (outs QPR:$dst), (ins QPR:$src),
IIC_VSHLiD, OpcodeStr, Dt, "$dst, $src", "",
[(set QPR:$dst, (Ty (vneg16 QPR:$src)))]>;
[(set QPR:$dst, (Ty (vnegq QPR:$src)))]>;
// VNEG : Vector Negate (integer)
def VNEGs8d : VNEGD<0b00, "vneg", "s8", v8i8>;
@ -2759,12 +2798,12 @@ def VNEGf32q : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 1, 0,
"vneg", "f32", "$dst, $src", "",
[(set QPR:$dst, (v4f32 (fneg QPR:$src)))]>;
def : Pat<(v8i8 (vneg8 DPR:$src)), (VNEGs8d DPR:$src)>;
def : Pat<(v4i16 (vneg8 DPR:$src)), (VNEGs16d DPR:$src)>;
def : Pat<(v2i32 (vneg8 DPR:$src)), (VNEGs32d DPR:$src)>;
def : Pat<(v16i8 (vneg16 QPR:$src)), (VNEGs8q QPR:$src)>;
def : Pat<(v8i16 (vneg16 QPR:$src)), (VNEGs16q QPR:$src)>;
def : Pat<(v4i32 (vneg16 QPR:$src)), (VNEGs32q QPR:$src)>;
def : Pat<(v8i8 (vnegd DPR:$src)), (VNEGs8d DPR:$src)>;
def : Pat<(v4i16 (vnegd DPR:$src)), (VNEGs16d DPR:$src)>;
def : Pat<(v2i32 (vnegd DPR:$src)), (VNEGs32d DPR:$src)>;
def : Pat<(v16i8 (vnegq QPR:$src)), (VNEGs8q QPR:$src)>;
def : Pat<(v8i16 (vnegq QPR:$src)), (VNEGs16q QPR:$src)>;
def : Pat<(v4i32 (vnegq QPR:$src)), (VNEGs32q QPR:$src)>;
// VQNEG : Vector Saturating Negate
defm VQNEG : N2VInt_QHS<0b11, 0b11, 0b00, 0b01111, 0,
@ -2818,74 +2857,42 @@ def VMOVQQQQ : PseudoInst<(outs QQQQPR:$dst), (ins QQQQPR:$src),
// VMOV : Vector Move (Immediate)
// VMOV_get_imm8 xform function: convert build_vector to VMOV.i8 imm.
def VMOV_get_imm8 : SDNodeXForm<build_vector, [{
return ARM::getNEONModImm(N, 1, true, *CurDAG);
}]>;
def vmovImm8 : PatLeaf<(build_vector), [{
return ARM::getNEONModImm(N, 1, true, *CurDAG).getNode() != 0;
}], VMOV_get_imm8>;
// VMOV_get_imm16 xform function: convert build_vector to VMOV.i16 imm.
def VMOV_get_imm16 : SDNodeXForm<build_vector, [{
return ARM::getNEONModImm(N, 2, true, *CurDAG);
}]>;
def vmovImm16 : PatLeaf<(build_vector), [{
return ARM::getNEONModImm(N, 2, true, *CurDAG).getNode() != 0;
}], VMOV_get_imm16>;
// VMOV_get_imm32 xform function: convert build_vector to VMOV.i32 imm.
def VMOV_get_imm32 : SDNodeXForm<build_vector, [{
return ARM::getNEONModImm(N, 4, true, *CurDAG);
}]>;
def vmovImm32 : PatLeaf<(build_vector), [{
return ARM::getNEONModImm(N, 4, true, *CurDAG).getNode() != 0;
}], VMOV_get_imm32>;
// VMOV_get_imm64 xform function: convert build_vector to VMOV.i64 imm.
def VMOV_get_imm64 : SDNodeXForm<build_vector, [{
return ARM::getNEONModImm(N, 8, true, *CurDAG);
}]>;
def vmovImm64 : PatLeaf<(build_vector), [{
return ARM::getNEONModImm(N, 8, true, *CurDAG).getNode() != 0;
}], VMOV_get_imm64>;
let isReMaterializable = 1 in {
def VMOVv8i8 : N1ModImm<1, 0b000, 0b1110, 0, 0, 0, 1, (outs DPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmov", "i8", "$dst, $SIMM", "",
[(set DPR:$dst, (v8i8 vmovImm8:$SIMM))]>;
[(set DPR:$dst, (v8i8 (NEONvmovImm timm:$SIMM)))]>;
def VMOVv16i8 : N1ModImm<1, 0b000, 0b1110, 0, 1, 0, 1, (outs QPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmov", "i8", "$dst, $SIMM", "",
[(set QPR:$dst, (v16i8 vmovImm8:$SIMM))]>;
[(set QPR:$dst, (v16i8 (NEONvmovImm timm:$SIMM)))]>;
def VMOVv4i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 0, 0, 1, (outs DPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmov", "i16", "$dst, $SIMM", "",
[(set DPR:$dst, (v4i16 vmovImm16:$SIMM))]>;
[(set DPR:$dst, (v4i16 (NEONvmovImm timm:$SIMM)))]>;
def VMOVv8i16 : N1ModImm<1, 0b000, {1,0,?,0}, 0, 1, 0, 1, (outs QPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmov", "i16", "$dst, $SIMM", "",
[(set QPR:$dst, (v8i16 vmovImm16:$SIMM))]>;
[(set QPR:$dst, (v8i16 (NEONvmovImm timm:$SIMM)))]>;
def VMOVv2i32 : N1ModImm<1, 0b000, {0,?,?,0}, 0, 0, 0, 1, (outs DPR:$dst),
def VMOVv2i32 : N1ModImm<1, 0b000, {?,?,?,?}, 0, 0, 0, 1, (outs DPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmov", "i32", "$dst, $SIMM", "",
[(set DPR:$dst, (v2i32 vmovImm32:$SIMM))]>;
def VMOVv4i32 : N1ModImm<1, 0b000, {0,?,?,0}, 0, 1, 0, 1, (outs QPR:$dst),
[(set DPR:$dst, (v2i32 (NEONvmovImm timm:$SIMM)))]>;
def VMOVv4i32 : N1ModImm<1, 0b000, {?,?,?,?}, 0, 1, 0, 1, (outs QPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmov", "i32", "$dst, $SIMM", "",
[(set QPR:$dst, (v4i32 vmovImm32:$SIMM))]>;
[(set QPR:$dst, (v4i32 (NEONvmovImm timm:$SIMM)))]>;
def VMOVv1i64 : N1ModImm<1, 0b000, 0b1110, 0, 0, 1, 1, (outs DPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmov", "i64", "$dst, $SIMM", "",
[(set DPR:$dst, (v1i64 vmovImm64:$SIMM))]>;
[(set DPR:$dst, (v1i64 (NEONvmovImm timm:$SIMM)))]>;
def VMOVv2i64 : N1ModImm<1, 0b000, 0b1110, 0, 1, 1, 1, (outs QPR:$dst),
(ins nModImm:$SIMM), IIC_VMOVImm,
"vmov", "i64", "$dst, $SIMM", "",
[(set QPR:$dst, (v2i64 vmovImm64:$SIMM))]>;
[(set QPR:$dst, (v2i64 (NEONvmovImm timm:$SIMM)))]>;
} // isReMaterializable
// VMOV : Vector Get Lane (move scalar to ARM core register)

View file

@ -122,6 +122,10 @@ def imm0_255_neg : PatLeaf<(i32 imm), [{
return (uint32_t)(-N->getZExtValue()) < 255;
}], imm_neg_XFORM>;
def imm0_255_not : PatLeaf<(i32 imm), [{
return (uint32_t)(~N->getZExtValue()) < 255;
}], imm_comp_XFORM>;
// Define Thumb2 specific addressing modes.
// t2addrmode_imm12 := reg + imm12
@ -1391,13 +1395,32 @@ defm t2RSBS : T2I_rbin_s_is <0b1110, "rsb",
BinOpFrag<(subc node:$LHS, node:$RHS)>>;
// (sub X, imm) gets canonicalized to (add X, -imm). Match this form.
// The assume-no-carry-in form uses the negation of the input since add/sub
// assume opposite meanings of the carry flag (i.e., carry == !borrow).
// See the definition of AddWithCarry() in the ARM ARM A2.2.1 for the gory
// details.
// The AddedComplexity preferences the first variant over the others since
// it can be shrunk to a 16-bit wide encoding, while the others cannot.
let AddedComplexity = 1 in
def : T2Pat<(add GPR:$src, imm0_255_neg:$imm),
(t2SUBri GPR:$src, imm0_255_neg:$imm)>;
def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm),
(t2SUBri GPR:$src, t2_so_imm_neg:$imm)>;
def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm),
(t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>;
def : T2Pat<(add GPR:$src, imm0_255_neg:$imm),
(t2SUBri GPR:$src, imm0_255_neg:$imm)>;
def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm),
(t2SUBri GPR:$src, t2_so_imm_neg:$imm)>;
def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm),
(t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>;
let AddedComplexity = 1 in
def : T2Pat<(addc GPR:$src, imm0_255_neg:$imm),
(t2SUBSri GPR:$src, imm0_255_neg:$imm)>;
def : T2Pat<(addc GPR:$src, t2_so_imm_neg:$imm),
(t2SUBSri GPR:$src, t2_so_imm_neg:$imm)>;
// The with-carry-in form matches bitwise not instead of the negation.
// Effectively, the inverse interpretation of the carry flag already accounts
// for part of the negation.
let AddedComplexity = 1 in
def : T2Pat<(adde GPR:$src, imm0_255_not:$imm),
(t2SBCSri GPR:$src, imm0_255_not:$imm)>;
def : T2Pat<(adde GPR:$src, t2_so_imm_not:$imm),
(t2SBCSri GPR:$src, t2_so_imm_not:$imm)>;
// Select Bytes -- for disassembly only
@ -2435,7 +2458,7 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
hasExtraDefRegAllocReq = 1 in
def t2LDM_RET : T2XIt<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
reglist:$dsts, variable_ops), IIC_Br,
"ldm${addr:submode}${p}${addr:wide}\t$addr, $dsts",
"ldm${addr:submode}${p}${addr:wide}\t$addr!, $dsts",
"$addr.addr = $wb", []> {
let Inst{31-27} = 0b11101;
let Inst{26-25} = 0b00;

View file

@ -54,6 +54,9 @@ protected:
/// the VML[AS] instructions are slow (if so, don't use them).
bool SlowVMLx;
/// SlowFPBrcc - True if floating point compare + branch is slow.
bool SlowFPBrcc;
/// IsThumb - True if we are in thumb mode, false if in ARM mode.
bool IsThumb;
@ -133,6 +136,7 @@ protected:
bool hasDivide() const { return HasHardwareDivide; }
bool hasT2ExtractPack() const { return HasT2ExtractPack; }
bool useVMLx() const {return hasVFP2() && !SlowVMLx; }
bool isFPBrccSlow() const { return SlowFPBrcc; }
bool hasFP16() const { return HasFP16; }

View file

@ -88,7 +88,7 @@ private:
/// its register number, or -1 if there is no match. To allow return values
/// to be used directly in register lists, arm registers have values between
/// 0 and 15.
int MatchRegisterName(const StringRef &Name);
int MatchRegisterName(StringRef Name);
/// }
@ -97,7 +97,7 @@ public:
ARMAsmParser(const Target &T, MCAsmParser &_Parser)
: TargetAsmParser(T), Parser(_Parser) {}
virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc,
virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
virtual bool ParseDirective(AsmToken DirectiveID);
@ -517,7 +517,7 @@ bool ARMAsmParser::ParseShift(ShiftType &St,
const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier))
return true;
const StringRef &ShiftName = Tok.getString();
StringRef ShiftName = Tok.getString();
if (ShiftName == "lsl" || ShiftName == "LSL")
St = Lsl;
else if (ShiftName == "lsr" || ShiftName == "LSR")
@ -549,7 +549,7 @@ bool ARMAsmParser::ParseShift(ShiftType &St,
}
/// A hack to allow some testing, to be replaced by a real table gen version.
int ARMAsmParser::MatchRegisterName(const StringRef &Name) {
int ARMAsmParser::MatchRegisterName(StringRef Name) {
if (Name == "r0" || Name == "R0")
return 0;
else if (Name == "r1" || Name == "R1")
@ -593,7 +593,7 @@ MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCInst &Inst) {
ARMOperand &Op0 = *(ARMOperand*)Operands[0];
assert(Op0.Kind == ARMOperand::Token && "First operand not a Token");
const StringRef &Mnemonic = Op0.getToken();
StringRef Mnemonic = Op0.getToken();
if (Mnemonic == "add" ||
Mnemonic == "stmfd" ||
Mnemonic == "str" ||
@ -658,7 +658,7 @@ bool ARMAsmParser::ParseOperand(OwningPtr<ARMOperand> &Op) {
}
/// Parse an arm instruction mnemonic followed by its operands.
bool ARMAsmParser::ParseInstruction(const StringRef &Name, SMLoc NameLoc,
bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
OwningPtr<ARMOperand> Op;
ARMOperand::CreateToken(Op, Name, NameLoc);
@ -761,7 +761,7 @@ bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
const AsmToken &Tok = Parser.getTok();
if (Tok.isNot(AsmToken::Identifier))
return Error(L, "unexpected token in .syntax directive");
const StringRef &Mode = Tok.getString();
StringRef Mode = Tok.getString();
if (Mode == "unified" || Mode == "UNIFIED")
Parser.Lex();
else if (Mode == "divided" || Mode == "DIVIDED")

View file

@ -602,12 +602,8 @@ void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op,
O << "[" << getRegisterName(MO1.getReg());
if (MO2.getImm()) {
unsigned Align = MO2.getImm();
assert((Align == 8 || Align == 16 || Align == 32) &&
"unexpected NEON load/store alignment");
Align <<= 3;
// FIXME: Both darwin as and GNU as violate ARM docs here.
O << ", :" << Align;
O << ", :" << (MO2.getImm() << 3);
}
O << "]";
}

View file

@ -442,7 +442,7 @@ void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum,
O << "[" << getRegisterName(MO1.getReg());
if (MO2.getImm()) {
// FIXME: Both darwin as and GNU as violate ARM docs here.
O << ", :" << MO2.getImm();
O << ", :" << (MO2.getImm() << 3);
}
O << "]";
}

View file

@ -590,3 +590,70 @@ than the Z bit, we'll need additional logic to reverse the conditionals
associated with the comparison. Perhaps a pseudo-instruction for the comparison,
with a post-codegen pass to clean up and handle the condition codes?
See PR5694 for testcase.
//===---------------------------------------------------------------------===//
Given the following on armv5:
int test1(int A, int B) {
return (A&-8388481)|(B&8388480);
}
We currently generate:
ldr r2, .LCPI0_0
and r0, r0, r2
ldr r2, .LCPI0_1
and r1, r1, r2
orr r0, r1, r0
bx lr
We should be able to replace the second ldr+and with a bic (i.e. reuse the
constant which was already loaded). Not sure what's necessary to do that.
//===---------------------------------------------------------------------===//
Given the following on ARMv7:
int test1(int A, int B) {
return (A&-8388481)|(B&8388480);
}
We currently generate:
bfc r0, #7, #16
movw r2, #:lower16:8388480
movt r2, #:upper16:8388480
and r1, r1, r2
orr r0, r1, r0
bx lr
The following is much shorter:
lsr r1, r1, #7
bfi r0, r1, #7, #16
bx lr
//===---------------------------------------------------------------------===//
The code generated for bswap on armv4/5 (CPUs without rev) is less than ideal:
int a(int x) { return __builtin_bswap32(x); }
a:
mov r1, #255, 24
mov r2, #255, 16
and r1, r1, r0, lsr #8
and r2, r2, r0, lsl #8
orr r1, r1, r0, lsr #24
orr r0, r2, r0, lsl #24
orr r0, r0, r1
bx lr
Something like the following would be better (fewer instructions/registers):
eor r1, r0, r0, ror #16
bic r1, r1, #0xff0000
mov r1, r1, lsr #8
eor r0, r1, r0, ror #8
bx lr
A custom Thumb version would also be a slight improvement over the generic
version.
//===---------------------------------------------------------------------===//

View file

@ -14,7 +14,7 @@
#include "AlphaMCAsmInfo.h"
using namespace llvm;
AlphaMCAsmInfo::AlphaMCAsmInfo(const Target &T, const StringRef &TT) {
AlphaMCAsmInfo::AlphaMCAsmInfo(const Target &T, StringRef TT) {
AlignmentIsInBytes = false;
PrivateGlobalPrefix = "$";
GPRel32Directive = ".gprel32";

View file

@ -14,14 +14,14 @@
#ifndef ALPHATARGETASMINFO_H
#define ALPHATARGETASMINFO_H
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
class Target;
class StringRef;
struct AlphaMCAsmInfo : public MCAsmInfo {
explicit AlphaMCAsmInfo(const Target &T, const StringRef &TT);
explicit AlphaMCAsmInfo(const Target &T, StringRef TT);
};
} // namespace llvm

View file

@ -15,7 +15,7 @@
using namespace llvm;
BlackfinMCAsmInfo::BlackfinMCAsmInfo(const Target &T, const StringRef &TT) {
BlackfinMCAsmInfo::BlackfinMCAsmInfo(const Target &T, StringRef TT) {
GlobalPrefix = "_";
CommentString = "//";
HasSetDirective = false;

View file

@ -14,14 +14,14 @@
#ifndef BLACKFINTARGETASMINFO_H
#define BLACKFINTARGETASMINFO_H
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
class Target;
class StringRef;
struct BlackfinMCAsmInfo : public MCAsmInfo {
explicit BlackfinMCAsmInfo(const Target &T, const StringRef &TT);
explicit BlackfinMCAsmInfo(const Target &T, StringRef TT);
};
} // namespace llvm

View file

@ -14,7 +14,7 @@
#include "SPUMCAsmInfo.h"
using namespace llvm;
SPULinuxMCAsmInfo::SPULinuxMCAsmInfo(const Target &T, const StringRef &TT) {
SPULinuxMCAsmInfo::SPULinuxMCAsmInfo(const Target &T, StringRef TT) {
ZeroDirective = "\t.space\t";
Data64bitsDirective = "\t.quad\t";
AlignmentIsInBytes = false;

View file

@ -14,14 +14,14 @@
#ifndef SPUTARGETASMINFO_H
#define SPUTARGETASMINFO_H
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
class Target;
class StringRef;
struct SPULinuxMCAsmInfo : public MCAsmInfo {
explicit SPULinuxMCAsmInfo(const Target &T, const StringRef &TT);
explicit SPULinuxMCAsmInfo(const Target &T, StringRef TT);
};
} // namespace llvm

View file

@ -14,7 +14,7 @@
#include "MBlazeMCAsmInfo.h"
using namespace llvm;
MBlazeMCAsmInfo::MBlazeMCAsmInfo(const Target &T, const StringRef &TT) {
MBlazeMCAsmInfo::MBlazeMCAsmInfo(const Target &T, StringRef TT) {
AlignmentIsInBytes = false;
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";

View file

@ -14,15 +14,15 @@
#ifndef MBLAZETARGETASMINFO_H
#define MBLAZETARGETASMINFO_H
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
class Target;
class StringRef;
class MBlazeMCAsmInfo : public MCAsmInfo {
public:
explicit MBlazeMCAsmInfo(const Target &T, const StringRef &TT);
explicit MBlazeMCAsmInfo(const Target &T, StringRef TT);
};
} // namespace llvm

View file

@ -1621,8 +1621,7 @@ const char* MSILWriter::getLibraryName(const GlobalVariable* GV) {
}
const char* MSILWriter::getLibraryForSymbol(const StringRef &Name,
bool isFunction,
const char* MSILWriter::getLibraryForSymbol(StringRef Name, bool isFunction,
CallingConv::ID CallingConv) {
// TODO: Read *.def file with function and libraries definitions.
return "MSVCRT.DLL";

View file

@ -246,7 +246,7 @@ namespace llvm {
const char* getLibraryName(const GlobalVariable* GV);
const char* getLibraryForSymbol(const StringRef &Name, bool isFunction,
const char* getLibraryForSymbol(StringRef Name, bool isFunction,
CallingConv::ID CallingConv);
void printExternals();

View file

@ -14,7 +14,7 @@
#include "MSP430MCAsmInfo.h"
using namespace llvm;
MSP430MCAsmInfo::MSP430MCAsmInfo(const Target &T, const StringRef &TT) {
MSP430MCAsmInfo::MSP430MCAsmInfo(const Target &T, StringRef TT) {
PrivateGlobalPrefix = ".L";
WeakRefDirective ="\t.weak\t";
PCSymbol=".";

View file

@ -14,13 +14,14 @@
#ifndef MSP430TARGETASMINFO_H
#define MSP430TARGETASMINFO_H
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
class Target;
class StringRef;
struct MSP430MCAsmInfo : public MCAsmInfo {
explicit MSP430MCAsmInfo(const Target &T, const StringRef &TT);
explicit MSP430MCAsmInfo(const Target &T, StringRef TT);
};
} // namespace llvm

View file

@ -14,7 +14,7 @@
#include "MipsMCAsmInfo.h"
using namespace llvm;
MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, const StringRef &TT) {
MipsMCAsmInfo::MipsMCAsmInfo(const Target &T, StringRef TT) {
AlignmentIsInBytes = false;
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";

View file

@ -14,15 +14,15 @@
#ifndef MIPSTARGETASMINFO_H
#define MIPSTARGETASMINFO_H
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
class Target;
class StringRef;
class MipsMCAsmInfo : public MCAsmInfo {
public:
explicit MipsMCAsmInfo(const Target &T, const StringRef &TT);
explicit MipsMCAsmInfo(const Target &T, StringRef TT);
};
} // namespace llvm

View file

@ -416,7 +416,7 @@ void PIC16DbgInfo::EmitAuxEntry(const std::string VarName, int Aux[], int Num,
if (!TagName.empty()) Tmp += ", " + TagName;
for (int i = 0; i<Num; i++)
Tmp += "," + utostr(Aux[i] && 0xff);
Tmp += "," + utostr(Aux[i] & 0xff);
OS.EmitRawText("\n\t.dim " + Twine(VarName) + ", 1" + Tmp);
}

View file

@ -20,7 +20,7 @@
#include "PIC16ISelLowering.h"
using namespace llvm;
PIC16MCAsmInfo::PIC16MCAsmInfo(const Target &T, const StringRef &TT) {
PIC16MCAsmInfo::PIC16MCAsmInfo(const Target &T, StringRef TT) {
CommentString = ";";
GlobalPrefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
GlobalDirective = "\tglobal\t";

View file

@ -25,7 +25,7 @@ namespace llvm {
const char *RomData16bitsDirective;
const char *RomData32bitsDirective;
public:
PIC16MCAsmInfo(const Target &T, const StringRef &TT);
PIC16MCAsmInfo(const Target &T, StringRef TT);
virtual const char *getDataASDirective(unsigned size, unsigned AS) const;
};

View file

@ -12,10 +12,9 @@
//===----------------------------------------------------------------------===//
#include "SparcMCAsmInfo.h"
#include "llvm/ADT/SmallVector.h"
using namespace llvm;
SparcELFMCAsmInfo::SparcELFMCAsmInfo(const Target &T, const StringRef &TT) {
SparcELFMCAsmInfo::SparcELFMCAsmInfo(const Target &T, StringRef TT) {
Data16bitsDirective = "\t.half\t";
Data32bitsDirective = "\t.word\t";
Data64bitsDirective = 0; // .xword is only supported by V9.

View file

@ -14,13 +14,14 @@
#ifndef SPARCTARGETASMINFO_H
#define SPARCTARGETASMINFO_H
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
class Target;
class StringRef;
struct SparcELFMCAsmInfo : public MCAsmInfo {
explicit SparcELFMCAsmInfo(const Target &T, const StringRef &TT);
explicit SparcELFMCAsmInfo(const Target &T, StringRef TT);
};
} // namespace llvm

View file

@ -16,7 +16,7 @@
#include "llvm/MC/MCSectionELF.h"
using namespace llvm;
SystemZMCAsmInfo::SystemZMCAsmInfo(const Target &T, const StringRef &TT) {
SystemZMCAsmInfo::SystemZMCAsmInfo(const Target &T, StringRef TT) {
PrivateGlobalPrefix = ".L";
WeakRefDirective = "\t.weak\t";
PCSymbol = ".";

View file

@ -21,7 +21,7 @@ namespace llvm {
class StringRef;
struct SystemZMCAsmInfo : public MCAsmInfo {
explicit SystemZMCAsmInfo(const Target &T, const StringRef &TT);
explicit SystemZMCAsmInfo(const Target &T, StringRef TT);
virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const;
};

View file

@ -294,7 +294,7 @@ namespace llvm {
/// option is specified on the command line. If this returns false (default),
/// the code generator is not allowed to assume that FP arithmetic arguments
/// and results are never NaNs or +-Infs.
bool FiniteOnlyFPMath() { return UnsafeFPMath || FiniteOnlyFPMathOption; }
bool FiniteOnlyFPMath() { return FiniteOnlyFPMathOption; }
/// HonorSignDependentRoundingFPMath - Return true if the codegen must assume
/// that the rounding mode of the FPU can change from its default.

View file

@ -65,7 +65,7 @@ public:
X86ATTAsmParser(const Target &T, MCAsmParser &_Parser)
: TargetAsmParser(T), Parser(_Parser) {}
virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc,
virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands);
virtual bool ParseDirective(AsmToken DirectiveID);
@ -602,7 +602,7 @@ X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
}
bool X86ATTAsmParser::
ParseInstruction(const StringRef &Name, SMLoc NameLoc,
ParseInstruction(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
// The various flavors of pushf and popf use Requires<In32BitMode> and
// Requires<In64BitMode>, but the assembler doesn't yet implement that.
@ -612,6 +612,8 @@ ParseInstruction(const StringRef &Name, SMLoc NameLoc,
return Error(NameLoc, "popfl cannot be encoded in 64-bit mode");
else if (Name == "pushfl")
return Error(NameLoc, "pushfl cannot be encoded in 64-bit mode");
else if (Name == "pusha")
return Error(NameLoc, "pusha cannot be encoded in 64-bit mode");
} else {
if (Name == "popfq")
return Error(NameLoc, "popfq cannot be encoded in 32-bit mode");

View file

@ -17,7 +17,6 @@
#include "X86IntelInstPrinter.h"
#include "X86MCInstLower.h"
#include "X86.h"
#include "X86COFF.h"
#include "X86COFFMachineModuleInfo.h"
#include "X86MachineFunctionInfo.h"
#include "X86TargetMachine.h"
@ -35,6 +34,7 @@
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetOptions.h"
@ -60,8 +60,10 @@ bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
if (Subtarget->isTargetCOFF()) {
bool Intrn = MF.getFunction()->hasInternalLinkage();
OutStreamer.BeginCOFFSymbolDef(CurrentFnSym);
OutStreamer.EmitCOFFSymbolStorageClass(Intrn ? COFF::C_STAT : COFF::C_EXT);
OutStreamer.EmitCOFFSymbolType(COFF::DT_FCN << COFF::N_BTSHFT);
OutStreamer.EmitCOFFSymbolStorageClass(Intrn ? COFF::IMAGE_SYM_CLASS_STATIC
: COFF::IMAGE_SYM_CLASS_EXTERNAL);
OutStreamer.EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION
<< COFF::SCT_COMPLEX_TYPE_SHIFT);
OutStreamer.EndCOFFSymbolDef();
}
@ -582,8 +584,9 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) {
E = COFFMMI.externals_end();
I != E; ++I) {
OutStreamer.BeginCOFFSymbolDef(CurrentFnSym);
OutStreamer.EmitCOFFSymbolStorageClass(COFF::C_EXT);
OutStreamer.EmitCOFFSymbolType(COFF::DT_FCN << COFF::N_BTSHFT);
OutStreamer.EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_EXTERNAL);
OutStreamer.EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION
<< COFF::SCT_COMPLEX_TYPE_SHIFT);
OutStreamer.EndCOFFSymbolDef();
}

View file

@ -154,15 +154,13 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
case X86II::MO_TLVP: RefKind = MCSymbolRefExpr::VK_TLVP; break;
case X86II::MO_TLVP_PIC_BASE:
Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_TLVP, Ctx);
// Subtract the pic base.
Expr
= MCBinaryExpr::CreateSub(Expr,
MCSymbolRefExpr::Create(GetPICBaseSymbol(),
Ctx),
Ctx);
break;
Expr = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_TLVP, Ctx);
// Subtract the pic base.
Expr = MCBinaryExpr::CreateSub(Expr,
MCSymbolRefExpr::Create(GetPICBaseSymbol(),
Ctx),
Ctx);
break;
case X86II::MO_TLSGD: RefKind = MCSymbolRefExpr::VK_TLSGD; break;
case X86II::MO_GOTTPOFF: RefKind = MCSymbolRefExpr::VK_GOTTPOFF; break;
case X86II::MO_INDNTPOFF: RefKind = MCSymbolRefExpr::VK_INDNTPOFF; break;

View file

@ -1,95 +0,0 @@
//===--- X86COFF.h - Some definitions from COFF documentations ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file just defines some symbols found in COFF documentation. They are
// used to emit function type information for COFF targets (Cygwin/Mingw32).
//
//===----------------------------------------------------------------------===//
#ifndef X86COFF_H
#define X86COFF_H
namespace COFF
{
/// Storage class tells where and what the symbol represents
enum StorageClass {
C_EFCN = -1, ///< Physical end of function
C_NULL = 0, ///< No symbol
C_AUTO = 1, ///< External definition
C_EXT = 2, ///< External symbol
C_STAT = 3, ///< Static
C_REG = 4, ///< Register variable
C_EXTDEF = 5, ///< External definition
C_LABEL = 6, ///< Label
C_ULABEL = 7, ///< Undefined label
C_MOS = 8, ///< Member of structure
C_ARG = 9, ///< Function argument
C_STRTAG = 10, ///< Structure tag
C_MOU = 11, ///< Member of union
C_UNTAG = 12, ///< Union tag
C_TPDEF = 13, ///< Type definition
C_USTATIC = 14, ///< Undefined static
C_ENTAG = 15, ///< Enumeration tag
C_MOE = 16, ///< Member of enumeration
C_REGPARM = 17, ///< Register parameter
C_FIELD = 18, ///< Bit field
C_BLOCK = 100, ///< ".bb" or ".eb" - beginning or end of block
C_FCN = 101, ///< ".bf" or ".ef" - beginning or end of function
C_EOS = 102, ///< End of structure
C_FILE = 103, ///< File name
C_LINE = 104, ///< Line number, reformatted as symbol
C_ALIAS = 105, ///< Duplicate tag
C_HIDDEN = 106 ///< External symbol in dmert public lib
};
/// The type of the symbol. This is made up of a base type and a derived type.
/// For example, pointer to int is "pointer to T" and "int"
enum SymbolType {
T_NULL = 0, ///< No type info
T_ARG = 1, ///< Void function argument (only used by compiler)
T_VOID = 1, ///< The same as above. Just named differently in some specs.
T_CHAR = 2, ///< Character
T_SHORT = 3, ///< Short integer
T_INT = 4, ///< Integer
T_LONG = 5, ///< Long integer
T_FLOAT = 6, ///< Floating point
T_DOUBLE = 7, ///< Double word
T_STRUCT = 8, ///< Structure
T_UNION = 9, ///< Union
T_ENUM = 10, ///< Enumeration
T_MOE = 11, ///< Member of enumeration
T_UCHAR = 12, ///< Unsigned character
T_USHORT = 13, ///< Unsigned short
T_UINT = 14, ///< Unsigned integer
T_ULONG = 15 ///< Unsigned long
};
/// Derived type of symbol
enum SymbolDerivedType {
DT_NON = 0, ///< No derived type
DT_PTR = 1, ///< Pointer to T
DT_FCN = 2, ///< Function returning T
DT_ARY = 3 ///< Array of T
};
/// Masks for extracting parts of type
enum SymbolTypeMasks {
N_BTMASK = 017, ///< Mask for base type
N_TMASK = 060 ///< Mask for derived type
};
/// Offsets of parts of type
enum Shifts {
N_BTSHFT = 4 ///< Type is formed as (base + derived << N_BTSHIFT)
};
}
#endif // X86COFF_H

View file

@ -540,7 +540,7 @@ bool X86FastISel::X86SelectAddress(const Value *V, X86AddressMode &AM) {
StubAM.GVOpFlags = GVFlags;
// Prepare for inserting code in the local-value area.
MachineBasicBlock::iterator SaveInsertPt = enterLocalValueArea();
SavePoint SaveInsertPt = enterLocalValueArea();
if (TLI.getPointerTy() == MVT::i64) {
Opc = X86::MOV64rm;
@ -1279,12 +1279,11 @@ bool X86FastISel::X86SelectTrunc(const Instruction *I) {
return false;
// First issue a copy to GR16_ABCD or GR32_ABCD.
unsigned CopyOpc = (SrcVT == MVT::i16) ? X86::MOV16rr : X86::MOV32rr;
const TargetRegisterClass *CopyRC = (SrcVT == MVT::i16)
? X86::GR16_ABCDRegisterClass : X86::GR32_ABCDRegisterClass;
unsigned CopyReg = createResultReg(CopyRC);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(CopyOpc), CopyReg)
.addReg(InputReg);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(TargetOpcode::COPY),
CopyReg).addReg(InputReg);
// Then issue an extract_subreg.
unsigned ResultReg = FastEmitInst_extractsubreg(MVT::i8,

View file

@ -2458,17 +2458,23 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
// If the tailcall address may be in a register, then make sure it's
// possible to register allocate for it. In 32-bit, the call address can
// only target EAX, EDX, or ECX since the tail call must be scheduled after
// callee-saved registers are restored. In 64-bit, it's RAX, RCX, RDX, RSI,
// RDI, R8, R9, R11.
if (!isa<GlobalAddressSDNode>(Callee) &&
// callee-saved registers are restored. These happen to be the same
// registers used to pass 'inreg' arguments so watch out for those.
if (!Subtarget->is64Bit() &&
!isa<GlobalAddressSDNode>(Callee) &&
!isa<ExternalSymbolSDNode>(Callee)) {
unsigned Limit = Subtarget->is64Bit() ? 8 : 3;
unsigned NumInRegs = 0;
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
CCValAssign &VA = ArgLocs[i];
if (VA.isRegLoc()) {
if (++NumInRegs == Limit)
if (!VA.isRegLoc())
continue;
unsigned Reg = VA.getLocReg();
switch (Reg) {
default: break;
case X86::EAX: case X86::EDX: case X86::ECX:
if (++NumInRegs == 3)
return false;
break;
}
}
}
@ -7993,7 +7999,6 @@ X86TargetLowering::EmitAtomicBitwiseWithCustomInserter(MachineInstr *bInstr,
unsigned immOpc,
unsigned LoadOpc,
unsigned CXchgOpc,
unsigned copyOpc,
unsigned notOpc,
unsigned EAXreg,
TargetRegisterClass *RC,
@ -8070,7 +8075,7 @@ X86TargetLowering::EmitAtomicBitwiseWithCustomInserter(MachineInstr *bInstr,
MIB.addReg(tt);
(*MIB).addOperand(*argOpers[valArgIndx]);
MIB = BuildMI(newMBB, dl, TII->get(copyOpc), EAXreg);
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), EAXreg);
MIB.addReg(t1);
MIB = BuildMI(newMBB, dl, TII->get(CXchgOpc));
@ -8081,7 +8086,7 @@ X86TargetLowering::EmitAtomicBitwiseWithCustomInserter(MachineInstr *bInstr,
(*MIB).setMemRefs(bInstr->memoperands_begin(),
bInstr->memoperands_end());
MIB = BuildMI(newMBB, dl, TII->get(copyOpc), destOper.getReg());
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), destOper.getReg());
MIB.addReg(EAXreg);
// insert branch
@ -8117,7 +8122,6 @@ X86TargetLowering::EmitAtomicBit6432WithCustomInserter(MachineInstr *bInstr,
const TargetRegisterClass *RC = X86::GR32RegisterClass;
const unsigned LoadOpc = X86::MOV32rm;
const unsigned copyOpc = X86::MOV32rr;
const unsigned NotOpc = X86::NOT32r;
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
const BasicBlock *LLVM_BB = MBB->getBasicBlock();
@ -8227,14 +8231,14 @@ X86TargetLowering::EmitAtomicBit6432WithCustomInserter(MachineInstr *bInstr,
MIB.addReg(t2);
(*MIB).addOperand(*argOpers[valArgIndx + 1]);
MIB = BuildMI(newMBB, dl, TII->get(copyOpc), X86::EAX);
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), X86::EAX);
MIB.addReg(t1);
MIB = BuildMI(newMBB, dl, TII->get(copyOpc), X86::EDX);
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), X86::EDX);
MIB.addReg(t2);
MIB = BuildMI(newMBB, dl, TII->get(copyOpc), X86::EBX);
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), X86::EBX);
MIB.addReg(t5);
MIB = BuildMI(newMBB, dl, TII->get(copyOpc), X86::ECX);
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), X86::ECX);
MIB.addReg(t6);
MIB = BuildMI(newMBB, dl, TII->get(X86::LCMPXCHG8B));
@ -8245,9 +8249,9 @@ X86TargetLowering::EmitAtomicBit6432WithCustomInserter(MachineInstr *bInstr,
(*MIB).setMemRefs(bInstr->memoperands_begin(),
bInstr->memoperands_end());
MIB = BuildMI(newMBB, dl, TII->get(copyOpc), t3);
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), t3);
MIB.addReg(X86::EAX);
MIB = BuildMI(newMBB, dl, TII->get(copyOpc), t4);
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), t4);
MIB.addReg(X86::EDX);
// insert branch
@ -8326,12 +8330,12 @@ X86TargetLowering::EmitAtomicMinMaxWithCustomInserter(MachineInstr *mInstr,
unsigned t2 = F->getRegInfo().createVirtualRegister(X86::GR32RegisterClass);
if (argOpers[valArgIndx]->isReg())
MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rr), t2);
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), t2);
else
MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rr), t2);
(*MIB).addOperand(*argOpers[valArgIndx]);
MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rr), X86::EAX);
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), X86::EAX);
MIB.addReg(t1);
MIB = BuildMI(newMBB, dl, TII->get(X86::CMP32rr));
@ -8353,7 +8357,7 @@ X86TargetLowering::EmitAtomicMinMaxWithCustomInserter(MachineInstr *mInstr,
(*MIB).setMemRefs(mInstr->memoperands_begin(),
mInstr->memoperands_end());
MIB = BuildMI(newMBB, dl, TII->get(X86::MOV32rr), destOper.getReg());
MIB = BuildMI(newMBB, dl, TII->get(TargetOpcode::COPY), destOper.getReg());
MIB.addReg(X86::EAX);
// insert branch
@ -8735,25 +8739,25 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
case X86::ATOMAND32:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND32rr,
X86::AND32ri, X86::MOV32rm,
X86::LCMPXCHG32, X86::MOV32rr,
X86::LCMPXCHG32,
X86::NOT32r, X86::EAX,
X86::GR32RegisterClass);
case X86::ATOMOR32:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::OR32rr,
X86::OR32ri, X86::MOV32rm,
X86::LCMPXCHG32, X86::MOV32rr,
X86::LCMPXCHG32,
X86::NOT32r, X86::EAX,
X86::GR32RegisterClass);
case X86::ATOMXOR32:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::XOR32rr,
X86::XOR32ri, X86::MOV32rm,
X86::LCMPXCHG32, X86::MOV32rr,
X86::LCMPXCHG32,
X86::NOT32r, X86::EAX,
X86::GR32RegisterClass);
case X86::ATOMNAND32:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND32rr,
X86::AND32ri, X86::MOV32rm,
X86::LCMPXCHG32, X86::MOV32rr,
X86::LCMPXCHG32,
X86::NOT32r, X86::EAX,
X86::GR32RegisterClass, true);
case X86::ATOMMIN32:
@ -8768,25 +8772,25 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
case X86::ATOMAND16:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND16rr,
X86::AND16ri, X86::MOV16rm,
X86::LCMPXCHG16, X86::MOV16rr,
X86::LCMPXCHG16,
X86::NOT16r, X86::AX,
X86::GR16RegisterClass);
case X86::ATOMOR16:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::OR16rr,
X86::OR16ri, X86::MOV16rm,
X86::LCMPXCHG16, X86::MOV16rr,
X86::LCMPXCHG16,
X86::NOT16r, X86::AX,
X86::GR16RegisterClass);
case X86::ATOMXOR16:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::XOR16rr,
X86::XOR16ri, X86::MOV16rm,
X86::LCMPXCHG16, X86::MOV16rr,
X86::LCMPXCHG16,
X86::NOT16r, X86::AX,
X86::GR16RegisterClass);
case X86::ATOMNAND16:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND16rr,
X86::AND16ri, X86::MOV16rm,
X86::LCMPXCHG16, X86::MOV16rr,
X86::LCMPXCHG16,
X86::NOT16r, X86::AX,
X86::GR16RegisterClass, true);
case X86::ATOMMIN16:
@ -8801,25 +8805,25 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
case X86::ATOMAND8:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND8rr,
X86::AND8ri, X86::MOV8rm,
X86::LCMPXCHG8, X86::MOV8rr,
X86::LCMPXCHG8,
X86::NOT8r, X86::AL,
X86::GR8RegisterClass);
case X86::ATOMOR8:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::OR8rr,
X86::OR8ri, X86::MOV8rm,
X86::LCMPXCHG8, X86::MOV8rr,
X86::LCMPXCHG8,
X86::NOT8r, X86::AL,
X86::GR8RegisterClass);
case X86::ATOMXOR8:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::XOR8rr,
X86::XOR8ri, X86::MOV8rm,
X86::LCMPXCHG8, X86::MOV8rr,
X86::LCMPXCHG8,
X86::NOT8r, X86::AL,
X86::GR8RegisterClass);
case X86::ATOMNAND8:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND8rr,
X86::AND8ri, X86::MOV8rm,
X86::LCMPXCHG8, X86::MOV8rr,
X86::LCMPXCHG8,
X86::NOT8r, X86::AL,
X86::GR8RegisterClass, true);
// FIXME: There are no CMOV8 instructions; MIN/MAX need some other way.
@ -8827,25 +8831,25 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
case X86::ATOMAND64:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND64rr,
X86::AND64ri32, X86::MOV64rm,
X86::LCMPXCHG64, X86::MOV64rr,
X86::LCMPXCHG64,
X86::NOT64r, X86::RAX,
X86::GR64RegisterClass);
case X86::ATOMOR64:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::OR64rr,
X86::OR64ri32, X86::MOV64rm,
X86::LCMPXCHG64, X86::MOV64rr,
X86::LCMPXCHG64,
X86::NOT64r, X86::RAX,
X86::GR64RegisterClass);
case X86::ATOMXOR64:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::XOR64rr,
X86::XOR64ri32, X86::MOV64rm,
X86::LCMPXCHG64, X86::MOV64rr,
X86::LCMPXCHG64,
X86::NOT64r, X86::RAX,
X86::GR64RegisterClass);
case X86::ATOMNAND64:
return EmitAtomicBitwiseWithCustomInserter(MI, BB, X86::AND64rr,
X86::AND64ri32, X86::MOV64rm,
X86::LCMPXCHG64, X86::MOV64rr,
X86::LCMPXCHG64,
X86::NOT64r, X86::RAX,
X86::GR64RegisterClass, true);
case X86::ATOMMIN64:

View file

@ -764,7 +764,6 @@ namespace llvm {
unsigned immOpc,
unsigned loadOpc,
unsigned cxchgOpc,
unsigned copyOpc,
unsigned notOpc,
unsigned EAXreg,
TargetRegisterClass *RC,

View file

@ -106,6 +106,7 @@ class VEX { bit hasVEXPrefix = 1; }
class VEX_W { bit hasVEX_WPrefix = 1; }
class VEX_4V : VEX { bit hasVEX_4VPrefix = 1; }
class VEX_I8IMM { bit hasVEX_i8ImmReg = 1; }
class VEX_L { bit hasVEX_L = 1; }
class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
string AsmStr, Domain d = GenericDomain>
@ -138,6 +139,7 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
bit hasVEX_4VPrefix = 0; // Does this inst requires the VEX.VVVV field?
bit hasVEX_i8ImmReg = 0; // Does this inst requires the last source register
// to be encoded in a immediate field?
bit hasVEX_L = 0; // Does this inst uses large (256-bit) registers?
// TSFlags layout should be kept in sync with X86InstrInfo.h.
let TSFlags{5-0} = FormBits;
@ -155,6 +157,7 @@ class X86Inst<bits<8> opcod, Format f, ImmType i, dag outs, dag ins,
let TSFlags{33} = hasVEX_WPrefix;
let TSFlags{34} = hasVEX_4VPrefix;
let TSFlags{35} = hasVEX_i8ImmReg;
let TSFlags{36} = hasVEX_L;
}
class I<bits<8> o, Format f, dag outs, dag ins, string asm,

View file

@ -453,7 +453,13 @@ namespace X86II {
// VEX_I8IMM - Specifies that the last register used in a AVX instruction,
// must be encoded in the i8 immediate field. This usually happens in
// instructions with 4 operands.
VEX_I8IMM = 1ULL << 35
VEX_I8IMM = 1ULL << 35,
// VEX_L - Stands for a bit in the VEX opcode prefix meaning the current
// instruction uses 256-bit wide registers. This is usually auto detected if
// a VR256 register is used, but some AVX instructions also have this field
// marked when using a f256 memory references.
VEX_L = 1ULL << 36
};
// getBaseOpcodeFor - This function returns the "base" X86 opcode for the

View file

@ -666,6 +666,9 @@ defm VCVTSS2SI : sse12_cvt_s<0x2D, FR32, GR32, undef, f32mem, load,
defm VCVTDQ2PS : sse12_cvt_p<0x5B, VR128, VR128, undef, f128mem, load,
"cvtdq2ps\t{$src, $dst|$dst, $src}",
SSEPackedSingle>, TB, VEX;
defm VCVTDQ2PSY : sse12_cvt_p<0x5B, VR256, VR256, undef, f256mem, load,
"cvtdq2ps\t{$src, $dst|$dst, $src}",
SSEPackedSingle>, TB, VEX;
}
let Pattern = []<dag> in {
defm CVTSS2SI : sse12_cvt_s<0x2D, FR32, GR32, undef, f32mem, load /*dummy*/,
@ -806,9 +809,13 @@ def Int_CVTDQ2PDrm : I<0xE6, MRMSrcMem, (outs VR128:$dst), (ins i64mem:$src),
// Convert packed single/double fp to doubleword
let isAsmParserOnly = 1 in {
def VCVTPS2DQrr : VPDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvtps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
"cvtps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPS2DQrm : VPDI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
"cvtps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
"cvtps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPS2DQYrr : VPDI<0x5B, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
"cvtps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPS2DQYrm : VPDI<0x5B, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src),
"cvtps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
}
def CVTPS2DQrr : PDI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvtps2dq\t{$src, $dst|$dst, $src}", []>;
@ -862,6 +869,10 @@ def VCVTTPS2DQrr : VSSI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTTPS2DQrm : VSSI<0x5B, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
"cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTTPS2DQYrr : VSSI<0x5B, MRMSrcReg, (outs VR256:$dst), (ins VR256:$src),
"cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTTPS2DQYrm : VSSI<0x5B, MRMSrcMem, (outs VR256:$dst), (ins f256mem:$src),
"cvttps2dq\t{$src, $dst|$dst, $src}", []>, VEX;
}
def CVTTPS2DQrr : SSI<0x5B, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvttps2dq\t{$src, $dst|$dst, $src}", []>;
@ -912,14 +923,39 @@ def Int_CVTTPD2DQrm : PDI<0xE6, MRMSrcMem, (outs VR128:$dst),(ins f128mem:$src),
[(set VR128:$dst, (int_x86_sse2_cvttpd2dq
(memop addr:$src)))]>;
let isAsmParserOnly = 1 in {
// The assembler can recognize rr 256-bit instructions by seeing a ymm
// register, but the same isn't true when using memory operands instead.
// Provide other assembly rr and rm forms to address this explicitly.
def VCVTTPD2DQrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvttpd2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTTPD2DQXrYr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src),
"cvttpd2dq\t{$src, $dst|$dst, $src}", []>, VEX;
// XMM only
def VCVTTPD2DQXrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvttpd2dqx\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTTPD2DQXrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
"cvttpd2dqx\t{$src, $dst|$dst, $src}", []>, VEX;
// YMM only
def VCVTTPD2DQYrr : VPDI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src),
"cvttpd2dqy\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTTPD2DQYrm : VPDI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src),
"cvttpd2dqy\t{$src, $dst|$dst, $src}", []>, VEX, VEX_L;
}
// Convert packed single to packed double
let isAsmParserOnly = 1 in { // SSE2 instructions without OpSize prefix
let isAsmParserOnly = 1, Predicates = [HasAVX] in {
// SSE2 instructions without OpSize prefix
def VCVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX,
Requires<[HasAVX]>;
"vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src),
"vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX,
Requires<[HasAVX]>;
"vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPS2PDYrr : I<0x5A, MRMSrcReg, (outs VR256:$dst), (ins VR128:$src),
"vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPS2PDYrm : I<0x5A, MRMSrcMem, (outs VR256:$dst), (ins f128mem:$src),
"vcvtps2pd\t{$src, $dst|$dst, $src}", []>, VEX;
}
def CVTPS2PDrr : I<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvtps2pd\t{$src, $dst|$dst, $src}", []>, TB;
@ -949,10 +985,25 @@ def Int_CVTPS2PDrm : I<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src),
// Convert packed double to packed single
let isAsmParserOnly = 1 in {
// The assembler can recognize rr 256-bit instructions by seeing a ymm
// register, but the same isn't true when using memory operands instead.
// Provide other assembly rr and rm forms to address this explicitly.
def VCVTPD2PSrr : VPDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvtpd2ps\t{$src, $dst|$dst, $src}", []>, VEX;
// FIXME: the memory form of this instruction should described using
// use extra asm syntax
"cvtpd2ps\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPD2PSXrYr : VPDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src),
"cvtpd2ps\t{$src, $dst|$dst, $src}", []>, VEX;
// XMM only
def VCVTPD2PSXrr : VPDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvtpd2psx\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPD2PSXrm : VPDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
"cvtpd2psx\t{$src, $dst|$dst, $src}", []>, VEX;
// YMM only
def VCVTPD2PSYrr : VPDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src),
"cvtpd2psy\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPD2PSYrm : VPDI<0x5A, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src),
"cvtpd2psy\t{$src, $dst|$dst, $src}", []>, VEX, VEX_L;
}
def CVTPD2PSrr : PDI<0x5A, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvtpd2ps\t{$src, $dst|$dst, $src}", []>;
@ -1142,6 +1193,16 @@ let isAsmParserOnly = 1 in {
"cmp${cc}pd\t{$src, $src1, $dst|$dst, $src1, $src}",
"cmppd\t{$src2, $src, $src1, $dst|$dst, $src1, $src, $src2}",
SSEPackedDouble>, OpSize, VEX_4V;
let Pattern = []<dag> in {
defm VCMPPSY : sse12_cmp_packed<VR256, f256mem, int_x86_sse_cmp_ps,
"cmp${cc}ps\t{$src, $src1, $dst|$dst, $src1, $src}",
"cmpps\t{$src2, $src, $src1, $dst|$dst, $src1, $src, $src2}",
SSEPackedSingle>, VEX_4V;
defm VCMPPDY : sse12_cmp_packed<VR256, f256mem, int_x86_sse2_cmp_pd,
"cmp${cc}pd\t{$src, $src1, $dst|$dst, $src1, $src}",
"cmppd\t{$src2, $src, $src1, $dst|$dst, $src1, $src, $src2}",
SSEPackedDouble>, OpSize, VEX_4V;
}
}
let Constraints = "$src1 = $dst" in {
defm CMPPS : sse12_cmp_packed<VR128, f128mem, int_x86_sse_cmp_ps,
@ -2935,19 +2996,46 @@ let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1,
// SSE3 - Conversion Instructions
//===---------------------------------------------------------------------===//
// Convert Packed Double FP to Packed DW Integers
let isAsmParserOnly = 1, Predicates = [HasAVX] in {
// The assembler can recognize rr 256-bit instructions by seeing a ymm
// register, but the same isn't true when using memory operands instead.
// Provide other assembly rr and rm forms to address this explicitly.
def VCVTPD2DQrr : S3DI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"vcvtpd2dq\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTDQ2PDrm : S3SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
"vcvtdq2pd\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTDQ2PDrr : S3SI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"vcvtdq2pd\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPD2DQXrYr : S3DI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src),
"vcvtpd2dq\t{$src, $dst|$dst, $src}", []>, VEX;
// XMM only
def VCVTPD2DQXrr : S3DI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"vcvtpd2dqx\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPD2DQXrm : S3DI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
"vcvtpd2dqx\t{$src, $dst|$dst, $src}", []>, VEX;
// YMM only
def VCVTPD2DQYrr : S3DI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR256:$src),
"vcvtpd2dqy\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTPD2DQYrm : S3DI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f256mem:$src),
"vcvtpd2dqy\t{$src, $dst|$dst, $src}", []>, VEX, VEX_L;
}
def CVTPD2DQrm : S3DI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
"cvtpd2dq\t{$src, $dst|$dst, $src}", []>;
def CVTPD2DQrr : S3DI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"cvtpd2dq\t{$src, $dst|$dst, $src}", []>;
// Convert Packed DW Integers to Packed Double FP
let isAsmParserOnly = 1, Predicates = [HasAVX] in {
def VCVTDQ2PDrm : S3SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
"vcvtdq2pd\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTDQ2PDrr : S3SI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),
"vcvtdq2pd\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTDQ2PDYrm : S3SI<0xE6, MRMSrcMem, (outs VR256:$dst), (ins f128mem:$src),
"vcvtdq2pd\t{$src, $dst|$dst, $src}", []>, VEX;
def VCVTDQ2PDYrr : S3SI<0xE6, MRMSrcReg, (outs VR256:$dst), (ins VR128:$src),
"vcvtdq2pd\t{$src, $dst|$dst, $src}", []>, VEX;
}
def CVTDQ2PDrm : S3SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src),
"cvtdq2pd\t{$src, $dst|$dst, $src}", []>;
def CVTDQ2PDrr : S3SI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src),

View file

@ -432,6 +432,9 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
if (TSFlags & X86II::VEX_W)
VEX_W = 1;
if (TSFlags & X86II::VEX_L)
VEX_L = 1;
switch (TSFlags & X86II::Op0Mask) {
default: assert(0 && "Invalid prefix!");
case X86II::T8: // 0F 38

View file

@ -10,7 +10,7 @@
#include "XCoreMCAsmInfo.h"
using namespace llvm;
XCoreMCAsmInfo::XCoreMCAsmInfo(const Target &T, const StringRef &TT) {
XCoreMCAsmInfo::XCoreMCAsmInfo(const Target &T, StringRef TT) {
SupportsDebugInformation = true;
Data16bitsDirective = "\t.short\t";
Data32bitsDirective = "\t.long\t";

View file

@ -14,14 +14,15 @@
#ifndef XCORETARGETASMINFO_H
#define XCORETARGETASMINFO_H
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCAsmInfo.h"
namespace llvm {
class Target;
class StringRef;
class XCoreMCAsmInfo : public MCAsmInfo {
public:
explicit XCoreMCAsmInfo(const Target &T, const StringRef &TT);
explicit XCoreMCAsmInfo(const Target &T, StringRef TT);
};
} // namespace llvm

View file

@ -399,7 +399,7 @@ bool Inliner::runOnSCC(CallGraphSCC &SCC) {
// We can only inline direct calls to non-declarations.
if (Callee == 0 || Callee->isDeclaration()) continue;
// If this call sites was obtained by inlining another function, verify
// If this call site was obtained by inlining another function, verify
// that the include path for the function did not include the callee
// itself. If so, we'd be recursively inlinling the same function,
// which would provide the same callsites, which would cause us to

View file

@ -603,6 +603,10 @@ static void ThunkGToF(Function *F, Function *G) {
}
static void AliasGToF(Function *F, Function *G) {
// Darwin will trigger llvm_unreachable if asked to codegen an alias.
return ThunkGToF(F, G);
#if 0
if (!G->hasExternalLinkage() && !G->hasLocalLinkage() && !G->hasWeakLinkage())
return ThunkGToF(F, G);
@ -614,6 +618,7 @@ static void AliasGToF(Function *F, Function *G) {
GA->setVisibility(G->getVisibility());
G->replaceAllUsesWith(GA);
G->eraseFromParent();
#endif
}
static bool fold(std::vector<Function *> &FnVec, unsigned i, unsigned j) {

View file

@ -472,6 +472,25 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
Value *NewOr = Builder->CreateOr(Val, Val2);
return Builder->CreateICmp(LHSCC, NewOr, LHSCst);
}
// (icmp ne (A & C1), 0) & (icmp ne (A & C2), 0) -->
// (icmp eq (A & (C1|C2)), (C1|C2))
if (LHSCC == ICmpInst::ICMP_NE && LHSCst->isZero()) {
Instruction *I1 = dyn_cast<Instruction>(Val);
Instruction *I2 = dyn_cast<Instruction>(Val2);
if (I1 && I1->getOpcode() == Instruction::And &&
I2 && I2->getOpcode() == Instruction::And &&
I1->getOperand(0) == I1->getOperand(0)) {
ConstantInt *CI1 = dyn_cast<ConstantInt>(I1->getOperand(1));
ConstantInt *CI2 = dyn_cast<ConstantInt>(I2->getOperand(1));
if (CI1 && !CI1->isZero() && CI2 && !CI2->isZero() &&
CI1->getValue().operator&(CI2->getValue()) == 0) {
Constant *ConstOr = ConstantExpr::getOr(CI1, CI2);
Value *NewAnd = Builder->CreateAnd(I1->getOperand(0), ConstOr);
return Builder->CreateICmp(ICmpInst::ICMP_EQ, NewAnd, ConstOr);
}
}
}
}
// From here on, we only handle:

View file

@ -699,6 +699,34 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
SI.setOperand(2, TrueVal);
return &SI;
}
// select (A == 0 | B == 0), T, F--> select (A != 0 & B != 0), F, T
// Note: This is a canonicalization rather than an optimization, and is used
// to expose opportunities to other instcombine transforms.
Instruction* CondInst = dyn_cast<Instruction>(CondVal);
if (CondInst && CondInst->hasOneUse() &&
CondInst->getOpcode() == Instruction::Or) {
ICmpInst *LHSCmp = dyn_cast<ICmpInst>(CondInst->getOperand(0));
ICmpInst *RHSCmp = dyn_cast<ICmpInst>(CondInst->getOperand(1));
if (LHSCmp && LHSCmp->hasOneUse() &&
LHSCmp->getPredicate() == ICmpInst::ICMP_EQ &&
RHSCmp && RHSCmp->hasOneUse() &&
RHSCmp->getPredicate() == ICmpInst::ICMP_EQ) {
ConstantInt* C1 = dyn_cast<ConstantInt>(LHSCmp->getOperand(1));
ConstantInt* C2 = dyn_cast<ConstantInt>(RHSCmp->getOperand(1));
if (C1 && C1->isZero() && C2 && C2->isZero()) {
LHSCmp->setPredicate(ICmpInst::ICMP_NE);
RHSCmp->setPredicate(ICmpInst::ICMP_NE);
Value *And =
InsertNewInstBefore(BinaryOperator::CreateAnd(LHSCmp, RHSCmp,
"and."+CondVal->getName()), SI);
SI.setOperand(0, And);
SI.setOperand(1, FalseVal);
SI.setOperand(2, TrueVal);
return &SI;
}
}
}
return 0;
}

View file

@ -2362,7 +2362,7 @@ void LSRInstance::GenerateConstantOffsets(LSRUse &LU, unsigned LUIdx,
Formula Base) {
// TODO: For now, just add the min and max offset, because it usually isn't
// worthwhile looking at everything inbetween.
SmallVector<int64_t, 4> Worklist;
SmallVector<int64_t, 2> Worklist;
Worklist.push_back(LU.MinOffset);
if (LU.MaxOffset != LU.MinOffset)
Worklist.push_back(LU.MaxOffset);
@ -2376,7 +2376,14 @@ void LSRInstance::GenerateConstantOffsets(LSRUse &LU, unsigned LUIdx,
F.AM.BaseOffs = (uint64_t)Base.AM.BaseOffs - *I;
if (isLegalUse(F.AM, LU.MinOffset - *I, LU.MaxOffset - *I,
LU.Kind, LU.AccessTy, TLI)) {
F.BaseRegs[i] = SE.getAddExpr(G, SE.getConstant(G->getType(), *I));
// Add the offset to the base register.
const SCEV *NewG = SE.getAddExpr(G, SE.getConstant(G->getType(), *I));
// If it cancelled out, drop the base register, otherwise update it.
if (NewG->isZero()) {
std::swap(F.BaseRegs[i], F.BaseRegs.back());
F.BaseRegs.pop_back();
} else
F.BaseRegs[i] = NewG;
(void)InsertFormula(LU, LUIdx, F);
}

View file

@ -306,7 +306,7 @@ bool llvm::SimplifyInstructionsInBlock(BasicBlock *BB, const TargetData *TD) {
WeakVH BIHandle(BI);
ReplaceAndSimplifyAllUses(Inst, V, TD);
MadeChange = true;
if (BIHandle == 0)
if (BIHandle != BI)
BI = BB->begin();
continue;
}
@ -354,12 +354,13 @@ void llvm::RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred,
// value into all of its uses.
assert(PNV != PN && "hasConstantValue broken");
Value *OldPhiIt = PhiIt;
ReplaceAndSimplifyAllUses(PN, PNV, TD);
// If recursive simplification ended up deleting the next PHI node we would
// iterate to, then our iterator is invalid, restart scanning from the top
// of the block.
if (PhiIt == 0) PhiIt = &BB->front();
if (PhiIt != OldPhiIt) PhiIt = &BB->front();
}
}

View file

@ -1377,8 +1377,9 @@ static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) {
bool llvm::FoldBranchToCommonDest(BranchInst *BI) {
BasicBlock *BB = BI->getParent();
Instruction *Cond = dyn_cast<Instruction>(BI->getCondition());
if (Cond == 0) return false;
if (Cond == 0 || (!isa<CmpInst>(Cond) && !isa<BinaryOperator>(Cond)) ||
Cond->getParent() != BB || !Cond->hasOneUse())
return false;
// Only allow this if the condition is a simple instruction that can be
// executed unconditionally. It must be in the same block as the branch, and
@ -1387,11 +1388,23 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) {
// Ignore dbg intrinsics.
while(isa<DbgInfoIntrinsic>(FrontIt))
++FrontIt;
if ((!isa<CmpInst>(Cond) && !isa<BinaryOperator>(Cond)) ||
Cond->getParent() != BB || &*FrontIt != Cond || !Cond->hasOneUse()) {
return false;
// Allow a single instruction to be hoisted in addition to the compare
// that feeds the branch. We later ensure that any values that _it_ uses
// were also live in the predecessor, so that we don't unnecessarily create
// register pressure or inhibit out-of-order execution.
Instruction *BonusInst = 0;
if (&*FrontIt != Cond &&
FrontIt->hasOneUse() && *FrontIt->use_begin() == Cond &&
FrontIt->isSafeToSpeculativelyExecute()) {
BonusInst = &*FrontIt;
++FrontIt;
}
// Only a single bonus inst is allowed.
if (&*FrontIt != Cond)
return false;
// Make sure the instruction after the condition is the cond branch.
BasicBlock::iterator CondIt = Cond; ++CondIt;
// Ingore dbg intrinsics.
@ -1429,6 +1442,44 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) {
!SafeToMergeTerminators(BI, PBI))
continue;
// Ensure that any values used in the bonus instruction are also used
// by the terminator of the predecessor. This means that those values
// must already have been resolved, so we won't be inhibiting the
// out-of-order core by speculating them earlier.
if (BonusInst) {
// Collect the values used by the bonus inst
SmallPtrSet<Value*, 4> UsedValues;
for (Instruction::op_iterator OI = BonusInst->op_begin(),
OE = BonusInst->op_end(); OI != OE; ++OI) {
Value* V = *OI;
if (!isa<Constant>(V))
UsedValues.insert(V);
}
SmallVector<std::pair<Value*, unsigned>, 4> Worklist;
Worklist.push_back(std::make_pair(PBI->getOperand(0), 0));
// Walk up to four levels back up the use-def chain of the predecessor's
// terminator to see if all those values were used. The choice of four
// levels is arbitrary, to provide a compile-time-cost bound.
while (!Worklist.empty()) {
std::pair<Value*, unsigned> Pair = Worklist.back();
Worklist.pop_back();
if (Pair.second >= 4) continue;
UsedValues.erase(Pair.first);
if (UsedValues.empty()) break;
if (Instruction* I = dyn_cast<Instruction>(Pair.first)) {
for (Instruction::op_iterator OI = I->op_begin(), OE = I->op_end();
OI != OE; ++OI)
Worklist.push_back(std::make_pair(OI->get(), Pair.second+1));
}
}
if (!UsedValues.empty()) return false;
}
Instruction::BinaryOps Opc;
bool InvertPredCond = false;
@ -1457,9 +1508,19 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI) {
PBI->setSuccessor(1, OldTrue);
}
// If we have a bonus inst, clone it into the predecessor block.
Instruction *NewBonus = 0;
if (BonusInst) {
NewBonus = BonusInst->clone();
PredBlock->getInstList().insert(PBI, NewBonus);
NewBonus->takeName(BonusInst);
BonusInst->setName(BonusInst->getName()+".old");
}
// Clone Cond into the predecessor basic block, and or/and the
// two conditions together.
Instruction *New = Cond->clone();
if (BonusInst) New->replaceUsesOfWith(BonusInst, NewBonus);
PredBlock->getInstList().insert(PBI, New);
New->takeName(Cond);
Cond->setName(New->getName()+".old");

View file

@ -90,8 +90,7 @@ enum PrefixType {
/// PrintLLVMName - Turn the specified name into an 'LLVM name', which is either
/// prefixed with % (if the string only contains simple characters) or is
/// surrounded with ""'s (if it has special chars in it). Print it out.
static void PrintLLVMName(raw_ostream &OS, const StringRef &Name,
PrefixType Prefix) {
static void PrintLLVMName(raw_ostream &OS, StringRef Name, PrefixType Prefix) {
assert(Name.data() && "Cannot get empty name!");
switch (Prefix) {
default: llvm_unreachable("Bad prefix!");
@ -855,8 +854,9 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {
}
}
static void WriteConstantInt(raw_ostream &Out, const Constant *CV,
TypePrinting &TypePrinter, SlotTracker *Machine) {
static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
TypePrinting &TypePrinter,
SlotTracker *Machine) {
if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
if (CI->getType()->isIntegerTy(1)) {
Out << (CI->getZExtValue() ? "true" : "false");
@ -1147,7 +1147,7 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
const Constant *CV = dyn_cast<Constant>(V);
if (CV && !isa<GlobalValue>(CV)) {
assert(TypePrinter && "Constants require TypePrinting!");
WriteConstantInt(Out, CV, *TypePrinter, Machine);
WriteConstantInternal(Out, CV, *TypePrinter, Machine);
return;
}
@ -2128,7 +2128,7 @@ void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const {
} else if (const MDNode *N = dyn_cast<MDNode>(this)) {
const Function *F = N->getFunction();
SlotTracker SlotTable(F);
AssemblyWriter W(OS, SlotTable, F ? getModuleFromVal(F) : 0, AAW);
AssemblyWriter W(OS, SlotTable, F ? F->getParent() : 0, AAW);
W.printMDNodeBody(N);
} else if (const NamedMDNode *N = dyn_cast<NamedMDNode>(this)) {
SlotTracker SlotTable(N->getParent());
@ -2138,7 +2138,7 @@ void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const {
TypePrinting TypePrinter;
TypePrinter.print(C->getType(), OS);
OS << ' ';
WriteConstantInt(OS, C, TypePrinter, 0);
WriteConstantInternal(OS, C, TypePrinter, 0);
} else if (isa<InlineAsm>(this) || isa<MDString>(this) ||
isa<Argument>(this)) {
WriteAsOperand(OS, this, true, 0);

View file

@ -78,7 +78,8 @@ void MDNodeOperand::allUsesReplacedWith(Value *NV) {
/// getOperandPtr - Helper function to get the MDNodeOperand's coallocated on
/// the end of the MDNode.
static MDNodeOperand *getOperandPtr(MDNode *N, unsigned Op) {
assert(Op < N->getNumOperands() && "Invalid operand number");
// Use <= instead of < to permit a one-past-the-end address.
assert(Op <= N->getNumOperands() && "Invalid operand number");
return reinterpret_cast<MDNodeOperand*>(N+1)+Op;
}

View file

@ -1,16 +1,24 @@
; RUN: llc < %s -march=arm -mattr=+vfp2 -enable-unsafe-fp-math -enable-finite-only-fp-math | FileCheck %s
; RUN: llc < %s -march=arm -mcpu=cortex-a8 -mattr=+vfp2 -enable-unsafe-fp-math -enable-finite-only-fp-math | FileCheck -check-prefix=FINITE %s
; RUN: llc < %s -march=arm -mcpu=cortex-a8 -mattr=+vfp2 -enable-unsafe-fp-math | FileCheck -check-prefix=NAN %s
; rdar://7461510
define arm_apcscc i32 @t1(float* %a, float* %b) nounwind {
entry:
; CHECK: t1:
; CHECK-NOT: vldr
; CHECK: ldr
; CHECK: ldr
; CHECK: cmp r0, r1
; CHECK-NOT: vcmpe.f32
; CHECK-NOT: vmrs
; CHECK: beq
; FINITE: t1:
; FINITE-NOT: vldr
; FINITE: ldr
; FINITE: ldr
; FINITE: cmp r0, r1
; FINITE-NOT: vcmpe.f32
; FINITE-NOT: vmrs
; FINITE: beq
; NAN: t1:
; NAN: vldr.32 s0,
; NAN: vldr.32 s1,
; NAN: vcmpe.f32 s1, s0
; NAN: vmrs apsr_nzcv, fpscr
; NAN: beq
%0 = load float* %a
%1 = load float* %b
%2 = fcmp une float %0, %1
@ -25,5 +33,50 @@ bb2:
ret i32 %4
}
define arm_apcscc i32 @t2(double* %a, double* %b) nounwind {
entry:
; FINITE: t2:
; FINITE-NOT: vldr
; FINITE: ldrd r0, [r0]
; FINITE: cmp r0, #0
; FINITE: cmpeq r1, #0
; FINITE-NOT: vcmpe.f32
; FINITE-NOT: vmrs
; FINITE: bne
%0 = load double* %a
%1 = fcmp oeq double %0, 0.000000e+00
br i1 %1, label %bb1, label %bb2
bb1:
%2 = call i32 @bar()
ret i32 %2
bb2:
%3 = call i32 @foo()
ret i32 %3
}
define arm_apcscc i32 @t3(float* %a, float* %b) nounwind {
entry:
; FINITE: t3:
; FINITE-NOT: vldr
; FINITE: ldr r0, [r0]
; FINITE: cmp r0, #0
; FINITE-NOT: vcmpe.f32
; FINITE-NOT: vmrs
; FINITE: bne
%0 = load float* %a
%1 = fcmp oeq float %0, 0.000000e+00
br i1 %1, label %bb1, label %bb2
bb1:
%2 = call i32 @bar()
ret i32 %2
bb2:
%3 = call i32 @foo()
ret i32 %3
}
declare i32 @bar()
declare i32 @foo()

View file

@ -239,7 +239,7 @@ define arm_aapcs_vfpcc float @t9(%0* nocapture, %3* nocapture) nounwind {
; CHECK: t9:
; CHECK: vldr.64
; CHECK-NOT: vmov d{{.*}}, d0
; CHECK: vmov.i8 d1
; CHECK: vmov.i32 d1
; CHECK-NEXT: vstmia r0, {d0, d1}
; CHECK-NEXT: vstmia r0, {d0, d1}
%3 = bitcast double 0.000000e+00 to <2 x float> ; <<2 x float>> [#uses=2]

29
test/CodeGen/ARM/sub.ll Normal file
View file

@ -0,0 +1,29 @@
; RUN: llc -march=arm < %s | FileCheck %s
; 171 = 0x000000ab
define i64 @f1(i64 %a) {
; CHECK: f1
; CHECK: subs r0, r0, #171
; CHECK: sbc r1, r1, #0
%tmp = sub i64 %a, 171
ret i64 %tmp
}
; 66846720 = 0x03fc0000
define i64 @f2(i64 %a) {
; CHECK: f2
; CHECK: subs r0, r0, #255, 14
; CHECK: sbc r1, r1, #0
%tmp = sub i64 %a, 66846720
ret i64 %tmp
}
; 734439407618 = 0x000000ab00000002
define i64 @f3(i64 %a) {
; CHECK: f3
; CHECK: subs r0, r0, #2
; CHECK: sbc r1, r1, #171
%tmp = sub i64 %a, 734439407618
ret i64 %tmp
}

View file

@ -267,3 +267,15 @@ entry:
%0 = shufflevector <2 x double> %arg0_int64x1_t, <2 x double> undef, <2 x i32> <i32 0, i32 0>
ret <2 x double> %0
}
; Radar 7373643
;CHECK: redundantVdup:
;CHECK: vmov.i8
;CHECK-NOT: vdup.8
;CHECK: vstr.64
define void @redundantVdup(<8 x i8>* %ptr) nounwind {
%1 = insertelement <8 x i8> undef, i8 -128, i32 0
%2 = shufflevector <8 x i8> %1, <8 x i8> undef, <8 x i32> zeroinitializer
store <8 x i8> %2, <8 x i8>* %ptr, align 8
ret void
}

View file

@ -18,6 +18,18 @@ define <4 x i16> @v_movi16b() nounwind {
ret <4 x i16> < i16 4096, i16 4096, i16 4096, i16 4096 >
}
define <4 x i16> @v_mvni16a() nounwind {
;CHECK: v_mvni16a:
;CHECK: vmvn.i16 d0, #0x10
ret <4 x i16> < i16 65519, i16 65519, i16 65519, i16 65519 >
}
define <4 x i16> @v_mvni16b() nounwind {
;CHECK: v_mvni16b:
;CHECK: vmvn.i16 d0, #0x1000
ret <4 x i16> < i16 61439, i16 61439, i16 61439, i16 61439 >
}
define <2 x i32> @v_movi32a() nounwind {
;CHECK: v_movi32a:
;CHECK: vmov.i32 d0, #0x20
@ -54,6 +66,42 @@ define <2 x i32> @v_movi32f() nounwind {
ret <2 x i32> < i32 2162687, i32 2162687 >
}
define <2 x i32> @v_mvni32a() nounwind {
;CHECK: v_mvni32a:
;CHECK: vmvn.i32 d0, #0x20
ret <2 x i32> < i32 4294967263, i32 4294967263 >
}
define <2 x i32> @v_mvni32b() nounwind {
;CHECK: v_mvni32b:
;CHECK: vmvn.i32 d0, #0x2000
ret <2 x i32> < i32 4294959103, i32 4294959103 >
}
define <2 x i32> @v_mvni32c() nounwind {
;CHECK: v_mvni32c:
;CHECK: vmvn.i32 d0, #0x200000
ret <2 x i32> < i32 4292870143, i32 4292870143 >
}
define <2 x i32> @v_mvni32d() nounwind {
;CHECK: v_mvni32d:
;CHECK: vmvn.i32 d0, #0x20000000
ret <2 x i32> < i32 3758096383, i32 3758096383 >
}
define <2 x i32> @v_mvni32e() nounwind {
;CHECK: v_mvni32e:
;CHECK: vmvn.i32 d0, #0x20FF
ret <2 x i32> < i32 4294958848, i32 4294958848 >
}
define <2 x i32> @v_mvni32f() nounwind {
;CHECK: v_mvni32f:
;CHECK: vmvn.i32 d0, #0x20FFFF
ret <2 x i32> < i32 4292804608, i32 4292804608 >
}
define <1 x i64> @v_movi64() nounwind {
;CHECK: v_movi64:
;CHECK: vmov.i64 d0, #0xFF0000FF0000FFFF

View file

@ -12,7 +12,7 @@ define weak arm_aapcs_vfpcc i32 @_ZNKSs7compareERKSs(%"struct.std::basic_string<
; CHECK: _ZNKSs7compareERKSs:
; CHECK: it eq
; CHECK-NEXT: subeq.w r0, r6, r8
; CHECK-NEXT: ldmia.w sp, {r4, r5, r6, r8, r9, pc}
; CHECK-NEXT: ldmia.w sp!, {r4, r5, r6, r8, r9, pc}
entry:
%0 = tail call arm_aapcs_vfpcc i32 @_ZNKSs4sizeEv(%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* %this) ; <i32> [#uses=3]
%1 = tail call arm_aapcs_vfpcc i32 @_ZNKSs4sizeEv(%"struct.std::basic_string<char,std::char_traits<char>,std::allocator<char> >"* %__str) ; <i32> [#uses=3]

View file

@ -1,8 +1,54 @@
; RUN: llc < %s -march=thumb -mattr=+thumb2 | FileCheck %s
; RUN: llc -march=thumb -mattr=+thumb2 < %s | FileCheck %s
define i64 @f1(i64 %a, i64 %b) {
; CHECK: f1:
; CHECK: f1
; CHECK: subs r0, r0, r2
%tmp = sub i64 %a, %b
ret i64 %tmp
}
; 734439407618 = 0x000000ab00000002
define i64 @f2(i64 %a) {
; CHECK: f2
; CHECK: subs r0, #2
; CHECK: sbc r1, r1, #171
%tmp = sub i64 %a, 734439407618
ret i64 %tmp
}
; 5066626890203138 = 0x0012001200000002
define i64 @f3(i64 %a) {
; CHECK: f3
; CHECK: subs r0, #2
; CHECK: sbc r1, r1, #1179666
%tmp = sub i64 %a, 5066626890203138
ret i64 %tmp
}
; 3747052064576897026 = 0x3400340000000002
define i64 @f4(i64 %a) {
; CHECK: f4
; CHECK: subs r0, #2
; CHECK: sbc r1, r1, #872428544
%tmp = sub i64 %a, 3747052064576897026
ret i64 %tmp
}
; 6221254862626095106 = 0x5656565600000002
define i64 @f5(i64 %a) {
; CHECK: f5
; CHECK: subs r0, #2
; CHECK: adc r1, r1, #-1448498775
%tmp = sub i64 %a, 6221254862626095106
ret i64 %tmp
}
; 287104476244869122 = 0x03fc000000000002
define i64 @f6(i64 %a) {
; CHECK: f6
; CHECK: subs r0, #2
; CHECK: sbc r1, r1, #66846720
%tmp = sub i64 %a, 287104476244869122
ret i64 %tmp
}

Some files were not shown because too many files have changed in this diff Show more