Update llvm/clang to trunk r126547.
There are several bugfixes in this update, but the most important one is to ensure __start_ and __stop_ symbols for linker sets and kernel module metadata are always emitted in object files: http://llvm.org/bugs/show_bug.cgi?id=9292 Before this fix, if you compiled kernel modules with clang, they would not be properly processed by kldxref, and if they had any dependencies, the kernel would fail to load those. Another problem occurred when attempting to mount a tmpfs filesystem, which would result in 'operation not supported by device'.
This commit is contained in:
commit
dd6029ff3a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=219077
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -597,9 +597,13 @@ bool X86FastISel::X86SelectCallAddress(const Value *V, X86AddressMode &AM) {
|
||||
(AM.Base.Reg != 0 || AM.IndexReg != 0))
|
||||
return false;
|
||||
|
||||
// Can't handle TLS or DLLImport.
|
||||
// Can't handle DLLImport.
|
||||
if (GV->hasDLLImportLinkage())
|
||||
return false;
|
||||
|
||||
// Can't handle TLS.
|
||||
if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV))
|
||||
if (GVar->isThreadLocal() || GVar->hasDLLImportLinkage())
|
||||
if (GVar->isThreadLocal())
|
||||
return false;
|
||||
|
||||
// Okay, we've committed to selecting this global. Set up the basic address.
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/VectorExtras.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Dwarf.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@ -56,10 +55,6 @@ using namespace dwarf;
|
||||
|
||||
STATISTIC(NumTailCalls, "Number of tail calls");
|
||||
|
||||
static cl::opt<bool>
|
||||
Disable256Bit("disable-256bit", cl::Hidden,
|
||||
cl::desc("Disable use of 256-bit vectors"));
|
||||
|
||||
// Forward declarations.
|
||||
static SDValue getMOVL(SelectionDAG &DAG, DebugLoc dl, EVT VT, SDValue V1,
|
||||
SDValue V2);
|
||||
@ -225,7 +220,6 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
|
||||
static MVT IntVTs[] = { MVT::i8, MVT::i16, MVT::i32, MVT::i64 };
|
||||
|
||||
// X86 is weird, it always uses i8 for shift amounts and setcc results.
|
||||
setShiftAmountType(MVT::i8);
|
||||
setBooleanContents(ZeroOrOneBooleanContent);
|
||||
setSchedulingPreference(Sched::RegPressure);
|
||||
setStackPointerRegisterToSaveRestore(X86StackPtr);
|
||||
@ -1713,7 +1707,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
else
|
||||
llvm_unreachable("Unknown argument type!");
|
||||
|
||||
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC, dl);
|
||||
unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC);
|
||||
ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
|
||||
|
||||
// If this is an 8 or 16-bit value, it is really passed promoted to 32
|
||||
@ -1845,7 +1839,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
SDValue FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), RSFIN,
|
||||
DAG.getIntPtrConstant(Offset));
|
||||
unsigned VReg = MF.addLiveIn(GPR64ArgRegs[NumIntRegs],
|
||||
X86::GR64RegisterClass, dl);
|
||||
X86::GR64RegisterClass);
|
||||
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64);
|
||||
SDValue Store =
|
||||
DAG.getStore(Val.getValue(1), dl, Val, FIN,
|
||||
@ -1861,7 +1855,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
SmallVector<SDValue, 11> SaveXMMOps;
|
||||
SaveXMMOps.push_back(Chain);
|
||||
|
||||
unsigned AL = MF.addLiveIn(X86::AL, X86::GR8RegisterClass, dl);
|
||||
unsigned AL = MF.addLiveIn(X86::AL, X86::GR8RegisterClass);
|
||||
SDValue ALVal = DAG.getCopyFromReg(DAG.getEntryNode(), dl, AL, MVT::i8);
|
||||
SaveXMMOps.push_back(ALVal);
|
||||
|
||||
@ -1872,7 +1866,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain,
|
||||
|
||||
for (; NumXMMRegs != TotalNumXMMRegs; ++NumXMMRegs) {
|
||||
unsigned VReg = MF.addLiveIn(XMMArgRegs64Bit[NumXMMRegs],
|
||||
X86::VR128RegisterClass, dl);
|
||||
X86::VR128RegisterClass);
|
||||
SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::v4f32);
|
||||
SaveXMMOps.push_back(Val);
|
||||
}
|
||||
@ -2693,6 +2687,10 @@ static bool isTargetShuffle(unsigned Opcode) {
|
||||
case X86ISD::MOVSD:
|
||||
case X86ISD::UNPCKLPS:
|
||||
case X86ISD::UNPCKLPD:
|
||||
case X86ISD::VUNPCKLPS:
|
||||
case X86ISD::VUNPCKLPD:
|
||||
case X86ISD::VUNPCKLPSY:
|
||||
case X86ISD::VUNPCKLPDY:
|
||||
case X86ISD::PUNPCKLWD:
|
||||
case X86ISD::PUNPCKLBW:
|
||||
case X86ISD::PUNPCKLDQ:
|
||||
@ -2760,6 +2758,10 @@ static SDValue getTargetShuffleNode(unsigned Opc, DebugLoc dl, EVT VT,
|
||||
case X86ISD::MOVSD:
|
||||
case X86ISD::UNPCKLPS:
|
||||
case X86ISD::UNPCKLPD:
|
||||
case X86ISD::VUNPCKLPS:
|
||||
case X86ISD::VUNPCKLPD:
|
||||
case X86ISD::VUNPCKLPSY:
|
||||
case X86ISD::VUNPCKLPDY:
|
||||
case X86ISD::PUNPCKLWD:
|
||||
case X86ISD::PUNPCKLBW:
|
||||
case X86ISD::PUNPCKLDQ:
|
||||
@ -4178,7 +4180,8 @@ static SDValue getVShift(bool isLeft, EVT VT, SDValue SrcOp,
|
||||
SrcOp = DAG.getNode(ISD::BITCAST, dl, ShVT, SrcOp);
|
||||
return DAG.getNode(ISD::BITCAST, dl, VT,
|
||||
DAG.getNode(Opc, dl, ShVT, SrcOp,
|
||||
DAG.getConstant(NumBits, TLI.getShiftAmountTy())));
|
||||
DAG.getConstant(NumBits,
|
||||
TLI.getShiftAmountTy(SrcOp.getValueType()))));
|
||||
}
|
||||
|
||||
SDValue
|
||||
@ -4327,16 +4330,15 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const {
|
||||
|
||||
// For AVX-length vectors, build the individual 128-bit pieces and
|
||||
// use shuffles to put them in place.
|
||||
if (VT.getSizeInBits() > 256 &&
|
||||
Subtarget->hasAVX() &&
|
||||
!Disable256Bit &&
|
||||
if (VT.getSizeInBits() > 256 &&
|
||||
Subtarget->hasAVX() &&
|
||||
!ISD::isBuildVectorAllZeros(Op.getNode())) {
|
||||
SmallVector<SDValue, 8> V;
|
||||
V.resize(NumElems);
|
||||
for (unsigned i = 0; i < NumElems; ++i) {
|
||||
V[i] = Op.getOperand(i);
|
||||
}
|
||||
|
||||
|
||||
EVT HVT = EVT::getVectorVT(*DAG.getContext(), ExtVT, NumElems/2);
|
||||
|
||||
// Build the lower subvector.
|
||||
@ -5044,7 +5046,8 @@ SDValue LowerVECTOR_SHUFFLEv16i8(ShuffleVectorSDNode *SVOp,
|
||||
DAG.getIntPtrConstant(Elt1 / 2));
|
||||
if ((Elt1 & 1) == 0)
|
||||
InsElt = DAG.getNode(ISD::SHL, dl, MVT::i16, InsElt,
|
||||
DAG.getConstant(8, TLI.getShiftAmountTy()));
|
||||
DAG.getConstant(8,
|
||||
TLI.getShiftAmountTy(InsElt.getValueType())));
|
||||
else if (Elt0 >= 0)
|
||||
InsElt = DAG.getNode(ISD::AND, dl, MVT::i16, InsElt,
|
||||
DAG.getConstant(0xFF00, MVT::i16));
|
||||
@ -5058,7 +5061,8 @@ SDValue LowerVECTOR_SHUFFLEv16i8(ShuffleVectorSDNode *SVOp,
|
||||
Elt0Src, DAG.getIntPtrConstant(Elt0 / 2));
|
||||
if ((Elt0 & 1) != 0)
|
||||
InsElt0 = DAG.getNode(ISD::SRL, dl, MVT::i16, InsElt0,
|
||||
DAG.getConstant(8, TLI.getShiftAmountTy()));
|
||||
DAG.getConstant(8,
|
||||
TLI.getShiftAmountTy(InsElt0.getValueType())));
|
||||
else if (Elt1 >= 0)
|
||||
InsElt0 = DAG.getNode(ISD::AND, dl, MVT::i16, InsElt0,
|
||||
DAG.getConstant(0x00FF, MVT::i16));
|
||||
@ -5475,7 +5479,7 @@ SDValue getMOVLP(SDValue &Op, DebugLoc &dl, SelectionDAG &DAG, bool HasSSE2) {
|
||||
// Both of them can't be memory operations though.
|
||||
if (MayFoldVectorLoad(V1) && MayFoldVectorLoad(V2))
|
||||
CanFoldLoad = false;
|
||||
|
||||
|
||||
if (CanFoldLoad) {
|
||||
if (HasSSE2 && NumElems == 2)
|
||||
return getTargetShuffleNode(X86ISD::MOVLPD, dl, VT, V1, V2, DAG);
|
||||
@ -6088,7 +6092,7 @@ X86TargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const {
|
||||
SDValue ScaledN2 = N2;
|
||||
if (Upper)
|
||||
ScaledN2 = DAG.getNode(ISD::SUB, dl, N2.getValueType(), N2,
|
||||
DAG.getConstant(NumElems /
|
||||
DAG.getConstant(NumElems /
|
||||
(VT.getSizeInBits() / 128),
|
||||
N2.getValueType()));
|
||||
Op = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, SubN0.getValueType(), SubN0,
|
||||
@ -9327,6 +9331,10 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::MOVSS: return "X86ISD::MOVSS";
|
||||
case X86ISD::UNPCKLPS: return "X86ISD::UNPCKLPS";
|
||||
case X86ISD::UNPCKLPD: return "X86ISD::UNPCKLPD";
|
||||
case X86ISD::VUNPCKLPS: return "X86ISD::VUNPCKLPS";
|
||||
case X86ISD::VUNPCKLPD: return "X86ISD::VUNPCKLPD";
|
||||
case X86ISD::VUNPCKLPSY: return "X86ISD::VUNPCKLPSY";
|
||||
case X86ISD::VUNPCKLPDY: return "X86ISD::VUNPCKLPDY";
|
||||
case X86ISD::UNPCKHPS: return "X86ISD::UNPCKHPS";
|
||||
case X86ISD::UNPCKHPD: return "X86ISD::UNPCKHPD";
|
||||
case X86ISD::PUNPCKLBW: return "X86ISD::PUNPCKLBW";
|
||||
@ -11984,6 +11992,10 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N,
|
||||
case X86ISD::PUNPCKLQDQ:
|
||||
case X86ISD::UNPCKLPS:
|
||||
case X86ISD::UNPCKLPD:
|
||||
case X86ISD::VUNPCKLPS:
|
||||
case X86ISD::VUNPCKLPD:
|
||||
case X86ISD::VUNPCKLPSY:
|
||||
case X86ISD::VUNPCKLPDY:
|
||||
case X86ISD::MOVHLPS:
|
||||
case X86ISD::MOVLHPS:
|
||||
case X86ISD::PSHUFD:
|
||||
|
@ -159,16 +159,16 @@ namespace llvm {
|
||||
|
||||
/// PSHUFB - Shuffle 16 8-bit values within a vector.
|
||||
PSHUFB,
|
||||
|
||||
|
||||
/// PANDN - and with not'd value.
|
||||
PANDN,
|
||||
|
||||
|
||||
/// PSIGNB/W/D - Copy integer sign.
|
||||
PSIGNB, PSIGNW, PSIGND,
|
||||
|
||||
PSIGNB, PSIGNW, PSIGND,
|
||||
|
||||
/// PBLENDVB - Variable blend
|
||||
PBLENDVB,
|
||||
|
||||
|
||||
/// FMAX, FMIN - Floating point max and min.
|
||||
///
|
||||
FMAX, FMIN,
|
||||
@ -212,7 +212,7 @@ namespace llvm {
|
||||
// ADD, SUB, SMUL, etc. - Arithmetic operations with FLAGS results.
|
||||
ADD, SUB, ADC, SBB, SMUL,
|
||||
INC, DEC, OR, XOR, AND,
|
||||
|
||||
|
||||
UMUL, // LOW, HI, FLAGS = umul LHS, RHS
|
||||
|
||||
// MUL_IMM - X86 specific multiply by immediate.
|
||||
@ -248,6 +248,10 @@ namespace llvm {
|
||||
MOVSS,
|
||||
UNPCKLPS,
|
||||
UNPCKLPD,
|
||||
VUNPCKLPS,
|
||||
VUNPCKLPD,
|
||||
VUNPCKLPSY,
|
||||
VUNPCKLPDY,
|
||||
UNPCKHPS,
|
||||
UNPCKHPD,
|
||||
PUNPCKLBW,
|
||||
@ -463,6 +467,8 @@ namespace llvm {
|
||||
|
||||
virtual unsigned getJumpTableEncoding() const;
|
||||
|
||||
virtual MVT getShiftAmountTy(EVT LHSTy) const { return MVT::i8; }
|
||||
|
||||
virtual const MCExpr *
|
||||
LowerCustomJumpTableEntry(const MachineJumpTableInfo *MJTI,
|
||||
const MachineBasicBlock *MBB, unsigned uid,
|
||||
|
@ -41,6 +41,8 @@ def MRM_F8 : Format<41>;
|
||||
def MRM_F9 : Format<42>;
|
||||
def RawFrmImm8 : Format<43>;
|
||||
def RawFrmImm16 : Format<44>;
|
||||
def MRM_D0 : Format<45>;
|
||||
def MRM_D1 : Format<46>;
|
||||
|
||||
// ImmType - This specifies the immediate type used by an instruction. This is
|
||||
// part of the ad-hoc solution used to emit machine instruction encodings by our
|
||||
|
@ -369,8 +369,6 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
|
||||
{ X86::IMUL32rri8, X86::IMUL32rmi8, 0 },
|
||||
{ X86::IMUL64rri32, X86::IMUL64rmi32, 0 },
|
||||
{ X86::IMUL64rri8, X86::IMUL64rmi8, 0 },
|
||||
{ X86::Int_CMPSDrr, X86::Int_CMPSDrm, 0 },
|
||||
{ X86::Int_CMPSSrr, X86::Int_CMPSSrm, 0 },
|
||||
{ X86::Int_COMISDrr, X86::Int_COMISDrm, 0 },
|
||||
{ X86::Int_COMISSrr, X86::Int_COMISSrm, 0 },
|
||||
{ X86::Int_CVTDQ2PDrr, X86::Int_CVTDQ2PDrm, 16 },
|
||||
@ -568,6 +566,8 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm)
|
||||
{ X86::IMUL16rr, X86::IMUL16rm, 0 },
|
||||
{ X86::IMUL32rr, X86::IMUL32rm, 0 },
|
||||
{ X86::IMUL64rr, X86::IMUL64rm, 0 },
|
||||
{ X86::Int_CMPSDrr, X86::Int_CMPSDrm, 0 },
|
||||
{ X86::Int_CMPSSrr, X86::Int_CMPSSrm, 0 },
|
||||
{ X86::MAXPDrr, X86::MAXPDrm, 16 },
|
||||
{ X86::MAXPDrr_Int, X86::MAXPDrm_Int, 16 },
|
||||
{ X86::MAXPSrr, X86::MAXPSrm, 16 },
|
||||
|
@ -311,6 +311,8 @@ namespace X86II {
|
||||
MRM_F0 = 40,
|
||||
MRM_F8 = 41,
|
||||
MRM_F9 = 42,
|
||||
MRM_D0 = 45,
|
||||
MRM_D1 = 46,
|
||||
|
||||
/// RawFrmImm8 - This is used for the ENTER instruction, which has two
|
||||
/// immediates, the first of which is a 16-bit immediate (specified by
|
||||
@ -577,6 +579,8 @@ namespace X86II {
|
||||
case X86II::MRM_F0:
|
||||
case X86II::MRM_F8:
|
||||
case X86II::MRM_F9:
|
||||
case X86II::MRM_D0:
|
||||
case X86II::MRM_D1:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1296,6 +1296,9 @@ def : MnemonicAlias<"lret", "lretl">;
|
||||
def : MnemonicAlias<"leavel", "leave">, Requires<[In32BitMode]>;
|
||||
def : MnemonicAlias<"leaveq", "leave">, Requires<[In64BitMode]>;
|
||||
|
||||
def : MnemonicAlias<"loopz", "loope">;
|
||||
def : MnemonicAlias<"loopnz", "loopne">;
|
||||
|
||||
def : MnemonicAlias<"pop", "popl">, Requires<[In32BitMode]>;
|
||||
def : MnemonicAlias<"pop", "popq">, Requires<[In64BitMode]>;
|
||||
def : MnemonicAlias<"popf", "popfl">, Requires<[In32BitMode]>;
|
||||
|
@ -388,3 +388,8 @@ def CPUID : I<0xA2, RawFrm, (outs), (ins), "cpuid", []>, TB;
|
||||
def INVD : I<0x08, RawFrm, (outs), (ins), "invd", []>, TB;
|
||||
def WBINVD : I<0x09, RawFrm, (outs), (ins), "wbinvd", []>, TB;
|
||||
|
||||
let Defs = [RDX, RAX], Uses = [RCX] in
|
||||
def XGETBV : I<0x01, MRM_D0, (outs), (ins), "xgetbv", []>, TB;
|
||||
|
||||
let Uses = [RDX, RAX, RCX] in
|
||||
def XSETBV : I<0x01, MRM_D1, (outs), (ins), "xsetbv", []>, TB;
|
||||
|
@ -979,6 +979,14 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
EmitByte(BaseOpcode, CurByte, OS);
|
||||
EmitByte(0xF9, CurByte, OS);
|
||||
break;
|
||||
case X86II::MRM_D0:
|
||||
EmitByte(BaseOpcode, CurByte, OS);
|
||||
EmitByte(0xD0, CurByte, OS);
|
||||
break;
|
||||
case X86II::MRM_D1:
|
||||
EmitByte(BaseOpcode, CurByte, OS);
|
||||
EmitByte(0xD1, CurByte, OS);
|
||||
break;
|
||||
}
|
||||
|
||||
// If there is a remaining operand, it must be a trailing immediate. Emit it
|
||||
|
@ -342,9 +342,10 @@ X86Subtarget::X86Subtarget(const std::string &TT, const std::string &FS,
|
||||
assert((!Is64Bit || HasX86_64) &&
|
||||
"64-bit code requested on a subtarget that doesn't support it!");
|
||||
|
||||
// Stack alignment is 16 bytes on Darwin and Linux (both 32 and 64 bit) and
|
||||
// for all 64-bit targets.
|
||||
if (isTargetDarwin() || isTargetLinux() || Is64Bit)
|
||||
// Stack alignment is 16 bytes on Darwin, FreeBSD, Linux and Solaris (both
|
||||
// 32 and 64 bit) and for all 64-bit targets.
|
||||
if (isTargetDarwin() || isTargetFreeBSD() || isTargetLinux() ||
|
||||
isTargetSolaris() || Is64Bit)
|
||||
stackAlignment = 16;
|
||||
|
||||
if (StackAlignment)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user