123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- // TEST_CONFIG
- #include "test.h"
- #include "testroot.i"
- #include <simd/simd.h>
-
- #if defined(__arm__)
- // rdar://8331406
- # define ALIGN_()
- #else
- # define ALIGN_() asm(".align 4");
- #endif
- @interface Super : TestRoot @end
- @implementation Super
- -(void)voidret_nop
- {
- return;
- }
- -(void)voidret_nop2
- {
- return;
- }
- -(id)idret_nop
- {
- return nil;
- }
- -(long long)llret_nop
- {
- return 0;
- }
- -(struct stret)stret_nop
- {
- return STRET_RESULT;
- }
- -(double)fpret_nop
- {
- return 0;
- }
- -(long double)lfpret_nop
- {
- return 0;
- }
- -(vector_ulong2)vecret_nop
- {
- return (vector_ulong2){0x1234567890abcdefULL, 0xfedcba0987654321ULL};
- }
- @end
- @interface Sub : Super @end
- @implementation Sub @end
- int main()
- {
- // cached message performance
- // catches failure to cache or (abi=2) failure to fixup (#5584187)
- // fixme unless they all fail
- uint64_t startTime;
- uint64_t totalTime;
- uint64_t targetTime;
- Sub *sub = [Sub new];
- // fill cache first
- [sub voidret_nop];
- [sub voidret_nop2];
- [sub llret_nop];
- [sub stret_nop];
- [sub fpret_nop];
- [sub lfpret_nop];
- [sub vecret_nop];
- [sub voidret_nop];
- [sub voidret_nop2];
- [sub llret_nop];
- [sub stret_nop];
- [sub fpret_nop];
- [sub lfpret_nop];
- [sub vecret_nop];
- [sub voidret_nop];
- [sub voidret_nop2];
- [sub llret_nop];
- [sub stret_nop];
- [sub fpret_nop];
- [sub lfpret_nop];
- [sub vecret_nop];
- // Some of these times have high variance on some compilers.
- // The errors we're trying to catch should be catastrophically slow,
- // so the margins here are generous to avoid false failures.
- // Use voidret because id return is too slow for perf test with ARC.
- // Pick smallest of voidret_nop and voidret_nop2 time
- // in the hopes that one of them didn't collide in the method cache.
- // ALIGN_ matches loop alignment to make -O0 work
- #define COUNT 1000000
- startTime = mach_absolute_time();
- ALIGN_();
- for (int i = 0; i < COUNT; i++) {
- [sub voidret_nop];
- }
- totalTime = mach_absolute_time() - startTime;
- testprintf("time: voidret %llu\n", totalTime);
- targetTime = totalTime;
- startTime = mach_absolute_time();
- ALIGN_();
- for (int i = 0; i < COUNT; i++) {
- [sub voidret_nop2];
- }
- totalTime = mach_absolute_time() - startTime;
- testprintf("time: voidret2 %llu\n", totalTime);
- if (totalTime < targetTime) targetTime = totalTime;
- startTime = mach_absolute_time();
- ALIGN_();
- for (int i = 0; i < COUNT; i++) {
- [sub llret_nop];
- }
- totalTime = mach_absolute_time() - startTime;
- timecheck("llret ", totalTime, targetTime * 0.65, targetTime * 2.0);
- startTime = mach_absolute_time();
- ALIGN_();
- for (int i = 0; i < COUNT; i++) {
- [sub stret_nop];
- }
- totalTime = mach_absolute_time() - startTime;
- timecheck("stret ", totalTime, targetTime * 0.65, targetTime * 5.0);
- startTime = mach_absolute_time();
- ALIGN_();
- for (int i = 0; i < COUNT; i++) {
- [sub fpret_nop];
- }
- totalTime = mach_absolute_time() - startTime;
- timecheck("fpret ", totalTime, targetTime * 0.65, targetTime * 4.0);
- startTime = mach_absolute_time();
- ALIGN_();
- for (int i = 0; i < COUNT; i++) {
- [sub lfpret_nop];
- }
- totalTime = mach_absolute_time() - startTime;
- timecheck("lfpret", totalTime, targetTime * 0.65, targetTime * 4.0);
- startTime = mach_absolute_time();
- ALIGN_();
- for (int i = 0; i < COUNT; i++) {
- [sub vecret_nop];
- }
- totalTime = mach_absolute_time() - startTime;
- timecheck("vecret", totalTime, targetTime * 0.65, targetTime * 4.0);
- succeed(__FILE__);
- }
|