Vendor import of llvm trunk r126547:
http://llvm.org/svn/llvm-project/llvm/trunk@126547
This commit is contained in:
parent
cf099d1121
commit
d0e4e96dc1
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/llvm/dist/; revision=219067 svn path=/vendor/llvm/llvm-r126547/; revision=219068; tag=vendor/llvm/llvm-r126547
@ -12,6 +12,8 @@ set(CMAKE_MODULE_PATH
|
||||
|
||||
set(PACKAGE_VERSION "2.9")
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
include(VersionFromVCS)
|
||||
|
||||
option(LLVM_APPEND_VC_REV
|
||||
@ -238,7 +240,6 @@ endif()
|
||||
|
||||
option(LLVM_BUILD_TESTS
|
||||
"Build LLVM unit tests. If OFF, just generate build targes." OFF)
|
||||
option(LLVM_INCLUDE_TESTS "Generate build targets for the LLVM unit tests." ON)
|
||||
if( LLVM_INCLUDE_TESTS )
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(utils/unittest)
|
||||
|
@ -973,7 +973,9 @@ $(NativeExportsFile): $(EXPORTED_SYMBOL_FILE) $(ObjDir)/.dir
|
||||
$(Verb) echo "{" > $@
|
||||
$(Verb) grep -q "\<" $< && echo " global:" >> $@ || :
|
||||
$(Verb) sed -e 's/$$/;/' -e 's/^/ /' < $< >> $@
|
||||
ifneq ($(HOST_OS),OpenBSD)
|
||||
$(Verb) echo " local: *;" >> $@
|
||||
endif
|
||||
$(Verb) echo "};" >> $@
|
||||
clean-local::
|
||||
-$(Verb) $(RM) -f $(NativeExportsFile)
|
||||
|
@ -5,7 +5,6 @@ macro(add_llvm_library name)
|
||||
llvm_process_sources( ALL_FILES ${ARGN} )
|
||||
add_library( ${name} ${ALL_FILES} )
|
||||
set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} )
|
||||
set_property( GLOBAL APPEND PROPERTY LLVM_LIB_TARGETS ${name} )
|
||||
if( LLVM_COMMON_DEPENDS )
|
||||
add_dependencies( ${name} ${LLVM_COMMON_DEPENDS} )
|
||||
endif( LLVM_COMMON_DEPENDS )
|
||||
@ -25,6 +24,7 @@ macro(add_llvm_library name)
|
||||
if( CURRENT_LLVM_TARGET )
|
||||
add_dependencies(${name} ${CURRENT_LLVM_TARGET})
|
||||
endif()
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Libraries")
|
||||
endmacro(add_llvm_library name)
|
||||
|
||||
|
||||
@ -55,6 +55,8 @@ ${name} ignored.")
|
||||
LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
|
||||
ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX})
|
||||
endif()
|
||||
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Loadable modules")
|
||||
endmacro(add_llvm_loadable_module name)
|
||||
|
||||
|
||||
@ -95,6 +97,7 @@ macro(add_llvm_tool name)
|
||||
if( LLVM_BUILD_TOOLS )
|
||||
install(TARGETS ${name} RUNTIME DESTINATION bin)
|
||||
endif()
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Tools")
|
||||
endmacro(add_llvm_tool name)
|
||||
|
||||
|
||||
@ -107,9 +110,16 @@ macro(add_llvm_example name)
|
||||
if( LLVM_BUILD_EXAMPLES )
|
||||
install(TARGETS ${name} RUNTIME DESTINATION examples)
|
||||
endif()
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Examples")
|
||||
endmacro(add_llvm_example name)
|
||||
|
||||
|
||||
macro(add_llvm_utility name)
|
||||
add_llvm_executable(${name} ${ARGN})
|
||||
set_target_properties(${name} PROPERTIES FOLDER "Utils")
|
||||
endmacro(add_llvm_utility name)
|
||||
|
||||
|
||||
macro(add_llvm_target target_name)
|
||||
if( TABLEGEN_OUTPUT )
|
||||
add_custom_target(${target_name}Table_gen
|
||||
@ -120,6 +130,7 @@ macro(add_llvm_target target_name)
|
||||
add_llvm_library(LLVM${target_name} ${ARGN} ${TABLEGEN_OUTPUT})
|
||||
if ( TABLEGEN_OUTPUT )
|
||||
add_dependencies(LLVM${target_name} ${target_name}Table_gen)
|
||||
set_target_properties(${target_name}Table_gen PROPERTIES FOLDER "Tablegenning")
|
||||
endif (TABLEGEN_OUTPUT)
|
||||
set( CURRENT_LLVM_TARGET LLVM${target_name} )
|
||||
endmacro(add_llvm_target)
|
||||
|
@ -1,7 +1,6 @@
|
||||
set(llvm_cmake_builddir "${LLVM_BINARY_DIR}/share/llvm/cmake")
|
||||
|
||||
get_property(llvm_libs GLOBAL PROPERTY LLVM_LIBS)
|
||||
get_property(llvm_lib_targets GLOBAL PROPERTY LLVM_LIB_TARGETS)
|
||||
|
||||
configure_file(
|
||||
LLVM.cmake
|
||||
|
@ -159,3 +159,4 @@ endif( MSVC )
|
||||
add_llvm_definitions( -D__STDC_LIMIT_MACROS )
|
||||
add_llvm_definitions( -D__STDC_CONSTANT_MACROS )
|
||||
|
||||
option(LLVM_INCLUDE_TESTS "Generate build targets for the LLVM unit tests." ON)
|
||||
|
@ -4,14 +4,14 @@ set(LLVM_PACKAGE_VERSION @PACKAGE_VERSION@)
|
||||
|
||||
set(LLVM_COMMON_DEPENDS @LLVM_COMMON_DEPENDS@)
|
||||
|
||||
set(llvm_libs @llvm_libs@)
|
||||
|
||||
set(llvm_lib_targets @llvm_lib_targets@)
|
||||
set_property( GLOBAL PROPERTY LLVM_LIBS "@llvm_libs@")
|
||||
|
||||
set(LLVM_ALL_TARGETS @LLVM_ALL_TARGETS@)
|
||||
|
||||
set(LLVM_TARGETS_TO_BUILD @LLVM_TARGETS_TO_BUILD@)
|
||||
|
||||
set(TARGET_TRIPLE "@TARGET_TRIPLE@")
|
||||
|
||||
set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@)
|
||||
|
||||
set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS@)
|
||||
|
@ -348,8 +348,6 @@ out:</p>
|
||||
<ul>
|
||||
<li><a href="http://llvm.org/">LLVM homepage</a></li>
|
||||
<li><a href="http://llvm.org/doxygen/">LLVM doxygen tree</a></li>
|
||||
<li><a href="http://llvm.org/docs/Projects.html">Starting a Project
|
||||
that Uses LLVM</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@ -365,7 +363,7 @@ out:</p>
|
||||
|
||||
<a href="mailto:jeffc@jolt-lang.org">Jeff Cohen</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2011-02-09 05:19:28 +0100 (Wed, 09 Feb 2011) $
|
||||
Last modified: $Date: 2011-02-20 16:34:12 +0100 (Sun, 20 Feb 2011) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -4575,12 +4575,12 @@ entry:
|
||||
type <tt>ty2</tt>.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The '<tt>trunc</tt>' instruction takes a <tt>value</tt> to trunc, which must
|
||||
be an <a href="#t_integer">integer</a> type, and a type that specifies the
|
||||
size and type of the result, which must be
|
||||
an <a href="#t_integer">integer</a> type. The bit size of <tt>value</tt> must
|
||||
be larger than the bit size of <tt>ty2</tt>. Equal sized types are not
|
||||
allowed.</p>
|
||||
<p>The '<tt>trunc</tt>' instruction takes a value to trunc, and a type to trunc it to.
|
||||
Both types must be of <a href="#t_integer">integer</a> types, or vectors
|
||||
of the same number of integers.
|
||||
The bit size of the <tt>value</tt> must be larger than
|
||||
the bit size of the destination type, <tt>ty2</tt>.
|
||||
Equal sized types are not allowed.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
<p>The '<tt>trunc</tt>' instruction truncates the high order bits
|
||||
@ -4590,9 +4590,10 @@ entry:
|
||||
|
||||
<h5>Example:</h5>
|
||||
<pre>
|
||||
%X = trunc i32 257 to i8 <i>; yields i8:1</i>
|
||||
%Y = trunc i32 123 to i1 <i>; yields i1:true</i>
|
||||
%Z = trunc i32 122 to i1 <i>; yields i1:false</i>
|
||||
%X = trunc i32 257 to i8 <i>; yields i8:1</i>
|
||||
%Y = trunc i32 123 to i1 <i>; yields i1:true</i>
|
||||
%Z = trunc i32 122 to i1 <i>; yields i1:false</i>
|
||||
%W = trunc <2 x i16> <i16 8, i16 7> to <2 x i8> <i>; yields <i8 8, i8 7></i>
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
@ -4614,10 +4615,11 @@ entry:
|
||||
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The '<tt>zext</tt>' instruction takes a value to cast, which must be of
|
||||
<a href="#t_integer">integer</a> type, and a type to cast it to, which must
|
||||
also be of <a href="#t_integer">integer</a> type. The bit size of the
|
||||
<tt>value</tt> must be smaller than the bit size of the destination type,
|
||||
<p>The '<tt>zext</tt>' instruction takes a value to cast, and a type to cast it to.
|
||||
Both types must be of <a href="#t_integer">integer</a> types, or vectors
|
||||
of the same number of integers.
|
||||
The bit size of the <tt>value</tt> must be smaller than
|
||||
the bit size of the destination type,
|
||||
<tt>ty2</tt>.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
@ -4630,6 +4632,7 @@ entry:
|
||||
<pre>
|
||||
%X = zext i32 257 to i64 <i>; yields i64:257</i>
|
||||
%Y = zext i1 true to i32 <i>; yields i32:1</i>
|
||||
%Z = zext <2 x i16> <i16 8, i16 7> to <2 x i32> <i>; yields <i32 8, i32 7></i>
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
@ -4649,10 +4652,11 @@ entry:
|
||||
<p>The '<tt>sext</tt>' sign extends <tt>value</tt> to the type <tt>ty2</tt>.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The '<tt>sext</tt>' instruction takes a value to cast, which must be of
|
||||
<a href="#t_integer">integer</a> type, and a type to cast it to, which must
|
||||
also be of <a href="#t_integer">integer</a> type. The bit size of the
|
||||
<tt>value</tt> must be smaller than the bit size of the destination type,
|
||||
<p>The '<tt>sext</tt>' instruction takes a value to cast, and a type to cast it to.
|
||||
Both types must be of <a href="#t_integer">integer</a> types, or vectors
|
||||
of the same number of integers.
|
||||
The bit size of the <tt>value</tt> must be smaller than
|
||||
the bit size of the destination type,
|
||||
<tt>ty2</tt>.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
@ -4666,6 +4670,7 @@ entry:
|
||||
<pre>
|
||||
%X = sext i8 -1 to i16 <i>; yields i16 :65535</i>
|
||||
%Y = sext i1 true to i32 <i>; yields i32:-1</i>
|
||||
%Z = sext <2 x i16> <i16 8, i16 7> to <2 x i32> <i>; yields <i32 8, i32 7></i>
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
@ -7781,7 +7786,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: 2011-02-09 17:44:44 +0100 (Wed, 09 Feb 2011) $
|
||||
Last modified: $Date: 2011-02-24 22:01:34 +0100 (Thu, 24 Feb 2011) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -1193,6 +1193,12 @@ class APInt {
|
||||
/// @brief Count the number of leading one bits.
|
||||
unsigned countLeadingOnes() const;
|
||||
|
||||
/// Computes the number of leading bits of this APInt that are equal to its
|
||||
/// sign bit.
|
||||
unsigned getNumSignBits() const {
|
||||
return isNegative() ? countLeadingOnes() : countLeadingZeros();
|
||||
}
|
||||
|
||||
/// countTrailingZeros - This function is an APInt version of the
|
||||
/// countTrailingZeros_{32,64} functions in MathExtras.h. It counts
|
||||
/// the number of zeros from the least significant bit to the first set bit.
|
||||
|
@ -64,7 +64,10 @@ namespace llvm {
|
||||
/*implicit*/ ArrayRef(const std::vector<T> &Vec)
|
||||
: Data(Vec.empty() ? (T*)0 : &Vec[0]), Length(Vec.size()) {}
|
||||
|
||||
// TODO: C arrays.
|
||||
/// Construct an ArrayRef from a C array.
|
||||
template <size_t N>
|
||||
/*implicit*/ ArrayRef(const T (&Arr)[N])
|
||||
: Data(Arr), Length(N) {}
|
||||
|
||||
/// @}
|
||||
/// @name Simple Operations
|
||||
|
@ -215,7 +215,7 @@ class ImmutableIntervalMap
|
||||
|
||||
ImmutableIntervalMap add(ImmutableIntervalMap Old,
|
||||
key_type_ref K, data_type_ref D) {
|
||||
TreeTy *T = F.add(Old.Root, std::make_pair<key_type, data_type>(K, D));
|
||||
TreeTy *T = F.add(Old.Root, std::pair<key_type, data_type>(K, D));
|
||||
return ImmutableIntervalMap(F.getCanonicalTree(T));
|
||||
}
|
||||
|
||||
|
@ -108,7 +108,7 @@ class ImmutableMap {
|
||||
ImmutableMap getEmptyMap() { return ImmutableMap(F.getEmptyTree()); }
|
||||
|
||||
ImmutableMap add(ImmutableMap Old, key_type_ref K, data_type_ref D) {
|
||||
TreeTy *T = F.add(Old.Root, std::make_pair<key_type,data_type>(K,D));
|
||||
TreeTy *T = F.add(Old.Root, std::pair<key_type,data_type>(K,D));
|
||||
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ namespace llvm {
|
||||
const MDNode *getCU() { return TheCU; }
|
||||
enum ComplexAddrKind { OpPlus=1, OpDeref };
|
||||
|
||||
/// CreateCompileUnit - A CompileUnit provides an anchor for all debugging
|
||||
/// createCompileUnit - A CompileUnit provides an anchor for all debugging
|
||||
/// information generated during this instance of compilation.
|
||||
/// @param Lang Source programming language, eg. dwarf::DW_LANG_C99
|
||||
/// @param File File name
|
||||
@ -72,67 +72,67 @@ namespace llvm {
|
||||
/// by a tool analyzing generated debugging information.
|
||||
/// @param RV This indicates runtime version for languages like
|
||||
/// Objective-C.
|
||||
void CreateCompileUnit(unsigned Lang, StringRef File, StringRef Dir,
|
||||
void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir,
|
||||
StringRef Producer,
|
||||
bool isOptimized, StringRef Flags, unsigned RV);
|
||||
|
||||
/// CreateFile - Create a file descriptor to hold debugging information
|
||||
/// createFile - Create a file descriptor to hold debugging information
|
||||
/// for a file.
|
||||
DIFile CreateFile(StringRef Filename, StringRef Directory);
|
||||
DIFile createFile(StringRef Filename, StringRef Directory);
|
||||
|
||||
/// CreateEnumerator - Create a single enumerator value.
|
||||
DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val);
|
||||
/// createEnumerator - Create a single enumerator value.
|
||||
DIEnumerator createEnumerator(StringRef Name, uint64_t Val);
|
||||
|
||||
/// CreateBasicType - Create debugging information entry for a basic
|
||||
/// createBasicType - Create debugging information entry for a basic
|
||||
/// type.
|
||||
/// @param Name Type name.
|
||||
/// @param SizeInBits Size of the type.
|
||||
/// @param AlignInBits Type alignment.
|
||||
/// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float.
|
||||
DIType CreateBasicType(StringRef Name, uint64_t SizeInBits,
|
||||
DIType createBasicType(StringRef Name, uint64_t SizeInBits,
|
||||
uint64_t AlignInBits, unsigned Encoding);
|
||||
|
||||
/// CreateQualifiedType - Create debugging information entry for a qualified
|
||||
/// createQualifiedType - Create debugging information entry for a qualified
|
||||
/// type, e.g. 'const int'.
|
||||
/// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type
|
||||
/// @param FromTy Base Type.
|
||||
DIType CreateQualifiedType(unsigned Tag, DIType FromTy);
|
||||
DIType createQualifiedType(unsigned Tag, DIType FromTy);
|
||||
|
||||
/// CreatePointerType - Create debugging information entry for a pointer.
|
||||
/// createPointerType - Create debugging information entry for a pointer.
|
||||
/// @param PointeeTy Type pointed by this pointer.
|
||||
/// @param SizeInBits Size.
|
||||
/// @param AlignInBits Alignment. (optional)
|
||||
/// @param Name Pointer type name. (optional)
|
||||
DIType CreatePointerType(DIType PointeeTy, uint64_t SizeInBits,
|
||||
DIType createPointerType(DIType PointeeTy, uint64_t SizeInBits,
|
||||
uint64_t AlignInBits = 0,
|
||||
StringRef Name = StringRef());
|
||||
|
||||
/// CreateReferenceType - Create debugging information entry for a c++
|
||||
/// createReferenceType - Create debugging information entry for a c++
|
||||
/// style reference.
|
||||
DIType CreateReferenceType(DIType RTy);
|
||||
DIType createReferenceType(DIType RTy);
|
||||
|
||||
/// CreateTypedef - Create debugging information entry for a typedef.
|
||||
/// createTypedef - Create debugging information entry for a typedef.
|
||||
/// @param Ty Original type.
|
||||
/// @param Name Typedef name.
|
||||
/// @param File File where this type is defined.
|
||||
/// @param LineNo Line number.
|
||||
DIType CreateTypedef(DIType Ty, StringRef Name, DIFile File,
|
||||
DIType createTypedef(DIType Ty, StringRef Name, DIFile File,
|
||||
unsigned LineNo);
|
||||
|
||||
/// CreateFriend - Create debugging information entry for a 'friend'.
|
||||
DIType CreateFriend(DIType Ty, DIType FriendTy);
|
||||
/// createFriend - Create debugging information entry for a 'friend'.
|
||||
DIType createFriend(DIType Ty, DIType FriendTy);
|
||||
|
||||
/// CreateInheritance - Create debugging information entry to establish
|
||||
/// createInheritance - Create debugging information entry to establish
|
||||
/// inheritance relationship between two types.
|
||||
/// @param Ty Original type.
|
||||
/// @param BaseTy Base type. Ty is inherits from base.
|
||||
/// @param BaseOffset Base offset.
|
||||
/// @param Flags Flags to describe inheritance attribute,
|
||||
/// e.g. private
|
||||
DIType CreateInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset,
|
||||
DIType createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset,
|
||||
unsigned Flags);
|
||||
|
||||
/// CreateMemberType - Create debugging information entry for a member.
|
||||
/// createMemberType - Create debugging information entry for a member.
|
||||
/// @param Name Member name.
|
||||
/// @param File File where this member is defined.
|
||||
/// @param LineNo Line number.
|
||||
@ -141,12 +141,12 @@ namespace llvm {
|
||||
/// @param OffsetInBits Member offset.
|
||||
/// @param Flags Flags to encode member attribute, e.g. private
|
||||
/// @param Ty Parent type.
|
||||
DIType CreateMemberType(StringRef Name, DIFile File,
|
||||
DIType createMemberType(StringRef Name, DIFile File,
|
||||
unsigned LineNo, uint64_t SizeInBits,
|
||||
uint64_t AlignInBits, uint64_t OffsetInBits,
|
||||
unsigned Flags, DIType Ty);
|
||||
|
||||
/// CreateClassType - Create debugging information entry for a class.
|
||||
/// createClassType - Create debugging information entry for a class.
|
||||
/// @param Scope Scope in which this class is defined.
|
||||
/// @param Name class name.
|
||||
/// @param File File where this member is defined.
|
||||
@ -161,14 +161,14 @@ namespace llvm {
|
||||
/// DW_AT_containing_type. See DWARF documentation
|
||||
/// for more info.
|
||||
/// @param TemplateParms Template type parameters.
|
||||
DIType CreateClassType(DIDescriptor Scope, StringRef Name, DIFile File,
|
||||
DIType createClassType(DIDescriptor Scope, StringRef Name, DIFile File,
|
||||
unsigned LineNumber, uint64_t SizeInBits,
|
||||
uint64_t AlignInBits, uint64_t OffsetInBits,
|
||||
unsigned Flags, DIType DerivedFrom,
|
||||
DIArray Elements, MDNode *VTableHolder = 0,
|
||||
MDNode *TemplateParms = 0);
|
||||
|
||||
/// CreateStructType - Create debugging information entry for a struct.
|
||||
/// createStructType - Create debugging information entry for a struct.
|
||||
/// @param Scope Scope in which this struct is defined.
|
||||
/// @param Name Struct name.
|
||||
/// @param File File where this member is defined.
|
||||
@ -178,12 +178,12 @@ namespace llvm {
|
||||
/// @param Flags Flags to encode member attribute, e.g. private
|
||||
/// @param Elements Struct elements.
|
||||
/// @param RunTimeLang Optional parameter, Objective-C runtime version.
|
||||
DIType CreateStructType(DIDescriptor Scope, StringRef Name, DIFile File,
|
||||
DIType createStructType(DIDescriptor Scope, StringRef Name, DIFile File,
|
||||
unsigned LineNumber, uint64_t SizeInBits,
|
||||
uint64_t AlignInBits, unsigned Flags,
|
||||
DIArray Elements, unsigned RunTimeLang = 0);
|
||||
|
||||
/// CreateUnionType - Create debugging information entry for an union.
|
||||
/// createUnionType - Create debugging information entry for an union.
|
||||
/// @param Scope Scope in which this union is defined.
|
||||
/// @param Name Union name.
|
||||
/// @param File File where this member is defined.
|
||||
@ -193,12 +193,12 @@ namespace llvm {
|
||||
/// @param Flags Flags to encode member attribute, e.g. private
|
||||
/// @param Elements Union elements.
|
||||
/// @param RunTimeLang Optional parameter, Objective-C runtime version.
|
||||
DIType CreateUnionType(DIDescriptor Scope, StringRef Name, DIFile File,
|
||||
DIType createUnionType(DIDescriptor Scope, StringRef Name, DIFile File,
|
||||
unsigned LineNumber, uint64_t SizeInBits,
|
||||
uint64_t AlignInBits, unsigned Flags,
|
||||
DIArray Elements, unsigned RunTimeLang = 0);
|
||||
|
||||
/// CreateTemplateTypeParameter - Create debugging information for template
|
||||
/// createTemplateTypeParameter - Create debugging information for template
|
||||
/// type parameter.
|
||||
/// @param Scope Scope in which this type is defined.
|
||||
/// @param Name Type parameter name.
|
||||
@ -207,11 +207,11 @@ namespace llvm {
|
||||
/// @param LineNo Line number.
|
||||
/// @param ColumnNo Column Number.
|
||||
DITemplateTypeParameter
|
||||
CreateTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
|
||||
createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
|
||||
MDNode *File = 0, unsigned LineNo = 0,
|
||||
unsigned ColumnNo = 0);
|
||||
|
||||
/// CreateTemplateValueParameter - Create debugging information for template
|
||||
/// createTemplateValueParameter - Create debugging information for template
|
||||
/// value parameter.
|
||||
/// @param Scope Scope in which this type is defined.
|
||||
/// @param Name Value parameter name.
|
||||
@ -221,28 +221,28 @@ namespace llvm {
|
||||
/// @param LineNo Line number.
|
||||
/// @param ColumnNo Column Number.
|
||||
DITemplateValueParameter
|
||||
CreateTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
|
||||
createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty,
|
||||
uint64_t Value,
|
||||
MDNode *File = 0, unsigned LineNo = 0,
|
||||
unsigned ColumnNo = 0);
|
||||
|
||||
/// CreateArrayType - Create debugging information entry for an array.
|
||||
/// createArrayType - Create debugging information entry for an array.
|
||||
/// @param Size Array size.
|
||||
/// @param AlignInBits Alignment.
|
||||
/// @param Ty Element type.
|
||||
/// @param Subscripts Subscripts.
|
||||
DIType CreateArrayType(uint64_t Size, uint64_t AlignInBits,
|
||||
DIType createArrayType(uint64_t Size, uint64_t AlignInBits,
|
||||
DIType Ty, DIArray Subscripts);
|
||||
|
||||
/// CreateVectorType - Create debugging information entry for a vector type.
|
||||
/// createVectorType - Create debugging information entry for a vector type.
|
||||
/// @param Size Array size.
|
||||
/// @param AlignInBits Alignment.
|
||||
/// @param Ty Element type.
|
||||
/// @param Subscripts Subscripts.
|
||||
DIType CreateVectorType(uint64_t Size, uint64_t AlignInBits,
|
||||
DIType createVectorType(uint64_t Size, uint64_t AlignInBits,
|
||||
DIType Ty, DIArray Subscripts);
|
||||
|
||||
/// CreateEnumerationType - Create debugging information entry for an
|
||||
/// createEnumerationType - Create debugging information entry for an
|
||||
/// enumeration.
|
||||
/// @param Scope Scope in which this enumeration is defined.
|
||||
/// @param Name Union name.
|
||||
@ -251,40 +251,40 @@ namespace llvm {
|
||||
/// @param SizeInBits Member size.
|
||||
/// @param AlignInBits Member alignment.
|
||||
/// @param Elements Enumeration elements.
|
||||
DIType CreateEnumerationType(DIDescriptor Scope, StringRef Name,
|
||||
DIType createEnumerationType(DIDescriptor Scope, StringRef Name,
|
||||
DIFile File, unsigned LineNumber,
|
||||
uint64_t SizeInBits,
|
||||
uint64_t AlignInBits, DIArray Elements);
|
||||
|
||||
/// CreateSubroutineType - Create subroutine type.
|
||||
/// createSubroutineType - Create subroutine type.
|
||||
/// @param File File in which this subroutine is defined.
|
||||
/// @param ParamterTypes An array of subroutine parameter types. This
|
||||
/// includes return type at 0th index.
|
||||
DIType CreateSubroutineType(DIFile File, DIArray ParameterTypes);
|
||||
DIType createSubroutineType(DIFile File, DIArray ParameterTypes);
|
||||
|
||||
/// CreateArtificialType - Create a new DIType with "artificial" flag set.
|
||||
DIType CreateArtificialType(DIType Ty);
|
||||
/// createArtificialType - Create a new DIType with "artificial" flag set.
|
||||
DIType createArtificialType(DIType Ty);
|
||||
|
||||
/// CreateTemporaryType - Create a temporary forward-declared type.
|
||||
DIType CreateTemporaryType();
|
||||
DIType CreateTemporaryType(DIFile F);
|
||||
/// createTemporaryType - Create a temporary forward-declared type.
|
||||
DIType createTemporaryType();
|
||||
DIType createTemporaryType(DIFile F);
|
||||
|
||||
/// RetainType - Retain DIType in a module even if it is not referenced
|
||||
/// retainType - Retain DIType in a module even if it is not referenced
|
||||
/// through debug info anchors.
|
||||
void RetainType(DIType T);
|
||||
void retainType(DIType T);
|
||||
|
||||
/// CreateUnspecifiedParameter - Create unspeicified type descriptor
|
||||
/// createUnspecifiedParameter - Create unspeicified type descriptor
|
||||
/// for a subroutine type.
|
||||
DIDescriptor CreateUnspecifiedParameter();
|
||||
DIDescriptor createUnspecifiedParameter();
|
||||
|
||||
/// GetOrCreateArray - Get a DIArray, create one if required.
|
||||
DIArray GetOrCreateArray(Value *const *Elements, unsigned NumElements);
|
||||
/// getOrCreateArray - Get a DIArray, create one if required.
|
||||
DIArray getOrCreateArray(Value *const *Elements, unsigned NumElements);
|
||||
|
||||
/// GetOrCreateSubrange - Create a descriptor for a value range. This
|
||||
/// getOrCreateSubrange - Create a descriptor for a value range. This
|
||||
/// implicitly uniques the values returned.
|
||||
DISubrange GetOrCreateSubrange(int64_t Lo, int64_t Hi);
|
||||
DISubrange getOrCreateSubrange(int64_t Lo, int64_t Hi);
|
||||
|
||||
/// CreateGlobalVariable - Create a new descriptor for the specified global.
|
||||
/// createGlobalVariable - Create a new descriptor for the specified global.
|
||||
/// @param Name Name of the variable.
|
||||
/// @param File File where this variable is defined.
|
||||
/// @param LineNo Line number.
|
||||
@ -293,11 +293,11 @@ namespace llvm {
|
||||
/// externally visible or not.
|
||||
/// @param Val llvm::Value of the variable.
|
||||
DIGlobalVariable
|
||||
CreateGlobalVariable(StringRef Name, DIFile File, unsigned LineNo,
|
||||
createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo,
|
||||
DIType Ty, bool isLocalToUnit, llvm::Value *Val);
|
||||
|
||||
|
||||
/// CreateStaticVariable - Create a new descriptor for the specified
|
||||
/// createStaticVariable - Create a new descriptor for the specified
|
||||
/// variable.
|
||||
/// @param Conext Variable scope.
|
||||
/// @param Name Name of the variable.
|
||||
@ -309,12 +309,12 @@ namespace llvm {
|
||||
/// externally visible or not.
|
||||
/// @param Val llvm::Value of the variable.
|
||||
DIGlobalVariable
|
||||
CreateStaticVariable(DIDescriptor Context, StringRef Name,
|
||||
createStaticVariable(DIDescriptor Context, StringRef Name,
|
||||
StringRef LinkageName, DIFile File, unsigned LineNo,
|
||||
DIType Ty, bool isLocalToUnit, llvm::Value *Val);
|
||||
|
||||
|
||||
/// CreateLocalVariable - Create a new descriptor for the specified
|
||||
/// createLocalVariable - Create a new descriptor for the specified
|
||||
/// local variable.
|
||||
/// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or
|
||||
/// DW_TAG_arg_variable.
|
||||
@ -326,14 +326,14 @@ namespace llvm {
|
||||
/// @param AlwaysPreserve Boolean. Set to true if debug info for this
|
||||
/// variable should be preserved in optimized build.
|
||||
/// @param Flags Flags, e.g. artificial variable.
|
||||
DIVariable CreateLocalVariable(unsigned Tag, DIDescriptor Scope,
|
||||
DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope,
|
||||
StringRef Name,
|
||||
DIFile File, unsigned LineNo,
|
||||
DIType Ty, bool AlwaysPreserve = false,
|
||||
unsigned Flags = 0);
|
||||
|
||||
|
||||
/// CreateComplexVariable - Create a new descriptor for the specified
|
||||
/// createComplexVariable - Create a new descriptor for the specified
|
||||
/// variable which has a complex address expression for its address.
|
||||
/// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or
|
||||
/// DW_TAG_arg_variable.
|
||||
@ -344,12 +344,12 @@ namespace llvm {
|
||||
/// @param Ty Variable Type
|
||||
/// @param Addr A pointer to a vector of complex address operations.
|
||||
/// @param NumAddr Num of address operations in the vector.
|
||||
DIVariable CreateComplexVariable(unsigned Tag, DIDescriptor Scope,
|
||||
DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope,
|
||||
StringRef Name, DIFile F, unsigned LineNo,
|
||||
DIType Ty, Value *const *Addr,
|
||||
unsigned NumAddr);
|
||||
|
||||
/// CreateFunction - Create a new descriptor for the specified subprogram.
|
||||
/// createFunction - Create a new descriptor for the specified subprogram.
|
||||
/// See comments in DISubprogram for descriptions of these fields.
|
||||
/// @param Scope Function scope.
|
||||
/// @param Name Function name.
|
||||
@ -363,7 +363,7 @@ namespace llvm {
|
||||
/// This flags are used to emit dwarf attributes.
|
||||
/// @param isOptimized True if optimization is ON.
|
||||
/// @param Fn llvm::Function pointer.
|
||||
DISubprogram CreateFunction(DIDescriptor Scope, StringRef Name,
|
||||
DISubprogram createFunction(DIDescriptor Scope, StringRef Name,
|
||||
StringRef LinkageName,
|
||||
DIFile File, unsigned LineNo,
|
||||
DIType Ty, bool isLocalToUnit,
|
||||
@ -372,7 +372,7 @@ namespace llvm {
|
||||
bool isOptimized = false,
|
||||
Function *Fn = 0);
|
||||
|
||||
/// CreateMethod - Create a new descriptor for the specified C++ method.
|
||||
/// createMethod - Create a new descriptor for the specified C++ method.
|
||||
/// See comments in DISubprogram for descriptions of these fields.
|
||||
/// @param Scope Function scope.
|
||||
/// @param Name Function name.
|
||||
@ -390,7 +390,7 @@ namespace llvm {
|
||||
/// This flags are used to emit dwarf attributes.
|
||||
/// @param isOptimized True if optimization is ON.
|
||||
/// @param Fn llvm::Function pointer.
|
||||
DISubprogram CreateMethod(DIDescriptor Scope, StringRef Name,
|
||||
DISubprogram createMethod(DIDescriptor Scope, StringRef Name,
|
||||
StringRef LinkageName,
|
||||
DIFile File, unsigned LineNo,
|
||||
DIType Ty, bool isLocalToUnit,
|
||||
@ -401,55 +401,55 @@ namespace llvm {
|
||||
bool isOptimized = false,
|
||||
Function *Fn = 0);
|
||||
|
||||
/// CreateNameSpace - This creates new descriptor for a namespace
|
||||
/// createNameSpace - This creates new descriptor for a namespace
|
||||
/// with the specified parent scope.
|
||||
/// @param Scope Namespace scope
|
||||
/// @param Name Name of this namespace
|
||||
/// @param File Source file
|
||||
/// @param LineNo Line number
|
||||
DINameSpace CreateNameSpace(DIDescriptor Scope, StringRef Name,
|
||||
DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name,
|
||||
DIFile File, unsigned LineNo);
|
||||
|
||||
|
||||
/// CreateLexicalBlock - This creates a descriptor for a lexical block
|
||||
/// createLexicalBlock - This creates a descriptor for a lexical block
|
||||
/// with the specified parent context.
|
||||
/// @param Scope Parent lexical scope.
|
||||
/// @param File Source file
|
||||
/// @param Line Line number
|
||||
/// @param Col Column number
|
||||
DILexicalBlock CreateLexicalBlock(DIDescriptor Scope, DIFile File,
|
||||
DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File,
|
||||
unsigned Line, unsigned Col);
|
||||
|
||||
/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
|
||||
/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
|
||||
/// @param Storage llvm::Value of the variable
|
||||
/// @param VarInfo Variable's debug info descriptor.
|
||||
/// @param InsertAtEnd Location for the new intrinsic.
|
||||
Instruction *InsertDeclare(llvm::Value *Storage, DIVariable VarInfo,
|
||||
Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo,
|
||||
BasicBlock *InsertAtEnd);
|
||||
|
||||
/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
|
||||
/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
|
||||
/// @param Storage llvm::Value of the variable
|
||||
/// @param VarInfo Variable's debug info descriptor.
|
||||
/// @param InsertBefore Location for the new intrinsic.
|
||||
Instruction *InsertDeclare(llvm::Value *Storage, DIVariable VarInfo,
|
||||
Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo,
|
||||
Instruction *InsertBefore);
|
||||
|
||||
|
||||
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
/// @param Val llvm::Value of the variable
|
||||
/// @param Offset Offset
|
||||
/// @param VarInfo Variable's debug info descriptor.
|
||||
/// @param InsertAtEnd Location for the new intrinsic.
|
||||
Instruction *InsertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
|
||||
Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
|
||||
DIVariable VarInfo,
|
||||
BasicBlock *InsertAtEnd);
|
||||
|
||||
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
/// @param Val llvm::Value of the variable
|
||||
/// @param Offset Offset
|
||||
/// @param VarInfo Variable's debug info descriptor.
|
||||
/// @param InsertBefore Location for the new intrinsic.
|
||||
Instruction *InsertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
|
||||
Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset,
|
||||
DIVariable VarInfo,
|
||||
Instruction *InsertBefore);
|
||||
|
||||
|
@ -4,6 +4,7 @@ tablegen(Intrinsics.gen -gen-intrinsic)
|
||||
|
||||
add_custom_target(intrinsics_gen ALL
|
||||
DEPENDS ${llvm_builded_incs_dir}/Intrinsics.gen)
|
||||
set_target_properties(intrinsics_gen PROPERTIES FOLDER "Tablegenning")
|
||||
|
||||
set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} intrinsics_gen PARENT_SCOPE)
|
||||
|
||||
@ -16,4 +17,5 @@ if( MSVC_IDE OR XCODE )
|
||||
# We need at least one source file:
|
||||
${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello/Hello.cpp
|
||||
${headers})
|
||||
set_target_properties(llvm_headers_do_not_build PROPERTIES FOLDER "Misc")
|
||||
endif()
|
||||
|
@ -445,7 +445,8 @@ namespace llvm {
|
||||
|
||||
/// EmitVisibility - This emits visibility information about symbol, if
|
||||
/// this is suported by the target.
|
||||
void EmitVisibility(MCSymbol *Sym, unsigned Visibility) const;
|
||||
void EmitVisibility(MCSymbol *Sym, unsigned Visibility,
|
||||
bool IsDefinition = true) const;
|
||||
|
||||
void EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const;
|
||||
|
||||
|
@ -101,13 +101,16 @@ class FunctionLoweringInfo {
|
||||
#endif
|
||||
|
||||
struct LiveOutInfo {
|
||||
unsigned NumSignBits;
|
||||
unsigned NumSignBits : 31;
|
||||
bool IsValid : 1;
|
||||
APInt KnownOne, KnownZero;
|
||||
LiveOutInfo() : NumSignBits(0), KnownOne(1, 0), KnownZero(1, 0) {}
|
||||
LiveOutInfo() : NumSignBits(0), IsValid(true), KnownOne(1, 0),
|
||||
KnownZero(1, 0) {}
|
||||
};
|
||||
|
||||
/// LiveOutRegInfo - Information about live out vregs.
|
||||
IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo;
|
||||
|
||||
/// VisitedBBs - The set of basic blocks visited thus far by instruction
|
||||
/// selection.
|
||||
DenseSet<const BasicBlock*> VisitedBBs;
|
||||
|
||||
/// PHINodesToUpdate - A list of phi instructions whose operand list will
|
||||
/// be updated after processing the current basic block.
|
||||
@ -143,12 +146,62 @@ class FunctionLoweringInfo {
|
||||
return R = CreateRegs(V->getType());
|
||||
}
|
||||
|
||||
/// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the
|
||||
/// register is a PHI destination and the PHI's LiveOutInfo is not valid.
|
||||
const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg) {
|
||||
if (!LiveOutRegInfo.inBounds(Reg))
|
||||
return NULL;
|
||||
|
||||
const LiveOutInfo *LOI = &LiveOutRegInfo[Reg];
|
||||
if (!LOI->IsValid)
|
||||
return NULL;
|
||||
|
||||
return LOI;
|
||||
}
|
||||
|
||||
/// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the
|
||||
/// register is a PHI destination and the PHI's LiveOutInfo is not valid. If
|
||||
/// the register's LiveOutInfo is for a smaller bit width, it is extended to
|
||||
/// the larger bit width by zero extension. The bit width must be no smaller
|
||||
/// than the LiveOutInfo's existing bit width.
|
||||
const LiveOutInfo *GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth);
|
||||
|
||||
/// AddLiveOutRegInfo - Adds LiveOutInfo for a register.
|
||||
void AddLiveOutRegInfo(unsigned Reg, unsigned NumSignBits,
|
||||
const APInt &KnownZero, const APInt &KnownOne) {
|
||||
// Only install this information if it tells us something.
|
||||
if (NumSignBits == 1 && KnownZero == 0 && KnownOne == 0)
|
||||
return;
|
||||
|
||||
LiveOutRegInfo.grow(Reg);
|
||||
LiveOutInfo &LOI = LiveOutRegInfo[Reg];
|
||||
LOI.NumSignBits = NumSignBits;
|
||||
LOI.KnownOne = KnownOne;
|
||||
LOI.KnownZero = KnownZero;
|
||||
}
|
||||
|
||||
/// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination
|
||||
/// register based on the LiveOutInfo of its operands.
|
||||
void ComputePHILiveOutRegInfo(const PHINode*);
|
||||
|
||||
/// InvalidatePHILiveOutRegInfo - Invalidates a PHI's LiveOutInfo, to be
|
||||
/// called when a block is visited before all of its predecessors.
|
||||
void InvalidatePHILiveOutRegInfo(const PHINode *PN) {
|
||||
unsigned Reg = ValueMap[PN];
|
||||
LiveOutRegInfo.grow(Reg);
|
||||
LiveOutRegInfo[Reg].IsValid = false;
|
||||
}
|
||||
|
||||
/// setByValArgumentFrameIndex - Record frame index for the byval
|
||||
/// argument.
|
||||
void setByValArgumentFrameIndex(const Argument *A, int FI);
|
||||
|
||||
/// getByValArgumentFrameIndex - Get frame index for the byval argument.
|
||||
int getByValArgumentFrameIndex(const Argument *A);
|
||||
|
||||
private:
|
||||
/// LiveOutRegInfo - Information about live out vregs.
|
||||
IndexedMap<LiveOutInfo, VirtReg2IndexFunctor> LiveOutRegInfo;
|
||||
};
|
||||
|
||||
/// AddCatchInfo - Extract the personality and type infos from an eh.selector
|
||||
|
@ -16,6 +16,7 @@
|
||||
#ifndef LLVM_CODEGEN_MACHINECONSTANTPOOL_H
|
||||
#define LLVM_CODEGEN_MACHINECONSTANTPOOL_H
|
||||
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <vector>
|
||||
@ -130,6 +131,8 @@ class MachineConstantPool {
|
||||
const TargetData *TD; ///< The machine's TargetData.
|
||||
unsigned PoolAlignment; ///< The alignment for the pool.
|
||||
std::vector<MachineConstantPoolEntry> Constants; ///< The pool of constants.
|
||||
/// MachineConstantPoolValues that use an existing MachineConstantPoolEntry.
|
||||
DenseSet<MachineConstantPoolValue*> MachineCPVsSharingEntries;
|
||||
public:
|
||||
/// @brief The only constructor.
|
||||
explicit MachineConstantPool(const TargetData *td)
|
||||
|
@ -281,7 +281,7 @@ class MachineFunction {
|
||||
|
||||
/// addLiveIn - Add the specified physical register as a live-in value and
|
||||
/// create a corresponding virtual register for it.
|
||||
unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC, DebugLoc DL);
|
||||
unsigned addLiveIn(unsigned PReg, const TargetRegisterClass *RC);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// BasicBlock accessor functions.
|
||||
|
@ -17,8 +17,6 @@
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/IndexedMap.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/DebugLoc.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
@ -66,10 +64,7 @@ class MachineRegisterInfo {
|
||||
/// stored in the second element.
|
||||
std::vector<std::pair<unsigned, unsigned> > LiveIns;
|
||||
std::vector<unsigned> LiveOuts;
|
||||
|
||||
/// LiveInLocs - Keep track of location livein registers.
|
||||
DenseMap<unsigned, DebugLoc> LiveInLocs;
|
||||
|
||||
|
||||
MachineRegisterInfo(const MachineRegisterInfo&); // DO NOT IMPLEMENT
|
||||
void operator=(const MachineRegisterInfo&); // DO NOT IMPLEMENT
|
||||
public:
|
||||
@ -276,12 +271,7 @@ class MachineRegisterInfo {
|
||||
LiveIns.push_back(std::make_pair(Reg, vreg));
|
||||
}
|
||||
void addLiveOut(unsigned Reg) { LiveOuts.push_back(Reg); }
|
||||
|
||||
/// addLiveInLoc - Keep track of location info for live in reg.
|
||||
void addLiveInLoc(unsigned VReg, DebugLoc DL) {
|
||||
LiveInLocs[VReg] = DL;
|
||||
}
|
||||
|
||||
|
||||
// Iteration support for live in/out sets. These sets are kept in sorted
|
||||
// order by their register number.
|
||||
typedef std::vector<std::pair<unsigned,unsigned> >::const_iterator
|
||||
|
@ -33,4 +33,23 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.".
|
||||
[NoCapture<0>]>;
|
||||
def int_xcore_setc : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty],
|
||||
[NoCapture<0>]>;
|
||||
def int_xcore_inshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty],
|
||||
[NoCapture<0>]>;
|
||||
def int_xcore_outshr : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty, llvm_i32_ty],
|
||||
[NoCapture<0>]>;
|
||||
def int_xcore_setpt : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty],
|
||||
[NoCapture<0>]>;
|
||||
def int_xcore_getts : Intrinsic<[llvm_i32_ty],[llvm_anyptr_ty],
|
||||
[NoCapture<0>]>;
|
||||
def int_xcore_syncr : Intrinsic<[],[llvm_anyptr_ty],
|
||||
[NoCapture<0>]>;
|
||||
def int_xcore_settw : Intrinsic<[],[llvm_anyptr_ty, llvm_i32_ty],
|
||||
[NoCapture<0>]>;
|
||||
def int_xcore_setv : Intrinsic<[],[llvm_anyptr_ty, llvm_ptr_ty],
|
||||
[NoCapture<0>]>;
|
||||
def int_xcore_eeu : Intrinsic<[],[llvm_anyptr_ty], [NoCapture<0>]>;
|
||||
|
||||
// Intrinsics for events.
|
||||
def int_xcore_waitevent : Intrinsic<[llvm_ptr_ty],[], [IntrReadMem]>;
|
||||
def int_xcore_clre : Intrinsic<[],[],[]>;
|
||||
}
|
||||
|
@ -246,6 +246,11 @@ namespace llvm {
|
||||
/// declare a symbol as having hidden visibility.
|
||||
MCSymbolAttr HiddenVisibilityAttr; // Defaults to MCSA_Hidden.
|
||||
|
||||
/// HiddenDeclarationVisibilityAttr - This attribute, if not MCSA_Invalid,
|
||||
/// is used to declare an undefined symbol as having hidden visibility.
|
||||
MCSymbolAttr HiddenDeclarationVisibilityAttr; // Defaults to MCSA_Hidden.
|
||||
|
||||
|
||||
/// ProtectedVisibilityAttr - This attribute, if not MCSA_Invalid, is used
|
||||
/// to declare a symbol as having protected visibility.
|
||||
MCSymbolAttr ProtectedVisibilityAttr; // Defaults to MCSA_Protected
|
||||
@ -425,6 +430,9 @@ namespace llvm {
|
||||
const char *getLinkOnceDirective() const { return LinkOnceDirective; }
|
||||
|
||||
MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr;}
|
||||
MCSymbolAttr getHiddenDeclarationVisibilityAttr() const {
|
||||
return HiddenDeclarationVisibilityAttr;
|
||||
}
|
||||
MCSymbolAttr getProtectedVisibilityAttr() const {
|
||||
return ProtectedVisibilityAttr;
|
||||
}
|
||||
|
@ -38,6 +38,8 @@ class MCAsmParserExtension {
|
||||
return (Obj->*Handler)(Directive, DirectiveLoc);
|
||||
}
|
||||
|
||||
bool BracketExpressionsSupported;
|
||||
|
||||
public:
|
||||
virtual ~MCAsmParserExtension();
|
||||
|
||||
@ -68,6 +70,8 @@ class MCAsmParserExtension {
|
||||
|
||||
const AsmToken &getTok() { return getParser().getTok(); }
|
||||
|
||||
bool HasBracketExpressions() const { return BracketExpressionsSupported; }
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
|
@ -57,13 +57,10 @@ namespace llvm {
|
||||
MCDwarfFrameInfo *getCurrentFrameInfo();
|
||||
void EnsureValidFrame();
|
||||
|
||||
/// CurSectionStack - This is stack of CurSection values saved by
|
||||
/// PushSection.
|
||||
SmallVector<const MCSection *, 4> CurSectionStack;
|
||||
|
||||
/// PrevSectionStack - This is stack of PrevSection values saved by
|
||||
/// PushSection.
|
||||
SmallVector<const MCSection *, 4> PrevSectionStack;
|
||||
/// SectionStack - This is stack of current and previous section
|
||||
/// values saved by PushSection.
|
||||
SmallVector<std::pair<const MCSection *,
|
||||
const MCSection *>, 4> SectionStack;
|
||||
|
||||
protected:
|
||||
MCStreamer(MCContext &Ctx);
|
||||
@ -117,16 +114,16 @@ namespace llvm {
|
||||
/// getCurrentSection - Return the current section that the streamer is
|
||||
/// emitting code to.
|
||||
const MCSection *getCurrentSection() const {
|
||||
if (!CurSectionStack.empty())
|
||||
return CurSectionStack.back();
|
||||
if (!SectionStack.empty())
|
||||
return SectionStack.back().first;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// getPreviousSection - Return the previous section that the streamer is
|
||||
/// emitting code to.
|
||||
const MCSection *getPreviousSection() const {
|
||||
if (!PrevSectionStack.empty())
|
||||
return PrevSectionStack.back();
|
||||
if (!SectionStack.empty())
|
||||
return SectionStack.back().second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -139,8 +136,8 @@ namespace llvm {
|
||||
/// pushSection - Save the current and previous section on the
|
||||
/// section stack.
|
||||
void PushSection() {
|
||||
PrevSectionStack.push_back(getPreviousSection());
|
||||
CurSectionStack.push_back(getCurrentSection());
|
||||
SectionStack.push_back(std::make_pair(getCurrentSection(),
|
||||
getPreviousSection()));
|
||||
}
|
||||
|
||||
/// popSection - Restore the current and previous section from
|
||||
@ -148,12 +145,10 @@ namespace llvm {
|
||||
///
|
||||
/// Returns false if the stack was empty.
|
||||
bool PopSection() {
|
||||
if (PrevSectionStack.size() <= 1)
|
||||
if (SectionStack.size() <= 1)
|
||||
return false;
|
||||
assert(CurSectionStack.size() > 1);
|
||||
PrevSectionStack.pop_back();
|
||||
const MCSection *oldSection = CurSectionStack.pop_back_val();
|
||||
const MCSection *curSection = CurSectionStack.back();
|
||||
const MCSection *oldSection = SectionStack.pop_back_val().first;
|
||||
const MCSection *curSection = SectionStack.back().first;
|
||||
|
||||
if (oldSection != curSection)
|
||||
ChangeSection(curSection);
|
||||
@ -166,10 +161,10 @@ namespace llvm {
|
||||
/// This corresponds to assembler directives like .section, .text, etc.
|
||||
void SwitchSection(const MCSection *Section) {
|
||||
assert(Section && "Cannot switch to a null section!");
|
||||
const MCSection *curSection = CurSectionStack.back();
|
||||
PrevSectionStack.back() = curSection;
|
||||
const MCSection *curSection = SectionStack.back().first;
|
||||
SectionStack.back().second = curSection;
|
||||
if (Section != curSection) {
|
||||
CurSectionStack.back() = Section;
|
||||
SectionStack.back().first = Section;
|
||||
ChangeSection(Section);
|
||||
}
|
||||
}
|
||||
|
@ -38,8 +38,12 @@ class NoFolder {
|
||||
// Binary Operators
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
Instruction *CreateAdd(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateAdd(LHS, RHS);
|
||||
Instruction *CreateAdd(Constant *LHS, Constant *RHS,
|
||||
bool HasNUW = false, bool HasNSW = false) const {
|
||||
BinaryOperator *BO = BinaryOperator::CreateAdd(LHS, RHS);
|
||||
if (HasNUW) BO->setHasNoUnsignedWrap();
|
||||
if (HasNSW) BO->setHasNoSignedWrap();
|
||||
return BO;
|
||||
}
|
||||
Instruction *CreateNSWAdd(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateNSWAdd(LHS, RHS);
|
||||
@ -50,8 +54,12 @@ class NoFolder {
|
||||
Instruction *CreateFAdd(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateFAdd(LHS, RHS);
|
||||
}
|
||||
Instruction *CreateSub(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateSub(LHS, RHS);
|
||||
Instruction *CreateSub(Constant *LHS, Constant *RHS,
|
||||
bool HasNUW = false, bool HasNSW = false) const {
|
||||
BinaryOperator *BO = BinaryOperator::CreateSub(LHS, RHS);
|
||||
if (HasNUW) BO->setHasNoUnsignedWrap();
|
||||
if (HasNSW) BO->setHasNoSignedWrap();
|
||||
return BO;
|
||||
}
|
||||
Instruction *CreateNSWSub(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateNSWSub(LHS, RHS);
|
||||
@ -62,8 +70,12 @@ class NoFolder {
|
||||
Instruction *CreateFSub(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateFSub(LHS, RHS);
|
||||
}
|
||||
Instruction *CreateMul(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateMul(LHS, RHS);
|
||||
Instruction *CreateMul(Constant *LHS, Constant *RHS,
|
||||
bool HasNUW = false, bool HasNSW = false) const {
|
||||
BinaryOperator *BO = BinaryOperator::CreateMul(LHS, RHS);
|
||||
if (HasNUW) BO->setHasNoUnsignedWrap();
|
||||
if (HasNSW) BO->setHasNoSignedWrap();
|
||||
return BO;
|
||||
}
|
||||
Instruction *CreateNSWMul(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateNSWMul(LHS, RHS);
|
||||
@ -74,14 +86,20 @@ class NoFolder {
|
||||
Instruction *CreateFMul(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateFMul(LHS, RHS);
|
||||
}
|
||||
Instruction *CreateUDiv(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateUDiv(LHS, RHS);
|
||||
Instruction *CreateUDiv(Constant *LHS, Constant *RHS,
|
||||
bool isExact = false) const {
|
||||
if (!isExact)
|
||||
return BinaryOperator::CreateUDiv(LHS, RHS);
|
||||
return BinaryOperator::CreateExactUDiv(LHS, RHS);
|
||||
}
|
||||
Instruction *CreateExactUDiv(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateExactUDiv(LHS, RHS);
|
||||
}
|
||||
Instruction *CreateSDiv(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateSDiv(LHS, RHS);
|
||||
Instruction *CreateSDiv(Constant *LHS, Constant *RHS,
|
||||
bool isExact = false) const {
|
||||
if (!isExact)
|
||||
return BinaryOperator::CreateSDiv(LHS, RHS);
|
||||
return BinaryOperator::CreateExactSDiv(LHS, RHS);
|
||||
}
|
||||
Instruction *CreateExactSDiv(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateExactSDiv(LHS, RHS);
|
||||
@ -98,14 +116,24 @@ class NoFolder {
|
||||
Instruction *CreateFRem(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateFRem(LHS, RHS);
|
||||
}
|
||||
Instruction *CreateShl(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateShl(LHS, RHS);
|
||||
Instruction *CreateShl(Constant *LHS, Constant *RHS, bool HasNUW = false,
|
||||
bool HasNSW = false) const {
|
||||
BinaryOperator *BO = BinaryOperator::CreateShl(LHS, RHS);
|
||||
if (HasNUW) BO->setHasNoUnsignedWrap();
|
||||
if (HasNSW) BO->setHasNoSignedWrap();
|
||||
return BO;
|
||||
}
|
||||
Instruction *CreateLShr(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateLShr(LHS, RHS);
|
||||
Instruction *CreateLShr(Constant *LHS, Constant *RHS,
|
||||
bool isExact = false) const {
|
||||
if (!isExact)
|
||||
return BinaryOperator::CreateLShr(LHS, RHS);
|
||||
return BinaryOperator::CreateExactLShr(LHS, RHS);
|
||||
}
|
||||
Instruction *CreateAShr(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateAShr(LHS, RHS);
|
||||
Instruction *CreateAShr(Constant *LHS, Constant *RHS,
|
||||
bool isExact = false) const {
|
||||
if (!isExact)
|
||||
return BinaryOperator::CreateAShr(LHS, RHS);
|
||||
return BinaryOperator::CreateExactAShr(LHS, RHS);
|
||||
}
|
||||
Instruction *CreateAnd(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateAnd(LHS, RHS);
|
||||
@ -126,8 +154,12 @@ class NoFolder {
|
||||
// Unary Operators
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
Instruction *CreateNeg(Constant *C) const {
|
||||
return BinaryOperator::CreateNeg(C);
|
||||
Instruction *CreateNeg(Constant *C,
|
||||
bool HasNUW = false, bool HasNSW = false) const {
|
||||
BinaryOperator *BO = BinaryOperator::CreateNeg(C);
|
||||
if (HasNUW) BO->setHasNoUnsignedWrap();
|
||||
if (HasNSW) BO->setHasNoSignedWrap();
|
||||
return BO;
|
||||
}
|
||||
Instruction *CreateNSWNeg(Constant *C) const {
|
||||
return BinaryOperator::CreateNSWNeg(C);
|
||||
|
@ -312,9 +312,9 @@ namespace sys {
|
||||
/// This function determines if the path name is absolute, as opposed to
|
||||
/// relative.
|
||||
/// @brief Determine if the path is absolute.
|
||||
//FIXME: LLVM_ATTRIBUTE_DEPRECATED(
|
||||
bool isAbsolute() const;
|
||||
//FIXME: LLVMV_PATH_DEPRECATED_MSG(path::is_absolute));
|
||||
LLVM_ATTRIBUTE_DEPRECATED(
|
||||
bool isAbsolute() const,
|
||||
LLVM_PATH_DEPRECATED_MSG(path::is_absolute));
|
||||
|
||||
/// This function determines if the path name is absolute, as opposed to
|
||||
/// relative.
|
||||
|
@ -111,7 +111,7 @@ class TargetLowering {
|
||||
bool isBigEndian() const { return !IsLittleEndian; }
|
||||
bool isLittleEndian() const { return IsLittleEndian; }
|
||||
MVT getPointerTy() const { return PointerTy; }
|
||||
MVT getShiftAmountTy() const { return ShiftAmountTy; }
|
||||
virtual MVT getShiftAmountTy(EVT LHSTy) const;
|
||||
|
||||
/// isSelectExpensive - Return true if the select operation is expensive for
|
||||
/// this target.
|
||||
@ -210,7 +210,7 @@ class TargetLowering {
|
||||
/// ValueTypeActions - For each value type, keep a LegalizeAction enum
|
||||
/// that indicates how instruction selection should deal with the type.
|
||||
uint8_t ValueTypeActions[MVT::LAST_VALUETYPE];
|
||||
|
||||
|
||||
LegalizeAction getExtendedTypeAction(EVT VT) const {
|
||||
// Handle non-vector integers.
|
||||
if (!VT.isVector()) {
|
||||
@ -221,42 +221,56 @@ class TargetLowering {
|
||||
return Promote;
|
||||
return Expand;
|
||||
}
|
||||
|
||||
// If this is a type smaller than a legal vector type, promote to that
|
||||
// type, e.g. <2 x float> -> <4 x float>.
|
||||
if (VT.getVectorElementType().isSimple() &&
|
||||
VT.getVectorNumElements() != 1) {
|
||||
MVT EltType = VT.getVectorElementType().getSimpleVT();
|
||||
unsigned NumElts = VT.getVectorNumElements();
|
||||
while (1) {
|
||||
// Round up to the nearest power of 2.
|
||||
NumElts = (unsigned)NextPowerOf2(NumElts);
|
||||
|
||||
MVT LargerVector = MVT::getVectorVT(EltType, NumElts);
|
||||
if (LargerVector == MVT()) break;
|
||||
|
||||
// If this the larger type is legal, promote to it.
|
||||
if (getTypeAction(LargerVector) == Legal) return Promote;
|
||||
}
|
||||
|
||||
// Vectors with only one element are always scalarized.
|
||||
if (VT.getVectorNumElements() == 1)
|
||||
return Expand;
|
||||
|
||||
// Vectors with a number of elements that is not a power of two are always
|
||||
// widened, for example <3 x float> -> <4 x float>.
|
||||
if (!VT.isPow2VectorType())
|
||||
return Promote;
|
||||
|
||||
// Vectors with a crazy element type are always expanded, for example
|
||||
// <4 x i2> is expanded into two vectors of type <2 x i2>.
|
||||
if (!VT.getVectorElementType().isSimple())
|
||||
return Expand;
|
||||
|
||||
// If this type is smaller than a legal vector type then widen it,
|
||||
// otherwise expand it. E.g. <2 x float> -> <4 x float>.
|
||||
MVT EltType = VT.getVectorElementType().getSimpleVT();
|
||||
unsigned NumElts = VT.getVectorNumElements();
|
||||
while (1) {
|
||||
// Round up to the next power of 2.
|
||||
NumElts = (unsigned)NextPowerOf2(NumElts);
|
||||
|
||||
// If there is no simple vector type with this many elements then there
|
||||
// cannot be a larger legal vector type. Note that this assumes that
|
||||
// there are no skipped intermediate vector types in the simple types.
|
||||
MVT LargerVector = MVT::getVectorVT(EltType, NumElts);
|
||||
if (LargerVector == MVT())
|
||||
return Expand;
|
||||
|
||||
// If this type is legal then widen the vector.
|
||||
if (getTypeAction(LargerVector) == Legal)
|
||||
return Promote;
|
||||
}
|
||||
|
||||
return VT.isPow2VectorType() ? Expand : Promote;
|
||||
}
|
||||
}
|
||||
public:
|
||||
ValueTypeActionImpl() {
|
||||
std::fill(ValueTypeActions, array_endof(ValueTypeActions), 0);
|
||||
}
|
||||
|
||||
|
||||
LegalizeAction getTypeAction(EVT VT) const {
|
||||
if (!VT.isExtended())
|
||||
return getTypeAction(VT.getSimpleVT());
|
||||
return getExtendedTypeAction(VT);
|
||||
}
|
||||
|
||||
|
||||
LegalizeAction getTypeAction(MVT VT) const {
|
||||
return (LegalizeAction)ValueTypeActions[VT.SimpleTy];
|
||||
}
|
||||
|
||||
|
||||
void setTypeAction(EVT VT, LegalizeAction Action) {
|
||||
unsigned I = VT.getSimpleVT().SimpleTy;
|
||||
ValueTypeActions[I] = Action;
|
||||
@ -277,7 +291,7 @@ class TargetLowering {
|
||||
LegalizeAction getTypeAction(MVT VT) const {
|
||||
return ValueTypeActions.getTypeAction(VT);
|
||||
}
|
||||
|
||||
|
||||
/// getTypeToTransformTo - For types supported by the target, this is an
|
||||
/// identity function. For types that must be promoted to larger types, this
|
||||
/// returns the larger type to promote to. For integer types that are larger
|
||||
@ -310,7 +324,7 @@ class TargetLowering {
|
||||
EVT NVT = VT.getRoundIntegerType(Context);
|
||||
if (NVT == VT) // Size is a power of two - expand to half the size.
|
||||
return EVT::getIntegerVT(Context, VT.getSizeInBits() / 2);
|
||||
|
||||
|
||||
// Promote to a power of two size, avoiding multi-step promotion.
|
||||
return getTypeAction(NVT) == Promote ?
|
||||
getTypeToTransformTo(Context, NVT) : NVT;
|
||||
@ -983,10 +997,6 @@ class TargetLowering {
|
||||
//
|
||||
|
||||
protected:
|
||||
/// setShiftAmountType - Describe the type that should be used for shift
|
||||
/// amounts. This type defaults to the pointer type.
|
||||
void setShiftAmountType(MVT VT) { ShiftAmountTy = VT; }
|
||||
|
||||
/// setBooleanContents - Specify how the target extends the result of a
|
||||
/// boolean value from i1 to a wider type. See getBooleanContents.
|
||||
void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; }
|
||||
@ -1033,12 +1043,12 @@ class TargetLowering {
|
||||
|
||||
/// SelectIsExpensive - Tells the code generator not to expand operations
|
||||
/// into sequences that use the select operations if possible.
|
||||
void setSelectIsExpensive(bool isExpensive = true) {
|
||||
SelectIsExpensive = isExpensive;
|
||||
void setSelectIsExpensive(bool isExpensive = true) {
|
||||
SelectIsExpensive = isExpensive;
|
||||
}
|
||||
|
||||
/// JumpIsExpensive - Tells the code generator not to expand sequence of
|
||||
/// operations into a seperate sequences that increases the amount of
|
||||
/// JumpIsExpensive - Tells the code generator not to expand sequence of
|
||||
/// operations into a seperate sequences that increases the amount of
|
||||
/// flow control.
|
||||
void setJumpIsExpensive(bool isExpensive = true) {
|
||||
JumpIsExpensive = isExpensive;
|
||||
@ -1355,7 +1365,7 @@ class TargetLowering {
|
||||
CW_Good = 1, // Good weight.
|
||||
CW_Better = 2, // Better weight.
|
||||
CW_Best = 3, // Best weight.
|
||||
|
||||
|
||||
// Well-known weights.
|
||||
CW_SpecificReg = CW_Okay, // Specific register operands.
|
||||
CW_Register = CW_Good, // Register operands.
|
||||
@ -1408,21 +1418,21 @@ class TargetLowering {
|
||||
CallOperandVal(0), ConstraintVT(MVT::Other) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<AsmOperandInfo> AsmOperandInfoVector;
|
||||
|
||||
|
||||
/// ParseConstraints - Split up the constraint string from the inline
|
||||
/// assembly value into the specific constraints and their prefixes,
|
||||
/// and also tie in the associated operand values.
|
||||
/// If this returns an empty vector, and if the constraint string itself
|
||||
/// isn't empty, there was an error parsing.
|
||||
virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const;
|
||||
|
||||
|
||||
/// Examine constraint type and operand type and determine a weight value.
|
||||
/// The operand object must already have been set up with the operand type.
|
||||
virtual ConstraintWeight getMultipleConstraintMatchWeight(
|
||||
AsmOperandInfo &info, int maIndex) const;
|
||||
|
||||
|
||||
/// Examine constraint string and operand type and determine a weight value.
|
||||
/// The operand object must already have been set up with the operand type.
|
||||
virtual ConstraintWeight getSingleConstraintMatchWeight(
|
||||
@ -1432,7 +1442,7 @@ class TargetLowering {
|
||||
/// type to use for the specific AsmOperandInfo, setting
|
||||
/// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand
|
||||
/// being passed in is available, it can be passed in as Op, otherwise an
|
||||
/// empty SDValue can be passed.
|
||||
/// empty SDValue can be passed.
|
||||
virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo,
|
||||
SDValue Op,
|
||||
SelectionDAG *DAG = 0) const;
|
||||
@ -1646,10 +1656,6 @@ class TargetLowering {
|
||||
/// llvm.longjmp. Defaults to false.
|
||||
bool UseUnderscoreLongJmp;
|
||||
|
||||
/// ShiftAmountTy - The type to use for shift amounts, usually i8 or whatever
|
||||
/// PointerTy is.
|
||||
MVT ShiftAmountTy;
|
||||
|
||||
/// BooleanContents - Information about the contents of the high-bits in
|
||||
/// boolean values held in a type wider than i1. See getBooleanContents.
|
||||
BooleanContent BooleanContents;
|
||||
|
@ -60,7 +60,7 @@ bool RecursivelyDeleteTriviallyDeadInstructions(Value *V);
|
||||
/// dead PHI node, due to being a def-use chain of single-use nodes that
|
||||
/// either forms a cycle or is terminated by a trivially dead instruction,
|
||||
/// delete it. If that makes any of its operands trivially dead, delete them
|
||||
/// too, recursively. Return true if the PHI node is actually deleted.
|
||||
/// too, recursively. Return true if a change was made.
|
||||
bool RecursivelyDeleteDeadPHINode(PHINode *PN);
|
||||
|
||||
|
||||
|
@ -31,9 +31,9 @@ static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) {
|
||||
DIBuilder::DIBuilder(Module &m)
|
||||
: M(m), VMContext(M.getContext()), TheCU(0), DeclareFn(0), ValueFn(0) {}
|
||||
|
||||
/// CreateCompileUnit - A CompileUnit provides an anchor for all debugging
|
||||
/// createCompileUnit - A CompileUnit provides an anchor for all debugging
|
||||
/// information generated during this instance of compilation.
|
||||
void DIBuilder::CreateCompileUnit(unsigned Lang, StringRef Filename,
|
||||
void DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename,
|
||||
StringRef Directory, StringRef Producer,
|
||||
bool isOptimized, StringRef Flags,
|
||||
unsigned RunTimeVer) {
|
||||
@ -53,9 +53,9 @@ void DIBuilder::CreateCompileUnit(unsigned Lang, StringRef Filename,
|
||||
TheCU = DICompileUnit(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateFile - Create a file descriptor to hold debugging information
|
||||
/// createFile - Create a file descriptor to hold debugging information
|
||||
/// for a file.
|
||||
DIFile DIBuilder::CreateFile(StringRef Filename, StringRef Directory) {
|
||||
DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) {
|
||||
assert(TheCU && "Unable to create DW_TAG_file_type without CompileUnit");
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(VMContext, dwarf::DW_TAG_file_type),
|
||||
@ -66,8 +66,8 @@ DIFile DIBuilder::CreateFile(StringRef Filename, StringRef Directory) {
|
||||
return DIFile(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateEnumerator - Create a single enumerator value.
|
||||
DIEnumerator DIBuilder::CreateEnumerator(StringRef Name, uint64_t Val) {
|
||||
/// createEnumerator - Create a single enumerator value.
|
||||
DIEnumerator DIBuilder::createEnumerator(StringRef Name, uint64_t Val) {
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(VMContext, dwarf::DW_TAG_enumerator),
|
||||
MDString::get(VMContext, Name),
|
||||
@ -76,9 +76,9 @@ DIEnumerator DIBuilder::CreateEnumerator(StringRef Name, uint64_t Val) {
|
||||
return DIEnumerator(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateBasicType - Create debugging information entry for a basic
|
||||
/// createBasicType - Create debugging information entry for a basic
|
||||
/// type, e.g 'char'.
|
||||
DIType DIBuilder::CreateBasicType(StringRef Name, uint64_t SizeInBits,
|
||||
DIType DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits,
|
||||
uint64_t AlignInBits,
|
||||
unsigned Encoding) {
|
||||
// Basic types are encoded in DIBasicType format. Line number, filename,
|
||||
@ -98,9 +98,9 @@ DIType DIBuilder::CreateBasicType(StringRef Name, uint64_t SizeInBits,
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateQaulifiedType - Create debugging information entry for a qualified
|
||||
/// createQaulifiedType - Create debugging information entry for a qualified
|
||||
/// type, e.g. 'const int'.
|
||||
DIType DIBuilder::CreateQualifiedType(unsigned Tag, DIType FromTy) {
|
||||
DIType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) {
|
||||
// Qualified types are encoded in DIDerivedType format.
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(VMContext, Tag),
|
||||
@ -117,8 +117,8 @@ DIType DIBuilder::CreateQualifiedType(unsigned Tag, DIType FromTy) {
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreatePointerType - Create debugging information entry for a pointer.
|
||||
DIType DIBuilder::CreatePointerType(DIType PointeeTy, uint64_t SizeInBits,
|
||||
/// createPointerType - Create debugging information entry for a pointer.
|
||||
DIType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits,
|
||||
uint64_t AlignInBits, StringRef Name) {
|
||||
// Pointer types are encoded in DIDerivedType format.
|
||||
Value *Elts[] = {
|
||||
@ -136,8 +136,8 @@ DIType DIBuilder::CreatePointerType(DIType PointeeTy, uint64_t SizeInBits,
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateReferenceType - Create debugging information entry for a reference.
|
||||
DIType DIBuilder::CreateReferenceType(DIType RTy) {
|
||||
/// createReferenceType - Create debugging information entry for a reference.
|
||||
DIType DIBuilder::createReferenceType(DIType RTy) {
|
||||
// References are encoded in DIDerivedType format.
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(VMContext, dwarf::DW_TAG_reference_type),
|
||||
@ -154,8 +154,8 @@ DIType DIBuilder::CreateReferenceType(DIType RTy) {
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateTypedef - Create debugging information entry for a typedef.
|
||||
DIType DIBuilder::CreateTypedef(DIType Ty, StringRef Name, DIFile File,
|
||||
/// createTypedef - Create debugging information entry for a typedef.
|
||||
DIType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File,
|
||||
unsigned LineNo) {
|
||||
// typedefs are encoded in DIDerivedType format.
|
||||
assert(Ty.Verify() && "Invalid typedef type!");
|
||||
@ -174,8 +174,8 @@ DIType DIBuilder::CreateTypedef(DIType Ty, StringRef Name, DIFile File,
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateFriend - Create debugging information entry for a 'friend'.
|
||||
DIType DIBuilder::CreateFriend(DIType Ty, DIType FriendTy) {
|
||||
/// createFriend - Create debugging information entry for a 'friend'.
|
||||
DIType DIBuilder::createFriend(DIType Ty, DIType FriendTy) {
|
||||
// typedefs are encoded in DIDerivedType format.
|
||||
assert(Ty.Verify() && "Invalid type!");
|
||||
assert(FriendTy.Verify() && "Invalid friend type!");
|
||||
@ -194,9 +194,9 @@ DIType DIBuilder::CreateFriend(DIType Ty, DIType FriendTy) {
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateInheritance - Create debugging information entry to establish
|
||||
/// createInheritance - Create debugging information entry to establish
|
||||
/// inheritnace relationship between two types.
|
||||
DIType DIBuilder::CreateInheritance(DIType Ty, DIType BaseTy,
|
||||
DIType DIBuilder::createInheritance(DIType Ty, DIType BaseTy,
|
||||
uint64_t BaseOffset, unsigned Flags) {
|
||||
// TAG_inheritance is encoded in DIDerivedType format.
|
||||
Value *Elts[] = {
|
||||
@ -214,8 +214,8 @@ DIType DIBuilder::CreateInheritance(DIType Ty, DIType BaseTy,
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateMemberType - Create debugging information entry for a member.
|
||||
DIType DIBuilder::CreateMemberType(StringRef Name,
|
||||
/// createMemberType - Create debugging information entry for a member.
|
||||
DIType DIBuilder::createMemberType(StringRef Name,
|
||||
DIFile File, unsigned LineNumber,
|
||||
uint64_t SizeInBits, uint64_t AlignInBits,
|
||||
uint64_t OffsetInBits, unsigned Flags,
|
||||
@ -236,8 +236,8 @@ DIType DIBuilder::CreateMemberType(StringRef Name,
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateClassType - Create debugging information entry for a class.
|
||||
DIType DIBuilder::CreateClassType(DIDescriptor Context, StringRef Name,
|
||||
/// createClassType - Create debugging information entry for a class.
|
||||
DIType DIBuilder::createClassType(DIDescriptor Context, StringRef Name,
|
||||
DIFile File, unsigned LineNumber,
|
||||
uint64_t SizeInBits, uint64_t AlignInBits,
|
||||
uint64_t OffsetInBits, unsigned Flags,
|
||||
@ -263,10 +263,10 @@ DIType DIBuilder::CreateClassType(DIDescriptor Context, StringRef Name,
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateTemplateTypeParameter - Create debugging information for template
|
||||
/// createTemplateTypeParameter - Create debugging information for template
|
||||
/// type parameter.
|
||||
DITemplateTypeParameter
|
||||
DIBuilder::CreateTemplateTypeParameter(DIDescriptor Context, StringRef Name,
|
||||
DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name,
|
||||
DIType Ty, MDNode *File, unsigned LineNo,
|
||||
unsigned ColumnNo) {
|
||||
Value *Elts[] = {
|
||||
@ -282,10 +282,10 @@ DIBuilder::CreateTemplateTypeParameter(DIDescriptor Context, StringRef Name,
|
||||
array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateTemplateValueParameter - Create debugging information for template
|
||||
/// createTemplateValueParameter - Create debugging information for template
|
||||
/// value parameter.
|
||||
DITemplateValueParameter
|
||||
DIBuilder::CreateTemplateValueParameter(DIDescriptor Context, StringRef Name,
|
||||
DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name,
|
||||
DIType Ty, uint64_t Val,
|
||||
MDNode *File, unsigned LineNo,
|
||||
unsigned ColumnNo) {
|
||||
@ -303,8 +303,8 @@ DIBuilder::CreateTemplateValueParameter(DIDescriptor Context, StringRef Name,
|
||||
array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateStructType - Create debugging information entry for a struct.
|
||||
DIType DIBuilder::CreateStructType(DIDescriptor Context, StringRef Name,
|
||||
/// createStructType - Create debugging information entry for a struct.
|
||||
DIType DIBuilder::createStructType(DIDescriptor Context, StringRef Name,
|
||||
DIFile File, unsigned LineNumber,
|
||||
uint64_t SizeInBits, uint64_t AlignInBits,
|
||||
unsigned Flags, DIArray Elements,
|
||||
@ -328,8 +328,8 @@ DIType DIBuilder::CreateStructType(DIDescriptor Context, StringRef Name,
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateUnionType - Create debugging information entry for an union.
|
||||
DIType DIBuilder::CreateUnionType(DIDescriptor Scope, StringRef Name,
|
||||
/// createUnionType - Create debugging information entry for an union.
|
||||
DIType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name,
|
||||
DIFile File,
|
||||
unsigned LineNumber, uint64_t SizeInBits,
|
||||
uint64_t AlignInBits, unsigned Flags,
|
||||
@ -353,8 +353,8 @@ DIType DIBuilder::CreateUnionType(DIDescriptor Scope, StringRef Name,
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateSubroutineType - Create subroutine type.
|
||||
DIType DIBuilder::CreateSubroutineType(DIFile File, DIArray ParameterTypes) {
|
||||
/// createSubroutineType - Create subroutine type.
|
||||
DIType DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) {
|
||||
// TAG_subroutine_type is encoded in DICompositeType format.
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type),
|
||||
@ -374,9 +374,9 @@ DIType DIBuilder::CreateSubroutineType(DIFile File, DIArray ParameterTypes) {
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateEnumerationType - Create debugging information entry for an
|
||||
/// createEnumerationType - Create debugging information entry for an
|
||||
/// enumeration.
|
||||
DIType DIBuilder::CreateEnumerationType(DIDescriptor Scope, StringRef Name,
|
||||
DIType DIBuilder::createEnumerationType(DIDescriptor Scope, StringRef Name,
|
||||
DIFile File, unsigned LineNumber,
|
||||
uint64_t SizeInBits,
|
||||
uint64_t AlignInBits, DIArray Elements) {
|
||||
@ -402,8 +402,8 @@ DIType DIBuilder::CreateEnumerationType(DIDescriptor Scope, StringRef Name,
|
||||
return DIType(Node);
|
||||
}
|
||||
|
||||
/// CreateArrayType - Create debugging information entry for an array.
|
||||
DIType DIBuilder::CreateArrayType(uint64_t Size, uint64_t AlignInBits,
|
||||
/// createArrayType - Create debugging information entry for an array.
|
||||
DIType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits,
|
||||
DIType Ty, DIArray Subscripts) {
|
||||
// TAG_array_type is encoded in DICompositeType format.
|
||||
Value *Elts[] = {
|
||||
@ -424,8 +424,8 @@ DIType DIBuilder::CreateArrayType(uint64_t Size, uint64_t AlignInBits,
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateVectorType - Create debugging information entry for a vector.
|
||||
DIType DIBuilder::CreateVectorType(uint64_t Size, uint64_t AlignInBits,
|
||||
/// createVectorType - Create debugging information entry for a vector.
|
||||
DIType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits,
|
||||
DIType Ty, DIArray Subscripts) {
|
||||
// TAG_vector_type is encoded in DICompositeType format.
|
||||
Value *Elts[] = {
|
||||
@ -446,8 +446,8 @@ DIType DIBuilder::CreateVectorType(uint64_t Size, uint64_t AlignInBits,
|
||||
return DIType(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// CreateArtificialType - Create a new DIType with "artificial" flag set.
|
||||
DIType DIBuilder::CreateArtificialType(DIType Ty) {
|
||||
/// createArtificialType - Create a new DIType with "artificial" flag set.
|
||||
DIType DIBuilder::createArtificialType(DIType Ty) {
|
||||
if (Ty.isArtificial())
|
||||
return Ty;
|
||||
|
||||
@ -470,24 +470,24 @@ DIType DIBuilder::CreateArtificialType(DIType Ty) {
|
||||
return DIType(MDNode::get(VMContext, Elts.data(), Elts.size()));
|
||||
}
|
||||
|
||||
/// RetainType - Retain DIType in a module even if it is not referenced
|
||||
/// retainType - Retain DIType in a module even if it is not referenced
|
||||
/// through debug info anchors.
|
||||
void DIBuilder::RetainType(DIType T) {
|
||||
void DIBuilder::retainType(DIType T) {
|
||||
NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.ty");
|
||||
NMD->addOperand(T);
|
||||
}
|
||||
|
||||
/// CreateUnspecifiedParameter - Create unspeicified type descriptor
|
||||
/// createUnspecifiedParameter - Create unspeicified type descriptor
|
||||
/// for the subroutine type.
|
||||
DIDescriptor DIBuilder::CreateUnspecifiedParameter() {
|
||||
DIDescriptor DIBuilder::createUnspecifiedParameter() {
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters)
|
||||
};
|
||||
return DIDescriptor(MDNode::get(VMContext, &Elts[0], 1));
|
||||
}
|
||||
|
||||
/// CreateTemporaryType - Create a temporary forward-declared type.
|
||||
DIType DIBuilder::CreateTemporaryType() {
|
||||
/// createTemporaryType - Create a temporary forward-declared type.
|
||||
DIType DIBuilder::createTemporaryType() {
|
||||
// Give the temporary MDNode a tag. It doesn't matter what tag we
|
||||
// use here as long as DIType accepts it.
|
||||
Value *Elts[] = { GetTagConstant(VMContext, DW_TAG_base_type) };
|
||||
@ -495,8 +495,8 @@ DIType DIBuilder::CreateTemporaryType() {
|
||||
return DIType(Node);
|
||||
}
|
||||
|
||||
/// CreateTemporaryType - Create a temporary forward-declared type.
|
||||
DIType DIBuilder::CreateTemporaryType(DIFile F) {
|
||||
/// createTemporaryType - Create a temporary forward-declared type.
|
||||
DIType DIBuilder::createTemporaryType(DIFile F) {
|
||||
// Give the temporary MDNode a tag. It doesn't matter what tag we
|
||||
// use here as long as DIType accepts it.
|
||||
Value *Elts[] = {
|
||||
@ -509,8 +509,8 @@ DIType DIBuilder::CreateTemporaryType(DIFile F) {
|
||||
return DIType(Node);
|
||||
}
|
||||
|
||||
/// GetOrCreateArray - Get a DIArray, create one if required.
|
||||
DIArray DIBuilder::GetOrCreateArray(Value *const *Elements, unsigned NumElements) {
|
||||
/// getOrCreateArray - Get a DIArray, create one if required.
|
||||
DIArray DIBuilder::getOrCreateArray(Value *const *Elements, unsigned NumElements) {
|
||||
if (NumElements == 0) {
|
||||
Value *Null = llvm::Constant::getNullValue(Type::getInt32Ty(VMContext));
|
||||
return DIArray(MDNode::get(VMContext, &Null, 1));
|
||||
@ -518,9 +518,9 @@ DIArray DIBuilder::GetOrCreateArray(Value *const *Elements, unsigned NumElements
|
||||
return DIArray(MDNode::get(VMContext, Elements, NumElements));
|
||||
}
|
||||
|
||||
/// GetOrCreateSubrange - Create a descriptor for a value range. This
|
||||
/// getOrCreateSubrange - Create a descriptor for a value range. This
|
||||
/// implicitly uniques the values returned.
|
||||
DISubrange DIBuilder::GetOrCreateSubrange(int64_t Lo, int64_t Hi) {
|
||||
DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Hi) {
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(VMContext, dwarf::DW_TAG_subrange_type),
|
||||
ConstantInt::get(Type::getInt64Ty(VMContext), Lo),
|
||||
@ -530,9 +530,9 @@ DISubrange DIBuilder::GetOrCreateSubrange(int64_t Lo, int64_t Hi) {
|
||||
return DISubrange(MDNode::get(VMContext, &Elts[0], 3));
|
||||
}
|
||||
|
||||
/// CreateGlobalVariable - Create a new descriptor for the specified global.
|
||||
/// createGlobalVariable - Create a new descriptor for the specified global.
|
||||
DIGlobalVariable DIBuilder::
|
||||
CreateGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber,
|
||||
createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber,
|
||||
DIType Ty, bool isLocalToUnit, llvm::Value *Val) {
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(VMContext, dwarf::DW_TAG_variable),
|
||||
@ -555,10 +555,10 @@ CreateGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber,
|
||||
return DIGlobalVariable(Node);
|
||||
}
|
||||
|
||||
/// CreateStaticVariable - Create a new descriptor for the specified static
|
||||
/// createStaticVariable - Create a new descriptor for the specified static
|
||||
/// variable.
|
||||
DIGlobalVariable DIBuilder::
|
||||
CreateStaticVariable(DIDescriptor Context, StringRef Name,
|
||||
createStaticVariable(DIDescriptor Context, StringRef Name,
|
||||
StringRef LinkageName, DIFile F, unsigned LineNumber,
|
||||
DIType Ty, bool isLocalToUnit, llvm::Value *Val) {
|
||||
Value *Elts[] = {
|
||||
@ -582,8 +582,8 @@ CreateStaticVariable(DIDescriptor Context, StringRef Name,
|
||||
return DIGlobalVariable(Node);
|
||||
}
|
||||
|
||||
/// CreateVariable - Create a new descriptor for the specified variable.
|
||||
DIVariable DIBuilder::CreateLocalVariable(unsigned Tag, DIDescriptor Scope,
|
||||
/// createVariable - Create a new descriptor for the specified variable.
|
||||
DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope,
|
||||
StringRef Name, DIFile File,
|
||||
unsigned LineNo, DIType Ty,
|
||||
bool AlwaysPreserve, unsigned Flags) {
|
||||
@ -614,9 +614,9 @@ DIVariable DIBuilder::CreateLocalVariable(unsigned Tag, DIDescriptor Scope,
|
||||
return DIVariable(Node);
|
||||
}
|
||||
|
||||
/// CreateComplexVariable - Create a new descriptor for the specified variable
|
||||
/// createComplexVariable - Create a new descriptor for the specified variable
|
||||
/// which has a complex address expression for its address.
|
||||
DIVariable DIBuilder::CreateComplexVariable(unsigned Tag, DIDescriptor Scope,
|
||||
DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope,
|
||||
StringRef Name, DIFile F,
|
||||
unsigned LineNo,
|
||||
DIType Ty, Value *const *Addr,
|
||||
@ -633,8 +633,8 @@ DIVariable DIBuilder::CreateComplexVariable(unsigned Tag, DIDescriptor Scope,
|
||||
return DIVariable(MDNode::get(VMContext, Elts.data(), Elts.size()));
|
||||
}
|
||||
|
||||
/// CreateFunction - Create a new descriptor for the specified function.
|
||||
DISubprogram DIBuilder::CreateFunction(DIDescriptor Context,
|
||||
/// createFunction - Create a new descriptor for the specified function.
|
||||
DISubprogram DIBuilder::createFunction(DIDescriptor Context,
|
||||
StringRef Name,
|
||||
StringRef LinkageName,
|
||||
DIFile File, unsigned LineNo,
|
||||
@ -670,8 +670,8 @@ DISubprogram DIBuilder::CreateFunction(DIDescriptor Context,
|
||||
return DISubprogram(Node);
|
||||
}
|
||||
|
||||
/// CreateMethod - Create a new descriptor for the specified C++ method.
|
||||
DISubprogram DIBuilder::CreateMethod(DIDescriptor Context,
|
||||
/// createMethod - Create a new descriptor for the specified C++ method.
|
||||
DISubprogram DIBuilder::createMethod(DIDescriptor Context,
|
||||
StringRef Name,
|
||||
StringRef LinkageName,
|
||||
DIFile F,
|
||||
@ -710,9 +710,9 @@ DISubprogram DIBuilder::CreateMethod(DIDescriptor Context,
|
||||
return DISubprogram(Node);
|
||||
}
|
||||
|
||||
/// CreateNameSpace - This creates new descriptor for a namespace
|
||||
/// createNameSpace - This creates new descriptor for a namespace
|
||||
/// with the specified parent scope.
|
||||
DINameSpace DIBuilder::CreateNameSpace(DIDescriptor Scope, StringRef Name,
|
||||
DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name,
|
||||
DIFile File, unsigned LineNo) {
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(VMContext, dwarf::DW_TAG_namespace),
|
||||
@ -724,7 +724,7 @@ DINameSpace DIBuilder::CreateNameSpace(DIDescriptor Scope, StringRef Name,
|
||||
return DINameSpace(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
DILexicalBlock DIBuilder::CreateLexicalBlock(DIDescriptor Scope, DIFile File,
|
||||
DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File,
|
||||
unsigned Line, unsigned Col) {
|
||||
// Defeat MDNode uniqing for lexical blocks by using unique id.
|
||||
static unsigned int unique_id = 0;
|
||||
@ -739,8 +739,8 @@ DILexicalBlock DIBuilder::CreateLexicalBlock(DIDescriptor Scope, DIFile File,
|
||||
return DILexicalBlock(MDNode::get(VMContext, &Elts[0], array_lengthof(Elts)));
|
||||
}
|
||||
|
||||
/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
|
||||
Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo,
|
||||
/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
|
||||
Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
|
||||
Instruction *InsertBefore) {
|
||||
assert(Storage && "no storage passed to dbg.declare");
|
||||
assert(VarInfo.Verify() && "empty DIVariable passed to dbg.declare");
|
||||
@ -751,8 +751,8 @@ Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo,
|
||||
return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore);
|
||||
}
|
||||
|
||||
/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call.
|
||||
Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo,
|
||||
/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
|
||||
Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
|
||||
BasicBlock *InsertAtEnd) {
|
||||
assert(Storage && "no storage passed to dbg.declare");
|
||||
assert(VarInfo.Verify() && "invalid DIVariable passed to dbg.declare");
|
||||
@ -769,8 +769,8 @@ Instruction *DIBuilder::InsertDeclare(Value *Storage, DIVariable VarInfo,
|
||||
return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd);
|
||||
}
|
||||
|
||||
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
Instruction *DIBuilder::InsertDbgValueIntrinsic(Value *V, uint64_t Offset,
|
||||
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
|
||||
DIVariable VarInfo,
|
||||
Instruction *InsertBefore) {
|
||||
assert(V && "no value passed to dbg.value");
|
||||
@ -784,8 +784,8 @@ Instruction *DIBuilder::InsertDbgValueIntrinsic(Value *V, uint64_t Offset,
|
||||
return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore);
|
||||
}
|
||||
|
||||
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
Instruction *DIBuilder::InsertDbgValueIntrinsic(Value *V, uint64_t Offset,
|
||||
/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
|
||||
DIVariable VarInfo,
|
||||
BasicBlock *InsertAtEnd) {
|
||||
assert(V && "no value passed to dbg.value");
|
||||
|
@ -1161,6 +1161,16 @@ static Value *SimplifyOrInst(Value *Op0, Value *Op1, const TargetData *TD,
|
||||
(A == Op0 || B == Op0))
|
||||
return Op0;
|
||||
|
||||
// ~(A & ?) | A = -1
|
||||
if (match(Op0, m_Not(m_And(m_Value(A), m_Value(B)))) &&
|
||||
(A == Op1 || B == Op1))
|
||||
return Constant::getAllOnesValue(Op1->getType());
|
||||
|
||||
// A | ~(A & ?) = -1
|
||||
if (match(Op1, m_Not(m_And(m_Value(A), m_Value(B)))) &&
|
||||
(A == Op0 || B == Op0))
|
||||
return Constant::getAllOnesValue(Op0->getType());
|
||||
|
||||
// Try some generic simplifications for associative operations.
|
||||
if (Value *V = SimplifyAssociativeBinOp(Instruction::Or, Op0, Op1, TD, DT,
|
||||
MaxRecurse))
|
||||
|
@ -47,6 +47,8 @@ class AllocationOrder {
|
||||
/// rewind - Start over from the beginning.
|
||||
void rewind() { Pos = 0; }
|
||||
|
||||
/// isHint - Return true if PhysReg is a preferred register.
|
||||
bool isHint(unsigned PhysReg) const { return PhysReg == Hint; }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -764,7 +764,7 @@ bool AsmPrinter::doFinalization(Module &M) {
|
||||
continue;
|
||||
|
||||
MCSymbol *Name = Mang->getSymbol(&F);
|
||||
EmitVisibility(Name, V);
|
||||
EmitVisibility(Name, V, false);
|
||||
}
|
||||
|
||||
// Finalize debug and EH information.
|
||||
@ -1820,13 +1820,17 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const {
|
||||
}
|
||||
}
|
||||
|
||||
void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility) const {
|
||||
void AsmPrinter::EmitVisibility(MCSymbol *Sym, unsigned Visibility,
|
||||
bool IsDefinition) const {
|
||||
MCSymbolAttr Attr = MCSA_Invalid;
|
||||
|
||||
switch (Visibility) {
|
||||
default: break;
|
||||
case GlobalValue::HiddenVisibility:
|
||||
Attr = MAI->getHiddenVisibilityAttr();
|
||||
if (IsDefinition)
|
||||
Attr = MAI->getHiddenVisibilityAttr();
|
||||
else
|
||||
Attr = MAI->getHiddenDeclarationVisibilityAttr();
|
||||
break;
|
||||
case GlobalValue::ProtectedVisibility:
|
||||
Attr = MAI->getProtectedVisibilityAttr();
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Analysis/DebugInfo.h"
|
||||
#include "llvm/Analysis/DIBuilder.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
@ -644,12 +645,12 @@ void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die,
|
||||
for (unsigned i = 0, N = DV->getNumAddrElements(); i < N; ++i) {
|
||||
uint64_t Element = DV->getAddrElement(i);
|
||||
|
||||
if (Element == DIFactory::OpPlus) {
|
||||
if (Element == DIBuilder::OpPlus) {
|
||||
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
|
||||
addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i));
|
||||
} else if (Element == DIFactory::OpDeref) {
|
||||
} else if (Element == DIBuilder::OpDeref) {
|
||||
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
|
||||
} else llvm_unreachable("unknown DIFactory Opcode");
|
||||
} else llvm_unreachable("unknown DIBuilder Opcode");
|
||||
}
|
||||
|
||||
// Now attach the location information to the DIE.
|
||||
@ -1894,7 +1895,7 @@ void DwarfDebug::constructCompileUnit(const MDNode *N) {
|
||||
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
|
||||
addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string,
|
||||
DIUnit.getProducer());
|
||||
addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data1,
|
||||
addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
|
||||
DIUnit.getLanguage());
|
||||
addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN);
|
||||
// Use DW_AT_entry_pc instead of DW_AT_low_pc/DW_AT_high_pc pair. This
|
||||
|
@ -501,10 +501,11 @@ static bool ProfitableToMerge(MachineBasicBlock *MBB1,
|
||||
MachineBasicBlock *SuccBB,
|
||||
MachineBasicBlock *PredBB) {
|
||||
CommonTailLen = ComputeCommonTailLength(MBB1, MBB2, I1, I2);
|
||||
MachineFunction *MF = MBB1->getParent();
|
||||
|
||||
if (CommonTailLen == 0)
|
||||
return false;
|
||||
DEBUG(dbgs() << "Common tail length of BB#" << MBB1->getNumber()
|
||||
<< " and BB#" << MBB2->getNumber() << " is " << CommonTailLen
|
||||
<< '\n');
|
||||
|
||||
// It's almost always profitable to merge any number of non-terminator
|
||||
// instructions with the block that falls through into the common successor.
|
||||
@ -541,6 +542,7 @@ static bool ProfitableToMerge(MachineBasicBlock *MBB1,
|
||||
// we don't have to split a block. At worst we will be introducing 1 new
|
||||
// branch instruction, which is likely to be smaller than the 2
|
||||
// instructions that would be deleted in the merge.
|
||||
MachineFunction *MF = MBB1->getParent();
|
||||
if (EffectiveTailLen >= 2 &&
|
||||
MF->getFunction()->hasFnAttr(Attribute::OptimizeForSize) &&
|
||||
(I1 == MBB1->begin() || I2 == MBB2->begin()))
|
||||
|
@ -102,8 +102,7 @@ Spiller *createInlineSpiller(MachineFunctionPass &pass,
|
||||
}
|
||||
}
|
||||
|
||||
/// reMaterializeFor - Attempt to rematerialize edit_->getReg() before MI instead of
|
||||
/// reloading it.
|
||||
/// reMaterializeFor - Attempt to rematerialize before MI instead of reloading.
|
||||
bool InlineSpiller::reMaterializeFor(MachineBasicBlock::iterator MI) {
|
||||
SlotIndex UseIdx = lis_.getInstructionIndex(MI).getUseIndex();
|
||||
VNInfo *OrigVNI = edit_->getParent().getVNInfoAt(UseIdx);
|
||||
@ -346,7 +345,8 @@ void InlineSpiller::spill(LiveRangeEdit &edit) {
|
||||
&& "Trying to spill a stack slot.");
|
||||
DEBUG(dbgs() << "Inline spilling "
|
||||
<< mri_.getRegClass(edit.getReg())->getName()
|
||||
<< ':' << edit.getParent() << "\n");
|
||||
<< ':' << edit.getParent() << "\nFrom original "
|
||||
<< PrintReg(vrm_.getOriginal(edit.getReg())) << '\n');
|
||||
assert(edit.getParent().isSpillable() &&
|
||||
"Attempting to spill already spilled value.");
|
||||
|
||||
@ -357,12 +357,20 @@ void InlineSpiller::spill(LiveRangeEdit &edit) {
|
||||
return;
|
||||
|
||||
rc_ = mri_.getRegClass(edit.getReg());
|
||||
stackSlot_ = vrm_.assignVirt2StackSlot(edit_->getReg());
|
||||
|
||||
// Share a stack slot among all descendants of Orig.
|
||||
unsigned Orig = vrm_.getOriginal(edit.getReg());
|
||||
stackSlot_ = vrm_.getStackSlot(Orig);
|
||||
if (stackSlot_ == VirtRegMap::NO_STACK_SLOT)
|
||||
stackSlot_ = vrm_.assignVirt2StackSlot(Orig);
|
||||
|
||||
if (Orig != edit.getReg())
|
||||
vrm_.assignVirt2StackSlot(edit.getReg(), stackSlot_);
|
||||
|
||||
// Update LiveStacks now that we are committed to spilling.
|
||||
LiveInterval &stacklvr = lss_.getOrCreateInterval(stackSlot_, rc_);
|
||||
assert(stacklvr.empty() && "Just created stack slot not empty");
|
||||
stacklvr.getNextValue(SlotIndex(), 0, lss_.getVNInfoAllocator());
|
||||
if (!stacklvr.hasAtLeastOneValue())
|
||||
stacklvr.getNextValue(SlotIndex(), 0, lss_.getVNInfoAllocator());
|
||||
stacklvr.MergeRangesInAsValue(edit_->getParent(), stacklvr.getValNumInfo(0));
|
||||
|
||||
// Iterate over instructions using register.
|
||||
|
@ -37,7 +37,7 @@ namespace {
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
LowerSubregsInstructionPass() : MachineFunctionPass(ID) {}
|
||||
|
||||
|
||||
const char *getPassName() const {
|
||||
return "Subregister lowering instruction pass";
|
||||
}
|
||||
@ -64,8 +64,8 @@ namespace {
|
||||
char LowerSubregsInstructionPass::ID = 0;
|
||||
}
|
||||
|
||||
FunctionPass *llvm::createLowerSubregsPass() {
|
||||
return new LowerSubregsInstructionPass();
|
||||
FunctionPass *llvm::createLowerSubregsPass() {
|
||||
return new LowerSubregsInstructionPass();
|
||||
}
|
||||
|
||||
/// TransferDeadFlag - MI is a pseudo-instruction with DstReg dead,
|
||||
@ -192,9 +192,9 @@ bool LowerSubregsInstructionPass::LowerCopy(MachineInstr *MI) {
|
||||
/// copies.
|
||||
///
|
||||
bool LowerSubregsInstructionPass::runOnMachineFunction(MachineFunction &MF) {
|
||||
DEBUG(dbgs() << "Machine Function\n"
|
||||
DEBUG(dbgs() << "Machine Function\n"
|
||||
<< "********** LOWERING SUBREG INSTRS **********\n"
|
||||
<< "********** Function: "
|
||||
<< "********** Function: "
|
||||
<< MF.getFunction()->getName() << '\n');
|
||||
TRI = MF.getTarget().getRegisterInfo();
|
||||
TII = MF.getTarget().getInstrInfo();
|
||||
|
@ -396,8 +396,7 @@ void MachineFunction::viewCFGOnly() const
|
||||
/// addLiveIn - Add the specified physical register as a live-in value and
|
||||
/// create a corresponding virtual register for it.
|
||||
unsigned MachineFunction::addLiveIn(unsigned PReg,
|
||||
const TargetRegisterClass *RC,
|
||||
DebugLoc DL) {
|
||||
const TargetRegisterClass *RC) {
|
||||
MachineRegisterInfo &MRI = getRegInfo();
|
||||
unsigned VReg = MRI.getLiveInVirtReg(PReg);
|
||||
if (VReg) {
|
||||
@ -406,7 +405,6 @@ unsigned MachineFunction::addLiveIn(unsigned PReg,
|
||||
}
|
||||
VReg = MRI.createVirtualRegister(RC);
|
||||
MRI.addLiveIn(PReg, VReg);
|
||||
MRI.addLiveInLoc(VReg, DL);
|
||||
return VReg;
|
||||
}
|
||||
|
||||
@ -646,6 +644,10 @@ MachineConstantPool::~MachineConstantPool() {
|
||||
for (unsigned i = 0, e = Constants.size(); i != e; ++i)
|
||||
if (Constants[i].isMachineConstantPoolEntry())
|
||||
delete Constants[i].Val.MachineCPVal;
|
||||
for (DenseSet<MachineConstantPoolValue*>::iterator I =
|
||||
MachineCPVsSharingEntries.begin(), E = MachineCPVsSharingEntries.end();
|
||||
I != E; ++I)
|
||||
delete *I;
|
||||
}
|
||||
|
||||
/// CanShareConstantPoolEntry - Test whether the given two constants
|
||||
@ -723,8 +725,10 @@ unsigned MachineConstantPool::getConstantPoolIndex(MachineConstantPoolValue *V,
|
||||
//
|
||||
// FIXME, this could be made much more efficient for large constant pools.
|
||||
int Idx = V->getExistingMachineCPValue(this, Alignment);
|
||||
if (Idx != -1)
|
||||
if (Idx != -1) {
|
||||
MachineCPVsSharingEntries.insert(V);
|
||||
return (unsigned)Idx;
|
||||
}
|
||||
|
||||
Constants.push_back(MachineConstantPoolEntry(V, Alignment));
|
||||
return Constants.size()-1;
|
||||
|
@ -210,15 +210,8 @@ MachineRegisterInfo::EmitLiveInCopies(MachineBasicBlock *EntryMBB,
|
||||
LiveIns.erase(LiveIns.begin() + i);
|
||||
--i; --e;
|
||||
} else {
|
||||
DebugLoc DL;
|
||||
// If there is a location for this live in then use it.
|
||||
DenseMap<unsigned, DebugLoc>::iterator DLI =
|
||||
LiveInLocs.find(LiveIns[i].second);
|
||||
if (DLI != LiveInLocs.end())
|
||||
DL = DLI->second;
|
||||
|
||||
// Emit a copy.
|
||||
BuildMI(*EntryMBB, EntryMBB->begin(), DL,
|
||||
BuildMI(*EntryMBB, EntryMBB->begin(), DebugLoc(),
|
||||
TII.get(TargetOpcode::COPY), LiveIns[i].second)
|
||||
.addReg(LiveIns[i].first);
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "LiveIntervalUnion.h"
|
||||
#include <queue>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -58,8 +57,8 @@ class LiveVirtRegQueue;
|
||||
/// be extended to add interesting heuristics.
|
||||
///
|
||||
/// Register allocators must override the selectOrSplit() method to implement
|
||||
/// live range splitting. They may also override getPriority() which otherwise
|
||||
/// defaults to the spill weight computed by CalculateSpillWeights.
|
||||
/// live range splitting. They must also override enqueue/dequeue to provide an
|
||||
/// assignment order.
|
||||
class RegAllocBase {
|
||||
LiveIntervalUnion::Allocator UnionAllocator;
|
||||
protected:
|
||||
@ -120,9 +119,11 @@ class RegAllocBase {
|
||||
// Get a temporary reference to a Spiller instance.
|
||||
virtual Spiller &spiller() = 0;
|
||||
|
||||
// getPriority - Calculate the allocation priority for VirtReg.
|
||||
// Virtual registers with higher priorities are allocated first.
|
||||
virtual float getPriority(LiveInterval *LI) = 0;
|
||||
/// enqueue - Add VirtReg to the priority queue of unassigned registers.
|
||||
virtual void enqueue(LiveInterval *LI) = 0;
|
||||
|
||||
/// dequeue - Return the next unassigned register, or NULL.
|
||||
virtual LiveInterval *dequeue() = 0;
|
||||
|
||||
// A RegAlloc pass should override this to provide the allocation heuristics.
|
||||
// Each call must guarantee forward progess by returning an available PhysReg
|
||||
@ -170,7 +171,7 @@ class RegAllocBase {
|
||||
static bool VerifyEnabled;
|
||||
|
||||
private:
|
||||
void seedLiveVirtRegs(std::priority_queue<std::pair<float, unsigned> >&);
|
||||
void seedLiveRegs();
|
||||
|
||||
void spillReg(LiveInterval &VirtReg, unsigned PhysReg,
|
||||
SmallVectorImpl<LiveInterval*> &SplitVRegs);
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "llvm/Support/Timer.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <queue>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -64,6 +65,14 @@ VerifyRegAlloc("verify-regalloc", cl::location(RegAllocBase::VerifyEnabled),
|
||||
const char *RegAllocBase::TimerGroupName = "Register Allocation";
|
||||
bool RegAllocBase::VerifyEnabled = false;
|
||||
|
||||
namespace {
|
||||
struct CompSpillWeight {
|
||||
bool operator()(LiveInterval *A, LiveInterval *B) const {
|
||||
return A->weight < B->weight;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// RABasic provides a minimal implementation of the basic register allocation
|
||||
/// algorithm. It prioritizes live virtual registers by spill weight and spills
|
||||
@ -82,7 +91,8 @@ class RABasic : public MachineFunctionPass, public RegAllocBase
|
||||
|
||||
// state
|
||||
std::auto_ptr<Spiller> SpillerInstance;
|
||||
|
||||
std::priority_queue<LiveInterval*, std::vector<LiveInterval*>,
|
||||
CompSpillWeight> Queue;
|
||||
public:
|
||||
RABasic();
|
||||
|
||||
@ -100,6 +110,18 @@ class RABasic : public MachineFunctionPass, public RegAllocBase
|
||||
|
||||
virtual float getPriority(LiveInterval *LI) { return LI->weight; }
|
||||
|
||||
virtual void enqueue(LiveInterval *LI) {
|
||||
Queue.push(LI);
|
||||
}
|
||||
|
||||
virtual LiveInterval *dequeue() {
|
||||
if (Queue.empty())
|
||||
return 0;
|
||||
LiveInterval *LI = Queue.top();
|
||||
Queue.pop();
|
||||
return LI;
|
||||
}
|
||||
|
||||
virtual unsigned selectOrSplit(LiveInterval &VirtReg,
|
||||
SmallVectorImpl<LiveInterval*> &SplitVRegs);
|
||||
|
||||
@ -227,18 +249,17 @@ void RegAllocBase::releaseMemory() {
|
||||
PhysReg2LiveUnion.clear();
|
||||
}
|
||||
|
||||
// Visit all the live virtual registers. If they are already assigned to a
|
||||
// physical register, unify them with the corresponding LiveIntervalUnion,
|
||||
// otherwise push them on the priority queue for later assignment.
|
||||
void RegAllocBase::
|
||||
seedLiveVirtRegs(std::priority_queue<std::pair<float, unsigned> > &VirtRegQ) {
|
||||
// Visit all the live registers. If they are already assigned to a physical
|
||||
// register, unify them with the corresponding LiveIntervalUnion, otherwise push
|
||||
// them on the priority queue for later assignment.
|
||||
void RegAllocBase::seedLiveRegs() {
|
||||
for (LiveIntervals::iterator I = LIS->begin(), E = LIS->end(); I != E; ++I) {
|
||||
unsigned RegNum = I->first;
|
||||
LiveInterval &VirtReg = *I->second;
|
||||
if (TargetRegisterInfo::isPhysicalRegister(RegNum))
|
||||
PhysReg2LiveUnion[RegNum].unify(VirtReg);
|
||||
else
|
||||
VirtRegQ.push(std::make_pair(getPriority(&VirtReg), RegNum));
|
||||
enqueue(&VirtReg);
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,38 +284,31 @@ void RegAllocBase::unassign(LiveInterval &VirtReg, unsigned PhysReg) {
|
||||
// Top-level driver to manage the queue of unassigned VirtRegs and call the
|
||||
// selectOrSplit implementation.
|
||||
void RegAllocBase::allocatePhysRegs() {
|
||||
|
||||
// Push each vreg onto a queue or "precolor" by adding it to a physreg union.
|
||||
std::priority_queue<std::pair<float, unsigned> > VirtRegQ;
|
||||
seedLiveVirtRegs(VirtRegQ);
|
||||
seedLiveRegs();
|
||||
|
||||
// Continue assigning vregs one at a time to available physical registers.
|
||||
while (!VirtRegQ.empty()) {
|
||||
// Pop the highest priority vreg.
|
||||
LiveInterval &VirtReg = LIS->getInterval(VirtRegQ.top().second);
|
||||
VirtRegQ.pop();
|
||||
|
||||
while (LiveInterval *VirtReg = dequeue()) {
|
||||
// selectOrSplit requests the allocator to return an available physical
|
||||
// register if possible and populate a list of new live intervals that
|
||||
// result from splitting.
|
||||
DEBUG(dbgs() << "\nselectOrSplit " << MRI->getRegClass(VirtReg.reg)->getName()
|
||||
<< ':' << VirtReg << '\n');
|
||||
DEBUG(dbgs() << "\nselectOrSplit "
|
||||
<< MRI->getRegClass(VirtReg->reg)->getName()
|
||||
<< ':' << *VirtReg << '\n');
|
||||
typedef SmallVector<LiveInterval*, 4> VirtRegVec;
|
||||
VirtRegVec SplitVRegs;
|
||||
unsigned AvailablePhysReg = selectOrSplit(VirtReg, SplitVRegs);
|
||||
unsigned AvailablePhysReg = selectOrSplit(*VirtReg, SplitVRegs);
|
||||
|
||||
if (AvailablePhysReg)
|
||||
assign(VirtReg, AvailablePhysReg);
|
||||
assign(*VirtReg, AvailablePhysReg);
|
||||
|
||||
for (VirtRegVec::iterator I = SplitVRegs.begin(), E = SplitVRegs.end();
|
||||
I != E; ++I) {
|
||||
LiveInterval* SplitVirtReg = *I;
|
||||
LiveInterval *SplitVirtReg = *I;
|
||||
if (SplitVirtReg->empty()) continue;
|
||||
DEBUG(dbgs() << "queuing new interval: " << *SplitVirtReg << "\n");
|
||||
assert(TargetRegisterInfo::isVirtualRegister(SplitVirtReg->reg) &&
|
||||
"expect split value in virtual register");
|
||||
VirtRegQ.push(std::make_pair(getPriority(SplitVirtReg),
|
||||
SplitVirtReg->reg));
|
||||
enqueue(SplitVirtReg);
|
||||
++NumNewQueued;
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,8 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
|
||||
#include <queue>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(NumGlobalSplits, "Number of split global live ranges");
|
||||
@ -71,6 +73,8 @@ class RAGreedy : public MachineFunctionPass, public RegAllocBase {
|
||||
// state
|
||||
std::auto_ptr<Spiller> SpillerInstance;
|
||||
std::auto_ptr<SplitAnalysis> SA;
|
||||
std::priority_queue<std::pair<unsigned, unsigned> > Queue;
|
||||
IndexedMap<unsigned, VirtReg2IndexFunctor> Generation;
|
||||
|
||||
// splitting state.
|
||||
|
||||
@ -91,13 +95,10 @@ class RAGreedy : public MachineFunctionPass, public RegAllocBase {
|
||||
|
||||
/// RAGreedy analysis usage.
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
virtual void releaseMemory();
|
||||
|
||||
virtual Spiller &spiller() { return *SpillerInstance; }
|
||||
|
||||
virtual float getPriority(LiveInterval *LI);
|
||||
|
||||
virtual void enqueue(LiveInterval *LI);
|
||||
virtual LiveInterval *dequeue();
|
||||
virtual unsigned selectOrSplit(LiveInterval&,
|
||||
SmallVectorImpl<LiveInterval*>&);
|
||||
|
||||
@ -119,9 +120,12 @@ class RAGreedy : public MachineFunctionPass, public RegAllocBase {
|
||||
SlotIndex getPrevMappedIndex(const MachineInstr*);
|
||||
void calcPrevSlots();
|
||||
unsigned nextSplitPoint(unsigned);
|
||||
bool canEvictInterference(LiveInterval&, unsigned, unsigned, float&);
|
||||
|
||||
unsigned tryReassignOrEvict(LiveInterval&, AllocationOrder&,
|
||||
unsigned tryReassign(LiveInterval&, AllocationOrder&,
|
||||
SmallVectorImpl<LiveInterval*>&);
|
||||
unsigned tryEvict(LiveInterval&, AllocationOrder&,
|
||||
SmallVectorImpl<LiveInterval*>&);
|
||||
unsigned tryRegionSplit(LiveInterval&, AllocationOrder&,
|
||||
SmallVectorImpl<LiveInterval*>&);
|
||||
unsigned tryLocalSplit(LiveInterval&, AllocationOrder&,
|
||||
@ -183,25 +187,42 @@ void RAGreedy::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
|
||||
void RAGreedy::releaseMemory() {
|
||||
SpillerInstance.reset(0);
|
||||
Generation.clear();
|
||||
RegAllocBase::releaseMemory();
|
||||
}
|
||||
|
||||
float RAGreedy::getPriority(LiveInterval *LI) {
|
||||
float Priority = LI->weight;
|
||||
void RAGreedy::enqueue(LiveInterval *LI) {
|
||||
// Prioritize live ranges by size, assigning larger ranges first.
|
||||
// The queue holds (size, reg) pairs.
|
||||
const unsigned Size = LI->getSize();
|
||||
const unsigned Reg = LI->reg;
|
||||
assert(TargetRegisterInfo::isVirtualRegister(Reg) &&
|
||||
"Can only enqueue virtual registers");
|
||||
const unsigned Hint = VRM->getRegAllocPref(Reg);
|
||||
unsigned Prio;
|
||||
|
||||
// Prioritize hinted registers so they are allocated first.
|
||||
std::pair<unsigned, unsigned> Hint;
|
||||
if (Hint.first || Hint.second) {
|
||||
// The hint can be target specific, a virtual register, or a physreg.
|
||||
Priority *= 2;
|
||||
Generation.grow(Reg);
|
||||
if (++Generation[Reg] == 1)
|
||||
// 1st generation ranges are handled first, long -> short.
|
||||
Prio = (1u << 31) + Size;
|
||||
else
|
||||
// Repeat offenders are handled second, short -> long
|
||||
Prio = (1u << 30) - Size;
|
||||
|
||||
// Prefer physreg hints above anything else.
|
||||
if (Hint.first == 0 && TargetRegisterInfo::isPhysicalRegister(Hint.second))
|
||||
Priority *= 2;
|
||||
}
|
||||
return Priority;
|
||||
// Boost ranges that have a physical register hint.
|
||||
if (TargetRegisterInfo::isPhysicalRegister(Hint))
|
||||
Prio |= (1u << 30);
|
||||
|
||||
Queue.push(std::make_pair(Prio, Reg));
|
||||
}
|
||||
|
||||
LiveInterval *RAGreedy::dequeue() {
|
||||
if (Queue.empty())
|
||||
return 0;
|
||||
LiveInterval *LI = &LIS->getInterval(Queue.top().second);
|
||||
Queue.pop();
|
||||
return LI;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Register Reassignment
|
||||
@ -230,8 +251,7 @@ LiveInterval *RAGreedy::getSingleInterference(LiveInterval &VirtReg,
|
||||
if (Q.checkInterference()) {
|
||||
if (Interference)
|
||||
return 0;
|
||||
Q.collectInterferingVRegs(1);
|
||||
if (!Q.seenAllInterferences())
|
||||
if (Q.collectInterferingVRegs(2) > 1)
|
||||
return 0;
|
||||
Interference = Q.interferingVRegs().front();
|
||||
}
|
||||
@ -276,21 +296,14 @@ bool RAGreedy::reassignVReg(LiveInterval &InterferingVReg,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// tryReassignOrEvict - Try to reassign a single interferences to a different
|
||||
/// physreg, or evict a single interference with a lower spill weight.
|
||||
/// tryReassign - Try to reassign a single interference to a different physreg.
|
||||
/// @param VirtReg Currently unassigned virtual register.
|
||||
/// @param Order Physregs to try.
|
||||
/// @return Physreg to assign VirtReg, or 0.
|
||||
unsigned RAGreedy::tryReassignOrEvict(LiveInterval &VirtReg,
|
||||
AllocationOrder &Order,
|
||||
SmallVectorImpl<LiveInterval*> &NewVRegs){
|
||||
unsigned RAGreedy::tryReassign(LiveInterval &VirtReg, AllocationOrder &Order,
|
||||
SmallVectorImpl<LiveInterval*> &NewVRegs){
|
||||
NamedRegionTimer T("Reassign", TimerGroupName, TimePassesIsEnabled);
|
||||
|
||||
// Keep track of the lightest single interference seen so far.
|
||||
float BestWeight = VirtReg.weight;
|
||||
LiveInterval *BestVirt = 0;
|
||||
unsigned BestPhys = 0;
|
||||
|
||||
Order.rewind();
|
||||
while (unsigned PhysReg = Order.next()) {
|
||||
LiveInterval *InterferingVReg = getSingleInterference(VirtReg, PhysReg);
|
||||
@ -300,25 +313,92 @@ unsigned RAGreedy::tryReassignOrEvict(LiveInterval &VirtReg,
|
||||
continue;
|
||||
if (reassignVReg(*InterferingVReg, PhysReg))
|
||||
return PhysReg;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Cannot reassign, is this an eviction candidate?
|
||||
if (InterferingVReg->weight < BestWeight) {
|
||||
BestVirt = InterferingVReg;
|
||||
BestPhys = PhysReg;
|
||||
BestWeight = InterferingVReg->weight;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Interference eviction
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// canEvict - Return true if all interferences between VirtReg and PhysReg can
|
||||
/// be evicted. Set maxWeight to the maximal spill weight of an interference.
|
||||
bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg,
|
||||
unsigned Size, float &MaxWeight) {
|
||||
float Weight = 0;
|
||||
for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) {
|
||||
LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI);
|
||||
// If there is 10 or more interferences, chances are one is smaller.
|
||||
if (Q.collectInterferingVRegs(10) >= 10)
|
||||
return false;
|
||||
|
||||
// CHeck if any interfering live range is shorter than VirtReg.
|
||||
for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) {
|
||||
LiveInterval *Intf = Q.interferingVRegs()[i];
|
||||
if (TargetRegisterInfo::isPhysicalRegister(Intf->reg))
|
||||
return false;
|
||||
if (Intf->getSize() <= Size)
|
||||
return false;
|
||||
Weight = std::max(Weight, Intf->weight);
|
||||
}
|
||||
}
|
||||
MaxWeight = Weight;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nothing reassigned, can we evict a lighter single interference?
|
||||
if (BestVirt) {
|
||||
DEBUG(dbgs() << "evicting lighter " << *BestVirt << '\n');
|
||||
unassign(*BestVirt, VRM->getPhys(BestVirt->reg));
|
||||
++NumEvicted;
|
||||
NewVRegs.push_back(BestVirt);
|
||||
return BestPhys;
|
||||
/// tryEvict - Try to evict all interferences for a physreg.
|
||||
/// @param VirtReg Currently unassigned virtual register.
|
||||
/// @param Order Physregs to try.
|
||||
/// @return Physreg to assign VirtReg, or 0.
|
||||
unsigned RAGreedy::tryEvict(LiveInterval &VirtReg,
|
||||
AllocationOrder &Order,
|
||||
SmallVectorImpl<LiveInterval*> &NewVRegs){
|
||||
NamedRegionTimer T("Evict", TimerGroupName, TimePassesIsEnabled);
|
||||
|
||||
// We can only evict interference if all interfering registers are virtual and
|
||||
// longer than VirtReg.
|
||||
const unsigned Size = VirtReg.getSize();
|
||||
|
||||
// Keep track of the lightest single interference seen so far.
|
||||
float BestWeight = 0;
|
||||
unsigned BestPhys = 0;
|
||||
|
||||
Order.rewind();
|
||||
while (unsigned PhysReg = Order.next()) {
|
||||
float Weight = 0;
|
||||
if (!canEvictInterference(VirtReg, PhysReg, Size, Weight))
|
||||
continue;
|
||||
|
||||
// This is an eviction candidate.
|
||||
DEBUG(dbgs() << "max " << PrintReg(PhysReg, TRI) << " interference = "
|
||||
<< Weight << '\n');
|
||||
if (BestPhys && Weight >= BestWeight)
|
||||
continue;
|
||||
|
||||
// Best so far.
|
||||
BestPhys = PhysReg;
|
||||
BestWeight = Weight;
|
||||
// Stop if the hint can be used.
|
||||
if (Order.isHint(PhysReg))
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (!BestPhys)
|
||||
return 0;
|
||||
|
||||
DEBUG(dbgs() << "evicting " << PrintReg(BestPhys, TRI) << " interference\n");
|
||||
for (const unsigned *AliasI = TRI->getOverlaps(BestPhys); *AliasI; ++AliasI) {
|
||||
LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI);
|
||||
assert(Q.seenAllInterferences() && "Didn't check all interfererences.");
|
||||
for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) {
|
||||
LiveInterval *Intf = Q.interferingVRegs()[i];
|
||||
unassign(*Intf, VRM->getPhys(Intf->reg));
|
||||
++NumEvicted;
|
||||
NewVRegs.push_back(Intf);
|
||||
}
|
||||
}
|
||||
return BestPhys;
|
||||
}
|
||||
|
||||
|
||||
@ -426,8 +506,13 @@ float RAGreedy::calcInterferenceInfo(LiveInterval &VirtReg, unsigned PhysReg) {
|
||||
if (!IntI.valid())
|
||||
break;
|
||||
// Not live in, but before the first use.
|
||||
if (IntI.start() < BI.FirstUse)
|
||||
if (IntI.start() < BI.FirstUse) {
|
||||
BC.Entry = SpillPlacement::PrefSpill;
|
||||
// If the block contains a kill from an earlier split, never split
|
||||
// again in the same block.
|
||||
if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Kill))
|
||||
BC.Entry = SpillPlacement::MustSpill;
|
||||
}
|
||||
}
|
||||
|
||||
// Does interference overlap the uses in the entry segment
|
||||
@ -458,8 +543,12 @@ float RAGreedy::calcInterferenceInfo(LiveInterval &VirtReg, unsigned PhysReg) {
|
||||
IntI.advanceTo(BI.LastUse);
|
||||
if (!IntI.valid())
|
||||
break;
|
||||
if (IntI.start() < Stop)
|
||||
if (IntI.start() < Stop) {
|
||||
BC.Exit = SpillPlacement::PrefSpill;
|
||||
// Avoid splitting twice in the same block.
|
||||
if (!BI.LiveThrough && !SA->isOriginalEndpoint(BI.Def))
|
||||
BC.Exit = SpillPlacement::MustSpill;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1221,12 +1310,22 @@ unsigned RAGreedy::selectOrSplit(LiveInterval &VirtReg,
|
||||
return PhysReg;
|
||||
}
|
||||
|
||||
// Try to reassign interferences.
|
||||
if (unsigned PhysReg = tryReassignOrEvict(VirtReg, Order, NewVRegs))
|
||||
if (unsigned PhysReg = tryReassign(VirtReg, Order, NewVRegs))
|
||||
return PhysReg;
|
||||
|
||||
if (unsigned PhysReg = tryEvict(VirtReg, Order, NewVRegs))
|
||||
return PhysReg;
|
||||
|
||||
assert(NewVRegs.empty() && "Cannot append to existing NewVRegs");
|
||||
|
||||
// The first time we see a live range, don't try to split or spill.
|
||||
// Wait until the second time, when all smaller ranges have been allocated.
|
||||
// This gives a better picture of the interference to split around.
|
||||
if (Generation[VirtReg.reg] == 1) {
|
||||
NewVRegs.push_back(&VirtReg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Try splitting VirtReg or interferences.
|
||||
unsigned PhysReg = trySplit(VirtReg, Order, NewVRegs);
|
||||
if (PhysReg || !NewVRegs.empty())
|
||||
|
@ -279,8 +279,8 @@ namespace {
|
||||
|
||||
/// getShiftAmountTy - Returns a type large enough to hold any valid
|
||||
/// shift amount - before type legalization these can be huge.
|
||||
EVT getShiftAmountTy() {
|
||||
return LegalTypes ? TLI.getShiftAmountTy() : TLI.getPointerTy();
|
||||
EVT getShiftAmountTy(EVT LHSTy) {
|
||||
return LegalTypes ? TLI.getShiftAmountTy(LHSTy) : TLI.getPointerTy();
|
||||
}
|
||||
|
||||
/// isTypeLegal - This method returns true if we are running before type
|
||||
@ -670,7 +670,7 @@ SDValue DAGCombiner::PromoteOperand(SDValue Op, EVT PVT, bool &Replace) {
|
||||
if (LoadSDNode *LD = dyn_cast<LoadSDNode>(Op)) {
|
||||
EVT MemVT = LD->getMemoryVT();
|
||||
ISD::LoadExtType ExtType = ISD::isNON_EXTLoad(LD)
|
||||
? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD
|
||||
? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD
|
||||
: ISD::EXTLOAD)
|
||||
: LD->getExtensionType();
|
||||
Replace = true;
|
||||
@ -894,7 +894,7 @@ bool DAGCombiner::PromoteLoad(SDValue Op) {
|
||||
LoadSDNode *LD = cast<LoadSDNode>(N);
|
||||
EVT MemVT = LD->getMemoryVT();
|
||||
ISD::LoadExtType ExtType = ISD::isNON_EXTLoad(LD)
|
||||
? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD
|
||||
? (TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT) ? ISD::ZEXTLOAD
|
||||
: ISD::EXTLOAD)
|
||||
: LD->getExtensionType();
|
||||
SDValue NewLD = DAG.getExtLoad(ExtType, dl, PVT,
|
||||
@ -1521,7 +1521,7 @@ SDValue DAGCombiner::visitADDE(SDNode *N) {
|
||||
// Since it may not be valid to emit a fold to zero for vector initializers
|
||||
// check if we can before folding.
|
||||
static SDValue tryFoldToZero(DebugLoc DL, const TargetLowering &TLI, EVT VT,
|
||||
SelectionDAG &DAG, bool LegalOperations) {
|
||||
SelectionDAG &DAG, bool LegalOperations) {
|
||||
if (!VT.isVector()) {
|
||||
return DAG.getConstant(0, VT);
|
||||
} else if (!LegalOperations || TLI.isOperationLegal(ISD::BUILD_VECTOR, VT)) {
|
||||
@ -1647,7 +1647,7 @@ SDValue DAGCombiner::visitMUL(SDNode *N) {
|
||||
if (N1C && N1C->getAPIntValue().isPowerOf2())
|
||||
return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0,
|
||||
DAG.getConstant(N1C->getAPIntValue().logBase2(),
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(N0.getValueType())));
|
||||
// fold (mul x, -(1 << c)) -> -(x << c) or (-x) << c
|
||||
if (N1C && (-N1C->getAPIntValue()).isPowerOf2()) {
|
||||
unsigned Log2Val = (-N1C->getAPIntValue()).logBase2();
|
||||
@ -1656,7 +1656,8 @@ SDValue DAGCombiner::visitMUL(SDNode *N) {
|
||||
return DAG.getNode(ISD::SUB, N->getDebugLoc(), VT,
|
||||
DAG.getConstant(0, VT),
|
||||
DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0,
|
||||
DAG.getConstant(Log2Val, getShiftAmountTy())));
|
||||
DAG.getConstant(Log2Val,
|
||||
getShiftAmountTy(N0.getValueType()))));
|
||||
}
|
||||
// (mul (shl X, c1), c2) -> (mul X, c2 << c1)
|
||||
if (N1C && N0.getOpcode() == ISD::SHL &&
|
||||
@ -1753,18 +1754,18 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) {
|
||||
// Splat the sign bit into the register
|
||||
SDValue SGN = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0,
|
||||
DAG.getConstant(VT.getSizeInBits()-1,
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(N0.getValueType())));
|
||||
AddToWorkList(SGN.getNode());
|
||||
|
||||
// Add (N0 < 0) ? abs2 - 1 : 0;
|
||||
SDValue SRL = DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, SGN,
|
||||
DAG.getConstant(VT.getSizeInBits() - lg2,
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(SGN.getValueType())));
|
||||
SDValue ADD = DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0, SRL);
|
||||
AddToWorkList(SRL.getNode());
|
||||
AddToWorkList(ADD.getNode()); // Divide by pow2
|
||||
SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, ADD,
|
||||
DAG.getConstant(lg2, getShiftAmountTy()));
|
||||
DAG.getConstant(lg2, getShiftAmountTy(ADD.getValueType())));
|
||||
|
||||
// If we're dividing by a positive value, we're done. Otherwise, we must
|
||||
// negate the result.
|
||||
@ -1814,7 +1815,7 @@ SDValue DAGCombiner::visitUDIV(SDNode *N) {
|
||||
if (N1C && N1C->getAPIntValue().isPowerOf2())
|
||||
return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0,
|
||||
DAG.getConstant(N1C->getAPIntValue().logBase2(),
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(N0.getValueType())));
|
||||
// fold (udiv x, (shl c, y)) -> x >>u (log2(c)+y) iff c is power of 2
|
||||
if (N1.getOpcode() == ISD::SHL) {
|
||||
if (ConstantSDNode *SHC = dyn_cast<ConstantSDNode>(N1.getOperand(0))) {
|
||||
@ -1955,7 +1956,7 @@ SDValue DAGCombiner::visitMULHS(SDNode *N) {
|
||||
if (N1C && N1C->getAPIntValue() == 1)
|
||||
return DAG.getNode(ISD::SRA, N->getDebugLoc(), N0.getValueType(), N0,
|
||||
DAG.getConstant(N0.getValueType().getSizeInBits() - 1,
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(N0.getValueType())));
|
||||
// fold (mulhs x, undef) -> 0
|
||||
if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF)
|
||||
return DAG.getConstant(0, VT);
|
||||
@ -1971,11 +1972,11 @@ SDValue DAGCombiner::visitMULHS(SDNode *N) {
|
||||
N1 = DAG.getNode(ISD::SIGN_EXTEND, DL, NewVT, N1);
|
||||
N1 = DAG.getNode(ISD::MUL, DL, NewVT, N0, N1);
|
||||
N1 = DAG.getNode(ISD::SRL, DL, NewVT, N1,
|
||||
DAG.getConstant(SimpleSize, getShiftAmountTy()));
|
||||
DAG.getConstant(SimpleSize, getShiftAmountTy(N1.getValueType())));
|
||||
return DAG.getNode(ISD::TRUNCATE, DL, VT, N1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
@ -2007,11 +2008,11 @@ SDValue DAGCombiner::visitMULHU(SDNode *N) {
|
||||
N1 = DAG.getNode(ISD::ZERO_EXTEND, DL, NewVT, N1);
|
||||
N1 = DAG.getNode(ISD::MUL, DL, NewVT, N0, N1);
|
||||
N1 = DAG.getNode(ISD::SRL, DL, NewVT, N1,
|
||||
DAG.getConstant(SimpleSize, getShiftAmountTy()));
|
||||
DAG.getConstant(SimpleSize, getShiftAmountTy(N1.getValueType())));
|
||||
return DAG.getNode(ISD::TRUNCATE, DL, VT, N1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
@ -2090,14 +2091,14 @@ SDValue DAGCombiner::visitSMUL_LOHI(SDNode *N) {
|
||||
Lo = DAG.getNode(ISD::MUL, DL, NewVT, Lo, Hi);
|
||||
// Compute the high part as N1.
|
||||
Hi = DAG.getNode(ISD::SRL, DL, NewVT, Lo,
|
||||
DAG.getConstant(SimpleSize, getShiftAmountTy()));
|
||||
DAG.getConstant(SimpleSize, getShiftAmountTy(Lo.getValueType())));
|
||||
Hi = DAG.getNode(ISD::TRUNCATE, DL, VT, Hi);
|
||||
// Compute the low part as N0.
|
||||
Lo = DAG.getNode(ISD::TRUNCATE, DL, VT, Lo);
|
||||
return CombineTo(N, Lo, Hi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
@ -2107,7 +2108,7 @@ SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) {
|
||||
|
||||
EVT VT = N->getValueType(0);
|
||||
DebugLoc DL = N->getDebugLoc();
|
||||
|
||||
|
||||
// If the type twice as wide is legal, transform the mulhu to a wider multiply
|
||||
// plus a shift.
|
||||
if (VT.isSimple() && !VT.isVector()) {
|
||||
@ -2120,14 +2121,14 @@ SDValue DAGCombiner::visitUMUL_LOHI(SDNode *N) {
|
||||
Lo = DAG.getNode(ISD::MUL, DL, NewVT, Lo, Hi);
|
||||
// Compute the high part as N1.
|
||||
Hi = DAG.getNode(ISD::SRL, DL, NewVT, Lo,
|
||||
DAG.getConstant(SimpleSize, getShiftAmountTy()));
|
||||
DAG.getConstant(SimpleSize, getShiftAmountTy(Lo.getValueType())));
|
||||
Hi = DAG.getNode(ISD::TRUNCATE, DL, VT, Hi);
|
||||
// Compute the low part as N0.
|
||||
Lo = DAG.getNode(ISD::TRUNCATE, DL, VT, Lo);
|
||||
return CombineTo(N, Lo, Hi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
@ -3004,7 +3005,7 @@ SDValue DAGCombiner::visitSHL(SDNode *N) {
|
||||
N0.getOpcode() == ISD::SIGN_EXTEND) &&
|
||||
N0.getOperand(0).getOpcode() == ISD::SHL &&
|
||||
isa<ConstantSDNode>(N0.getOperand(0)->getOperand(1))) {
|
||||
uint64_t c1 =
|
||||
uint64_t c1 =
|
||||
cast<ConstantSDNode>(N0.getOperand(0)->getOperand(1))->getZExtValue();
|
||||
uint64_t c2 = N1C->getZExtValue();
|
||||
EVT InnerShiftVT = N0.getOperand(0).getValueType();
|
||||
@ -3133,7 +3134,8 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
|
||||
TLI.isOperationLegalOrCustom(ISD::TRUNCATE, VT) &&
|
||||
TLI.isTruncateFree(VT, TruncVT)) {
|
||||
|
||||
SDValue Amt = DAG.getConstant(ShiftAmt, getShiftAmountTy());
|
||||
SDValue Amt = DAG.getConstant(ShiftAmt,
|
||||
getShiftAmountTy(N0.getOperand(0).getValueType()));
|
||||
SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT,
|
||||
N0.getOperand(0), Amt);
|
||||
SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), TruncVT,
|
||||
@ -3180,7 +3182,7 @@ SDValue DAGCombiner::visitSRA(SDNode *N) {
|
||||
LargeShiftAmt->getZExtValue()) {
|
||||
SDValue Amt =
|
||||
DAG.getConstant(LargeShiftAmt->getZExtValue() + N1C->getZExtValue(),
|
||||
getShiftAmountTy());
|
||||
getShiftAmountTy(N0.getOperand(0).getOperand(0).getValueType()));
|
||||
SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), LargeVT,
|
||||
N0.getOperand(0).getOperand(0), Amt);
|
||||
return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, SRA);
|
||||
@ -3245,7 +3247,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
|
||||
if (N1C && N0.getOpcode() == ISD::TRUNCATE &&
|
||||
N0.getOperand(0).getOpcode() == ISD::SRL &&
|
||||
isa<ConstantSDNode>(N0.getOperand(0)->getOperand(1))) {
|
||||
uint64_t c1 =
|
||||
uint64_t c1 =
|
||||
cast<ConstantSDNode>(N0.getOperand(0)->getOperand(1))->getZExtValue();
|
||||
uint64_t c2 = N1C->getZExtValue();
|
||||
EVT InnerShiftVT = N0.getOperand(0).getValueType();
|
||||
@ -3256,7 +3258,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
|
||||
if (c1 + c2 >= InnerShiftSize)
|
||||
return DAG.getConstant(0, VT);
|
||||
return DAG.getNode(ISD::TRUNCATE, N0->getDebugLoc(), VT,
|
||||
DAG.getNode(ISD::SRL, N0->getDebugLoc(), InnerShiftVT,
|
||||
DAG.getNode(ISD::SRL, N0->getDebugLoc(), InnerShiftVT,
|
||||
N0.getOperand(0)->getOperand(0),
|
||||
DAG.getConstant(c1 + c2, ShiftCountVT)));
|
||||
}
|
||||
@ -3320,7 +3322,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) {
|
||||
|
||||
if (ShAmt) {
|
||||
Op = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, Op,
|
||||
DAG.getConstant(ShAmt, getShiftAmountTy()));
|
||||
DAG.getConstant(ShAmt, getShiftAmountTy(Op.getValueType())));
|
||||
AddToWorkList(Op.getNode());
|
||||
}
|
||||
|
||||
@ -3685,7 +3687,9 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) {
|
||||
}
|
||||
|
||||
// fold (sext (load x)) -> (sext (truncate (sextload x)))
|
||||
if (ISD::isNON_EXTLoad(N0.getNode()) &&
|
||||
// None of the supported targets knows how to perform load and sign extend
|
||||
// in one instruction. We only perform this transformation on scalars.
|
||||
if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() &&
|
||||
((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) ||
|
||||
TLI.isLoadExtLegal(ISD::SEXTLOAD, N0.getValueType()))) {
|
||||
bool DoXform = true;
|
||||
@ -3887,7 +3891,9 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
|
||||
}
|
||||
|
||||
// fold (zext (load x)) -> (zext (truncate (zextload x)))
|
||||
if (ISD::isNON_EXTLoad(N0.getNode()) &&
|
||||
// None of the supported targets knows how to perform load and vector_zext
|
||||
// in one instruction. We only perform this transformation on scalar zext.
|
||||
if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() &&
|
||||
((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) ||
|
||||
TLI.isLoadExtLegal(ISD::ZEXTLOAD, N0.getValueType()))) {
|
||||
bool DoXform = true;
|
||||
@ -4021,11 +4027,11 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) {
|
||||
}
|
||||
|
||||
DebugLoc DL = N->getDebugLoc();
|
||||
|
||||
// Ensure that the shift amount is wide enough for the shifted value.
|
||||
|
||||
// Ensure that the shift amount is wide enough for the shifted value.
|
||||
if (VT.getSizeInBits() >= 256)
|
||||
ShAmt = DAG.getNode(ISD::ZERO_EXTEND, DL, MVT::i32, ShAmt);
|
||||
|
||||
|
||||
return DAG.getNode(N0.getOpcode(), DL, VT,
|
||||
DAG.getNode(ISD::ZERO_EXTEND, DL, VT, N0.getOperand(0)),
|
||||
ShAmt);
|
||||
@ -4094,7 +4100,9 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) {
|
||||
}
|
||||
|
||||
// fold (aext (load x)) -> (aext (truncate (extload x)))
|
||||
if (ISD::isNON_EXTLoad(N0.getNode()) &&
|
||||
// None of the supported targets knows how to perform load and any_ext
|
||||
// in one instruction. We only perform this transformation on scalars.
|
||||
if (ISD::isNON_EXTLoad(N0.getNode()) && !VT.isVector() &&
|
||||
((!LegalOperations && !cast<LoadSDNode>(N0)->isVolatile()) ||
|
||||
TLI.isLoadExtLegal(ISD::EXTLOAD, N0.getValueType()))) {
|
||||
bool DoXform = true;
|
||||
@ -4272,12 +4280,12 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) {
|
||||
return SDValue();
|
||||
|
||||
unsigned EVTBits = ExtVT.getSizeInBits();
|
||||
|
||||
|
||||
// Do not generate loads of non-round integer types since these can
|
||||
// be expensive (and would be wrong if the type is not byte sized).
|
||||
if (!ExtVT.isRound())
|
||||
return SDValue();
|
||||
|
||||
|
||||
unsigned ShAmt = 0;
|
||||
if (N0.getOpcode() == ISD::SRL && N0.hasOneUse()) {
|
||||
if (ConstantSDNode *N01 = dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
|
||||
@ -4292,7 +4300,7 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) {
|
||||
|
||||
// At this point, we must have a load or else we can't do the transform.
|
||||
if (!isa<LoadSDNode>(N0)) return SDValue();
|
||||
|
||||
|
||||
// If the shift amount is larger than the input type then we're not
|
||||
// accessing any of the loaded bytes. If the load was a zextload/extload
|
||||
// then the result of the shift+trunc is zero/undef (handled elsewhere).
|
||||
@ -4313,18 +4321,18 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) {
|
||||
N0 = N0.getOperand(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If we haven't found a load, we can't narrow it. Don't transform one with
|
||||
// multiple uses, this would require adding a new load.
|
||||
if (!isa<LoadSDNode>(N0) || !N0.hasOneUse() ||
|
||||
// Don't change the width of a volatile load.
|
||||
cast<LoadSDNode>(N0)->isVolatile())
|
||||
return SDValue();
|
||||
|
||||
|
||||
// Verify that we are actually reducing a load width here.
|
||||
if (cast<LoadSDNode>(N0)->getMemoryVT().getSizeInBits() < EVTBits)
|
||||
return SDValue();
|
||||
|
||||
|
||||
LoadSDNode *LN0 = cast<LoadSDNode>(N0);
|
||||
EVT PtrType = N0.getOperand(1).getValueType();
|
||||
|
||||
@ -4362,7 +4370,7 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) {
|
||||
// Shift the result left, if we've swallowed a left shift.
|
||||
SDValue Result = Load;
|
||||
if (ShLeftAmt != 0) {
|
||||
EVT ShImmTy = getShiftAmountTy();
|
||||
EVT ShImmTy = getShiftAmountTy(Result.getValueType());
|
||||
if (!isUIntN(ShImmTy.getSizeInBits(), ShLeftAmt))
|
||||
ShImmTy = VT;
|
||||
Result = DAG.getNode(ISD::SHL, N0.getDebugLoc(), VT,
|
||||
@ -4504,14 +4512,17 @@ SDValue DAGCombiner::visitTRUNCATE(SDNode *N) {
|
||||
}
|
||||
|
||||
// See if we can simplify the input to this truncate through knowledge that
|
||||
// only the low bits are being used. For example "trunc (or (shl x, 8), y)"
|
||||
// -> trunc y
|
||||
SDValue Shorter =
|
||||
GetDemandedBits(N0, APInt::getLowBitsSet(N0.getValueSizeInBits(),
|
||||
VT.getSizeInBits()));
|
||||
if (Shorter.getNode())
|
||||
return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Shorter);
|
||||
|
||||
// only the low bits are being used.
|
||||
// For example "trunc (or (shl x, 8), y)" // -> trunc y
|
||||
// Currenly we only perform this optimization on scalars because vectors
|
||||
// may have different active low bits.
|
||||
if (!VT.isVector()) {
|
||||
SDValue Shorter =
|
||||
GetDemandedBits(N0, APInt::getLowBitsSet(N0.getValueSizeInBits(),
|
||||
VT.getSizeInBits()));
|
||||
if (Shorter.getNode())
|
||||
return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), VT, Shorter);
|
||||
}
|
||||
// fold (truncate (load x)) -> (smaller load x)
|
||||
// fold (truncate (srl (load x), c)) -> (smaller load (x+c/evtbits))
|
||||
if (!LegalTypes || TLI.isTypeDesirableForOp(N0.getOpcode(), VT)) {
|
||||
@ -5975,7 +5986,8 @@ ShrinkLoadReplaceStoreWithStore(const std::pair<unsigned, unsigned> &MaskInfo,
|
||||
// shifted by ByteShift and truncated down to NumBytes.
|
||||
if (ByteShift)
|
||||
IVal = DAG.getNode(ISD::SRL, IVal->getDebugLoc(), IVal.getValueType(), IVal,
|
||||
DAG.getConstant(ByteShift*8, DC->getShiftAmountTy()));
|
||||
DAG.getConstant(ByteShift*8,
|
||||
DC->getShiftAmountTy(IVal.getValueType())));
|
||||
|
||||
// Figure out the offset for the store and the alignment of the access.
|
||||
unsigned StOffset;
|
||||
@ -6390,7 +6402,7 @@ SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *N) {
|
||||
|
||||
EVT VT = InVec.getValueType();
|
||||
|
||||
// If we can't generate a legal BUILD_VECTOR, exit
|
||||
// If we can't generate a legal BUILD_VECTOR, exit
|
||||
if (LegalOperations && !TLI.isOperationLegal(ISD::BUILD_VECTOR, VT))
|
||||
return SDValue();
|
||||
|
||||
@ -7098,7 +7110,8 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
|
||||
if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue()-1)) == 0)) {
|
||||
unsigned ShCtV = N2C->getAPIntValue().logBase2();
|
||||
ShCtV = XType.getSizeInBits()-ShCtV-1;
|
||||
SDValue ShCt = DAG.getConstant(ShCtV, getShiftAmountTy());
|
||||
SDValue ShCt = DAG.getConstant(ShCtV,
|
||||
getShiftAmountTy(N0.getValueType()));
|
||||
SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(),
|
||||
XType, N0, ShCt);
|
||||
AddToWorkList(Shift.getNode());
|
||||
@ -7114,7 +7127,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
|
||||
SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(),
|
||||
XType, N0,
|
||||
DAG.getConstant(XType.getSizeInBits()-1,
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(N0.getValueType())));
|
||||
AddToWorkList(Shift.getNode());
|
||||
|
||||
if (XType.bitsGT(AType)) {
|
||||
@ -7142,13 +7155,15 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
|
||||
// Shift the tested bit over the sign bit.
|
||||
APInt AndMask = ConstAndRHS->getAPIntValue();
|
||||
SDValue ShlAmt =
|
||||
DAG.getConstant(AndMask.countLeadingZeros(), getShiftAmountTy());
|
||||
DAG.getConstant(AndMask.countLeadingZeros(),
|
||||
getShiftAmountTy(AndLHS.getValueType()));
|
||||
SDValue Shl = DAG.getNode(ISD::SHL, N0.getDebugLoc(), VT, AndLHS, ShlAmt);
|
||||
|
||||
// Now arithmetic right shift it all the way over, so the result is either
|
||||
// all-ones, or zero.
|
||||
SDValue ShrAmt =
|
||||
DAG.getConstant(AndMask.getBitWidth()-1, getShiftAmountTy());
|
||||
DAG.getConstant(AndMask.getBitWidth()-1,
|
||||
getShiftAmountTy(Shl.getValueType()));
|
||||
SDValue Shr = DAG.getNode(ISD::SRA, N0.getDebugLoc(), VT, Shl, ShrAmt);
|
||||
|
||||
return DAG.getNode(ISD::AND, DL, VT, Shr, N3);
|
||||
@ -7192,7 +7207,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
|
||||
// shl setcc result by log2 n2c
|
||||
return DAG.getNode(ISD::SHL, DL, N2.getValueType(), Temp,
|
||||
DAG.getConstant(N2C->getAPIntValue().logBase2(),
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(Temp.getValueType())));
|
||||
}
|
||||
|
||||
// Check to see if this is the equivalent of setcc
|
||||
@ -7215,7 +7230,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
|
||||
SDValue Ctlz = DAG.getNode(ISD::CTLZ, N0.getDebugLoc(), XType, N0);
|
||||
return DAG.getNode(ISD::SRL, DL, XType, Ctlz,
|
||||
DAG.getConstant(Log2_32(XType.getSizeInBits()),
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(Ctlz.getValueType())));
|
||||
}
|
||||
// fold (setgt X, 0) -> (srl (and (-X, ~X), size(X)-1))
|
||||
if (N1C && N1C->isNullValue() && CC == ISD::SETGT) {
|
||||
@ -7225,13 +7240,13 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
|
||||
return DAG.getNode(ISD::SRL, DL, XType,
|
||||
DAG.getNode(ISD::AND, DL, XType, NegN0, NotN0),
|
||||
DAG.getConstant(XType.getSizeInBits()-1,
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(XType)));
|
||||
}
|
||||
// fold (setgt X, -1) -> (xor (srl (X, size(X)-1), 1))
|
||||
if (N1C && N1C->isAllOnesValue() && CC == ISD::SETGT) {
|
||||
SDValue Sign = DAG.getNode(ISD::SRL, N0.getDebugLoc(), XType, N0,
|
||||
DAG.getConstant(XType.getSizeInBits()-1,
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(N0.getValueType())));
|
||||
return DAG.getNode(ISD::XOR, DL, XType, Sign, DAG.getConstant(1, XType));
|
||||
}
|
||||
}
|
||||
@ -7258,7 +7273,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1,
|
||||
SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType,
|
||||
N0,
|
||||
DAG.getConstant(XType.getSizeInBits()-1,
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(N0.getValueType())));
|
||||
SDValue Add = DAG.getNode(ISD::ADD, N0.getDebugLoc(),
|
||||
XType, N0, Shift);
|
||||
AddToWorkList(Shift.getNode());
|
||||
|
@ -219,6 +219,7 @@ void FunctionLoweringInfo::clear() {
|
||||
CatchInfoFound.clear();
|
||||
#endif
|
||||
LiveOutRegInfo.clear();
|
||||
VisitedBBs.clear();
|
||||
ArgDbgValues.clear();
|
||||
ByValArgFrameIndexMap.clear();
|
||||
RegFixups.clear();
|
||||
@ -254,6 +255,123 @@ unsigned FunctionLoweringInfo::CreateRegs(const Type *Ty) {
|
||||
return FirstReg;
|
||||
}
|
||||
|
||||
/// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the
|
||||
/// register is a PHI destination and the PHI's LiveOutInfo is not valid. If
|
||||
/// the register's LiveOutInfo is for a smaller bit width, it is extended to
|
||||
/// the larger bit width by zero extension. The bit width must be no smaller
|
||||
/// than the LiveOutInfo's existing bit width.
|
||||
const FunctionLoweringInfo::LiveOutInfo *
|
||||
FunctionLoweringInfo::GetLiveOutRegInfo(unsigned Reg, unsigned BitWidth) {
|
||||
if (!LiveOutRegInfo.inBounds(Reg))
|
||||
return NULL;
|
||||
|
||||
LiveOutInfo *LOI = &LiveOutRegInfo[Reg];
|
||||
if (!LOI->IsValid)
|
||||
return NULL;
|
||||
|
||||
if (BitWidth > LOI->KnownZero.getBitWidth()) {
|
||||
LOI->NumSignBits = 1;
|
||||
LOI->KnownZero = LOI->KnownZero.zextOrTrunc(BitWidth);
|
||||
LOI->KnownOne = LOI->KnownOne.zextOrTrunc(BitWidth);
|
||||
}
|
||||
|
||||
return LOI;
|
||||
}
|
||||
|
||||
/// ComputePHILiveOutRegInfo - Compute LiveOutInfo for a PHI's destination
|
||||
/// register based on the LiveOutInfo of its operands.
|
||||
void FunctionLoweringInfo::ComputePHILiveOutRegInfo(const PHINode *PN) {
|
||||
const Type *Ty = PN->getType();
|
||||
if (!Ty->isIntegerTy() || Ty->isVectorTy())
|
||||
return;
|
||||
|
||||
SmallVector<EVT, 1> ValueVTs;
|
||||
ComputeValueVTs(TLI, Ty, ValueVTs);
|
||||
assert(ValueVTs.size() == 1 &&
|
||||
"PHIs with non-vector integer types should have a single VT.");
|
||||
EVT IntVT = ValueVTs[0];
|
||||
|
||||
if (TLI.getNumRegisters(PN->getContext(), IntVT) != 1)
|
||||
return;
|
||||
IntVT = TLI.getTypeToTransformTo(PN->getContext(), IntVT);
|
||||
unsigned BitWidth = IntVT.getSizeInBits();
|
||||
|
||||
unsigned DestReg = ValueMap[PN];
|
||||
if (!TargetRegisterInfo::isVirtualRegister(DestReg))
|
||||
return;
|
||||
LiveOutRegInfo.grow(DestReg);
|
||||
LiveOutInfo &DestLOI = LiveOutRegInfo[DestReg];
|
||||
|
||||
Value *V = PN->getIncomingValue(0);
|
||||
if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
|
||||
DestLOI.NumSignBits = 1;
|
||||
APInt Zero(BitWidth, 0);
|
||||
DestLOI.KnownZero = Zero;
|
||||
DestLOI.KnownOne = Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
||||
APInt Val = CI->getValue().zextOrTrunc(BitWidth);
|
||||
DestLOI.NumSignBits = Val.getNumSignBits();
|
||||
DestLOI.KnownZero = ~Val;
|
||||
DestLOI.KnownOne = Val;
|
||||
} else {
|
||||
assert(ValueMap.count(V) && "V should have been placed in ValueMap when its"
|
||||
"CopyToReg node was created.");
|
||||
unsigned SrcReg = ValueMap[V];
|
||||
if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) {
|
||||
DestLOI.IsValid = false;
|
||||
return;
|
||||
}
|
||||
const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth);
|
||||
if (!SrcLOI) {
|
||||
DestLOI.IsValid = false;
|
||||
return;
|
||||
}
|
||||
DestLOI = *SrcLOI;
|
||||
}
|
||||
|
||||
assert(DestLOI.KnownZero.getBitWidth() == BitWidth &&
|
||||
DestLOI.KnownOne.getBitWidth() == BitWidth &&
|
||||
"Masks should have the same bit width as the type.");
|
||||
|
||||
for (unsigned i = 1, e = PN->getNumIncomingValues(); i != e; ++i) {
|
||||
Value *V = PN->getIncomingValue(i);
|
||||
if (isa<UndefValue>(V) || isa<ConstantExpr>(V)) {
|
||||
DestLOI.NumSignBits = 1;
|
||||
APInt Zero(BitWidth, 0);
|
||||
DestLOI.KnownZero = Zero;
|
||||
DestLOI.KnownOne = Zero;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
|
||||
APInt Val = CI->getValue().zextOrTrunc(BitWidth);
|
||||
DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, Val.getNumSignBits());
|
||||
DestLOI.KnownZero &= ~Val;
|
||||
DestLOI.KnownOne &= Val;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(ValueMap.count(V) && "V should have been placed in ValueMap when "
|
||||
"its CopyToReg node was created.");
|
||||
unsigned SrcReg = ValueMap[V];
|
||||
if (!TargetRegisterInfo::isVirtualRegister(SrcReg)) {
|
||||
DestLOI.IsValid = false;
|
||||
return;
|
||||
}
|
||||
const LiveOutInfo *SrcLOI = GetLiveOutRegInfo(SrcReg, BitWidth);
|
||||
if (!SrcLOI) {
|
||||
DestLOI.IsValid = false;
|
||||
return;
|
||||
}
|
||||
DestLOI.NumSignBits = std::min(DestLOI.NumSignBits, SrcLOI->NumSignBits);
|
||||
DestLOI.KnownZero &= SrcLOI->KnownZero;
|
||||
DestLOI.KnownOne &= SrcLOI->KnownOne;
|
||||
}
|
||||
}
|
||||
|
||||
/// setByValArgumentFrameIndex - Record frame index for the byval
|
||||
/// argument. This overrides previous frame index entry for this argument,
|
||||
/// if any.
|
||||
|
@ -87,7 +87,7 @@ class SelectionDAGLegalize {
|
||||
// If someone requests legalization of the new node, return itself.
|
||||
if (From != To)
|
||||
LegalizedNodes.insert(std::make_pair(To, To));
|
||||
|
||||
|
||||
// Transfer SDDbgValues.
|
||||
DAG.TransferDbgValues(From, To);
|
||||
}
|
||||
@ -498,7 +498,8 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG,
|
||||
int IncrementSize = NumBits / 8;
|
||||
|
||||
// Divide the stored value in two parts.
|
||||
SDValue ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
|
||||
SDValue ShiftAmount = DAG.getConstant(NumBits,
|
||||
TLI.getShiftAmountTy(Val.getValueType()));
|
||||
SDValue Lo = Val;
|
||||
SDValue Hi = DAG.getNode(ISD::SRL, dl, VT, Val, ShiftAmount);
|
||||
|
||||
@ -645,7 +646,8 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG,
|
||||
}
|
||||
|
||||
// aggregate the two parts
|
||||
SDValue ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
|
||||
SDValue ShiftAmount = DAG.getConstant(NumBits,
|
||||
TLI.getShiftAmountTy(Hi.getValueType()));
|
||||
SDValue Result = DAG.getNode(ISD::SHL, dl, VT, Hi, ShiftAmount);
|
||||
Result = DAG.getNode(ISD::OR, dl, VT, Result, Lo);
|
||||
|
||||
@ -1264,7 +1266,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
||||
|
||||
// Move the top bits to the right place.
|
||||
Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi,
|
||||
DAG.getConstant(RoundWidth, TLI.getShiftAmountTy()));
|
||||
DAG.getConstant(RoundWidth,
|
||||
TLI.getShiftAmountTy(Hi.getValueType())));
|
||||
|
||||
// Join the hi and lo parts.
|
||||
Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi);
|
||||
@ -1293,7 +1296,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
||||
|
||||
// Move the top bits to the right place.
|
||||
Hi = DAG.getNode(ISD::SHL, dl, Hi.getValueType(), Hi,
|
||||
DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy()));
|
||||
DAG.getConstant(ExtraWidth,
|
||||
TLI.getShiftAmountTy(Hi.getValueType())));
|
||||
|
||||
// Join the hi and lo parts.
|
||||
Result = DAG.getNode(ISD::OR, dl, Node->getValueType(0), Lo, Hi);
|
||||
@ -1482,7 +1486,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
||||
Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2,
|
||||
DAG.getIntPtrConstant(IncrementSize));
|
||||
Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3,
|
||||
DAG.getConstant(RoundWidth, TLI.getShiftAmountTy()));
|
||||
DAG.getConstant(RoundWidth,
|
||||
TLI.getShiftAmountTy(Tmp3.getValueType())));
|
||||
Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2,
|
||||
ST->getPointerInfo().getWithOffset(IncrementSize),
|
||||
ExtraVT, isVolatile, isNonTemporal,
|
||||
@ -1492,7 +1497,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
||||
// TRUNCSTORE:i24 X -> TRUNCSTORE:i16 (srl X, 8), TRUNCSTORE@+2:i8 X
|
||||
// Store the top RoundWidth bits.
|
||||
Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3,
|
||||
DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy()));
|
||||
DAG.getConstant(ExtraWidth,
|
||||
TLI.getShiftAmountTy(Tmp3.getValueType())));
|
||||
Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getPointerInfo(),
|
||||
RoundVT, isVolatile, isNonTemporal, Alignment);
|
||||
|
||||
@ -1727,7 +1733,8 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) {
|
||||
assert(BitShift < LoadTy.getSizeInBits() && "Pointer advanced wrong?");
|
||||
if (BitShift)
|
||||
SignBit = DAG.getNode(ISD::SHL, dl, LoadTy, SignBit,
|
||||
DAG.getConstant(BitShift,TLI.getShiftAmountTy()));
|
||||
DAG.getConstant(BitShift,
|
||||
TLI.getShiftAmountTy(SignBit.getValueType())));
|
||||
}
|
||||
}
|
||||
// Now get the sign bit proper, by seeing whether the value is negative.
|
||||
@ -2207,7 +2214,8 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
|
||||
if (!isSigned) {
|
||||
SDValue Fast = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, Op0);
|
||||
|
||||
SDValue ShiftConst = DAG.getConstant(1, TLI.getShiftAmountTy());
|
||||
SDValue ShiftConst =
|
||||
DAG.getConstant(1, TLI.getShiftAmountTy(Op0.getValueType()));
|
||||
SDValue Shr = DAG.getNode(ISD::SRL, dl, MVT::i64, Op0, ShiftConst);
|
||||
SDValue AndConst = DAG.getConstant(1, MVT::i64);
|
||||
SDValue And = DAG.getNode(ISD::AND, dl, MVT::i64, Op0, AndConst);
|
||||
@ -2226,7 +2234,6 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
|
||||
}
|
||||
|
||||
// Otherwise, implement the fully general conversion.
|
||||
EVT SHVT = TLI.getShiftAmountTy();
|
||||
|
||||
SDValue And = DAG.getNode(ISD::AND, dl, MVT::i64, Op0,
|
||||
DAG.getConstant(UINT64_C(0xfffffffffffff800), MVT::i64));
|
||||
@ -2241,6 +2248,7 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
|
||||
Op0, DAG.getConstant(UINT64_C(0x0020000000000000), MVT::i64),
|
||||
ISD::SETUGE);
|
||||
SDValue Sel2 = DAG.getNode(ISD::SELECT, dl, MVT::i64, Ge, Sel, Op0);
|
||||
EVT SHVT = TLI.getShiftAmountTy(Sel2.getValueType());
|
||||
|
||||
SDValue Sh = DAG.getNode(ISD::SRL, dl, MVT::i64, Sel2,
|
||||
DAG.getConstant(32, SHVT));
|
||||
@ -2387,7 +2395,7 @@ SDValue SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDValue LegalOp,
|
||||
///
|
||||
SDValue SelectionDAGLegalize::ExpandBSWAP(SDValue Op, DebugLoc dl) {
|
||||
EVT VT = Op.getValueType();
|
||||
EVT SHVT = TLI.getShiftAmountTy();
|
||||
EVT SHVT = TLI.getShiftAmountTy(VT);
|
||||
SDValue Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6, Tmp7, Tmp8;
|
||||
switch (VT.getSimpleVT().SimpleTy) {
|
||||
default: assert(0 && "Unhandled Expand type in BSWAP!");
|
||||
@ -2450,7 +2458,7 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op,
|
||||
default: assert(0 && "Cannot expand this yet!");
|
||||
case ISD::CTPOP: {
|
||||
EVT VT = Op.getValueType();
|
||||
EVT ShVT = TLI.getShiftAmountTy();
|
||||
EVT ShVT = TLI.getShiftAmountTy(VT);
|
||||
unsigned Len = VT.getSizeInBits();
|
||||
|
||||
assert(VT.isInteger() && Len <= 128 && Len % 8 == 0 &&
|
||||
@ -2487,7 +2495,7 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op,
|
||||
Op = DAG.getNode(ISD::SRL, dl, VT,
|
||||
DAG.getNode(ISD::MUL, dl, VT, Op, Mask01),
|
||||
DAG.getConstant(Len - 8, ShVT));
|
||||
|
||||
|
||||
return Op;
|
||||
}
|
||||
case ISD::CTLZ: {
|
||||
@ -2501,7 +2509,7 @@ SDValue SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDValue Op,
|
||||
//
|
||||
// but see also: http://www.hackersdelight.org/HDcode/nlz.cc
|
||||
EVT VT = Op.getValueType();
|
||||
EVT ShVT = TLI.getShiftAmountTy();
|
||||
EVT ShVT = TLI.getShiftAmountTy(VT);
|
||||
unsigned len = VT.getSizeInBits();
|
||||
for (unsigned i = 0; (1U << i) <= (len / 2); ++i) {
|
||||
SDValue Tmp3 = DAG.getConstant(1ULL << i, ShVT);
|
||||
@ -2737,7 +2745,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
|
||||
// SAR. However, it is doubtful that any exist.
|
||||
EVT ExtraVT = cast<VTSDNode>(Node->getOperand(1))->getVT();
|
||||
EVT VT = Node->getValueType(0);
|
||||
EVT ShiftAmountTy = TLI.getShiftAmountTy();
|
||||
EVT ShiftAmountTy = TLI.getShiftAmountTy(VT);
|
||||
if (VT.isVector())
|
||||
ShiftAmountTy = VT;
|
||||
unsigned BitsDiff = VT.getScalarType().getSizeInBits() -
|
||||
@ -2901,7 +2909,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
|
||||
// 1 -> Hi
|
||||
Tmp1 = DAG.getNode(ISD::SRL, dl, OpTy, Node->getOperand(0),
|
||||
DAG.getConstant(OpTy.getSizeInBits()/2,
|
||||
TLI.getShiftAmountTy()));
|
||||
TLI.getShiftAmountTy(Node->getOperand(0).getValueType())));
|
||||
Tmp1 = DAG.getNode(ISD::TRUNCATE, dl, Node->getValueType(0), Tmp1);
|
||||
} else {
|
||||
// 0 -> Lo
|
||||
@ -3260,7 +3268,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
|
||||
assert(LC != RTLIB::UNKNOWN_LIBCALL && "Cannot expand this operation!");
|
||||
LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS);
|
||||
RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS);
|
||||
|
||||
|
||||
SDValue Ret = ExpandLibCall(LC, Node, isSigned);
|
||||
BottomHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, Ret);
|
||||
TopHalf = DAG.getNode(ISD::SRL, dl, Ret.getValueType(), Ret,
|
||||
@ -3268,7 +3276,8 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
|
||||
TopHalf = DAG.getNode(ISD::TRUNCATE, dl, VT, TopHalf);
|
||||
}
|
||||
if (isSigned) {
|
||||
Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1, TLI.getShiftAmountTy());
|
||||
Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1,
|
||||
TLI.getShiftAmountTy(BottomHalf.getValueType()));
|
||||
Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, Tmp1);
|
||||
TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf, Tmp1,
|
||||
ISD::SETNE);
|
||||
@ -3286,7 +3295,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
|
||||
Tmp2 = DAG.getNode(ISD::ANY_EXTEND, dl, PairTy, Node->getOperand(1));
|
||||
Tmp2 = DAG.getNode(ISD::SHL, dl, PairTy, Tmp2,
|
||||
DAG.getConstant(PairTy.getSizeInBits()/2,
|
||||
TLI.getShiftAmountTy()));
|
||||
TLI.getShiftAmountTy(PairTy)));
|
||||
Results.push_back(DAG.getNode(ISD::OR, dl, PairTy, Tmp1, Tmp2));
|
||||
break;
|
||||
}
|
||||
@ -3464,7 +3473,7 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node,
|
||||
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, NVT, Node->getOperand(0));
|
||||
Tmp1 = DAG.getNode(ISD::BSWAP, dl, NVT, Tmp1);
|
||||
Tmp1 = DAG.getNode(ISD::SRL, dl, NVT, Tmp1,
|
||||
DAG.getConstant(DiffBits, TLI.getShiftAmountTy()));
|
||||
DAG.getConstant(DiffBits, TLI.getShiftAmountTy(NVT)));
|
||||
Results.push_back(Tmp1);
|
||||
break;
|
||||
}
|
||||
|
@ -177,25 +177,27 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_FCOPYSIGN(SDNode *N) {
|
||||
// First get the sign bit of second operand.
|
||||
SDValue SignBit = DAG.getNode(ISD::SHL, dl, RVT, DAG.getConstant(1, RVT),
|
||||
DAG.getConstant(RSize - 1,
|
||||
TLI.getShiftAmountTy()));
|
||||
TLI.getShiftAmountTy(RVT)));
|
||||
SignBit = DAG.getNode(ISD::AND, dl, RVT, RHS, SignBit);
|
||||
|
||||
// Shift right or sign-extend it if the two operands have different types.
|
||||
int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits();
|
||||
if (SizeDiff > 0) {
|
||||
SignBit = DAG.getNode(ISD::SRL, dl, RVT, SignBit,
|
||||
DAG.getConstant(SizeDiff, TLI.getShiftAmountTy()));
|
||||
DAG.getConstant(SizeDiff,
|
||||
TLI.getShiftAmountTy(SignBit.getValueType())));
|
||||
SignBit = DAG.getNode(ISD::TRUNCATE, dl, LVT, SignBit);
|
||||
} else if (SizeDiff < 0) {
|
||||
SignBit = DAG.getNode(ISD::ANY_EXTEND, dl, LVT, SignBit);
|
||||
SignBit = DAG.getNode(ISD::SHL, dl, LVT, SignBit,
|
||||
DAG.getConstant(-SizeDiff, TLI.getShiftAmountTy()));
|
||||
DAG.getConstant(-SizeDiff,
|
||||
TLI.getShiftAmountTy(SignBit.getValueType())));
|
||||
}
|
||||
|
||||
// Clear the sign bit of the first operand.
|
||||
SDValue Mask = DAG.getNode(ISD::SHL, dl, LVT, DAG.getConstant(1, LVT),
|
||||
DAG.getConstant(LSize - 1,
|
||||
TLI.getShiftAmountTy()));
|
||||
TLI.getShiftAmountTy(LVT)));
|
||||
Mask = DAG.getNode(ISD::SUB, dl, LVT, Mask, DAG.getConstant(1, LVT));
|
||||
LHS = DAG.getNode(ISD::AND, dl, LVT, LHS, Mask);
|
||||
|
||||
|
@ -1420,7 +1420,7 @@ SDValue SelectionDAG::getMDNode(const MDNode *MD) {
|
||||
/// the target's desired shift amount type.
|
||||
SDValue SelectionDAG::getShiftAmountOperand(SDValue Op) {
|
||||
EVT OpTy = Op.getValueType();
|
||||
MVT ShTy = TLI.getShiftAmountTy();
|
||||
MVT ShTy = TLI.getShiftAmountTy(OpTy);
|
||||
if (OpTy == ShTy || OpTy.isVector()) return Op;
|
||||
|
||||
ISD::NodeType Opcode = OpTy.bitsGT(ShTy) ? ISD::TRUNCATE : ISD::ZERO_EXTEND;
|
||||
@ -2048,7 +2048,7 @@ void SelectionDAG::ComputeMaskedBits(SDValue Op, const APInt &Mask,
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
// Allow the target to implement this method for its nodes.
|
||||
if (Op.getOpcode() >= ISD::BUILTIN_OP_END) {
|
||||
@ -2088,12 +2088,7 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const{
|
||||
|
||||
case ISD::Constant: {
|
||||
const APInt &Val = cast<ConstantSDNode>(Op)->getAPIntValue();
|
||||
// If negative, return # leading ones.
|
||||
if (Val.isNegative())
|
||||
return Val.countLeadingOnes();
|
||||
|
||||
// Return # leading zeros.
|
||||
return Val.countLeadingZeros();
|
||||
return Val.getNumSignBits();
|
||||
}
|
||||
|
||||
case ISD::SIGN_EXTEND:
|
||||
@ -2297,12 +2292,12 @@ bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const {
|
||||
if ((Op.getOpcode() != ISD::ADD && Op.getOpcode() != ISD::OR) ||
|
||||
!isa<ConstantSDNode>(Op.getOperand(1)))
|
||||
return false;
|
||||
|
||||
if (Op.getOpcode() == ISD::OR &&
|
||||
|
||||
if (Op.getOpcode() == ISD::OR &&
|
||||
!MaskedValueIsZero(Op.getOperand(0),
|
||||
cast<ConstantSDNode>(Op.getOperand(1))->getAPIntValue()))
|
||||
return false;
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2753,7 +2748,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT,
|
||||
// i8, which is easy to fall into in generic code that uses
|
||||
// TLI.getShiftAmount().
|
||||
assert(N2.getValueType().getSizeInBits() >=
|
||||
Log2_32_Ceil(N1.getValueType().getSizeInBits()) &&
|
||||
Log2_32_Ceil(N1.getValueType().getSizeInBits()) &&
|
||||
"Invalid use of small shift amount with oversized value!");
|
||||
|
||||
// Always fold shifts of i1 values so the code generator doesn't need to
|
||||
|
@ -641,16 +641,17 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
|
||||
// If the source register was virtual and if we know something about it,
|
||||
// add an assert node.
|
||||
if (!TargetRegisterInfo::isVirtualRegister(Regs[Part+i]) ||
|
||||
!RegisterVT.isInteger() || RegisterVT.isVector() ||
|
||||
!FuncInfo.LiveOutRegInfo.inBounds(Regs[Part+i]))
|
||||
!RegisterVT.isInteger() || RegisterVT.isVector())
|
||||
continue;
|
||||
|
||||
const FunctionLoweringInfo::LiveOutInfo *LOI =
|
||||
FuncInfo.GetLiveOutRegInfo(Regs[Part+i]);
|
||||
if (!LOI)
|
||||
continue;
|
||||
|
||||
const FunctionLoweringInfo::LiveOutInfo &LOI =
|
||||
FuncInfo.LiveOutRegInfo[Regs[Part+i]];
|
||||
|
||||
unsigned RegSize = RegisterVT.getSizeInBits();
|
||||
unsigned NumSignBits = LOI.NumSignBits;
|
||||
unsigned NumZeroBits = LOI.KnownZero.countLeadingOnes();
|
||||
unsigned NumSignBits = LOI->NumSignBits;
|
||||
unsigned NumZeroBits = LOI->KnownZero.countLeadingOnes();
|
||||
|
||||
// FIXME: We capture more information than the dag can represent. For
|
||||
// now, just use the tightest assertzext/assertsext possible.
|
||||
@ -908,7 +909,7 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
|
||||
Val.getResNo(), Offset, dl, DbgSDNodeOrder);
|
||||
DAG.AddDbgValue(SDV, Val.getNode(), false);
|
||||
}
|
||||
} else
|
||||
} else
|
||||
DEBUG(dbgs() << "Dropping debug info for " << DI);
|
||||
DanglingDebugInfoMap[V] = DanglingDebugInfo();
|
||||
}
|
||||
@ -1417,7 +1418,7 @@ void SelectionDAGBuilder::visitBr(const BranchInst &I) {
|
||||
// jle foo
|
||||
//
|
||||
if (const BinaryOperator *BOp = dyn_cast<BinaryOperator>(CondVal)) {
|
||||
if (!TLI.isJumpExpensive() &&
|
||||
if (!TLI.isJumpExpensive() &&
|
||||
BOp->hasOneUse() &&
|
||||
(BOp->getOpcode() == Instruction::And ||
|
||||
BOp->getOpcode() == Instruction::Or)) {
|
||||
@ -1915,7 +1916,7 @@ bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR,
|
||||
DEBUG(dbgs() << "Lowering jump table\n"
|
||||
<< "First entry: " << First << ". Last entry: " << Last << '\n'
|
||||
<< "Range: " << Range
|
||||
<< "Size: " << TSize << ". Density: " << Density << "\n\n");
|
||||
<< ". Size: " << TSize << ". Density: " << Density << "\n\n");
|
||||
|
||||
// Get the MachineFunction which holds the current MBB. This is used when
|
||||
// inserting any additional MBBs necessary to represent the switch.
|
||||
@ -2408,19 +2409,19 @@ void SelectionDAGBuilder::visitBinary(const User &I, unsigned OpCode) {
|
||||
void SelectionDAGBuilder::visitShift(const User &I, unsigned Opcode) {
|
||||
SDValue Op1 = getValue(I.getOperand(0));
|
||||
SDValue Op2 = getValue(I.getOperand(1));
|
||||
|
||||
MVT ShiftTy = TLI.getShiftAmountTy();
|
||||
|
||||
|
||||
MVT ShiftTy = TLI.getShiftAmountTy(Op2.getValueType());
|
||||
|
||||
// Coerce the shift amount to the right type if we can.
|
||||
if (!I.getType()->isVectorTy() && Op2.getValueType() != ShiftTy) {
|
||||
unsigned ShiftSize = ShiftTy.getSizeInBits();
|
||||
unsigned Op2Size = Op2.getValueType().getSizeInBits();
|
||||
DebugLoc DL = getCurDebugLoc();
|
||||
|
||||
|
||||
// If the operand is smaller than the shift count type, promote it.
|
||||
if (ShiftSize > Op2Size)
|
||||
Op2 = DAG.getNode(ISD::ZERO_EXTEND, DL, ShiftTy, Op2);
|
||||
|
||||
|
||||
// If the operand is larger than the shift count type but the shift
|
||||
// count type has enough bits to represent any shift value, truncate
|
||||
// it now. This is a common case and it exposes the truncate to
|
||||
|
@ -348,7 +348,7 @@ class SelectionDAGBuilder {
|
||||
SDValue getControlRoot();
|
||||
|
||||
DebugLoc getCurDebugLoc() const { return CurDebugLoc; }
|
||||
void setCurDebugLoc(DebugLoc dl){ CurDebugLoc = dl; }
|
||||
|
||||
unsigned getSDNodeOrder() const { return SDNodeOrder; }
|
||||
|
||||
void CopyValueToVirtualRegister(const Value *V, unsigned Reg);
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/ADT/PostOrderIterator.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include <algorithm>
|
||||
using namespace llvm;
|
||||
@ -479,16 +480,7 @@ void SelectionDAGISel::ComputeLiveOutVRegInfo() {
|
||||
unsigned NumSignBits = CurDAG->ComputeNumSignBits(Src);
|
||||
Mask = APInt::getAllOnesValue(SrcVT.getSizeInBits());
|
||||
CurDAG->ComputeMaskedBits(Src, Mask, KnownZero, KnownOne);
|
||||
|
||||
// Only install this information if it tells us something.
|
||||
if (NumSignBits != 1 || KnownZero != 0 || KnownOne != 0) {
|
||||
FuncInfo->LiveOutRegInfo.grow(DestReg);
|
||||
FunctionLoweringInfo::LiveOutInfo &LOI =
|
||||
FuncInfo->LiveOutRegInfo[DestReg];
|
||||
LOI.NumSignBits = NumSignBits;
|
||||
LOI.KnownOne = KnownOne;
|
||||
LOI.KnownZero = KnownZero;
|
||||
}
|
||||
FuncInfo->AddLiveOutRegInfo(DestReg, NumSignBits, KnownZero, KnownOne);
|
||||
} while (!Worklist.empty());
|
||||
}
|
||||
|
||||
@ -832,11 +824,39 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
||||
FastIS = TLI.createFastISel(*FuncInfo);
|
||||
|
||||
// Iterate over all basic blocks in the function.
|
||||
for (Function::const_iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
|
||||
const BasicBlock *LLVMBB = &*I;
|
||||
ReversePostOrderTraversal<const Function*> RPOT(&Fn);
|
||||
for (ReversePostOrderTraversal<const Function*>::rpo_iterator
|
||||
I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {
|
||||
const BasicBlock *LLVMBB = *I;
|
||||
#ifndef NDEBUG
|
||||
CheckLineNumbers(LLVMBB);
|
||||
#endif
|
||||
|
||||
if (OptLevel != CodeGenOpt::None) {
|
||||
bool AllPredsVisited = true;
|
||||
for (const_pred_iterator PI = pred_begin(LLVMBB), PE = pred_end(LLVMBB);
|
||||
PI != PE; ++PI) {
|
||||
if (!FuncInfo->VisitedBBs.count(*PI)) {
|
||||
AllPredsVisited = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (AllPredsVisited) {
|
||||
for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end();
|
||||
I != E && isa<PHINode>(I); ++I) {
|
||||
FuncInfo->ComputePHILiveOutRegInfo(cast<PHINode>(I));
|
||||
}
|
||||
} else {
|
||||
for (BasicBlock::const_iterator I = LLVMBB->begin(), E = LLVMBB->end();
|
||||
I != E && isa<PHINode>(I); ++I) {
|
||||
FuncInfo->InvalidatePHILiveOutRegInfo(cast<PHINode>(I));
|
||||
}
|
||||
}
|
||||
|
||||
FuncInfo->VisitedBBs.insert(LLVMBB);
|
||||
}
|
||||
|
||||
FuncInfo->MBB = FuncInfo->MBBMap[LLVMBB];
|
||||
FuncInfo->InsertPt = FuncInfo->MBB->getFirstNonPHI();
|
||||
|
||||
@ -851,17 +871,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
||||
PrepareEHLandingPad();
|
||||
|
||||
// Lower any arguments needed in this block if this is the entry block.
|
||||
if (LLVMBB == &Fn.getEntryBlock()) {
|
||||
for (BasicBlock::const_iterator DBI = LLVMBB->begin(), DBE = LLVMBB->end();
|
||||
DBI != DBE; ++DBI) {
|
||||
if (const DbgInfoIntrinsic *DI = dyn_cast<DbgInfoIntrinsic>(DBI)) {
|
||||
const DebugLoc DL = DI->getDebugLoc();
|
||||
SDB->setCurDebugLoc(DL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (LLVMBB == &Fn.getEntryBlock())
|
||||
LowerArguments(LLVMBB);
|
||||
}
|
||||
|
||||
// Before doing SelectionDAG ISel, see if FastISel has been requested.
|
||||
if (FastIS) {
|
||||
|
@ -563,7 +563,7 @@ TargetLowering::TargetLowering(const TargetMachine &tm,
|
||||
setOperationAction(ISD::TRAP, MVT::Other, Expand);
|
||||
|
||||
IsLittleEndian = TD->isLittleEndian();
|
||||
ShiftAmountTy = PointerTy = MVT::getIntegerVT(8*TD->getPointerSize());
|
||||
PointerTy = MVT::getIntegerVT(8*TD->getPointerSize());
|
||||
memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*));
|
||||
memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray));
|
||||
maxStoresPerMemset = maxStoresPerMemcpy = maxStoresPerMemmove = 8;
|
||||
@ -596,6 +596,10 @@ TargetLowering::~TargetLowering() {
|
||||
delete &TLOF;
|
||||
}
|
||||
|
||||
MVT TargetLowering::getShiftAmountTy(EVT LHSTy) const {
|
||||
return MVT::getIntegerVT(8*TD->getPointerSize());
|
||||
}
|
||||
|
||||
/// canOpTrap - Returns true if the operation can trap for the value type.
|
||||
/// VT must be a legal type.
|
||||
bool TargetLowering::canOpTrap(unsigned Op, EVT VT) const {
|
||||
@ -1401,7 +1405,7 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op,
|
||||
BitWidth - InnerVT.getSizeInBits()) &
|
||||
DemandedMask) == 0 &&
|
||||
isTypeDesirableForOp(ISD::SHL, InnerVT)) {
|
||||
EVT ShTy = getShiftAmountTy();
|
||||
EVT ShTy = getShiftAmountTy(InnerVT);
|
||||
if (!APInt(BitWidth, ShAmt).isIntN(ShTy.getSizeInBits()))
|
||||
ShTy = InnerVT;
|
||||
SDValue NarrowShl =
|
||||
@ -2188,7 +2192,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
|
||||
if (ConstantSDNode *AndRHS =
|
||||
dyn_cast<ConstantSDNode>(N0.getOperand(1))) {
|
||||
EVT ShiftTy = DCI.isBeforeLegalize() ?
|
||||
getPointerTy() : getShiftAmountTy();
|
||||
getPointerTy() : getShiftAmountTy(N0.getValueType());
|
||||
if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3
|
||||
// Perform the xform if the AND RHS is a single bit.
|
||||
if (AndRHS->getAPIntValue().isPowerOf2()) {
|
||||
@ -2359,7 +2363,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
|
||||
// (Z-X) == X --> Z == X<<1
|
||||
SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(),
|
||||
N1,
|
||||
DAG.getConstant(1, getShiftAmountTy()));
|
||||
DAG.getConstant(1, getShiftAmountTy(N1.getValueType())));
|
||||
if (!DCI.isCalledByLegalizer())
|
||||
DCI.AddToWorklist(SH.getNode());
|
||||
return DAG.getSetCC(dl, VT, N0.getOperand(0), SH, Cond);
|
||||
@ -2381,7 +2385,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1,
|
||||
assert(N1.getOpcode() == ISD::SUB && "Unexpected operation!");
|
||||
// X == (Z-X) --> X<<1 == Z
|
||||
SDValue SH = DAG.getNode(ISD::SHL, dl, N1.getValueType(), N0,
|
||||
DAG.getConstant(1, getShiftAmountTy()));
|
||||
DAG.getConstant(1, getShiftAmountTy(N0.getValueType())));
|
||||
if (!DCI.isCalledByLegalizer())
|
||||
DCI.AddToWorklist(SH.getNode());
|
||||
return DAG.getSetCC(dl, VT, SH, N1.getOperand(0), Cond);
|
||||
@ -2493,7 +2497,7 @@ bool TargetLowering::isGAPlusOffset(SDNode *N, const GlobalValue *&GA,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3141,14 +3145,14 @@ SDValue TargetLowering::BuildSDIV(SDNode *N, SelectionDAG &DAG,
|
||||
// Shift right algebraic if shift value is nonzero
|
||||
if (magics.s > 0) {
|
||||
Q = DAG.getNode(ISD::SRA, dl, VT, Q,
|
||||
DAG.getConstant(magics.s, getShiftAmountTy()));
|
||||
DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType())));
|
||||
if (Created)
|
||||
Created->push_back(Q.getNode());
|
||||
}
|
||||
// Extract the sign bit and add it to the quotient
|
||||
SDValue T =
|
||||
DAG.getNode(ISD::SRL, dl, VT, Q, DAG.getConstant(VT.getSizeInBits()-1,
|
||||
getShiftAmountTy()));
|
||||
getShiftAmountTy(Q.getValueType())));
|
||||
if (Created)
|
||||
Created->push_back(T.getNode());
|
||||
return DAG.getNode(ISD::ADD, dl, VT, Q, T);
|
||||
@ -3192,19 +3196,19 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
|
||||
assert(magics.s < N1C->getAPIntValue().getBitWidth() &&
|
||||
"We shouldn't generate an undefined shift!");
|
||||
return DAG.getNode(ISD::SRL, dl, VT, Q,
|
||||
DAG.getConstant(magics.s, getShiftAmountTy()));
|
||||
DAG.getConstant(magics.s, getShiftAmountTy(Q.getValueType())));
|
||||
} else {
|
||||
SDValue NPQ = DAG.getNode(ISD::SUB, dl, VT, N->getOperand(0), Q);
|
||||
if (Created)
|
||||
Created->push_back(NPQ.getNode());
|
||||
NPQ = DAG.getNode(ISD::SRL, dl, VT, NPQ,
|
||||
DAG.getConstant(1, getShiftAmountTy()));
|
||||
DAG.getConstant(1, getShiftAmountTy(NPQ.getValueType())));
|
||||
if (Created)
|
||||
Created->push_back(NPQ.getNode());
|
||||
NPQ = DAG.getNode(ISD::ADD, dl, VT, NPQ, Q);
|
||||
if (Created)
|
||||
Created->push_back(NPQ.getNode());
|
||||
return DAG.getNode(ISD::SRL, dl, VT, NPQ,
|
||||
DAG.getConstant(magics.s-1, getShiftAmountTy()));
|
||||
DAG.getConstant(magics.s-1, getShiftAmountTy(NPQ.getValueType())));
|
||||
}
|
||||
}
|
||||
|
@ -167,6 +167,20 @@ void SplitAnalysis::calcLiveBlockInfo() {
|
||||
}
|
||||
}
|
||||
|
||||
bool SplitAnalysis::isOriginalEndpoint(SlotIndex Idx) const {
|
||||
unsigned OrigReg = VRM.getOriginal(CurLI->reg);
|
||||
const LiveInterval &Orig = LIS.getInterval(OrigReg);
|
||||
assert(!Orig.empty() && "Splitting empty interval?");
|
||||
LiveInterval::const_iterator I = Orig.find(Idx);
|
||||
|
||||
// Range containing Idx should begin at Idx.
|
||||
if (I != Orig.end() && I->start <= Idx)
|
||||
return I->start == Idx;
|
||||
|
||||
// Range does not contain Idx, previous must end at Idx.
|
||||
return I != Orig.begin() && (--I)->end == Idx;
|
||||
}
|
||||
|
||||
void SplitAnalysis::print(const BlockPtrSet &B, raw_ostream &OS) const {
|
||||
for (BlockPtrSet::const_iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
||||
unsigned count = UsingBlocks.lookup(*I);
|
||||
@ -947,10 +961,10 @@ void SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) {
|
||||
|
||||
openIntv();
|
||||
SlotIndex SegStart = enterIntvBefore(BI.FirstUse);
|
||||
if (BI.LastUse < BI.LastSplitPoint) {
|
||||
if (!BI.LiveOut || BI.LastUse < BI.LastSplitPoint) {
|
||||
useIntv(SegStart, leaveIntvAfter(BI.LastUse));
|
||||
} else {
|
||||
// THe last use os after tha last valid split point.
|
||||
// The last use is after the last valid split point.
|
||||
SlotIndex SegStop = leaveIntvBefore(BI.LastSplitPoint);
|
||||
useIntv(SegStart, SegStop);
|
||||
overlapIntv(SegStop, BI.LastUse);
|
||||
|
@ -125,6 +125,13 @@ class SplitAnalysis {
|
||||
return UsingBlocks.lookup(MBB);
|
||||
}
|
||||
|
||||
/// isOriginalEndpoint - Return true if the original live range was killed or
|
||||
/// (re-)defined at Idx. Idx should be the 'def' slot for a normal kill/def,
|
||||
/// and 'use' for an early-clobber def.
|
||||
/// This can be used to recognize code inserted by earlier live range
|
||||
/// splitting.
|
||||
bool isOriginalEndpoint(SlotIndex Idx) const;
|
||||
|
||||
typedef SmallPtrSet<const MachineBasicBlock*, 16> BlockPtrSet;
|
||||
|
||||
// Print a set of blocks with use counts.
|
||||
|
@ -178,6 +178,10 @@ const MCSection *TargetLoweringObjectFileELF::getEHFrameSection() const {
|
||||
|
||||
static SectionKind
|
||||
getELFKindForNamedSection(StringRef Name, SectionKind K) {
|
||||
// FIXME: Why is this here? Codegen is should not be in the business
|
||||
// of figuring section flags. If the user wrote section(".eh_frame"),
|
||||
// we should just pass that to MC which will defer to the assembly
|
||||
// or use its default if producing an object file.
|
||||
if (Name.empty() || Name[0] != '.') return K;
|
||||
|
||||
// Some lame default implementation based on some magic section names.
|
||||
@ -203,6 +207,9 @@ getELFKindForNamedSection(StringRef Name, SectionKind K) {
|
||||
Name.startswith(".llvm.linkonce.tb."))
|
||||
return SectionKind::getThreadBSS();
|
||||
|
||||
if (Name == ".eh_frame")
|
||||
return SectionKind::getDataRel();
|
||||
|
||||
return K;
|
||||
}
|
||||
|
||||
@ -441,11 +448,15 @@ void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx,
|
||||
|
||||
Triple T(((LLVMTargetMachine&)TM).getTargetTriple());
|
||||
if (T.getOS() == Triple::Darwin) {
|
||||
unsigned MajNum = T.getDarwinMajorNumber();
|
||||
if (MajNum == 7 || MajNum == 8) // 10.3 Panther, 10.4 Tiger
|
||||
switch (T.getDarwinMajorNumber()) {
|
||||
case 7: // 10.3 Panther.
|
||||
case 8: // 10.4 Tiger.
|
||||
CommDirectiveSupportsAlignment = false;
|
||||
if (MajNum > 9) // 10.6 SnowLeopard
|
||||
IsFunctionEHSymbolGlobal = false;
|
||||
break;
|
||||
case 9: // 10.5 Leopard.
|
||||
case 10: // 10.6 SnowLeopard.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TargetLoweringObjectFile::Initialize(Ctx, TM);
|
||||
@ -630,7 +641,7 @@ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
|
||||
Mangler *Mang, const TargetMachine &TM) const {
|
||||
// Parse the section specifier and create it if valid.
|
||||
StringRef Segment, Section;
|
||||
unsigned TAA, StubSize;
|
||||
unsigned TAA = (unsigned)MCSectionMachO::SECTION_ATTRIBUTES, StubSize = 0;
|
||||
std::string ErrorCode =
|
||||
MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section,
|
||||
TAA, StubSize);
|
||||
@ -643,10 +654,19 @@ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
|
||||
return DataSection;
|
||||
}
|
||||
|
||||
bool TAAWasSet = (TAA != MCSectionMachO::SECTION_ATTRIBUTES);
|
||||
if (!TAAWasSet)
|
||||
TAA = 0; // Sensible default if this is a new section.
|
||||
|
||||
// Get the section.
|
||||
const MCSectionMachO *S =
|
||||
getContext().getMachOSection(Segment, Section, TAA, StubSize, Kind);
|
||||
|
||||
// If TAA wasn't set by ParseSectionSpecifier() above,
|
||||
// use the value returned by getMachOSection() as a default.
|
||||
if (!TAAWasSet)
|
||||
TAA = S->getTypeAndAttributes();
|
||||
|
||||
// Okay, now that we got the section, verify that the TAA & StubSize agree.
|
||||
// If the user declared multiple globals with different section flags, we need
|
||||
// to reject it here.
|
||||
|
@ -478,7 +478,8 @@ static void ResurrectConfirmedKill(unsigned Reg, const TargetRegisterInfo* TRI,
|
||||
if (!RegKills[KReg])
|
||||
return;
|
||||
|
||||
assert(KillOps[KReg] == KillOp && "invalid superreg kill flags");
|
||||
assert(KillOps[KReg]->getParent() == KillOp->getParent() &&
|
||||
"invalid superreg kill flags");
|
||||
KillOps[KReg] = NULL;
|
||||
RegKills.reset(KReg);
|
||||
|
||||
@ -487,7 +488,8 @@ static void ResurrectConfirmedKill(unsigned Reg, const TargetRegisterInfo* TRI,
|
||||
for (const unsigned *SR = TRI->getSubRegisters(KReg); *SR; ++SR) {
|
||||
DEBUG(dbgs() << " Resurrect subreg " << TRI->getName(*SR) << "\n");
|
||||
|
||||
assert(KillOps[*SR] == KillOp && "invalid subreg kill flags");
|
||||
assert(KillOps[*SR]->getParent() == KillOp->getParent() &&
|
||||
"invalid subreg kill flags");
|
||||
KillOps[*SR] = NULL;
|
||||
RegKills.reset(*SR);
|
||||
}
|
||||
|
@ -833,7 +833,11 @@ static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data,
|
||||
return true;
|
||||
|
||||
const MCSymbol &A = Symbol.AliasedSymbol();
|
||||
if (!A.isVariable() && A.isUndefined() && !Data.isCommon())
|
||||
if (Symbol.isVariable() && !A.isVariable() && A.isUndefined())
|
||||
return false;
|
||||
|
||||
bool IsGlobal = GetBinding(Data) == ELF::STB_GLOBAL;
|
||||
if (!Symbol.isVariable() && Symbol.isUndefined() && !IsGlobal)
|
||||
return false;
|
||||
|
||||
if (!Asm.isSymbolLinkerVisible(Symbol) && !Symbol.isUndefined())
|
||||
@ -1732,6 +1736,10 @@ unsigned X86ELFObjectWriter::GetRelocType(const MCValue &Target,
|
||||
assert(Modifier == MCSymbolRefExpr::VK_None);
|
||||
Type = ELF::R_X86_64_PC16;
|
||||
break;
|
||||
case FK_PCRel_1:
|
||||
assert(Modifier == MCSymbolRefExpr::VK_None);
|
||||
Type = ELF::R_X86_64_PC8;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch ((unsigned)Fixup.getKind()) {
|
||||
|
@ -65,6 +65,7 @@ MCAsmInfo::MCAsmInfo() {
|
||||
WeakDefDirective = 0;
|
||||
LinkOnceDirective = 0;
|
||||
HiddenVisibilityAttr = MCSA_Hidden;
|
||||
HiddenDeclarationVisibilityAttr = MCSA_Hidden;
|
||||
ProtectedVisibilityAttr = MCSA_Protected;
|
||||
HasLEB128 = false;
|
||||
SupportsDebugInformation = false;
|
||||
|
@ -45,6 +45,7 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() {
|
||||
HasAggressiveSymbolFolding = false;
|
||||
|
||||
HiddenVisibilityAttr = MCSA_PrivateExtern;
|
||||
HiddenDeclarationVisibilityAttr = MCSA_Invalid;
|
||||
// Doesn't support protected visibility.
|
||||
ProtectedVisibilityAttr = MCSA_Global;
|
||||
|
||||
|
@ -152,10 +152,23 @@ int EDOperand::evaluate(uint64_t &result,
|
||||
uint64_t scaleAmount = Inst.Inst->getOperand(MCOpIndex+1).getImm();
|
||||
unsigned indexReg = Inst.Inst->getOperand(MCOpIndex+2).getReg();
|
||||
int64_t displacement = Inst.Inst->getOperand(MCOpIndex+3).getImm();
|
||||
//unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
|
||||
|
||||
|
||||
uint64_t addr = 0;
|
||||
|
||||
unsigned segmentReg = Inst.Inst->getOperand(MCOpIndex+4).getReg();
|
||||
|
||||
if (segmentReg != 0 && Disassembler.Key.Arch == Triple::x86_64) {
|
||||
unsigned fsID = Disassembler.registerIDWithName("FS");
|
||||
unsigned gsID = Disassembler.registerIDWithName("GS");
|
||||
|
||||
if (segmentReg == fsID ||
|
||||
segmentReg == gsID) {
|
||||
uint64_t segmentBase;
|
||||
if (!callback(&segmentBase, segmentReg, arg))
|
||||
addr += segmentBase;
|
||||
}
|
||||
}
|
||||
|
||||
if (baseReg) {
|
||||
uint64_t baseVal;
|
||||
if (callback(&baseVal, baseReg, arg))
|
||||
@ -175,7 +188,7 @@ int EDOperand::evaluate(uint64_t &result,
|
||||
result = addr;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // switch (operandType)
|
||||
break;
|
||||
case Triple::arm:
|
||||
case Triple::thumb:
|
||||
@ -203,6 +216,7 @@ int EDOperand::evaluate(uint64_t &result,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
@ -194,6 +194,10 @@ int EDToken::tokenize(std::vector<EDToken*> &tokens,
|
||||
tokens.push_back(token);
|
||||
}
|
||||
|
||||
// Free any parsed operands.
|
||||
for (unsigned i = 0, e = parsedOperands.size(); i != e; ++i)
|
||||
delete parsedOperands[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -242,7 +242,23 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
|
||||
|
||||
void MCObjectStreamer::EmitValueToOffset(const MCExpr *Offset,
|
||||
unsigned char Value) {
|
||||
new MCOrgFragment(*Offset, Value, getCurrentSectionData());
|
||||
int64_t Res;
|
||||
if (Offset->EvaluateAsAbsolute(Res, getAssembler())) {
|
||||
new MCOrgFragment(*Offset, Value, getCurrentSectionData());
|
||||
return;
|
||||
}
|
||||
|
||||
MCSymbol *CurrentPos = getContext().CreateTempSymbol();
|
||||
EmitLabel(CurrentPos);
|
||||
MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
|
||||
const MCExpr *Ref =
|
||||
MCSymbolRefExpr::Create(CurrentPos, Variant, getContext());
|
||||
const MCExpr *Delta =
|
||||
MCBinaryExpr::Create(MCBinaryExpr::Sub, Offset, Ref, getContext());
|
||||
|
||||
if (!Delta->EvaluateAsAbsolute(Res, getAssembler()))
|
||||
report_fatal_error("expected assembly-time absolute expression");
|
||||
EmitFill(Res, Value, 0);
|
||||
}
|
||||
|
||||
void MCObjectStreamer::Finish() {
|
||||
|
@ -603,6 +603,8 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
|
||||
Lex(); // Eat the '('.
|
||||
return ParseParenExpr(Res, EndLoc);
|
||||
case AsmToken::LBrac:
|
||||
if (!PlatformParser->HasBracketExpressions())
|
||||
return TokError("brackets expression not supported on this target");
|
||||
Lex(); // Eat the '['.
|
||||
return ParseBracketExpr(Res, EndLoc);
|
||||
case AsmToken::Minus:
|
||||
|
@ -30,9 +30,12 @@ class ELFAsmParser : public MCAsmParserExtension {
|
||||
|
||||
bool ParseSectionSwitch(StringRef Section, unsigned Type,
|
||||
unsigned Flags, SectionKind Kind);
|
||||
bool SeenIdent;
|
||||
|
||||
public:
|
||||
ELFAsmParser() {}
|
||||
ELFAsmParser() : SeenIdent(false) {
|
||||
BracketExpressionsSupported = true;
|
||||
}
|
||||
|
||||
virtual void Initialize(MCAsmParser &Parser) {
|
||||
// Call the base implementation.
|
||||
@ -456,13 +459,12 @@ bool ELFAsmParser::ParseDirectiveIdent(StringRef, SMLoc) {
|
||||
SectionKind::getReadOnly(),
|
||||
1, "");
|
||||
|
||||
static bool First = true;
|
||||
|
||||
getStreamer().PushSection();
|
||||
getStreamer().SwitchSection(Comment);
|
||||
if (First)
|
||||
if (!SeenIdent) {
|
||||
getStreamer().EmitIntValue(0, 1);
|
||||
First = false;
|
||||
SeenIdent = true;
|
||||
}
|
||||
getStreamer().EmitBytes(Data, 0);
|
||||
getStreamer().EmitIntValue(0, 1);
|
||||
getStreamer().PopSection();
|
||||
|
@ -10,7 +10,8 @@
|
||||
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
|
||||
using namespace llvm;
|
||||
|
||||
MCAsmParserExtension::MCAsmParserExtension() {
|
||||
MCAsmParserExtension::MCAsmParserExtension() :
|
||||
BracketExpressionsSupported(false) {
|
||||
}
|
||||
|
||||
MCAsmParserExtension::~MCAsmParserExtension() {
|
||||
|
@ -101,16 +101,18 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
|
||||
return;
|
||||
}
|
||||
|
||||
OS << ',';
|
||||
|
||||
unsigned SectionType = TAA & MCSectionMachO::SECTION_TYPE;
|
||||
assert(SectionType <= MCSectionMachO::LAST_KNOWN_SECTION_TYPE &&
|
||||
"Invalid SectionType specified!");
|
||||
|
||||
if (SectionTypeDescriptors[SectionType].AssemblerName)
|
||||
if (SectionTypeDescriptors[SectionType].AssemblerName) {
|
||||
OS << ',';
|
||||
OS << SectionTypeDescriptors[SectionType].AssemblerName;
|
||||
else
|
||||
OS << "<<" << SectionTypeDescriptors[SectionType].EnumName << ">>";
|
||||
} else {
|
||||
// If we have no name for the attribute, stop here.
|
||||
OS << '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't have any attributes, we're done.
|
||||
unsigned SectionAttrs = TAA & MCSectionMachO::SECTION_ATTRIBUTES;
|
||||
@ -125,7 +127,9 @@ void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
|
||||
|
||||
// Check each attribute to see if we have it.
|
||||
char Separator = ',';
|
||||
for (unsigned i = 0; SectionAttrDescriptors[i].AttrFlag; ++i) {
|
||||
for (unsigned i = 0;
|
||||
SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag;
|
||||
++i) {
|
||||
// Check to see if we have this attribute.
|
||||
if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0)
|
||||
continue;
|
||||
@ -207,7 +211,6 @@ std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.
|
||||
"between 1 and 16 characters";
|
||||
|
||||
// If there is no comma after the section, we're done.
|
||||
TAA = 0;
|
||||
StubSize = 0;
|
||||
if (Comma.second.empty())
|
||||
return "";
|
||||
|
@ -20,8 +20,8 @@
|
||||
using namespace llvm;
|
||||
|
||||
MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx) {
|
||||
PrevSectionStack.push_back(NULL);
|
||||
CurSectionStack.push_back(NULL);
|
||||
const MCSection *section = NULL;
|
||||
SectionStack.push_back(std::make_pair(section, section));
|
||||
}
|
||||
|
||||
MCStreamer::~MCStreamer() {
|
||||
|
@ -1505,7 +1505,7 @@ APInt::ms APInt::magic() const {
|
||||
r2 = r2 - ad;
|
||||
}
|
||||
delta = ad - r2;
|
||||
} while (q1.ule(delta) || (q1 == delta && r1 == 0));
|
||||
} while (q1.ult(delta) || (q1 == delta && r1 == 0));
|
||||
|
||||
mag.m = q2 + 1;
|
||||
if (d.isNegative()) mag.m = -mag.m; // resulting magic number
|
||||
|
@ -155,10 +155,11 @@ namespace ARMII {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Code domain.
|
||||
DomainShift = 18,
|
||||
DomainMask = 3 << DomainShift,
|
||||
DomainMask = 7 << DomainShift,
|
||||
DomainGeneral = 0 << DomainShift,
|
||||
DomainVFP = 1 << DomainShift,
|
||||
DomainNEON = 2 << DomainShift,
|
||||
DomainNEONA8 = 4 << DomainShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Field shifts - such shifts are used to set field while generating
|
||||
|
@ -172,6 +172,7 @@ class ARMFastISel : public FastISel {
|
||||
unsigned ARMMaterializeGV(const GlobalValue *GV, EVT VT);
|
||||
unsigned ARMMoveToFPReg(EVT VT, unsigned SrcReg);
|
||||
unsigned ARMMoveToIntReg(EVT VT, unsigned SrcReg);
|
||||
unsigned ARMSelectCallOp(const GlobalValue *GV);
|
||||
|
||||
// Call handling routines.
|
||||
private:
|
||||
@ -1633,6 +1634,25 @@ bool ARMFastISel::SelectRet(const Instruction *I) {
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned ARMFastISel::ARMSelectCallOp(const GlobalValue *GV) {
|
||||
|
||||
// Depend our opcode for thumb on whether or not we're targeting an
|
||||
// externally callable function. For libcalls we'll just pass a NULL GV
|
||||
// in here.
|
||||
bool isExternal = false;
|
||||
if (!GV || GV->hasExternalLinkage()) isExternal = true;
|
||||
|
||||
// Darwin needs the r9 versions of the opcodes.
|
||||
bool isDarwin = Subtarget->isTargetDarwin();
|
||||
if (isThumb && isExternal) {
|
||||
return isDarwin ? ARM::tBLXi_r9 : ARM::tBLXi;
|
||||
} else if (isThumb) {
|
||||
return isDarwin ? ARM::tBLr9 : ARM::tBL;
|
||||
} else {
|
||||
return isDarwin ? ARM::BLr9 : ARM::BL;
|
||||
}
|
||||
}
|
||||
|
||||
// A quick function that will emit a call for a named libcall in F with the
|
||||
// vector of passed arguments for the Instruction in I. We can assume that we
|
||||
// can emit a call for any libcall we can produce. This is an abridged version
|
||||
@ -1694,20 +1714,17 @@ bool ARMFastISel::ARMEmitLibcall(const Instruction *I, RTLIB::Libcall Call) {
|
||||
// Issue the call, BLXr9 for darwin, BLX otherwise. This uses V5 ops.
|
||||
// TODO: Turn this into the table of arm call ops.
|
||||
MachineInstrBuilder MIB;
|
||||
unsigned CallOpc;
|
||||
if(isThumb) {
|
||||
CallOpc = Subtarget->isTargetDarwin() ? ARM::tBLXi_r9 : ARM::tBLXi;
|
||||
unsigned CallOpc = ARMSelectCallOp(NULL);
|
||||
if(isThumb)
|
||||
// Explicitly adding the predicate here.
|
||||
MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
|
||||
TII.get(CallOpc)))
|
||||
.addExternalSymbol(TLI.getLibcallName(Call));
|
||||
} else {
|
||||
CallOpc = Subtarget->isTargetDarwin() ? ARM::BLr9 : ARM::BL;
|
||||
else
|
||||
// Explicitly adding the predicate here.
|
||||
MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
|
||||
TII.get(CallOpc))
|
||||
.addExternalSymbol(TLI.getLibcallName(Call)));
|
||||
}
|
||||
|
||||
// Add implicit physical register uses to the call.
|
||||
for (unsigned i = 0, e = RegArgs.size(); i != e; ++i)
|
||||
@ -1813,21 +1830,18 @@ bool ARMFastISel::SelectCall(const Instruction *I) {
|
||||
// Issue the call, BLXr9 for darwin, BLX otherwise. This uses V5 ops.
|
||||
// TODO: Turn this into the table of arm call ops.
|
||||
MachineInstrBuilder MIB;
|
||||
unsigned CallOpc;
|
||||
unsigned CallOpc = ARMSelectCallOp(GV);
|
||||
// Explicitly adding the predicate here.
|
||||
if(isThumb) {
|
||||
CallOpc = Subtarget->isTargetDarwin() ? ARM::tBLXi_r9 : ARM::tBLXi;
|
||||
if(isThumb)
|
||||
// Explicitly adding the predicate here.
|
||||
MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
|
||||
TII.get(CallOpc)))
|
||||
.addGlobalAddress(GV, 0, 0);
|
||||
} else {
|
||||
CallOpc = Subtarget->isTargetDarwin() ? ARM::BLr9 : ARM::BL;
|
||||
else
|
||||
// Explicitly adding the predicate here.
|
||||
MIB = AddDefaultPred(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
|
||||
TII.get(CallOpc))
|
||||
.addGlobalAddress(GV, 0, 0));
|
||||
}
|
||||
|
||||
// Add implicit physical register uses to the call.
|
||||
for (unsigned i = 0, e = RegArgs.size(); i != e; ++i)
|
||||
|
@ -215,7 +215,13 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset);
|
||||
|
||||
// Move past area 3.
|
||||
if (DPRCSSize > 0) MBBI++;
|
||||
if (DPRCSSize > 0) {
|
||||
MBBI++;
|
||||
// Since vpush register list cannot have gaps, there may be multiple vpush
|
||||
// instructions in the prologue.
|
||||
while (MBBI->getOpcode() == ARM::VSTMDDB_UPD)
|
||||
MBBI++;
|
||||
}
|
||||
|
||||
NumBytes = DPRCSOffset;
|
||||
if (NumBytes) {
|
||||
@ -370,7 +376,13 @@ void ARMFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
emitSPUpdate(isARM, MBB, MBBI, dl, TII, NumBytes);
|
||||
|
||||
// Increment past our save areas.
|
||||
if (AFI->getDPRCalleeSavedAreaSize()) MBBI++;
|
||||
if (AFI->getDPRCalleeSavedAreaSize()) {
|
||||
MBBI++;
|
||||
// Since vpop register list cannot have gaps, there may be multiple vpop
|
||||
// instructions in the epilogue.
|
||||
while (MBBI->getOpcode() == ARM::VLDMDIA_UPD)
|
||||
MBBI++;
|
||||
}
|
||||
if (AFI->getGPRCalleeSavedArea2Size()) MBBI++;
|
||||
if (AFI->getGPRCalleeSavedArea1Size()) MBBI++;
|
||||
}
|
||||
|
@ -21,17 +21,14 @@ static bool hasRAWHazard(MachineInstr *DefMI, MachineInstr *MI,
|
||||
// FIXME: Detect integer instructions properly.
|
||||
const TargetInstrDesc &TID = MI->getDesc();
|
||||
unsigned Domain = TID.TSFlags & ARMII::DomainMask;
|
||||
if (Domain == ARMII::DomainVFP) {
|
||||
unsigned Opcode = MI->getOpcode();
|
||||
if (Opcode == ARM::VSTRS || Opcode == ARM::VSTRD ||
|
||||
Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
|
||||
return false;
|
||||
} else if (Domain == ARMII::DomainNEON) {
|
||||
if (MI->getDesc().mayStore() || MI->getDesc().mayLoad())
|
||||
return false;
|
||||
} else
|
||||
if (TID.mayStore())
|
||||
return false;
|
||||
return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI);
|
||||
unsigned Opcode = TID.getOpcode();
|
||||
if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
|
||||
return false;
|
||||
if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON))
|
||||
return MI->readsRegister(DefMI->getOperand(0).getReg(), &TRI);
|
||||
return false;
|
||||
}
|
||||
|
||||
ScheduleHazardRecognizer::HazardType
|
||||
|
@ -126,6 +126,7 @@ class ARMDAGToDAGISel : public SelectionDAGISel {
|
||||
bool SelectAddrMode5(SDValue N, SDValue &Base,
|
||||
SDValue &Offset);
|
||||
bool SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,SDValue &Align);
|
||||
bool SelectAddrMode6Offset(SDNode *Op, SDValue N, SDValue &Offset);
|
||||
|
||||
bool SelectAddrModePC(SDValue N, SDValue &Offset, SDValue &Label);
|
||||
|
||||
@ -886,6 +887,20 @@ bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Parent, SDValue N, SDValue &Addr,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectAddrMode6Offset(SDNode *Op, SDValue N,
|
||||
SDValue &Offset) {
|
||||
LSBaseSDNode *LdSt = cast<LSBaseSDNode>(Op);
|
||||
ISD::MemIndexedMode AM = LdSt->getAddressingMode();
|
||||
if (AM != ISD::POST_INC)
|
||||
return false;
|
||||
Offset = N;
|
||||
if (ConstantSDNode *NC = dyn_cast<ConstantSDNode>(N)) {
|
||||
if (NC->getZExtValue() * 8 == LdSt->getMemoryVT().getSizeInBits())
|
||||
Offset = CurDAG->getRegister(0, MVT::i32);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectAddrModePC(SDValue N,
|
||||
SDValue &Offset, SDValue &Label) {
|
||||
if (N.getOpcode() == ARMISD::PIC_ADD && N.hasOneUse()) {
|
||||
|
@ -2236,7 +2236,7 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA,
|
||||
RC = ARM::GPRRegisterClass;
|
||||
|
||||
// Transform the arguments stored in physical registers into virtual ones.
|
||||
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl);
|
||||
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
|
||||
SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32);
|
||||
|
||||
SDValue ArgValue2;
|
||||
@ -2250,7 +2250,7 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA,
|
||||
MachinePointerInfo::getFixedStack(FI),
|
||||
false, false, 0);
|
||||
} else {
|
||||
Reg = MF.addLiveIn(NextVA.getLocReg(), RC, dl);
|
||||
Reg = MF.addLiveIn(NextVA.getLocReg(), RC);
|
||||
ArgValue2 = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32);
|
||||
}
|
||||
|
||||
@ -2331,7 +2331,7 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
llvm_unreachable("RegVT not supported by FORMAL_ARGUMENTS Lowering");
|
||||
|
||||
// Transform the arguments in physical registers into virtual ones.
|
||||
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl);
|
||||
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
|
||||
ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
|
||||
}
|
||||
|
||||
@ -2408,7 +2408,7 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
else
|
||||
RC = ARM::GPRRegisterClass;
|
||||
|
||||
unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC, dl);
|
||||
unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC);
|
||||
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
|
||||
SDValue Store =
|
||||
DAG.getStore(Val.getValue(1), dl, Val, FIN,
|
||||
@ -2838,8 +2838,51 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
EVT VT = Op.getValueType();
|
||||
EVT SrcVT = Tmp1.getValueType();
|
||||
bool F2IisFast = Subtarget->isCortexA9() ||
|
||||
Tmp0.getOpcode() == ISD::BITCAST || Tmp0.getOpcode() == ARMISD::VMOVDRR;
|
||||
bool InGPR = Tmp0.getOpcode() == ISD::BITCAST ||
|
||||
Tmp0.getOpcode() == ARMISD::VMOVDRR;
|
||||
bool UseNEON = !InGPR && Subtarget->hasNEON();
|
||||
|
||||
if (UseNEON) {
|
||||
// Use VBSL to copy the sign bit.
|
||||
unsigned EncodedVal = ARM_AM::createNEONModImm(0x6, 0x80);
|
||||
SDValue Mask = DAG.getNode(ARMISD::VMOVIMM, dl, MVT::v2i32,
|
||||
DAG.getTargetConstant(EncodedVal, MVT::i32));
|
||||
EVT OpVT = (VT == MVT::f32) ? MVT::v2i32 : MVT::v1i64;
|
||||
if (VT == MVT::f64)
|
||||
Mask = DAG.getNode(ARMISD::VSHL, dl, OpVT,
|
||||
DAG.getNode(ISD::BITCAST, dl, OpVT, Mask),
|
||||
DAG.getConstant(32, MVT::i32));
|
||||
else /*if (VT == MVT::f32)*/
|
||||
Tmp0 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2f32, Tmp0);
|
||||
if (SrcVT == MVT::f32) {
|
||||
Tmp1 = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MVT::v2f32, Tmp1);
|
||||
if (VT == MVT::f64)
|
||||
Tmp1 = DAG.getNode(ARMISD::VSHL, dl, OpVT,
|
||||
DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1),
|
||||
DAG.getConstant(32, MVT::i32));
|
||||
}
|
||||
Tmp0 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp0);
|
||||
Tmp1 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1);
|
||||
|
||||
SDValue AllOnes = DAG.getTargetConstant(ARM_AM::createNEONModImm(0xe, 0xff),
|
||||
MVT::i32);
|
||||
AllOnes = DAG.getNode(ARMISD::VMOVIMM, dl, MVT::v8i8, AllOnes);
|
||||
SDValue MaskNot = DAG.getNode(ISD::XOR, dl, OpVT, Mask,
|
||||
DAG.getNode(ISD::BITCAST, dl, OpVT, AllOnes));
|
||||
|
||||
SDValue Res = DAG.getNode(ISD::OR, dl, OpVT,
|
||||
DAG.getNode(ISD::AND, dl, OpVT, Tmp1, Mask),
|
||||
DAG.getNode(ISD::AND, dl, OpVT, Tmp0, MaskNot));
|
||||
if (SrcVT == MVT::f32) {
|
||||
Res = DAG.getNode(ISD::BITCAST, dl, MVT::v2f32, Res);
|
||||
Res = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, MVT::f32, Res,
|
||||
DAG.getConstant(0, MVT::i32));
|
||||
} else {
|
||||
Res = DAG.getNode(ISD::BITCAST, dl, MVT::f64, Res);
|
||||
}
|
||||
|
||||
return Res;
|
||||
}
|
||||
|
||||
// Bitcast operand 1 to i32.
|
||||
if (SrcVT == MVT::f64)
|
||||
@ -2847,37 +2890,24 @@ SDValue ARMTargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
|
||||
&Tmp1, 1).getValue(1);
|
||||
Tmp1 = DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp1);
|
||||
|
||||
// If float to int conversion isn't going to be super expensive, then simply
|
||||
// or in the signbit.
|
||||
if (F2IisFast) {
|
||||
SDValue Mask1 = DAG.getConstant(0x80000000, MVT::i32);
|
||||
SDValue Mask2 = DAG.getConstant(0x7fffffff, MVT::i32);
|
||||
Tmp1 = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp1, Mask1);
|
||||
if (VT == MVT::f32) {
|
||||
Tmp0 = DAG.getNode(ISD::AND, dl, MVT::i32,
|
||||
DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
|
||||
return DAG.getNode(ISD::BITCAST, dl, MVT::f32,
|
||||
DAG.getNode(ISD::OR, dl, MVT::i32, Tmp0, Tmp1));
|
||||
}
|
||||
|
||||
// f64: Or the high part with signbit and then combine two parts.
|
||||
Tmp0 = DAG.getNode(ARMISD::VMOVRRD, dl, DAG.getVTList(MVT::i32, MVT::i32),
|
||||
&Tmp0, 1);
|
||||
SDValue Lo = Tmp0.getValue(0);
|
||||
SDValue Hi = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp0.getValue(1), Mask2);
|
||||
Hi = DAG.getNode(ISD::OR, dl, MVT::i32, Hi, Tmp1);
|
||||
return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi);
|
||||
// Or in the signbit with integer operations.
|
||||
SDValue Mask1 = DAG.getConstant(0x80000000, MVT::i32);
|
||||
SDValue Mask2 = DAG.getConstant(0x7fffffff, MVT::i32);
|
||||
Tmp1 = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp1, Mask1);
|
||||
if (VT == MVT::f32) {
|
||||
Tmp0 = DAG.getNode(ISD::AND, dl, MVT::i32,
|
||||
DAG.getNode(ISD::BITCAST, dl, MVT::i32, Tmp0), Mask2);
|
||||
return DAG.getNode(ISD::BITCAST, dl, MVT::f32,
|
||||
DAG.getNode(ISD::OR, dl, MVT::i32, Tmp0, Tmp1));
|
||||
}
|
||||
|
||||
// Remove the signbit of operand 0.
|
||||
Tmp0 = DAG.getNode(ISD::FABS, dl, VT, Tmp0);
|
||||
|
||||
// If operand 1 signbit is one, then negate operand 0.
|
||||
SDValue ARMcc;
|
||||
SDValue Cmp = getARMCmp(Tmp1, DAG.getConstant(0, MVT::i32),
|
||||
ISD::SETLT, ARMcc, DAG, dl);
|
||||
SDValue CCR = DAG.getRegister(ARM::CPSR, MVT::i32);
|
||||
return DAG.getNode(ARMISD::CNEG, dl, VT, Tmp0, Tmp0, ARMcc, CCR, Cmp);
|
||||
// f64: Or the high part with signbit and then combine two parts.
|
||||
Tmp0 = DAG.getNode(ARMISD::VMOVRRD, dl, DAG.getVTList(MVT::i32, MVT::i32),
|
||||
&Tmp0, 1);
|
||||
SDValue Lo = Tmp0.getValue(0);
|
||||
SDValue Hi = DAG.getNode(ISD::AND, dl, MVT::i32, Tmp0.getValue(1), Mask2);
|
||||
Hi = DAG.getNode(ISD::OR, dl, MVT::i32, Hi, Tmp1);
|
||||
return DAG.getNode(ARMISD::VMOVDRR, dl, MVT::f64, Lo, Hi);
|
||||
}
|
||||
|
||||
SDValue ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const{
|
||||
@ -2897,7 +2927,7 @@ SDValue ARMTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const{
|
||||
}
|
||||
|
||||
// Return LR, which contains the return address. Mark it an implicit live-in.
|
||||
unsigned Reg = MF.addLiveIn(ARM::LR, getRegClassFor(MVT::i32), dl);
|
||||
unsigned Reg = MF.addLiveIn(ARM::LR, getRegClassFor(MVT::i32));
|
||||
return DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, VT);
|
||||
}
|
||||
|
||||
|
@ -127,13 +127,14 @@ def IndexModePost : IndexMode<2>;
|
||||
def IndexModeUpd : IndexMode<3>;
|
||||
|
||||
// Instruction execution domain.
|
||||
class Domain<bits<2> val> {
|
||||
bits<2> Value = val;
|
||||
class Domain<bits<3> val> {
|
||||
bits<3> Value = val;
|
||||
}
|
||||
def GenericDomain : Domain<0>;
|
||||
def VFPDomain : Domain<1>; // Instructions in VFP domain only
|
||||
def NeonDomain : Domain<2>; // Instructions in Neon domain only
|
||||
def VFPNeonDomain : Domain<3>; // Instructions in both VFP & Neon domains
|
||||
def VFPNeonA8Domain : Domain<5>; // Instructions in VFP & Neon under A8
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ARM special operands.
|
||||
@ -249,7 +250,7 @@ class InstTemplate<AddrMode am, SizeFlagVal sz, IndexMode im,
|
||||
let TSFlags{15-10} = Form;
|
||||
let TSFlags{16} = isUnaryDataProc;
|
||||
let TSFlags{17} = canXformTo16Bit;
|
||||
let TSFlags{19-18} = D.Value;
|
||||
let TSFlags{20-18} = D.Value;
|
||||
|
||||
let Constraints = cstr;
|
||||
let Itinerary = itin;
|
||||
|
@ -561,7 +561,9 @@ def addrmode6 : Operand<i32>,
|
||||
let EncoderMethod = "getAddrMode6AddressOpValue";
|
||||
}
|
||||
|
||||
def am6offset : Operand<i32> {
|
||||
def am6offset : Operand<i32>,
|
||||
ComplexPattern<i32, 1, "SelectAddrMode6Offset",
|
||||
[], [SDNPWantRoot]> {
|
||||
let PrintMethod = "printAddrMode6OffsetOperand";
|
||||
let MIOperandInfo = (ops GPR);
|
||||
let EncoderMethod = "getAddrMode6OffsetOpValue";
|
||||
|
@ -1402,31 +1402,42 @@ def : Pat<(store (extractelt (v2f32 DPR:$src), imm:$lane), addrmode6:$addr),
|
||||
def : Pat<(store (extractelt (v4f32 QPR:$src), imm:$lane), addrmode6:$addr),
|
||||
(VST1LNq32Pseudo addrmode6:$addr, QPR:$src, imm:$lane)>;
|
||||
|
||||
let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in {
|
||||
|
||||
// ...with address register writeback:
|
||||
class VST1LNWB<bits<4> op11_8, bits<4> op7_4, string Dt>
|
||||
class VST1LNWB<bits<4> op11_8, bits<4> op7_4, string Dt, ValueType Ty,
|
||||
PatFrag StoreOp, SDNode ExtractOp>
|
||||
: NLdStLn<1, 0b00, op11_8, op7_4, (outs GPR:$wb),
|
||||
(ins addrmode6:$Rn, am6offset:$Rm,
|
||||
DPR:$Vd, nohash_imm:$lane), IIC_VST1lnu, "vst1", Dt,
|
||||
"\\{$Vd[$lane]\\}, $Rn$Rm",
|
||||
"$Rn.addr = $wb", []>;
|
||||
"$Rn.addr = $wb",
|
||||
[(set GPR:$wb, (StoreOp (ExtractOp (Ty DPR:$Vd), imm:$lane),
|
||||
addrmode6:$Rn, am6offset:$Rm))]>;
|
||||
class VST1QLNWBPseudo<ValueType Ty, PatFrag StoreOp, SDNode ExtractOp>
|
||||
: VSTQLNWBPseudo<IIC_VST1lnu> {
|
||||
let Pattern = [(set GPR:$wb, (StoreOp (ExtractOp (Ty QPR:$src), imm:$lane),
|
||||
addrmode6:$addr, am6offset:$offset))];
|
||||
}
|
||||
|
||||
def VST1LNd8_UPD : VST1LNWB<0b0000, {?,?,?,0}, "8"> {
|
||||
def VST1LNd8_UPD : VST1LNWB<0b0000, {?,?,?,0}, "8", v8i8, post_truncsti8,
|
||||
NEONvgetlaneu> {
|
||||
let Inst{7-5} = lane{2-0};
|
||||
}
|
||||
def VST1LNd16_UPD : VST1LNWB<0b0100, {?,?,0,?}, "16"> {
|
||||
def VST1LNd16_UPD : VST1LNWB<0b0100, {?,?,0,?}, "16", v4i16, post_truncsti16,
|
||||
NEONvgetlaneu> {
|
||||
let Inst{7-6} = lane{1-0};
|
||||
let Inst{4} = Rn{5};
|
||||
}
|
||||
def VST1LNd32_UPD : VST1LNWB<0b1000, {?,0,?,?}, "32"> {
|
||||
def VST1LNd32_UPD : VST1LNWB<0b1000, {?,0,?,?}, "32", v2i32, post_store,
|
||||
extractelt> {
|
||||
let Inst{7} = lane{0};
|
||||
let Inst{5-4} = Rn{5-4};
|
||||
}
|
||||
|
||||
def VST1LNq8Pseudo_UPD : VSTQLNWBPseudo<IIC_VST1lnu>;
|
||||
def VST1LNq16Pseudo_UPD : VSTQLNWBPseudo<IIC_VST1lnu>;
|
||||
def VST1LNq32Pseudo_UPD : VSTQLNWBPseudo<IIC_VST1lnu>;
|
||||
def VST1LNq8Pseudo_UPD : VST1QLNWBPseudo<v16i8, post_truncsti8, NEONvgetlaneu>;
|
||||
def VST1LNq16Pseudo_UPD : VST1QLNWBPseudo<v8i16, post_truncsti16,NEONvgetlaneu>;
|
||||
def VST1LNq32Pseudo_UPD : VST1QLNWBPseudo<v4i32, post_store, extractelt>;
|
||||
|
||||
let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in {
|
||||
|
||||
// VST2LN : Vector Store (single 2-element structure from one lane)
|
||||
class VST2LN<bits<4> op11_8, bits<4> op7_4, string Dt>
|
||||
|
@ -197,9 +197,9 @@ def VADDS : ASbIn<0b11100, 0b11, 0, 0,
|
||||
(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm),
|
||||
IIC_fpALU32, "vadd", ".f32\t$Sd, $Sn, $Sm",
|
||||
[(set SPR:$Sd, (fadd SPR:$Sn, SPR:$Sm))]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VSUBD : ADbI<0b11100, 0b11, 1, 0,
|
||||
@ -211,9 +211,9 @@ def VSUBS : ASbIn<0b11100, 0b11, 1, 0,
|
||||
(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm),
|
||||
IIC_fpALU32, "vsub", ".f32\t$Sd, $Sn, $Sm",
|
||||
[(set SPR:$Sd, (fsub SPR:$Sn, SPR:$Sm))]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VDIVD : ADbI<0b11101, 0b00, 0, 0,
|
||||
@ -235,9 +235,9 @@ def VMULS : ASbIn<0b11100, 0b10, 0, 0,
|
||||
(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm),
|
||||
IIC_fpMUL32, "vmul", ".f32\t$Sd, $Sn, $Sm",
|
||||
[(set SPR:$Sd, (fmul SPR:$Sn, SPR:$Sm))]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VNMULD : ADbI<0b11100, 0b10, 1, 0,
|
||||
@ -249,9 +249,9 @@ def VNMULS : ASbI<0b11100, 0b10, 1, 0,
|
||||
(outs SPR:$Sd), (ins SPR:$Sn, SPR:$Sm),
|
||||
IIC_fpMUL32, "vnmul", ".f32\t$Sd, $Sn, $Sm",
|
||||
[(set SPR:$Sd, (fneg (fmul SPR:$Sn, SPR:$Sm)))]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
// Match reassociated forms only if not sign dependent rounding.
|
||||
@ -271,9 +271,9 @@ def VCMPES : ASuI<0b11101, 0b11, 0b0100, 0b11, 0,
|
||||
(outs), (ins SPR:$Sd, SPR:$Sm),
|
||||
IIC_fpCMP32, "vcmpe", ".f32\t$Sd, $Sm",
|
||||
[(arm_cmpfp SPR:$Sd, SPR:$Sm)]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
// FIXME: Verify encoding after integrated assembler is working.
|
||||
@ -286,9 +286,9 @@ def VCMPS : ASuI<0b11101, 0b11, 0b0100, 0b01, 0,
|
||||
(outs), (ins SPR:$Sd, SPR:$Sm),
|
||||
IIC_fpCMP32, "vcmp", ".f32\t$Sd, $Sm",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
} // Defs = [FPSCR]
|
||||
|
||||
@ -305,9 +305,9 @@ def VABSS : ASuIn<0b11101, 0b11, 0b0000, 0b11, 0,
|
||||
(outs SPR:$Sd), (ins SPR:$Sm),
|
||||
IIC_fpUNA32, "vabs", ".f32\t$Sd, $Sm",
|
||||
[(set SPR:$Sd, (fabs SPR:$Sm))]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
let Defs = [FPSCR] in {
|
||||
@ -326,9 +326,9 @@ def VCMPEZS : ASuI<0b11101, 0b11, 0b0101, 0b11, 0,
|
||||
let Inst{3-0} = 0b0000;
|
||||
let Inst{5} = 0;
|
||||
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
// FIXME: Verify encoding after integrated assembler is working.
|
||||
@ -347,9 +347,9 @@ def VCMPZS : ASuI<0b11101, 0b11, 0b0101, 0b01, 0,
|
||||
let Inst{3-0} = 0b0000;
|
||||
let Inst{5} = 0;
|
||||
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
} // Defs = [FPSCR]
|
||||
|
||||
@ -423,9 +423,9 @@ def VNEGS : ASuIn<0b11101, 0b11, 0b0001, 0b01, 0,
|
||||
(outs SPR:$Sd), (ins SPR:$Sm),
|
||||
IIC_fpUNA32, "vneg", ".f32\t$Sd, $Sm",
|
||||
[(set SPR:$Sd, (fneg SPR:$Sm))]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VSQRTD : ADuI<0b11101, 0b11, 0b0001, 0b11, 0,
|
||||
@ -598,9 +598,9 @@ def VSITOS : AVConv1InSs_Encode<0b11101, 0b11, 0b1000, 0b1010,
|
||||
[(set SPR:$Sd, (arm_sitof SPR:$Sm))]> {
|
||||
let Inst{7} = 1; // s32
|
||||
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VUITOD : AVConv1IDs_Encode<0b11101, 0b11, 0b1000, 0b1011,
|
||||
@ -616,9 +616,9 @@ def VUITOS : AVConv1InSs_Encode<0b11101, 0b11, 0b1000, 0b1010,
|
||||
[(set SPR:$Sd, (arm_uitof SPR:$Sm))]> {
|
||||
let Inst{7} = 0; // u32
|
||||
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
// FP -> Int:
|
||||
@ -671,9 +671,9 @@ def VTOSIZS : AVConv1InsS_Encode<0b11101, 0b11, 0b1101, 0b1010,
|
||||
[(set SPR:$Sd, (arm_ftosi SPR:$Sm))]> {
|
||||
let Inst{7} = 1; // Z bit
|
||||
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VTOUIZD : AVConv1IsD_Encode<0b11101, 0b11, 0b1100, 0b1011,
|
||||
@ -689,9 +689,9 @@ def VTOUIZS : AVConv1InsS_Encode<0b11101, 0b11, 0b1100, 0b1010,
|
||||
[(set SPR:$Sd, (arm_ftoui SPR:$Sm))]> {
|
||||
let Inst{7} = 1; // Z bit
|
||||
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
// And the Z bit '0' variants, i.e. use the rounding mode specified by FPSCR.
|
||||
@ -743,36 +743,36 @@ def VTOSHS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 0,
|
||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
||||
IIC_fpCVTSI, "vcvt", ".s16.f32\t$dst, $a, $fbits",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VTOUHS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 0,
|
||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
||||
IIC_fpCVTSI, "vcvt", ".u16.f32\t$dst, $a, $fbits",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VTOSLS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 1,
|
||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
||||
IIC_fpCVTSI, "vcvt", ".s32.f32\t$dst, $a, $fbits",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VTOULS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 1,
|
||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
||||
IIC_fpCVTSI, "vcvt", ".u32.f32\t$dst, $a, $fbits",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VTOSHD : AVConv1XI<0b11101, 0b11, 0b1110, 0b1011, 0,
|
||||
@ -801,36 +801,36 @@ def VSHTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 0,
|
||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
||||
IIC_fpCVTIS, "vcvt", ".f32.s16\t$dst, $a, $fbits",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VUHTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 0,
|
||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
||||
IIC_fpCVTIS, "vcvt", ".f32.u16\t$dst, $a, $fbits",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VSLTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 1,
|
||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
||||
IIC_fpCVTIS, "vcvt", ".f32.s32\t$dst, $a, $fbits",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VULTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 1,
|
||||
(outs SPR:$dst), (ins SPR:$a, i32imm:$fbits),
|
||||
IIC_fpCVTIS, "vcvt", ".f32.u32\t$dst, $a, $fbits",
|
||||
[/* For disassembly only; pattern left blank */]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def VSHTOD : AVConv1XI<0b11101, 0b11, 0b1010, 0b1011, 0,
|
||||
@ -874,9 +874,9 @@ def VMLAS : ASbIn<0b11100, 0b00, 0, 0,
|
||||
SPR:$Sdin))]>,
|
||||
RegConstraint<"$Sdin = $Sd">,
|
||||
Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def : Pat<(fadd_mlx DPR:$dstin, (fmul_su DPR:$a, (f64 DPR:$b))),
|
||||
@ -901,9 +901,9 @@ def VMLSS : ASbIn<0b11100, 0b00, 1, 0,
|
||||
SPR:$Sdin))]>,
|
||||
RegConstraint<"$Sdin = $Sd">,
|
||||
Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def : Pat<(fsub_mlx DPR:$dstin, (fmul_su DPR:$a, (f64 DPR:$b))),
|
||||
@ -928,9 +928,9 @@ def VNMLAS : ASbI<0b11100, 0b01, 1, 0,
|
||||
SPR:$Sdin))]>,
|
||||
RegConstraint<"$Sdin = $Sd">,
|
||||
Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def : Pat<(fsub_mlx (fneg (fmul_su DPR:$a, (f64 DPR:$b))), DPR:$dstin),
|
||||
@ -954,9 +954,9 @@ def VNMLSS : ASbI<0b11100, 0b01, 0, 0,
|
||||
[(set SPR:$Sd, (fsub_mlx (fmul_su SPR:$Sn, SPR:$Sm), SPR:$Sdin))]>,
|
||||
RegConstraint<"$Sdin = $Sd">,
|
||||
Requires<[HasVFP2,DontUseNEONForFP,UseFPVMLx]> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
|
||||
def : Pat<(fsub_mlx (fmul_su DPR:$a, (f64 DPR:$b)), DPR:$dstin),
|
||||
@ -995,9 +995,9 @@ def VNEGScc : ASuI<0b11101, 0b11, 0b0001, 0b01, 0,
|
||||
IIC_fpUNA32, "vneg", ".f32\t$Sd, $Sm",
|
||||
[/*(set SPR:$Sd, (ARMcneg SPR:$Sn, SPR:$Sm, imm:$cc))*/]>,
|
||||
RegConstraint<"$Sn = $Sd"> {
|
||||
// Some single precision VFP instructions may be executed on both NEON and VFP
|
||||
// pipelines.
|
||||
let D = VFPNeonDomain;
|
||||
// Some single precision VFP instructions may be executed on both NEON and
|
||||
// VFP pipelines on A8.
|
||||
let D = VFPNeonA8Domain;
|
||||
}
|
||||
} // neverHasSideEffects
|
||||
|
||||
|
@ -171,7 +171,9 @@ ARMSubtarget::GVIsIndirectSymbol(const GlobalValue *GV,
|
||||
|
||||
// Materializable GVs (in JIT lazy compilation mode) do not require an extra
|
||||
// load from stub.
|
||||
bool isDecl = GV->isDeclaration() && !GV->isMaterializable();
|
||||
bool isDecl = GV->hasAvailableExternallyLinkage();
|
||||
if (GV->isDeclaration() && !GV->isMaterializable())
|
||||
isDecl = true;
|
||||
|
||||
if (!isTargetDarwin()) {
|
||||
// Extra load is needed for all externally visible.
|
||||
|
@ -132,22 +132,16 @@ unsigned MLxExpansion::getDefReg(MachineInstr *MI) const {
|
||||
}
|
||||
|
||||
bool MLxExpansion::hasRAWHazard(unsigned Reg, MachineInstr *MI) const {
|
||||
const TargetInstrDesc &TID = MI->getDesc();
|
||||
// FIXME: Detect integer instructions properly.
|
||||
const TargetInstrDesc &TID = MI->getDesc();
|
||||
unsigned Domain = TID.TSFlags & ARMII::DomainMask;
|
||||
if (Domain == ARMII::DomainVFP) {
|
||||
unsigned Opcode = TID.getOpcode();
|
||||
if (Opcode == ARM::VSTRS || Opcode == ARM::VSTRD ||
|
||||
Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
|
||||
return false;
|
||||
} else if (Domain == ARMII::DomainNEON) {
|
||||
if (TID.mayStore() || TID.mayLoad())
|
||||
return false;
|
||||
} else {
|
||||
if (TID.mayStore())
|
||||
return false;
|
||||
}
|
||||
|
||||
return MI->readsRegister(Reg, TRI);
|
||||
unsigned Opcode = TID.getOpcode();
|
||||
if (Opcode == ARM::VMOVRS || Opcode == ARM::VMOVRRD)
|
||||
return false;
|
||||
if ((Domain & ARMII::DomainVFP) || (Domain & ARMII::DomainNEON))
|
||||
return MI->readsRegister(Reg, TRI);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ namespace {
|
||||
private:
|
||||
const TargetRegisterInfo *TRI;
|
||||
const ARMBaseInstrInfo *TII;
|
||||
bool isA8;
|
||||
|
||||
typedef DenseMap<unsigned, const MachineInstr*> RegMap;
|
||||
|
||||
@ -43,6 +44,11 @@ namespace {
|
||||
char NEONMoveFixPass::ID = 0;
|
||||
}
|
||||
|
||||
static bool inNEONDomain(unsigned Domain, bool isA8) {
|
||||
return (Domain & ARMII::DomainNEON) ||
|
||||
(isA8 && (Domain & ARMII::DomainNEONA8));
|
||||
}
|
||||
|
||||
bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
|
||||
RegMap Defs;
|
||||
bool Modified = false;
|
||||
@ -70,7 +76,7 @@ bool NEONMoveFixPass::InsertMoves(MachineBasicBlock &MBB) {
|
||||
Domain = ARMII::DomainNEON;
|
||||
}
|
||||
|
||||
if (Domain & ARMII::DomainNEON) {
|
||||
if (inNEONDomain(Domain, isA8)) {
|
||||
// Convert VMOVD to VMOVDneon
|
||||
unsigned DestReg = MI->getOperand(0).getReg();
|
||||
|
||||
@ -123,6 +129,7 @@ bool NEONMoveFixPass::runOnMachineFunction(MachineFunction &Fn) {
|
||||
|
||||
TRI = TM.getRegisterInfo();
|
||||
TII = static_cast<const ARMBaseInstrInfo*>(TM.getInstrInfo());
|
||||
isA8 = TM.getSubtarget<ARMSubtarget>().isCortexA8();
|
||||
|
||||
bool Modified = false;
|
||||
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
|
||||
|
@ -95,6 +95,12 @@ Thumb2InstrInfo::ReplaceTailWithBranchTo(MachineBasicBlock::iterator Tail,
|
||||
bool
|
||||
Thumb2InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI) const {
|
||||
while (MBBI->isDebugValue()) {
|
||||
++MBBI;
|
||||
if (MBBI == MBB.end())
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned PredReg = 0;
|
||||
return llvm::getITInstrPredicate(MBBI, PredReg) == ARMCC::AL;
|
||||
}
|
||||
|
@ -48,7 +48,6 @@ AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM)
|
||||
: TargetLowering(TM, new TargetLoweringObjectFileELF()) {
|
||||
// Set up the TargetLowering object.
|
||||
//I am having problems with shr n i8 1
|
||||
setShiftAmountType(MVT::i64);
|
||||
setBooleanContents(ZeroOrOneBooleanContent);
|
||||
|
||||
addRegisterClass(MVT::i64, Alpha::GPRCRegisterClass);
|
||||
|
@ -31,25 +31,25 @@ namespace llvm {
|
||||
|
||||
/// GPRelHi/GPRelLo - These represent the high and low 16-bit
|
||||
/// parts of a global address respectively.
|
||||
GPRelHi, GPRelLo,
|
||||
GPRelHi, GPRelLo,
|
||||
|
||||
/// RetLit - Literal Relocation of a Global
|
||||
RelLit,
|
||||
|
||||
/// GlobalRetAddr - used to restore the return address
|
||||
GlobalRetAddr,
|
||||
|
||||
|
||||
/// CALL - Normal call.
|
||||
CALL,
|
||||
|
||||
/// DIVCALL - used for special library calls for div and rem
|
||||
DivCall,
|
||||
|
||||
|
||||
/// return flag operand
|
||||
RET_FLAG,
|
||||
|
||||
/// CHAIN = COND_BRANCH CHAIN, OPC, (G|F)PRC, DESTBB [, INFLAG] - This
|
||||
/// corresponds to the COND_BRANCH pseudo instruction.
|
||||
/// corresponds to the COND_BRANCH pseudo instruction.
|
||||
/// *PRC is the input register to compare to zero,
|
||||
/// OPC is the branch opcode to use (e.g. Alpha::BEQ),
|
||||
/// DESTBB is the destination block to branch to, and INFLAG is
|
||||
@ -62,7 +62,9 @@ namespace llvm {
|
||||
class AlphaTargetLowering : public TargetLowering {
|
||||
public:
|
||||
explicit AlphaTargetLowering(TargetMachine &TM);
|
||||
|
||||
|
||||
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i64; }
|
||||
|
||||
/// getSetCCResultType - Get the SETCC result ValueType
|
||||
virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
|
||||
|
||||
@ -92,7 +94,7 @@ namespace llvm {
|
||||
ConstraintWeight getSingleConstraintMatchWeight(
|
||||
AsmOperandInfo &info, const char *constraint) const;
|
||||
|
||||
std::vector<unsigned>
|
||||
std::vector<unsigned>
|
||||
getRegClassForInlineAsmConstraint(const std::string &Constraint,
|
||||
EVT VT) const;
|
||||
|
||||
|
@ -41,7 +41,6 @@ using namespace llvm;
|
||||
|
||||
BlackfinTargetLowering::BlackfinTargetLowering(TargetMachine &TM)
|
||||
: TargetLowering(TM, new TargetLoweringObjectFileELF()) {
|
||||
setShiftAmountType(MVT::i16);
|
||||
setBooleanContents(ZeroOrOneBooleanContent);
|
||||
setStackPointerRegisterToSaveRestore(BF::SP);
|
||||
setIntDivIsCheap(false);
|
||||
|
@ -32,6 +32,7 @@ namespace llvm {
|
||||
class BlackfinTargetLowering : public TargetLowering {
|
||||
public:
|
||||
BlackfinTargetLowering(TargetMachine &TM);
|
||||
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i16; }
|
||||
virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
|
||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
||||
virtual void ReplaceNodeResults(SDNode *N,
|
||||
|
@ -435,7 +435,6 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
|
||||
|
||||
setOperationAction(ISD::FDIV, MVT::v4f32, Legal);
|
||||
|
||||
setShiftAmountType(MVT::i32);
|
||||
setBooleanContents(ZeroOrNegativeOneBooleanContent);
|
||||
|
||||
setStackPointerRegisterToSaveRestore(SPU::R1);
|
||||
@ -1219,7 +1218,7 @@ SPUTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
FuncInfo->setVarArgsFrameIndex(
|
||||
MFI->CreateFixedObject(StackSlotSize, ArgOffset, true));
|
||||
SDValue FIN = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT);
|
||||
unsigned VReg = MF.addLiveIn(ArgRegs[ArgRegIdx], &SPU::R32CRegClass, dl);
|
||||
unsigned VReg = MF.addLiveIn(ArgRegs[ArgRegIdx], &SPU::R32CRegClass);
|
||||
SDValue ArgVal = DAG.getRegister(VReg, MVT::v16i8);
|
||||
SDValue Store = DAG.getStore(Chain, dl, ArgVal, FIN, MachinePointerInfo(),
|
||||
false, false, 0);
|
||||
@ -2190,7 +2189,7 @@ static SDValue LowerI8Math(SDValue Op, SelectionDAG &DAG, unsigned Opc,
|
||||
{
|
||||
SDValue N0 = Op.getOperand(0); // Everything has at least one operand
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
EVT ShiftVT = TLI.getShiftAmountTy();
|
||||
EVT ShiftVT = TLI.getShiftAmountTy(N0.getValueType());
|
||||
|
||||
assert(Op.getValueType() == MVT::i8);
|
||||
switch (Opc) {
|
||||
@ -3112,7 +3111,7 @@ SPUTargetLowering::getSingleConstraintMatchWeight(
|
||||
switch (*constraint) {
|
||||
default:
|
||||
weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
|
||||
break;
|
||||
break;
|
||||
//FIXME: Seems like the supported constraint letters were just copied
|
||||
// from PPC, as the following doesn't correspond to the GCC docs.
|
||||
// I'm leaving it so until someone adds the corresponding lowering support.
|
||||
|
@ -109,6 +109,8 @@ namespace llvm {
|
||||
/// getSetCCResultType - Return the ValueType for ISD::SETCC
|
||||
virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
|
||||
|
||||
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; }
|
||||
|
||||
//! Custom lowering hooks
|
||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
@ -179,9 +181,9 @@ namespace llvm {
|
||||
|
||||
virtual bool isLegalICmpImmediate(int64_t Imm) const;
|
||||
|
||||
virtual bool isLegalAddressingMode(const AddrMode &AM,
|
||||
virtual bool isLegalAddressingMode(const AddrMode &AM,
|
||||
const Type *Ty) const;
|
||||
|
||||
|
||||
/// After allocating this many registers, the allocator should feel
|
||||
/// register pressure. The value is a somewhat random guess, based on the
|
||||
/// number of non callee saved registers in the C calling convention.
|
||||
|
@ -907,7 +907,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
|
||||
|
||||
// Transform the arguments stored on
|
||||
// physical registers into virtual ones
|
||||
unsigned Reg = MF.addLiveIn(ArgRegEnd, RC, dl);
|
||||
unsigned Reg = MF.addLiveIn(ArgRegEnd, RC);
|
||||
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
|
||||
|
||||
// If this is an 8 or 16-bit value, it has been passed promoted
|
||||
@ -973,7 +973,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
|
||||
|
||||
for (; Start <= End; ++Start, ++StackLoc) {
|
||||
unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start);
|
||||
unsigned LiveReg = MF.addLiveIn(Reg, RC, dl);
|
||||
unsigned LiveReg = MF.addLiveIn(Reg, RC);
|
||||
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32);
|
||||
|
||||
int FI = MFI->CreateFixedObject(4, 0, true);
|
||||
|
@ -77,10 +77,6 @@ MSP430TargetLowering::MSP430TargetLowering(MSP430TargetMachine &tm) :
|
||||
// Division is expensive
|
||||
setIntDivIsCheap(false);
|
||||
|
||||
// Even if we have only 1 bit shift here, we can perform
|
||||
// shifts of the whole bitwidth 1 bit per step.
|
||||
setShiftAmountType(MVT::i8);
|
||||
|
||||
setStackPointerRegisterToSaveRestore(MSP430::SPW);
|
||||
setBooleanContents(ZeroOrOneBooleanContent);
|
||||
setSchedulingPreference(Sched::Latency);
|
||||
@ -330,7 +326,7 @@ MSP430TargetLowering::LowerCCCArguments(SDValue Chain,
|
||||
// Arguments passed in registers
|
||||
EVT RegVT = VA.getLocVT();
|
||||
switch (RegVT.getSimpleVT().SimpleTy) {
|
||||
default:
|
||||
default:
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
errs() << "LowerFormalArguments Unhandled argument type: "
|
||||
|
@ -73,6 +73,8 @@ namespace llvm {
|
||||
public:
|
||||
explicit MSP430TargetLowering(MSP430TargetMachine &TM);
|
||||
|
||||
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i8; }
|
||||
|
||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
|
@ -362,7 +362,6 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
|
||||
setOperationAction(ISD::BUILD_VECTOR, MVT::v4f32, Custom);
|
||||
}
|
||||
|
||||
setShiftAmountType(MVT::i32);
|
||||
setBooleanContents(ZeroOrOneBooleanContent);
|
||||
|
||||
if (TM.getSubtarget<PPCSubtarget>().isPPC64()) {
|
||||
@ -1597,7 +1596,7 @@ PPCTargetLowering::LowerFormalArguments_SVR4(
|
||||
}
|
||||
|
||||
// Transform the arguments stored in physical registers into virtual ones.
|
||||
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl);
|
||||
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
|
||||
SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, ValVT);
|
||||
|
||||
InVals.push_back(ArgValue);
|
||||
@ -1689,7 +1688,7 @@ PPCTargetLowering::LowerFormalArguments_SVR4(
|
||||
// Get an existing live-in vreg, or add a new one.
|
||||
unsigned VReg = MF.getRegInfo().getLiveInVirtReg(GPArgRegs[GPRIndex]);
|
||||
if (!VReg)
|
||||
VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass, dl);
|
||||
VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass);
|
||||
|
||||
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
|
||||
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN,
|
||||
@ -1708,7 +1707,7 @@ PPCTargetLowering::LowerFormalArguments_SVR4(
|
||||
// Get an existing live-in vreg, or add a new one.
|
||||
unsigned VReg = MF.getRegInfo().getLiveInVirtReg(FPArgRegs[FPRIndex]);
|
||||
if (!VReg)
|
||||
VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass, dl);
|
||||
VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass);
|
||||
|
||||
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::f64);
|
||||
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN,
|
||||
@ -1872,7 +1871,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
|
||||
InVals.push_back(FIN);
|
||||
if (ObjSize==1 || ObjSize==2) {
|
||||
if (GPR_idx != Num_GPR_Regs) {
|
||||
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl);
|
||||
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
|
||||
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
|
||||
SDValue Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN,
|
||||
MachinePointerInfo(),
|
||||
@ -1891,7 +1890,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
|
||||
// to memory. ArgVal will be address of the beginning of
|
||||
// the object.
|
||||
if (GPR_idx != Num_GPR_Regs) {
|
||||
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl);
|
||||
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
|
||||
int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset, true);
|
||||
SDValue FIN = DAG.getFrameIndex(FI, PtrVT);
|
||||
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
|
||||
@ -1914,7 +1913,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
|
||||
case MVT::i32:
|
||||
if (!isPPC64) {
|
||||
if (GPR_idx != Num_GPR_Regs) {
|
||||
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl);
|
||||
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
|
||||
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32);
|
||||
++GPR_idx;
|
||||
} else {
|
||||
@ -1928,7 +1927,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
|
||||
// FALLTHROUGH
|
||||
case MVT::i64: // PPC64
|
||||
if (GPR_idx != Num_GPR_Regs) {
|
||||
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass, dl);
|
||||
unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass);
|
||||
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64);
|
||||
|
||||
if (ObjectVT == MVT::i32) {
|
||||
@ -1966,9 +1965,9 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
|
||||
unsigned VReg;
|
||||
|
||||
if (ObjectVT == MVT::f32)
|
||||
VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F4RCRegClass, dl);
|
||||
VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F4RCRegClass);
|
||||
else
|
||||
VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F8RCRegClass, dl);
|
||||
VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F8RCRegClass);
|
||||
|
||||
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT);
|
||||
++FPR_idx;
|
||||
@ -1986,7 +1985,7 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
|
||||
// Note that vector arguments in registers don't reserve stack space,
|
||||
// except in varargs functions.
|
||||
if (VR_idx != Num_VR_Regs) {
|
||||
unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass, dl);
|
||||
unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass);
|
||||
ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT);
|
||||
if (isVarArg) {
|
||||
while ((ArgOffset % 16) != 0) {
|
||||
@ -2064,9 +2063,9 @@ PPCTargetLowering::LowerFormalArguments_Darwin(
|
||||
unsigned VReg;
|
||||
|
||||
if (isPPC64)
|
||||
VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass, dl);
|
||||
VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass);
|
||||
else
|
||||
VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass, dl);
|
||||
VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass);
|
||||
|
||||
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT);
|
||||
SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN,
|
||||
|
@ -29,36 +29,36 @@ namespace llvm {
|
||||
/// FSEL - Traditional three-operand fsel node.
|
||||
///
|
||||
FSEL,
|
||||
|
||||
|
||||
/// FCFID - The FCFID instruction, taking an f64 operand and producing
|
||||
/// and f64 value containing the FP representation of the integer that
|
||||
/// was temporarily in the f64 operand.
|
||||
FCFID,
|
||||
|
||||
/// FCTI[D,W]Z - The FCTIDZ and FCTIWZ instructions, taking an f32 or f64
|
||||
|
||||
/// FCTI[D,W]Z - The FCTIDZ and FCTIWZ instructions, taking an f32 or f64
|
||||
/// operand, producing an f64 value containing the integer representation
|
||||
/// of that FP value.
|
||||
FCTIDZ, FCTIWZ,
|
||||
|
||||
|
||||
/// STFIWX - The STFIWX instruction. The first operand is an input token
|
||||
/// chain, then an f64 value to store, then an address to store it to.
|
||||
STFIWX,
|
||||
|
||||
|
||||
// VMADDFP, VNMSUBFP - The VMADDFP and VNMSUBFP instructions, taking
|
||||
// three v4f32 operands and producing a v4f32 result.
|
||||
VMADDFP, VNMSUBFP,
|
||||
|
||||
|
||||
/// VPERM - The PPC VPERM Instruction.
|
||||
///
|
||||
VPERM,
|
||||
|
||||
|
||||
/// Hi/Lo - These represent the high and low 16-bit parts of a global
|
||||
/// address respectively. These nodes have two operands, the first of
|
||||
/// which must be a TargetGlobalAddress, and the second of which must be a
|
||||
/// Constant. Selected naively, these turn into 'lis G+C' and 'li G+C',
|
||||
/// though these are usually folded into other nodes.
|
||||
Hi, Lo,
|
||||
|
||||
|
||||
TOC_ENTRY,
|
||||
|
||||
/// The following three target-specific nodes are used for calls through
|
||||
@ -80,37 +80,37 @@ namespace llvm {
|
||||
/// This instruction is lowered in PPCRegisterInfo::eliminateFrameIndex to
|
||||
/// compute an allocation on the stack.
|
||||
DYNALLOC,
|
||||
|
||||
|
||||
/// GlobalBaseReg - On Darwin, this node represents the result of the mflr
|
||||
/// at function entry, used for PIC code.
|
||||
GlobalBaseReg,
|
||||
|
||||
|
||||
/// These nodes represent the 32-bit PPC shifts that operate on 6-bit
|
||||
/// shift amounts. These nodes are generated by the multi-precision shift
|
||||
/// code.
|
||||
SRL, SRA, SHL,
|
||||
|
||||
|
||||
/// EXTSW_32 - This is the EXTSW instruction for use with "32-bit"
|
||||
/// registers.
|
||||
EXTSW_32,
|
||||
|
||||
/// CALL - A direct function call.
|
||||
CALL_Darwin, CALL_SVR4,
|
||||
|
||||
|
||||
/// NOP - Special NOP which follows 64-bit SVR4 calls.
|
||||
NOP,
|
||||
|
||||
/// CHAIN,FLAG = MTCTR(VAL, CHAIN[, INFLAG]) - Directly corresponds to a
|
||||
/// MTCTR instruction.
|
||||
MTCTR,
|
||||
|
||||
|
||||
/// CHAIN,FLAG = BCTRL(CHAIN, INFLAG) - Directly corresponds to a
|
||||
/// BCTRL instruction.
|
||||
BCTRL_Darwin, BCTRL_SVR4,
|
||||
|
||||
|
||||
/// Return with a flag operand, matched by 'blr'
|
||||
RET_FLAG,
|
||||
|
||||
|
||||
/// R32 = MFCR(CRREG, INFLAG) - Represents the MFCRpseud/MFOCRF
|
||||
/// instructions. This copies the bits corresponding to the specified
|
||||
/// CRREG into the resultant GPR. Bits corresponding to other CR regs
|
||||
@ -122,20 +122,20 @@ namespace llvm {
|
||||
/// encoding for the OPC field to identify the compare. For example, 838
|
||||
/// is VCMPGTSH.
|
||||
VCMP,
|
||||
|
||||
|
||||
/// RESVEC, OUTFLAG = VCMPo(LHS, RHS, OPC) - Represents one of the
|
||||
/// altivec VCMP*o instructions. For lack of better number, we use the
|
||||
/// altivec VCMP*o instructions. For lack of better number, we use the
|
||||
/// opcode number encoding for the OPC field to identify the compare. For
|
||||
/// example, 838 is VCMPGTSH.
|
||||
VCMPo,
|
||||
|
||||
|
||||
/// CHAIN = COND_BRANCH CHAIN, CRRC, OPC, DESTBB [, INFLAG] - This
|
||||
/// corresponds to the COND_BRANCH pseudo instruction. CRRC is the
|
||||
/// condition register to branch on, OPC is the branch opcode to use (e.g.
|
||||
/// PPC::BLE), DESTBB is the destination block to branch to, and INFLAG is
|
||||
/// an optional input flag argument.
|
||||
COND_BRANCH,
|
||||
|
||||
|
||||
// The following 5 instructions are used only as part of the
|
||||
// long double-to-int conversion sequence.
|
||||
|
||||
@ -150,7 +150,7 @@ namespace llvm {
|
||||
MTFSB1,
|
||||
|
||||
/// F8RC, OUTFLAG = FADDRTZ F8RC, F8RC, INFLAG - This is an FADD done with
|
||||
/// rounding towards zero. It has flags added so it won't move past the
|
||||
/// rounding towards zero. It has flags added so it won't move past the
|
||||
/// FPSCR-setting instructions.
|
||||
FADDRTZ,
|
||||
|
||||
@ -174,14 +174,14 @@ namespace llvm {
|
||||
|
||||
/// STD_32 - This is the STD instruction for use with "32-bit" registers.
|
||||
STD_32 = ISD::FIRST_TARGET_MEMORY_OPCODE,
|
||||
|
||||
/// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a
|
||||
|
||||
/// CHAIN = STBRX CHAIN, GPRC, Ptr, Type - This is a
|
||||
/// byte-swapping store instruction. It byte-swaps the low "Type" bits of
|
||||
/// the GPRC input, then stores it through Ptr. Type can be either i16 or
|
||||
/// i32.
|
||||
STBRX,
|
||||
|
||||
/// GPRC, CHAIN = LBRX CHAIN, Ptr, Type - This is a
|
||||
STBRX,
|
||||
|
||||
/// GPRC, CHAIN = LBRX CHAIN, Ptr, Type - This is a
|
||||
/// byte-swapping load instruction. It loads "Type" bits, byte swaps it,
|
||||
/// then puts it in the bottom bits of the GPRC. TYPE can be either i16
|
||||
/// or i32.
|
||||
@ -194,7 +194,7 @@ namespace llvm {
|
||||
/// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a
|
||||
/// VPKUHUM instruction.
|
||||
bool isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary);
|
||||
|
||||
|
||||
/// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a
|
||||
/// VPKUWUM instruction.
|
||||
bool isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary);
|
||||
@ -208,16 +208,16 @@ namespace llvm {
|
||||
/// a VRGH* instruction with the specified unit size (1,2 or 4 bytes).
|
||||
bool isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize,
|
||||
bool isUnary);
|
||||
|
||||
|
||||
/// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift
|
||||
/// amount, otherwise return -1.
|
||||
int isVSLDOIShuffleMask(SDNode *N, bool isUnary);
|
||||
|
||||
|
||||
/// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||
/// specifies a splat of a single element that is suitable for input to
|
||||
/// VSPLTB/VSPLTH/VSPLTW.
|
||||
bool isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize);
|
||||
|
||||
|
||||
/// isAllNegativeZeroVector - Returns true if all elements of build_vector
|
||||
/// are -0.0.
|
||||
bool isAllNegativeZeroVector(SDNode *N);
|
||||
@ -225,24 +225,26 @@ namespace llvm {
|
||||
/// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the
|
||||
/// specified isSplatShuffleMask VECTOR_SHUFFLE mask.
|
||||
unsigned getVSPLTImmediate(SDNode *N, unsigned EltSize);
|
||||
|
||||
|
||||
/// get_VSPLTI_elt - If this is a build_vector of constants which can be
|
||||
/// formed by using a vspltis[bhw] instruction of the specified element
|
||||
/// size, return the constant being splatted. The ByteSize field indicates
|
||||
/// the number of bytes of each element [124] -> [bhw].
|
||||
SDValue get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG);
|
||||
}
|
||||
|
||||
|
||||
class PPCTargetLowering : public TargetLowering {
|
||||
const PPCSubtarget &PPCSubTarget;
|
||||
|
||||
public:
|
||||
explicit PPCTargetLowering(PPCTargetMachine &TM);
|
||||
|
||||
|
||||
/// getTargetNodeName() - This method returns the name of a target specific
|
||||
/// DAG node.
|
||||
virtual const char *getTargetNodeName(unsigned Opcode) const;
|
||||
|
||||
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i32; }
|
||||
|
||||
/// getSetCCResultType - Return the ISD::SETCC ValueType
|
||||
virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const;
|
||||
|
||||
@ -253,19 +255,19 @@ namespace llvm {
|
||||
SDValue &Offset,
|
||||
ISD::MemIndexedMode &AM,
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
|
||||
/// SelectAddressRegReg - Given the specified addressed, check to see if it
|
||||
/// can be represented as an indexed [r+r] operation. Returns false if it
|
||||
/// can be more efficiently represented with [r+imm].
|
||||
bool SelectAddressRegReg(SDValue N, SDValue &Base, SDValue &Index,
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
|
||||
/// SelectAddressRegImm - Returns true if the address N can be represented
|
||||
/// by a base register plus a signed 16-bit displacement [r+imm], and if it
|
||||
/// is not better represented as reg+reg.
|
||||
bool SelectAddressRegImm(SDValue N, SDValue &Disp, SDValue &Base,
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
|
||||
/// SelectAddressRegRegOnly - Given the specified addressed, force it to be
|
||||
/// represented as an indexed [r+r] operation.
|
||||
bool SelectAddressRegRegOnly(SDValue N, SDValue &Base, SDValue &Index,
|
||||
@ -277,7 +279,7 @@ namespace llvm {
|
||||
bool SelectAddressRegImmShift(SDValue N, SDValue &Disp, SDValue &Base,
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
|
||||
|
||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||
///
|
||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
||||
@ -289,10 +291,10 @@ namespace llvm {
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||
|
||||
|
||||
virtual void computeMaskedBitsForTargetNode(const SDValue Op,
|
||||
const APInt &Mask,
|
||||
APInt &KnownZero,
|
||||
APInt &KnownZero,
|
||||
APInt &KnownOne,
|
||||
const SelectionDAG &DAG,
|
||||
unsigned Depth = 0) const;
|
||||
@ -300,13 +302,13 @@ namespace llvm {
|
||||
virtual MachineBasicBlock *
|
||||
EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
MachineBasicBlock *MBB) const;
|
||||
MachineBasicBlock *EmitAtomicBinary(MachineInstr *MI,
|
||||
MachineBasicBlock *EmitAtomicBinary(MachineInstr *MI,
|
||||
MachineBasicBlock *MBB, bool is64Bit,
|
||||
unsigned BinOpcode) const;
|
||||
MachineBasicBlock *EmitPartwordAtomicBinary(MachineInstr *MI,
|
||||
MachineBasicBlock *MBB,
|
||||
MachineBasicBlock *EmitPartwordAtomicBinary(MachineInstr *MI,
|
||||
MachineBasicBlock *MBB,
|
||||
bool is8bit, unsigned Opcode) const;
|
||||
|
||||
|
||||
ConstraintType getConstraintType(const std::string &Constraint) const;
|
||||
|
||||
/// Examine constraint string and operand type and determine a weight value.
|
||||
@ -314,7 +316,7 @@ namespace llvm {
|
||||
ConstraintWeight getSingleConstraintMatchWeight(
|
||||
AsmOperandInfo &info, const char *constraint) const;
|
||||
|
||||
std::pair<unsigned, const TargetRegisterClass*>
|
||||
std::pair<unsigned, const TargetRegisterClass*>
|
||||
getRegForInlineAsmConstraint(const std::string &Constraint,
|
||||
EVT VT) const;
|
||||
|
||||
@ -329,11 +331,11 @@ namespace llvm {
|
||||
char ConstraintLetter,
|
||||
std::vector<SDValue> &Ops,
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
|
||||
/// isLegalAddressingMode - Return true if the addressing mode represented
|
||||
/// by AM is legal for this target, for a load/store of the specified type.
|
||||
virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty)const;
|
||||
|
||||
|
||||
/// isLegalAddressImmediate - Return true if the integer value can be used
|
||||
/// as the offset of the target addressing mode for load / store of the
|
||||
/// given type.
|
||||
@ -344,7 +346,7 @@ namespace llvm {
|
||||
virtual bool isLegalAddressImmediate(GlobalValue *GV) const;
|
||||
|
||||
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
|
||||
|
||||
|
||||
/// getOptimalMemOpType - Returns the target specific optimal type for load
|
||||
/// and store operations as a result of memset, memcpy, and memmove
|
||||
/// lowering. If DstAlign is zero that means it's safe to destination
|
||||
|
@ -254,6 +254,20 @@ unsigned long reverse(unsigned v) {
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
[LOOP DELETION]
|
||||
|
||||
We don't delete this output free loop, because trip count analysis doesn't
|
||||
realize that it is finite (if it were infinite, it would be undefined). Not
|
||||
having this blocks Loop Idiom from matching strlen and friends.
|
||||
|
||||
void foo(char *C) {
|
||||
int x = 0;
|
||||
while (*C)
|
||||
++x,++C;
|
||||
}
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
[LOOP RECOGNITION]
|
||||
|
||||
These idioms should be recognized as popcount (see PR1488):
|
||||
@ -287,6 +301,16 @@ unsigned int popcount(unsigned int input) {
|
||||
return count;
|
||||
}
|
||||
|
||||
This should be recognized as CLZ: rdar://8459039
|
||||
|
||||
unsigned clz_a(unsigned a) {
|
||||
int i;
|
||||
for (i=0;i<32;i++)
|
||||
if (a & (1<<(31-i)))
|
||||
return i;
|
||||
return 32;
|
||||
}
|
||||
|
||||
This sort of thing should be added to the loop idiom pass.
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
@ -79,6 +79,7 @@ namespace {
|
||||
MachineBasicBlock::iterator
|
||||
findDelayInstr(MachineBasicBlock &MBB, MachineBasicBlock::iterator slot);
|
||||
|
||||
bool needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize);
|
||||
|
||||
};
|
||||
char Filler::ID = 0;
|
||||
@ -91,6 +92,7 @@ FunctionPass *llvm::createSparcDelaySlotFillerPass(TargetMachine &tm) {
|
||||
return new Filler(tm);
|
||||
}
|
||||
|
||||
|
||||
/// runOnMachineBasicBlock - Fill in delay slots for the given basic block.
|
||||
/// We assume there is only one delay slot per delayed instruction.
|
||||
///
|
||||
@ -112,6 +114,13 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
|
||||
BuildMI(MBB, ++J, I->getDebugLoc(), TII->get(SP::NOP));
|
||||
else
|
||||
MBB.splice(++J, &MBB, D);
|
||||
unsigned structSize = 0;
|
||||
if (needsUnimp(I, structSize)) {
|
||||
MachineBasicBlock::iterator J = I;
|
||||
++J; //skip the delay filler.
|
||||
BuildMI(MBB, ++J, I->getDebugLoc(),
|
||||
TII->get(SP::UNIMP)).addImm(structSize);
|
||||
}
|
||||
}
|
||||
return Changed;
|
||||
}
|
||||
@ -287,6 +296,28 @@ bool Filler::isDelayFiller(MachineBasicBlock &MBB,
|
||||
{
|
||||
if (candidate == MBB.begin())
|
||||
return false;
|
||||
if (candidate->getOpcode() == SP::UNIMP)
|
||||
return true;
|
||||
const TargetInstrDesc &prevdesc = (--candidate)->getDesc();
|
||||
return prevdesc.hasDelaySlot();
|
||||
}
|
||||
|
||||
bool Filler::needsUnimp(MachineBasicBlock::iterator I, unsigned &StructSize)
|
||||
{
|
||||
if (!I->getDesc().isCall())
|
||||
return false;
|
||||
|
||||
unsigned structSizeOpNum = 0;
|
||||
switch (I->getOpcode()) {
|
||||
default: llvm_unreachable("Unknown call opcode.");
|
||||
case SP::CALL: structSizeOpNum = 1; break;
|
||||
case SP::JMPLrr:
|
||||
case SP::JMPLri: structSizeOpNum = 2; break;
|
||||
}
|
||||
|
||||
const MachineOperand &MO = I->getOperand(structSizeOpNum);
|
||||
if (!MO.isImm())
|
||||
return false;
|
||||
StructSize = MO.getImm();
|
||||
return true;
|
||||
}
|
||||
|
@ -16,7 +16,9 @@
|
||||
#include "SparcISelLowering.h"
|
||||
#include "SparcTargetMachine.h"
|
||||
#include "SparcMachineFunctionInfo.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/CodeGen/CallingConvLower.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
@ -116,6 +118,8 @@ SparcTargetLowering::LowerReturn(SDValue Chain,
|
||||
// Guarantee that all emitted copies are stuck together with flags.
|
||||
Flag = Chain.getValue(1);
|
||||
}
|
||||
|
||||
unsigned RetAddrOffset = 8; //Call Inst + Delay Slot
|
||||
// If the function returns a struct, copy the SRetReturnReg to I0
|
||||
if (MF.getFunction()->hasStructRetAttr()) {
|
||||
SparcMachineFunctionInfo *SFI = MF.getInfo<SparcMachineFunctionInfo>();
|
||||
@ -127,11 +131,16 @@ SparcTargetLowering::LowerReturn(SDValue Chain,
|
||||
Flag = Chain.getValue(1);
|
||||
if (MF.getRegInfo().liveout_empty())
|
||||
MF.getRegInfo().addLiveOut(SP::I0);
|
||||
RetAddrOffset = 12; // CallInst + Delay Slot + Unimp
|
||||
}
|
||||
|
||||
SDValue RetAddrOffsetNode = DAG.getConstant(RetAddrOffset, MVT::i32);
|
||||
|
||||
if (Flag.getNode())
|
||||
return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain, Flag);
|
||||
return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain);
|
||||
return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain,
|
||||
RetAddrOffsetNode, Flag);
|
||||
return DAG.getNode(SPISD::RET_FLAG, dl, MVT::Other, Chain,
|
||||
RetAddrOffsetNode);
|
||||
}
|
||||
|
||||
/// LowerFormalArguments - V8 uses a very simple ABI, where all values are
|
||||
@ -194,7 +203,7 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
false, false, 0);
|
||||
} else {
|
||||
unsigned loReg = MF.addLiveIn(NextVA.getLocReg(),
|
||||
&SP::IntRegsRegClass, dl);
|
||||
&SP::IntRegsRegClass);
|
||||
LoVal = DAG.getCopyFromReg(Chain, dl, loReg, MVT::i32);
|
||||
}
|
||||
SDValue WholeValue =
|
||||
@ -393,6 +402,7 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
||||
SmallVector<SDValue, 8> MemOpChains;
|
||||
|
||||
const unsigned StackOffset = 92;
|
||||
bool hasStructRetAttr = false;
|
||||
// Walk the register/memloc assignments, inserting copies/loads.
|
||||
for (unsigned i = 0, realArgIdx = 0, byvalArgIdx = 0, e = ArgLocs.size();
|
||||
i != e;
|
||||
@ -433,6 +443,7 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
||||
MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
|
||||
MachinePointerInfo(),
|
||||
false, false, 0));
|
||||
hasStructRetAttr = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -546,6 +557,8 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
||||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
|
||||
unsigned SRetArgSize = (hasStructRetAttr)? getSRetArgSize(DAG, Callee):0;
|
||||
|
||||
// If the callee is a GlobalAddress node (quite common, every direct call is)
|
||||
// turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
|
||||
// Likewise ExternalSymbol -> TargetExternalSymbol.
|
||||
@ -559,6 +572,8 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
||||
SmallVector<SDValue, 8> Ops;
|
||||
Ops.push_back(Chain);
|
||||
Ops.push_back(Callee);
|
||||
if (hasStructRetAttr)
|
||||
Ops.push_back(DAG.getTargetConstant(SRetArgSize, MVT::i32));
|
||||
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
|
||||
unsigned Reg = RegsToPass[i].first;
|
||||
if (Reg >= SP::I0 && Reg <= SP::I7)
|
||||
@ -600,7 +615,29 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
|
||||
return Chain;
|
||||
}
|
||||
|
||||
unsigned
|
||||
SparcTargetLowering::getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const
|
||||
{
|
||||
const Function *CalleeFn = 0;
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
||||
CalleeFn = dyn_cast<Function>(G->getGlobal());
|
||||
} else if (ExternalSymbolSDNode *E =
|
||||
dyn_cast<ExternalSymbolSDNode>(Callee)) {
|
||||
const Function *Fn = DAG.getMachineFunction().getFunction();
|
||||
const Module *M = Fn->getParent();
|
||||
CalleeFn = M->getFunction(E->getSymbol());
|
||||
}
|
||||
|
||||
if (!CalleeFn)
|
||||
return 0;
|
||||
|
||||
assert(CalleeFn->hasStructRetAttr() &&
|
||||
"Callee does not have the StructRet attribute.");
|
||||
|
||||
const PointerType *Ty = cast<PointerType>(CalleeFn->arg_begin()->getType());
|
||||
const Type *ElementTy = Ty->getElementType();
|
||||
return getTargetData()->getTypeAllocSize(ElementTy);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TargetLowering Implementation
|
||||
|
@ -101,6 +101,8 @@ namespace llvm {
|
||||
|
||||
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
unsigned getSRetArgSize(SelectionDAG &DAG, SDValue Callee) const;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -124,7 +124,8 @@ def call : SDNode<"SPISD::CALL", SDT_SPCall,
|
||||
[SDNPHasChain, SDNPOptInGlue, SDNPOutGlue,
|
||||
SDNPVariadic]>;
|
||||
|
||||
def retflag : SDNode<"SPISD::RET_FLAG", SDTNone,
|
||||
def SDT_SPRet : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
|
||||
def retflag : SDNode<"SPISD::RET_FLAG", SDT_SPRet,
|
||||
[SDNPHasChain, SDNPOptInGlue]>;
|
||||
|
||||
def flushw : SDNode<"SPISD::FLUSHW", SDTNone,
|
||||
@ -132,7 +133,7 @@ def flushw : SDNode<"SPISD::FLUSHW", SDTNone,
|
||||
|
||||
def getPCX : Operand<i32> {
|
||||
let PrintMethod = "printGetPCX";
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SPARC Flag Conditions
|
||||
@ -232,6 +233,9 @@ let hasSideEffects = 1, mayStore = 1 in {
|
||||
[(flushw)]>;
|
||||
}
|
||||
|
||||
def UNIMP : F2_1<0b000, (outs), (ins i32imm:$val),
|
||||
"unimp $val", []>;
|
||||
|
||||
// FpMOVD/FpNEGD/FpABSD - These are lowered to single-precision ops by the
|
||||
// fpmover pass.
|
||||
let Predicates = [HasNoV9] in { // Only emit these in V8 mode.
|
||||
@ -292,11 +296,13 @@ let usesCustomInserter = 1, Uses = [FCC] in {
|
||||
// Section A.3 - Synthetic Instructions, p. 85
|
||||
// special cases of JMPL:
|
||||
let isReturn = 1, isTerminator = 1, hasDelaySlot = 1, isBarrier = 1 in {
|
||||
let rd = O7.Num, rs1 = G0.Num, simm13 = 8 in
|
||||
def RETL: F3_2<2, 0b111000, (outs), (ins), "retl", [(retflag)]>;
|
||||
let rd = O7.Num, rs1 = G0.Num in
|
||||
def RETL: F3_2<2, 0b111000, (outs), (ins i32imm:$val),
|
||||
"jmp %o7+$val", [(retflag simm13:$val)]>;
|
||||
|
||||
let rd = I7.Num, rs1 = G0.Num, simm13 = 8 in
|
||||
def RET: F3_2<2, 0b111000, (outs), (ins), "ret", []>;
|
||||
let rd = I7.Num, rs1 = G0.Num in
|
||||
def RET: F3_2<2, 0b111000, (outs), (ins i32imm:$val),
|
||||
"jmp %i7+$val", []>;
|
||||
}
|
||||
|
||||
// Section B.1 - Load Integer Instructions, p. 90
|
||||
|
@ -59,9 +59,6 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) :
|
||||
// Compute derived properties from the register classes
|
||||
computeRegisterProperties();
|
||||
|
||||
// Set shifts properties
|
||||
setShiftAmountType(MVT::i64);
|
||||
|
||||
// Provide all sorts of operation actions
|
||||
setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote);
|
||||
setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote);
|
||||
|
@ -57,6 +57,8 @@ namespace llvm {
|
||||
public:
|
||||
explicit SystemZTargetLowering(SystemZTargetMachine &TM);
|
||||
|
||||
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i64; }
|
||||
|
||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
|
@ -775,6 +775,19 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
|
||||
delete &Op;
|
||||
}
|
||||
}
|
||||
// Same hack for "in[bwl]? (%dx), %al" -> "inb %dx, %al".
|
||||
if ((Name == "inb" || Name == "inw" || Name == "inl" || Name == "in") &&
|
||||
Operands.size() == 3) {
|
||||
X86Operand &Op = *(X86Operand*)Operands.begin()[1];
|
||||
if (Op.isMem() && Op.Mem.SegReg == 0 &&
|
||||
isa<MCConstantExpr>(Op.Mem.Disp) &&
|
||||
cast<MCConstantExpr>(Op.Mem.Disp)->getValue() == 0 &&
|
||||
Op.Mem.BaseReg == MatchRegisterName("dx") && Op.Mem.IndexReg == 0) {
|
||||
SMLoc Loc = Op.getEndLoc();
|
||||
Operands.begin()[1] = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc);
|
||||
delete &Op;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to
|
||||
// "shift <op>".
|
||||
|
@ -168,16 +168,16 @@ static void translateImmediate(MCInst &mcInst, uint64_t immediate,
|
||||
switch (insn.displacementSize) {
|
||||
default:
|
||||
break;
|
||||
case 8:
|
||||
case 1:
|
||||
type = TYPE_MOFFS8;
|
||||
break;
|
||||
case 16:
|
||||
case 2:
|
||||
type = TYPE_MOFFS16;
|
||||
break;
|
||||
case 32:
|
||||
case 4:
|
||||
type = TYPE_MOFFS32;
|
||||
break;
|
||||
case 64:
|
||||
case 8:
|
||||
type = TYPE_MOFFS64;
|
||||
break;
|
||||
}
|
||||
|
@ -399,7 +399,7 @@ struct InternalInstruction {
|
||||
/* The segment override type */
|
||||
SegmentOverride segmentOverride;
|
||||
|
||||
/* Sizes of various critical pieces of data */
|
||||
/* Sizes of various critical pieces of data, in bytes */
|
||||
uint8_t registerSize;
|
||||
uint8_t addressSize;
|
||||
uint8_t displacementSize;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user