1 /* Functional tests of the htm __builtin_... macros. */
4 /* { dg-require-effective-target htm } */
5 /* { dg-options "-O3 -march=zEC12 -mzarch" } */
7 /* ---------------------------- included header files ---------------------- */
12 #include <htmintrin.h>
14 /* ---------------------------- local definitions -------------------------- */
16 #define DEFAULT_MAX_REPETITIONS 7
17 #define DEFAULT_REQUIRED_QUORUM 4
18 #define NUM_WARMUP_RUNS 2
20 /* ---------------------------- local macros ------------------------------- */
22 #define TEST_DF_REP(name) \
23 { #name, name, DEFAULT_MAX_REPETITIONS, DEFAULT_REQUIRED_QUORUM }
24 #define TEST_NO_REP(name) { #name, name, 1, 1 }
26 /* ---------------------------- local types -------------------------------- */
28 typedef int (*test_func_t
)(void);
33 test_func_t test_func
;
38 /* ---------------------------- local variables ---------------------------- */
40 __attribute__ ((aligned(256))) static struct __htm_tdb local_tdb256
;
41 static struct __htm_tdb local_tdb
;
42 static int do_dump_tdb
= 0;
44 /* ---------------------------- exported variables (globals) --------------- */
46 __attribute__ ((aligned(256))) struct
51 } global
= { 1.0, 2.5, 0.0 };
53 __attribute__ ((aligned(256))) struct
56 char pad1
[256 - sizeof(uint64_t)];
58 char pad2
[256 - sizeof(uint64_t)];
62 /* ---------------------------- local helper functions --------------------- */
64 static void dump_tdb (struct __htm_tdb
*tdb
)
74 p
= (unsigned char *)tdb
;
75 for (i
= 0; i
< 16; i
++)
77 fprintf (stderr
, "0x%02x ", i
* 16);
78 for (j
= 0; j
< 16; j
++)
80 fprintf (stderr
, "%02x", (int)p
[i
* 16 + j
]);
83 fprintf (stderr
, " ");
87 fprintf (stderr
, " ");
90 fprintf (stderr
, "\n");
96 /* ---------------------------- local test functions ----------------------- */
98 /* Check values of the constants defined in htmintrin.h. */
99 static int test_constants (void)
101 if (_HTM_TBEGIN_STARTED
!= 0)
103 return 100 * _HTM_TBEGIN_STARTED
+ 1;
105 if (_HTM_TBEGIN_INDETERMINATE
!= 1)
107 return 100 * _HTM_TBEGIN_INDETERMINATE
+ 2;
109 if (_HTM_TBEGIN_TRANSIENT
!= 2)
111 return 100 * _HTM_TBEGIN_TRANSIENT
+ 3;
113 if (_HTM_TBEGIN_PERSISTENT
!= 3)
115 return 100 * _HTM_TBEGIN_PERSISTENT
+ 4;
121 static int test_tbegin_ntstg_tend (void)
127 if ((rc
= __builtin_tbegin ((void *)0)) == 0)
129 __builtin_non_tx_store ((uint64_t *)&counters
.c1
, 1);
131 rc
= __builtin_tend ();
136 if (counters
.c1
!= 1)
138 return 100 * counters
.c1
+ 2;
140 if (counters
.c2
!= 2)
142 return 100 * counters
.c2
+ 3;
153 static int test_tbegin_ntstg_tabort (void)
160 if (__builtin_tbegin ((void *)0) == 0)
162 __builtin_non_tx_store ((uint64_t *)&counters
.c1
, 1);
165 __builtin_tabort (256);
168 if (counters
.c1
!= 1)
170 return 100 * counters
.c1
+ 2;
172 if (counters
.c2
!= 0)
174 return 100 * counters
.c2
+ 3;
184 static int test_tbegin_nofloat (void)
190 if ((rc
= __builtin_tbegin_nofloat ((void *)0)) == 0)
192 __builtin_non_tx_store ((uint64_t *)&counters
.c1
, 1);
194 rc
= __builtin_tend ();
199 if (counters
.c1
!= 1)
201 return 100 * counters
.c1
+ 2;
203 if (counters
.c2
!= 2)
205 return 100 * counters
.c2
+ 3;
216 static int test_tbegin_retry (void)
223 if ((rc
= __builtin_tbegin_retry ((void *)0, 5)) == 0)
227 do_abort
= (counters
.c1
== 0) ? 1 : 0;
228 __builtin_non_tx_store (
229 (uint64_t *)&counters
.c1
, counters
.c1
+ 1);
232 __builtin_tabort (256);
234 counters
.c2
= counters
.c2
+ 10;
235 __builtin_non_tx_store ((uint64_t *)&counters
.c3
, 3);
236 rc
= __builtin_tend ();
241 if (counters
.c1
!= 2)
243 return 100 * counters
.c1
+ 2;
245 if (counters
.c2
!= 10)
247 return 100 * counters
.c2
+ 3;
249 if (counters
.c3
!= 3)
251 return 100 * counters
.c3
+ 6;
262 static int test_tbegin_retry_nofloat (void)
269 if ((rc
= __builtin_tbegin_retry_nofloat ((void *)0, 5)) == 0)
273 do_abort
= (counters
.c1
== 0) ? 1 : 0;
274 __builtin_non_tx_store (
275 (uint64_t *)&counters
.c1
, counters
.c1
+ 1);
278 __builtin_tabort (256);
280 counters
.c2
= counters
.c2
+ 10;
281 __builtin_non_tx_store ((uint64_t *)&counters
.c3
, 3);
282 rc
= __builtin_tend ();
287 if (counters
.c1
!= 2)
289 return 100 * counters
.c1
+ 2;
291 if (counters
.c2
!= 10)
293 return 100 * counters
.c2
+ 3;
295 if (counters
.c3
!= 3)
297 return 100 * counters
.c3
+ 6;
308 static int test_tbegin_aborts (void)
314 if ((rc
= __builtin_tbegin ((void *)0)) == 0)
317 __builtin_tabort (256);
329 if ((rc
= __builtin_tbegin ((void *)0)) == 0)
332 __builtin_tabort (257);
343 if ((rc
= __builtin_tbegin ((void *)0)) == 0)
345 global
.float_3
= global
.float_1
+ global
.float_2
;
346 rc
= __builtin_tend ();
356 if (global
.float_3
!= global
.float_1
+ global
.float_2
)
358 return 100 * rc
+ 10;
364 static __attribute__((noinline
)) void indirect_abort(int abort_code
)
366 __builtin_tabort (abort_code
);
371 static int test_tbegin_indirect_aborts (void)
377 if ((rc
= __builtin_tbegin ((void *)0)) == 0)
392 if ((rc
= __builtin_tbegin ((void *)0)) == 0)
410 static int test_tbegin_nofloat_aborts (void)
414 if ((rc
= __builtin_tbegin_nofloat ((void *)0)) == 0)
416 __builtin_tabort (256);
419 if ((rc
= __builtin_tbegin_nofloat ((void *)0)) == 0)
421 __builtin_tabort (257);
426 return 1000 * rc
+ 6;
432 static int test_tbegin_nofloat_indirect_aborts (void)
436 if ((rc
= __builtin_tbegin_nofloat ((void *)0)) == 0)
438 indirect_abort (256);
441 if ((rc
= __builtin_tbegin_nofloat ((void *)0)) == 0)
443 indirect_abort (257);
448 return 1000 * rc
+ 6;
455 int _test_tbegin_retry_aborts (int retries
, uint64_t abort_code
)
460 if ((rc
= __builtin_tbegin_retry ((void *)0, retries
)) == 0)
462 __builtin_non_tx_store ((uint64_t *)&counters
.c1
, counters
.c1
+ 1);
463 __builtin_tabort (abort_code
);
468 if ((abort_code
& 1) == 0)
472 return 100 * rc
+ 2003;
474 else if (counters
.c1
!= (uint64_t)retries
+ 1)
476 return 1000 * counters
.c1
+ 100 * retries
+ 4;
483 return 100 * rc
+ 3005;
485 else if (counters
.c1
!= 1)
487 return 1000 * counters
.c1
+ 100 * retries
+ 6;
495 static int test_tbegin_retry_aborts (void)
500 for (retries
= 1; retries
<= 3; retries
++)
502 rc
= _test_tbegin_retry_aborts (retries
, 256);
508 for (retries
= 1; retries
<= 3; retries
++)
510 rc
= _test_tbegin_retry_aborts (retries
, 257);
516 if ((rc
= __builtin_tbegin_retry ((void *)0, 5)) == 0)
518 global
.float_3
= global
.float_1
+ global
.float_2
;
519 rc
= __builtin_tend ();
522 return 30000 + 100 * rc
+ 6;
527 return 30000 + 100 * rc
+ 7;
533 static int _test_tbegin_retry_nofloat_aborts (int retries
, uint64_t abort_code
)
538 if ((rc
= __builtin_tbegin_retry_nofloat ((void *)0, retries
)) == 0)
540 __builtin_non_tx_store ((uint64_t *)&counters
.c1
, counters
.c1
+ 1);
541 __builtin_tabort (abort_code
);
546 if ((abort_code
& 1) == 0)
550 return 100 * rc
+ 2003;
552 else if (counters
.c1
!= (uint64_t)retries
+ 1)
554 return 1000 * counters
.c1
+ 100 * retries
+ 4;
561 return 100 * rc
+ 3005;
563 else if (counters
.c1
!= 1)
565 return 1000 * counters
.c1
+ 100 * retries
+ 6;
573 static int test_tbegin_retry_nofloat_aborts (void)
578 for (retries
= 1; retries
<= 3; retries
++)
580 rc
= _test_tbegin_retry_nofloat_aborts (retries
, 256);
583 return 10 * retries
+ rc
;
586 for (retries
= 1; retries
<= 3; retries
++)
588 rc
= _test_tbegin_retry_nofloat_aborts (retries
, 257);
591 return 10000 + 10 * retries
+ rc
;
598 static int test_tbegin_tdb (void)
602 local_tdb
.format
= 0;
603 if ((rc
= __builtin_tbegin (&local_tdb
)) == 0)
605 rc
= __builtin_tend ();
610 if (local_tdb
.format
!= 0)
612 dump_tdb (&local_tdb
);
613 return 100 * local_tdb
.format
+ 2;
620 local_tdb
.format
= 0;
621 if ((rc
= __builtin_tbegin (&local_tdb
)) == 0)
623 __builtin_tabort (257);
632 if (local_tdb
.format
!= 1)
634 dump_tdb (&local_tdb
);
635 return 100 * local_tdb
.format
+ 6;
638 local_tdb256
.format
= 0;
639 if ((rc
= __builtin_tbegin (&local_tdb256
)) == 0)
641 rc
= __builtin_tend ();
644 return 1100 * rc
+ 1;
646 if (local_tdb256
.format
!= 0)
648 dump_tdb (&local_tdb256
);
649 return 1100 * local_tdb256
.format
+ 2;
654 return 1100 * rc
+ 3;
656 local_tdb256
.format
= 0;
657 if ((rc
= __builtin_tbegin (&local_tdb256
)) == 0)
659 __builtin_tabort (257);
666 return 2100 * rc
+ 5;
668 if (local_tdb256
.format
!= 1)
670 dump_tdb (&local_tdb256
);
671 return 2100 * local_tdb256
.format
+ 6;
678 static int test_tbegin_nofloat_tdb (void)
682 local_tdb
.format
= 0;
683 if ((rc
= __builtin_tbegin_nofloat (&local_tdb
)) == 0)
685 rc
= __builtin_tend ();
690 if (local_tdb
.format
!= 0)
692 dump_tdb (&local_tdb
);
693 return 100 * local_tdb
.format
+ 2;
700 local_tdb
.format
= 0;
701 if ((rc
= __builtin_tbegin_nofloat (&local_tdb
)) == 0)
703 __builtin_tabort (257);
712 if (local_tdb
.format
!= 1)
714 dump_tdb (&local_tdb
);
715 return 100 * local_tdb
.format
+ 6;
718 local_tdb256
.format
= 0;
719 if ((rc
= __builtin_tbegin_nofloat (&local_tdb256
)) == 0)
721 rc
= __builtin_tend ();
724 return 1100 * rc
+ 1;
726 if (local_tdb256
.format
!= 0)
728 dump_tdb (&local_tdb256
);
729 return 1100 * local_tdb256
.format
+ 2;
736 local_tdb256
.format
= 0;
737 if ((rc
= __builtin_tbegin_nofloat (&local_tdb256
)) == 0)
739 __builtin_tabort (257);
746 return 2100 * rc
+ 5;
748 if (local_tdb256
.format
!= 1)
750 dump_tdb (&local_tdb256
);
751 return 2100 * local_tdb256
.format
+ 6;
758 static int test_tbegin_retry_tdb (void)
762 local_tdb256
.format
= 0;
763 if ((rc
= __builtin_tbegin_retry (&local_tdb256
, 2)) == 0)
765 rc
= __builtin_tend ();
768 return 1100 * rc
+ 1;
770 if (local_tdb256
.format
!= 0)
772 dump_tdb (&local_tdb256
);
773 return 1100 * local_tdb256
.format
+ 2;
780 local_tdb256
.format
= 0;
781 if ((rc
= __builtin_tbegin_retry (&local_tdb256
, 2)) == 0)
783 __builtin_tabort (257);
790 return 2100 * rc
+ 5;
792 if (local_tdb256
.format
!= 1)
794 dump_tdb (&local_tdb256
);
795 return 2100 * local_tdb256
.format
+ 6;
802 static int test_tbegin_retry_nofloat_tdb (void)
806 local_tdb
.format
= 0;
807 if ((rc
= __builtin_tbegin_retry_nofloat (&local_tdb
, 2)) == 0)
809 rc
= __builtin_tend ();
814 if (local_tdb
.format
!= 0)
816 dump_tdb (&local_tdb
);
817 return 100 * local_tdb
.format
+ 2;
824 local_tdb
.format
= 0;
825 if ((rc
= __builtin_tbegin_retry_nofloat (&local_tdb
, 2)) == 0)
827 __builtin_tabort (257);
836 if (local_tdb
.format
!= 1)
838 dump_tdb (&local_tdb
);
839 return 100 * local_tdb
.format
+ 6;
842 local_tdb256
.format
= 0;
843 if ((rc
= __builtin_tbegin_retry_nofloat (&local_tdb256
, 2)) == 0)
845 rc
= __builtin_tend ();
848 return 1100 * rc
+ 1;
850 if (local_tdb256
.format
!= 0)
852 dump_tdb (&local_tdb256
);
853 return 1100 * local_tdb256
.format
+ 2;
858 return 1100 * rc
+ 3;
860 local_tdb256
.format
= 0;
861 if ((rc
= __builtin_tbegin_retry_nofloat (&local_tdb256
, 2)) == 0)
863 __builtin_tabort (257);
870 return 2100 * rc
+ 5;
872 if (local_tdb256
.format
!= 1)
874 dump_tdb (&local_tdb256
);
875 return 2100 * local_tdb256
.format
+ 6;
882 static int test_etnd (void)
889 if ((rc
= __builtin_tbegin ((void *)0)) == 0)
891 counters
.c1
= __builtin_tx_nesting_depth ();
892 if (__builtin_tbegin ((void *)0) == 0)
894 counters
.c2
= __builtin_tx_nesting_depth ();
895 if (__builtin_tbegin ((void *)0) == 0)
897 counters
.c3
= __builtin_tx_nesting_depth ();
908 if (counters
.c1
!= 1)
910 return 100 * counters
.c1
+ 2;
912 if (counters
.c2
!= 2)
914 return 100 * counters
.c2
+ 3;
916 if (counters
.c3
!= 3)
918 return 100 * counters
.c3
+ 4;
924 static int test_tbeginc (void)
929 __builtin_tbeginc ();
931 rc
= __builtin_tend ();
934 return 10000 * rc
+ 1;
936 if (counters
.c1
!= 1)
938 return 100000 * counters
.c1
+ 3;
944 /* ---------------------------- local testing framework functions ---------- */
946 static int run_one_test (const test_table_entry_t
*test_entry
)
953 /* Warmup run to get all necessary data and instruction pages into the page
959 for (run
= 0; run
< NUM_WARMUP_RUNS
; run
++)
961 test_entry
->test_func ();
966 test_entry
->required_quorum
!= 1 ||
967 test_entry
->max_repetitions
!= 1);
968 printf ("RRR RUN %s\n", test_entry
->name
);
969 if (do_print_passes
== 1)
972 " (requires %d successful out of %d runs)\n",
973 test_entry
->required_quorum
,
974 test_entry
->max_repetitions
);
978 for (rc
= 0, i
= 0; i
< test_entry
->max_repetitions
; i
++)
980 if (do_print_passes
== 1)
991 rc
= test_entry
->test_func ();
994 if (do_print_passes
== 1)
999 if (succeeded
>= test_entry
->required_quorum
)
1006 printf (" failed (rc = %d)", rc
);
1009 if (do_print_passes
== 1 || rc
!= 0)
1013 if (succeeded
>= test_entry
->required_quorum
)
1015 printf ("+++ OK %s\n", test_entry
->name
);
1021 printf ("--- FAIL %s\n", test_entry
->name
);
1023 return (rc
!= 0) ? rc
: -1;
1027 static int run_all_tests (const test_table_entry_t
*test_table
)
1029 const test_table_entry_t
*test
;
1033 rc
= 0, test
= &test_table
[0];
1034 test
->test_func
!= NULL
&& rc
== 0; test
++)
1036 rc
= run_one_test (test
);
1042 /* ---------------------------- interface functions ------------------------ */
1046 const test_table_entry_t test_table
[] = {
1047 TEST_NO_REP (test_constants
),
1048 TEST_DF_REP (test_tbegin_ntstg_tend
),
1049 TEST_DF_REP (test_tbegin_ntstg_tabort
),
1050 TEST_DF_REP (test_tbegin_nofloat
),
1051 TEST_NO_REP (test_tbegin_retry
),
1052 TEST_NO_REP (test_tbegin_retry_nofloat
),
1053 TEST_DF_REP (test_tbegin_aborts
),
1054 TEST_DF_REP (test_tbegin_indirect_aborts
),
1055 TEST_DF_REP (test_tbegin_nofloat_aborts
),
1056 TEST_DF_REP (test_tbegin_nofloat_indirect_aborts
),
1057 TEST_NO_REP (test_tbegin_retry_aborts
),
1058 TEST_NO_REP (test_tbegin_retry_nofloat_aborts
),
1059 TEST_DF_REP (test_tbegin_tdb
),
1060 TEST_DF_REP (test_tbegin_nofloat_tdb
),
1061 TEST_NO_REP (test_tbegin_retry_tdb
),
1062 TEST_NO_REP (test_tbegin_retry_nofloat_tdb
),
1063 TEST_DF_REP (test_etnd
),
1064 TEST_DF_REP (test_tbeginc
),
1071 rc
= run_all_tests (test_table
);