[cfe-commits] r63383 - /cfe/trunk/lib/CodeGen/CGCall.cpp
Daniel Dunbar
daniel at zuster.org
Fri Jan 30 00:09:33 PST 2009
Author: ddunbar
Date: Fri Jan 30 02:09:32 2009
New Revision: 63383
URL: http://llvm.org/viewvc/llvm-project?rev=63383&view=rev
Log:
x86_64 ABI: Implement classification for arrays.
- This brings us down to an 8% failure rate on the first 500 return
types tests (from 12%).
Modified:
cfe/trunk/lib/CodeGen/CGCall.cpp
Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=63383&r1=63382&r2=63383&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Fri Jan 30 02:09:32 2009
@@ -406,6 +406,16 @@
Memory
};
+ /// merge - Implement the X86_64 ABI merging algorithm.
+ ///
+ /// \param Offset - The offset of the current field.
+ /// \param FieldLo - The low classification of the current field.
+ /// \param FieldHi - The high classification of the current field.
+ /// \param Lo [in] [out] - The accumulated low classification.
+ /// \param Lo [in] [out] - The accumulated high classification.
+ void merge(uint64_t Offset, Class FieldLo, Class FieldHi,
+ Class &Lo, Class &Hi) const;
+
/// classify - Determine the x86_64 register classes in which the
/// given type T should be passed.
///
@@ -435,6 +445,58 @@
};
}
+void X86_64ABIInfo::merge(uint64_t Offset, Class FieldLo, Class FieldHi,
+ Class &Lo, Class &Hi) const {
+ // Determine which half of the structure we are classifying.
+ //
+ // AMD64-ABI 3.2.3p2: Rule 3. f the size of the aggregate
+ // exceeds a single eightbyte, each is classified
+ // separately. Each eightbyte gets initialized to class
+ // NO_CLASS.
+ Class &Target = Offset < 64 ? Lo : Hi;
+
+ // Merge the lo field classifcation.
+ //
+ // AMD64-ABI 3.2.3p2: Rule 4. Each field of an object is
+ // classified recursively so that always two fields are
+ // considered. The resulting class is calculated according to
+ // the classes of the fields in the eightbyte:
+ //
+ // (a) If both classes are equal, this is the resulting class.
+ //
+ // (b) If one of the classes is NO_CLASS, the resulting class is
+ // the other class.
+ //
+ // (c) If one of the classes is MEMORY, the result is the MEMORY
+ // class.
+ //
+ // (d) If one of the classes is INTEGER, the result is the
+ // INTEGER.
+ //
+ // (e) If one of the classes is X87, X87UP, COMPLEX_X87 class,
+ // MEMORY is used as class.
+ //
+ // (f) Otherwise class SSE is used.
+ if (Target == FieldLo || FieldLo == NoClass) ;
+ else if (FieldLo == Memory)
+ Lo = Memory;
+ else if (Target == NoClass)
+ Target = FieldLo;
+ else if (Target == Integer || FieldLo == Integer)
+ Target = Integer;
+ else if (FieldLo == X87 || FieldLo == X87Up || FieldLo == ComplexX87)
+ Lo = Memory;
+ else
+ Target = SSE;
+
+ // It isn't clear from the ABI spec what the role of the high
+ // classification is here, but since this should only happen
+ // when we have a struct with a two eightbyte member, we can
+ // just push the field high class into the overall high class.
+ if (FieldHi != NoClass)
+ Hi = FieldHi;
+}
+
void X86_64ABIInfo::classify(QualType Ty,
ASTContext &Context,
uint64_t OffsetBase,
@@ -494,6 +556,39 @@
uint64_t EB_Imag = (OffsetBase + Context.getTypeSize(ET)) >> 3;
if (Hi == NoClass && EB_Real != EB_Imag)
Hi = Lo;
+ } else if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
+ // Arrays are treated like structures.
+
+ uint64_t Size = Context.getTypeSize(Ty);
+
+ // AMD64-ABI 3.2.3p2: Rule 1. If the size of an object is larger
+ // than two eightbytes, ..., it has class MEMORY.
+ if (Size > 128)
+ return;
+
+ // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned
+ // fields, it has class MEMORY.
+ //
+ // Only need to check alignment of array base.
+ if (OffsetBase % Context.getTypeAlign(AT->getElementType())) {
+ Lo = Memory;
+ return;
+ }
+
+ // Otherwise implement simplified merge. We could be smarter about
+ // this, but it isn't worth it and would be harder to verify.
+ Lo = NoClass;
+ uint64_t EltSize = Context.getTypeSize(AT->getElementType());
+ uint64_t ArraySize = AT->getSize().getZExtValue();
+ for (uint64_t i=0, Offset=OffsetBase; i<ArraySize; ++i, Offset += EltSize) {
+ Class FieldLo, FieldHi;
+ classify(AT->getElementType(), Context, Offset, FieldLo, FieldHi);
+
+ merge(Offset, FieldLo, FieldHi, Lo, Hi);
+ // Memory is never over-ridden, exit early if we see it.
+ if (Lo == Memory)
+ return;
+ }
} else if (const RecordType *RT = Ty->getAsRecordType()) {
uint64_t Size = Context.getTypeSize(Ty);
@@ -515,72 +610,23 @@
unsigned idx = 0;
for (RecordDecl::field_iterator i = RD->field_begin(),
e = RD->field_end(); i != e; ++i, ++idx) {
- unsigned Offset = OffsetBase + Layout.getFieldOffset(idx);
+ uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx);
- // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned
- // fields, it has class MEMORY.
+ // AMD64-ABI 3.2.3p2: Rule 1. If ..., or it contains unaligned
+ // fields, it has class MEMORY.
if (Offset % Context.getTypeAlign(i->getType())) {
Lo = Memory;
return;
}
- // Determine which half of the structure we are classifying.
- //
- // AMD64-ABI 3.2.3p2: Rule 3. f the size of the aggregate
- // exceeds a single eightbyte, each is classified
- // separately. Each eightbyte gets initialized to class
- // NO_CLASS.
- Class &Target = Offset < 64 ? Lo : Hi;
-
// Classify this field.
Class FieldLo, FieldHi;
classify(i->getType(), Context, Offset, FieldLo, FieldHi);
- // Merge the lo field classifcation.
- //
- // AMD64-ABI 3.2.3p2: Rule 4. Each field of an object is
- // classified recursively so that always two fields are
- // considered. The resulting class is calculated according to
- // the classes of the fields in the eightbyte:
- //
- // (a) If both classes are equal, this is the resulting class.
- //
- // (b) If one of the classes is NO_CLASS, the resulting class is
- // the other class.
- //
- // (c) If one of the classes is MEMORY, the result is the MEMORY
- // class.
- //
- // (d) If one of the classes is INTEGER, the result is the
- // INTEGER.
- //
- // (e) If one of the classes is X87, X87UP, COMPLEX_X87 class,
- // MEMORY is used as class.
- //
- // (f) Otherwise class SSE is used.
- if (Target == FieldLo || FieldLo == NoClass) ;
- else if (FieldLo == Memory) {
- // Memory is never over-ridden, just bail.
- Lo = Memory;
+ merge(Offset, FieldLo, FieldHi, Lo, Hi);
+ // Memory is never over-ridden, exit early if we see it.
+ if (Lo == Memory)
return;
- }
- else if (Target == NoClass)
- Target = FieldLo;
- else if (Target == Integer || FieldLo == Integer)
- Target = Integer;
- else if (FieldLo == X87 || FieldLo == X87Up || FieldLo == ComplexX87) {
- // As before, just bail once we generate a memory class.
- Lo = Memory;
- return;
- } else
- Target = SSE;
-
- // It isn't clear from the ABI spec what the role of the high
- // classification is here, but since this should only happen
- // when we have a struct with a two eightbyte member, we can
- // just push the field high class into the overall high class.
- if (FieldHi != NoClass)
- Hi = FieldHi;
}
// AMD64-ABI 3.2.3p2: Rule 5. Then a post merger cleanup is done:
More information about the cfe-commits
mailing list