S/390: Fix conditional returns on z196+
[official-gcc.git] / gcc / testsuite / gcc.target / s390 / htm-builtins-2.c
blobbb9d346ea560a73ff8bb1c324295064814b0a595
1 /* Functional tests of the htm __TM_... macros. */
3 /* { dg-do run } */
4 /* { dg-require-effective-target htm } */
5 /* { dg-options "-O3 -march=zEC12 -mzarch" } */
7 /* ---------------------------- included header files ---------------------- */
9 #include <stdio.h>
10 #include <string.h>
11 #include <inttypes.h>
12 #include <htmxlintrin.h>
14 /* ---------------------------- local definitions -------------------------- */
16 #define DEFAULT_MAX_REPETITIONS 7
17 #define DEFAULT_REQUIRED_QUORUM 4
18 #define DEFAULT_ABORT_ADDRESS (0x12345678u)
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);
30 typedef struct
32 const char *name;
33 test_func_t test_func;
34 int max_repetitions;
35 int required_quorum;
36 } test_table_entry_t;
38 typedef enum
40 ABORT_T_SYSTEM = 0,
41 ABORT_T_USER = 1,
42 } abort_user_t;
44 typedef enum
46 ABORT_T_NONE = 0,
47 ABORT_T_ILLEGAL,
48 ABORT_T_FOOTPRINT_EXCEEDED,
49 ABORT_T_NESTED_TOO_DEEP,
50 ABORT_T_CONFLICT,
52 ABORT_T_INVALID_ABORT_CODE
53 } abort_t;
55 /* ---------------------------- local variables ---------------------------- */
57 __attribute__ ((aligned(256))) static struct __htm_tdb local_tdb256;
58 static struct __htm_tdb local_tdb;
60 static abort_t const abort_classes[] =
62 ABORT_T_INVALID_ABORT_CODE,
63 ABORT_T_NONE,
64 ABORT_T_NONE,
65 ABORT_T_NONE,
67 ABORT_T_ILLEGAL,
68 ABORT_T_NONE,
69 ABORT_T_NONE,
70 ABORT_T_FOOTPRINT_EXCEEDED,
72 ABORT_T_FOOTPRINT_EXCEEDED,
73 ABORT_T_CONFLICT,
74 ABORT_T_CONFLICT,
75 ABORT_T_ILLEGAL,
77 ABORT_T_NONE,
78 ABORT_T_NESTED_TOO_DEEP,
79 ABORT_T_NONE,
80 ABORT_T_NONE,
82 ABORT_T_NONE
85 static size_t num_abort_classes = sizeof(abort_classes) / sizeof(abort_t);
87 /* ---------------------------- exported variables (globals) --------------- */
89 int global_int = 0;
90 uint64_t global_u64 = 0;
91 float global_float_1 = 1.0;
92 float global_float_2 = 2.5;
93 float global_float_3 = 0.0;
94 __attribute__ ((aligned(256))) struct
96 volatile uint64_t c1;
97 volatile uint64_t c2;
98 volatile uint64_t c3;
99 } counters = { 0, 0, 0 };
101 /* ---------------------------- local helper functions --------------------- */
103 static void dump_tdb(struct __htm_tdb *tdb)
105 unsigned char *p;
106 int i;
107 int j;
109 p = (unsigned char *)tdb;
110 for (i = 0; i < 16; i++)
112 fprintf(stderr, "0x%02x ", i * 16);
113 for (j = 0; j < 16; j++)
115 fprintf(stderr, "%02x", (int)p[i * 16 + j]);
116 if (j < 15)
118 fprintf(stderr, " ");
120 if (j == 7)
122 fprintf(stderr, " ");
125 fprintf(stderr, "\n");
128 return;
131 static void make_fake_tdb(struct __htm_tdb *tdb)
133 memset(tdb, 0, sizeof(*tdb));
134 tdb->format = 1;
135 tdb->nesting_depth = 1;
136 tdb->atia = DEFAULT_ABORT_ADDRESS;
137 tdb->abort_code = 11;
139 return;
142 static int check_abort_code_in_tdb(struct __htm_tdb *tdb, uint64_t abort_code)
144 long expect_rc;
145 long rc;
147 if (abort_code != 0)
149 long addr;
151 addr = __TM_failure_address(&local_tdb);
152 if (addr != DEFAULT_ABORT_ADDRESS)
154 return 11;
158 long long tdb_abort_code;
160 tdb_abort_code = __TM_failure_code(tdb);
161 if ((uint64_t)tdb_abort_code != abort_code)
163 fprintf(
164 stderr, "tm_ac %" PRIu64 ", ac %" PRIu64
165 ", tdb_ac %" PRIu64 "\n",
166 (uint64_t)tdb_abort_code, abort_code,
167 (uint64_t)tdb->abort_code);
168 return 10;
171 expect_rc = (abort_code >= 256) ? 1 : 0;
172 rc = __TM_is_user_abort(tdb);
173 if (rc != expect_rc)
175 fprintf(stderr, "rc %ld, expect_rc %ld\n", rc, expect_rc);
176 return 1;
179 unsigned char code;
181 code = 0xffu;
182 rc = __TM_is_named_user_abort(tdb, &code);
183 if (rc != expect_rc)
185 fprintf(
186 stderr, "rc %ld, expect_rc %ld\n", rc,
187 expect_rc);
188 return 2;
190 if (expect_rc == 1 && code != abort_code - 256)
192 return 3;
195 if (abort_code > (uint64_t)num_abort_classes)
197 abort_code = (uint64_t)num_abort_classes;
199 expect_rc = (abort_classes[abort_code] == ABORT_T_ILLEGAL) ? 1 : 0;
200 rc = __TM_is_illegal(tdb);
201 if (rc != expect_rc)
203 dump_tdb(tdb);
204 fprintf(stderr, "rc %ld, expect_rc %ld\n", rc, expect_rc);
205 return 4;
207 expect_rc =
208 (abort_classes[abort_code] == ABORT_T_FOOTPRINT_EXCEEDED) ?
209 1 : 0;
210 rc = __TM_is_footprint_exceeded(tdb);
211 if (rc != expect_rc)
213 dump_tdb(tdb);
214 fprintf(stderr, "rc %ld, expect_rc %ld\n", rc, expect_rc);
215 return 5;
217 expect_rc =
218 (abort_classes[abort_code] == ABORT_T_NESTED_TOO_DEEP) ? 1 : 0;
219 rc = __TM_is_nested_too_deep(tdb);
220 if (rc != expect_rc)
222 dump_tdb(tdb);
223 fprintf(stderr, "rc %ld, expect_rc %ld\n", rc, expect_rc);
224 return 6;
226 expect_rc = (abort_classes[abort_code] == ABORT_T_CONFLICT) ? 1 : 0;
227 rc = __TM_is_conflict(tdb);
228 if (rc != expect_rc)
230 dump_tdb(tdb);
231 fprintf(stderr, "rc %ld, expect_rc %ld\n", rc, expect_rc);
232 return 7;
235 return 0;
238 /* ---------------------------- local test functions ----------------------- */
240 /* Not a test; make sure that the involved global cachelines are reserved for
241 * writing. */
242 static int init_cache(void)
244 make_fake_tdb(&local_tdb);
245 make_fake_tdb(&local_tdb256);
246 global_int = 0;
247 global_u64 = 0;
248 global_float_1 = 1.0;
249 global_float_2 = 2.5;
250 global_float_3 = 0.0;
251 counters.c1 = 0;
252 counters.c2 = 0;
253 counters.c3 = 0;
255 return 0;
258 static int test_abort_classification(void)
260 int i;
262 make_fake_tdb(&local_tdb);
263 for (i = 0; i <= 256; i++)
265 int rc;
267 local_tdb.abort_code = (uint64_t)i;
268 rc = check_abort_code_in_tdb(&local_tdb, (uint64_t)i);
269 if (rc != 0)
271 return 100 * i + rc;
275 return 0;
278 static int test_cc_classification(void)
280 long rc;
282 rc = __TM_is_failure_persistent(0);
283 if (rc != 0)
285 return 1;
287 rc = __TM_is_failure_persistent(1);
288 if (rc != 0)
290 return 2;
292 rc = __TM_is_failure_persistent(2);
293 if (rc != 0)
295 return 3;
297 rc = __TM_is_failure_persistent(3);
298 if (rc != 1)
300 return 4;
303 return 0;
306 static int test_tbegin_ntstg_tend(void)
308 long rc;
310 counters.c1 = 0;
311 counters.c2 = 0;
312 if ((rc = __TM_simple_begin()) == 0)
314 __TM_non_transactional_store((uint64_t *)&counters.c1, 1);
315 counters.c2 = 2;
316 rc = __TM_end();
317 if (rc != 0)
319 return 100 * rc + 5;
321 if (counters.c1 != 1)
323 return 100 * counters.c1 + 2;
325 if (counters.c2 != 2)
327 return 100 * counters.c2 + 3;
330 else
332 return 100 * rc + 4;
335 return 0;
338 static int test_tbegin_ntstg_tabort(void)
340 register float f;
342 counters.c1 = 0;
343 counters.c2 = 0;
344 f = 0;
345 if (__TM_simple_begin() == 0)
347 __TM_non_transactional_store((uint64_t *)&counters.c1, 1);
348 counters.c2 = 2;
349 f = 1;
350 __TM_named_abort(0);
351 return 1;
353 if (counters.c1 != 1)
355 return 100 * counters.c1 + 2;
357 if (counters.c2 != 0)
359 return 100 * counters.c2 + 3;
361 if (f != 0)
363 return 100 * f + 4;
366 return 0;
369 static int test_tbegin_aborts(void)
371 float f;
372 long rc;
374 f = 77;
375 if ((rc = __TM_simple_begin()) == 0)
377 f = 88;
378 __TM_abort();
379 return 2;
381 else if (rc != 2)
383 return 3;
385 if (f != 77)
387 return 4;
389 f = 66;
390 if ((rc = __TM_simple_begin()) == 0)
392 f = 99;
393 __TM_named_abort(3);
394 return 5;
396 else if (rc != 3)
398 return 100 * rc + 6;
400 if (f != 66)
402 return 100 * f + 7;
404 if ((rc = __TM_simple_begin()) == 0)
406 global_float_3 = global_float_1 + global_float_2;
407 rc = __TM_end();
408 if (rc != 0)
410 return 100 * rc + 8;
413 else
415 return 100 * rc + 9;
417 if (global_float_3 != global_float_1 + global_float_2)
419 return 100 * rc + 10;
422 return 0;
425 static int test_tbegin_tdb(void)
427 long rc;
429 local_tdb.format = 0;
430 if ((rc = __TM_begin(&local_tdb)) == 0)
432 rc = __TM_end();
433 if (rc != 0)
435 return 100 * rc + 1;
437 if (local_tdb.format != 0)
439 dump_tdb(&local_tdb);
440 return 100 * local_tdb.format + 2;
443 else
445 return 100 * rc + 3;
447 local_tdb.format = 0;
448 if ((rc = __TM_begin(&local_tdb)) == 0)
450 __TM_named_abort(1);
451 return 4;
453 else
455 if (rc != 3)
457 return 100 * rc + 5;
459 if (local_tdb.format != 1)
461 dump_tdb(&local_tdb);
462 return 100 * local_tdb.format + 6;
465 local_tdb256.format = 0;
466 if ((rc = __TM_begin(&local_tdb256)) == 0)
468 rc = __TM_end();
469 if (rc != 0)
471 return 1100 * rc + 1;
473 if (local_tdb256.format != 0)
475 dump_tdb(&local_tdb256);
476 return 1100 * local_tdb256.format + 2;
479 else
481 return 1100 * rc + 3;
483 #if 1 /*!!!does not work*/
484 local_tdb256.format = 0;
485 if ((rc = __TM_begin(&local_tdb256)) == 0)
487 __TM_named_abort(1);
488 return 2004;
490 else
492 if (rc != 3)
494 return 2100 * rc + 5;
496 if (local_tdb256.format != 1)
498 dump_tdb(&local_tdb256);
499 return 2100 * local_tdb256.format + 6;
502 #endif
504 return 0;
507 static int test_etnd(void)
509 long rc;
512 long nd;
514 make_fake_tdb(&local_tdb);
515 local_tdb.nesting_depth = 0;
516 nd = __TM_nesting_depth(&local_tdb);
517 if (nd != 0)
519 return 1;
521 local_tdb.nesting_depth = 7;
522 nd = __TM_nesting_depth(&local_tdb);
523 if (nd != 7)
525 return 7;
527 local_tdb.format = 0;
528 nd = __TM_nesting_depth(&local_tdb);
529 if (nd != 0)
531 return 2;
534 counters.c1 = 0;
535 counters.c1 = 0;
536 counters.c2 = 0;
537 counters.c3 = 0;
538 if ((rc = __TM_simple_begin()) == 0)
540 counters.c1 = __TM_nesting_depth(0);
541 if (__TM_simple_begin() == 0)
543 counters.c2 = __TM_nesting_depth(0);
544 if (__TM_simple_begin() == 0)
546 counters.c3 = __TM_nesting_depth(0);
547 __TM_end();
549 __TM_end();
551 __TM_end();
553 else
555 return 100 * rc + 1;
557 if (counters.c1 != 1)
559 return 100 * counters.c1 + 2;
561 if (counters.c2 != 2)
563 return 100 * counters.c2 + 3;
565 if (counters.c3 != 3)
567 return 100 * counters.c3 + 4;
570 return 0;
573 /* ---------------------------- local testing framework functions ---------- */
575 static int run_one_test(const test_table_entry_t *test_entry)
577 int do_print_passes;
578 int succeeded;
579 int rc;
580 int i;
582 do_print_passes = (
583 test_entry->required_quorum != 1 ||
584 test_entry->max_repetitions != 1);
585 printf("RRR RUN %s\n", test_entry->name);
586 if (do_print_passes == 1)
588 printf(
589 " (requires %d successful out of %d runs)\n",
590 test_entry->required_quorum,
591 test_entry->max_repetitions);
593 succeeded = 0;
594 rc = 0;
595 for (rc = 0, i = 0; i < test_entry->max_repetitions; i++)
597 if (do_print_passes == 1)
599 if (i == 0)
601 printf(" ");
603 else
605 printf(",");
608 rc = test_entry->test_func();
609 if (rc == 0)
611 if (do_print_passes == 1)
613 printf(" success");
615 succeeded++;
616 if (succeeded >= test_entry->required_quorum)
618 break;
621 else
623 printf(" failed (rc = %d)", rc);
626 if (do_print_passes == 1 || rc != 0)
628 printf("\n");
630 if (succeeded >= test_entry->required_quorum)
632 printf("+++ OK %s\n", test_entry->name);
634 return 0;
636 else
638 printf("--- FAIL %s\n", test_entry->name);
640 return (rc != 0) ? rc : -1;
644 static int run_all_tests(const test_table_entry_t *test_table)
646 const test_table_entry_t *test;
647 int rc;
649 for (
650 rc = 0, test = &test_table[0];
651 test->test_func != NULL && rc == 0; test++)
653 rc = run_one_test(test);
656 return rc;
659 /* ---------------------------- interface functions ------------------------ */
661 int main(void)
663 const test_table_entry_t test_table[] = {
664 TEST_NO_REP(init_cache),
665 TEST_NO_REP(test_abort_classification),
666 TEST_NO_REP(test_cc_classification),
667 TEST_DF_REP(test_tbegin_ntstg_tend),
668 TEST_DF_REP(test_tbegin_ntstg_tabort),
669 TEST_DF_REP(test_tbegin_aborts),
670 TEST_DF_REP(test_tbegin_tdb),
671 TEST_DF_REP(test_etnd),
672 { (void *)0, 0, 0 }
676 int rc;
678 rc = run_all_tests(test_table);
680 return rc;