Hi! I've backported following 9 patches from gcc-8-branch to gcc-7-branch, bootstrapped/regtested and committed to gcc-7-branch.
Jakub
2018-10-12 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-07-16 Jakub Jelinek <ja...@redhat.com> PR c++/3698 PR c++/86208 * cp-gimplify.c (cp_genericize_r): When using extern_decl_map, or in TREE_USED flag from stmt to h->to. * g++.dg/opt/pr3698.C: New test. --- gcc/cp/cp-gimplify.c (revision 262678) +++ gcc/cp/cp-gimplify.c (revision 262679) @@ -1085,6 +1085,7 @@ cp_genericize_r (tree *stmt_p, int *walk if (h) { *stmt_p = h->to; + TREE_USED (h->to) |= TREE_USED (stmt); *walk_subtrees = 0; return NULL; } --- gcc/testsuite/g++.dg/opt/pr3698.C (nonexistent) +++ gcc/testsuite/g++.dg/opt/pr3698.C (revision 262679) @@ -0,0 +1,21 @@ +// PR c++/3698 +// { dg-do link } +// { dg-options "-O0" } + +struct X { + int i; +}; + +inline const int& +OHashKey (const X& x) +{ + return x.i; +} + +int +main () +{ + extern const int& OHashKey (const X& x); + X x; + return OHashKey (x); +}
2018-10-12 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-07-26 Jakub Jelinek <ja...@redhat.com> PR middle-end/86660 * omp-low.c (scan_sharing_clauses): Don't ignore map clauses for declare target to variables if they have always,{to,from,tofrom} map kinds. * testsuite/libgomp.c/pr86660.c: New test. --- gcc/omp-low.c (revision 263011) +++ gcc/omp-low.c (revision 263012) @@ -1190,13 +1190,16 @@ scan_sharing_clauses (tree clauses, omp_ /* Global variables with "omp declare target" attribute don't need to be copied, the receiver side will use them directly. However, global variables with "omp declare target link" - attribute need to be copied. */ + attribute need to be copied. Or when ALWAYS modifier is used. */ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && DECL_P (decl) && ((OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_POINTER && (OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_FIRSTPRIVATE_REFERENCE)) || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) + && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TO + && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_FROM + && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ALWAYS_TOFROM && is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx)) && varpool_node::get_create (decl)->offloadable && !lookup_attribute ("omp declare target link", --- libgomp/testsuite/libgomp.c/pr86660.c (nonexistent) +++ libgomp/testsuite/libgomp.c/pr86660.c (revision 263012) @@ -0,0 +1,28 @@ +/* PR middle-end/86660 */ + +#pragma omp declare target +int v[20]; + +void +foo (void) +{ + if (v[7] != 2) + __builtin_abort (); + v[7] = 1; +} +#pragma omp end declare target + +int +main () +{ + v[5] = 8; + v[7] = 2; + #pragma omp target map (always, tofrom: v) + { + foo (); + v[5] = 3; + } + if (v[7] != 1 || v[5] != 3) + __builtin_abort (); + return 0; +}
2018-10-12 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-07-10 Jakub Jelinek <ja...@redhat.com> PR fortran/86421 * module.c (omp_declare_simd_clauses): Add LINEAR with _REF, _VAL and _UVAL suffixes. (mio_omp_declare_simd): Save and restore ref, val and uval modifiers on linear clauses. Initialize n->where to gfc_current_locus. * gfortran.dg/vect/pr86421.f90: New test. --- gcc/fortran/module.c (revision 263012) +++ gcc/fortran/module.c (revision 263013) @@ -4100,6 +4100,9 @@ static const mstring omp_declare_simd_cl minit ("UNIFORM", 3), minit ("LINEAR", 4), minit ("ALIGNED", 5), + minit ("LINEAR_REF", 33), + minit ("LINEAR_VAL", 34), + minit ("LINEAR_UVAL", 35), minit (NULL, -1) }; @@ -4142,7 +4145,10 @@ mio_omp_declare_simd (gfc_namespace *ns, } for (n = ods->clauses->lists[OMP_LIST_LINEAR]; n; n = n->next) { - mio_name (4, omp_declare_simd_clauses); + if (n->u.linear_op == OMP_LINEAR_DEFAULT) + mio_name (4, omp_declare_simd_clauses); + else + mio_name (32 + n->u.linear_op, omp_declare_simd_clauses); mio_symbol_ref (&n->sym); mio_expr (&n->expr); } @@ -4183,11 +4189,20 @@ mio_omp_declare_simd (gfc_namespace *ns, case 4: case 5: *ptrs[t - 3] = n = gfc_get_omp_namelist (); + finish_namelist: + n->where = gfc_current_locus; ptrs[t - 3] = &n->next; mio_symbol_ref (&n->sym); if (t != 3) mio_expr (&n->expr); break; + case 33: + case 34: + case 35: + *ptrs[1] = n = gfc_get_omp_namelist (); + n->u.linear_op = (enum gfc_omp_linear_op) (t - 32); + t = 4; + goto finish_namelist; } } } --- gcc/testsuite/gfortran.dg/vect/pr86421.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/vect/pr86421.f90 (revision 263013) @@ -0,0 +1,35 @@ +! PR fortran/86421 +! { dg-require-effective-target vect_simd_clones } +! { dg-additional-options "-fopenmp-simd" } +! { dg-additional-options "-mavx" { target avx_runtime } } + +module mod86421 + implicit none +contains + subroutine foo(x, y, z) + real :: x + integer :: y, z + !$omp declare simd linear(ref(x)) linear(val(y)) linear(uval(z)) + x = x + y + z = z + 1 + end subroutine +end module mod86421 + +program pr86421 + use mod86421 + implicit none + integer :: i, j + real :: a(64) + j = 0 + do i = 1, 64 + a(i) = i + end do + !$omp simd + do i = 1, 64 + call foo (a(i), i, j) + end do + do i = 1, 64 + if (a(i) .ne. (2 * i)) stop 1 + end do + if (j .ne. 64) stop 2 +end program pr86421
2018-10-12 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-07-17 Jakub Jelinek <ja...@redhat.com> PR middle-end/86539 * gimplify.c (gimplify_omp_for): Ensure taskloop firstprivatized init and cond temporaries don't have reference type if iterator has pointer type. For init use &for_pre_body instead of pre_p if for_pre_body is non-empty. * testsuite/libgomp.c++/pr86539.C: New test. --- gcc/gimplify.c (revision 263013) +++ gcc/gimplify.c (revision 263014) @@ -9734,9 +9734,26 @@ gimplify_omp_for (tree *expr_p, gimple_s t = TREE_VEC_ELT (OMP_FOR_INIT (for_stmt), i); if (!is_gimple_constant (TREE_OPERAND (t, 1))) { + tree type = TREE_TYPE (TREE_OPERAND (t, 0)); TREE_OPERAND (t, 1) = get_initialized_tmp_var (TREE_OPERAND (t, 1), - pre_p, NULL, false); + gimple_seq_empty_p (for_pre_body) + ? pre_p : &for_pre_body, NULL, + false); + /* Reference to pointer conversion is considered useless, + but is significant for firstprivate clause. Force it + here. */ + if (TREE_CODE (type) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 1))) + == REFERENCE_TYPE)) + { + tree v = create_tmp_var (TYPE_MAIN_VARIANT (type)); + tree m = build2 (INIT_EXPR, TREE_TYPE (v), v, + TREE_OPERAND (t, 1)); + gimplify_and_add (m, gimple_seq_empty_p (for_pre_body) + ? pre_p : &for_pre_body); + TREE_OPERAND (t, 1) = v; + } tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); OMP_CLAUSE_DECL (c) = TREE_OPERAND (t, 1); @@ -9748,11 +9765,26 @@ gimplify_omp_for (tree *expr_p, gimple_s t = TREE_VEC_ELT (OMP_FOR_COND (for_stmt), i); if (!is_gimple_constant (TREE_OPERAND (t, 1))) { + tree type = TREE_TYPE (TREE_OPERAND (t, 0)); TREE_OPERAND (t, 1) = get_initialized_tmp_var (TREE_OPERAND (t, 1), gimple_seq_empty_p (for_pre_body) ? pre_p : &for_pre_body, NULL, false); + /* Reference to pointer conversion is considered useless, + but is significant for firstprivate clause. Force it + here. */ + if (TREE_CODE (type) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 1))) + == REFERENCE_TYPE)) + { + tree v = create_tmp_var (TYPE_MAIN_VARIANT (type)); + tree m = build2 (INIT_EXPR, TREE_TYPE (v), v, + TREE_OPERAND (t, 1)); + gimplify_and_add (m, gimple_seq_empty_p (for_pre_body) + ? pre_p : &for_pre_body); + TREE_OPERAND (t, 1) = v; + } tree c = build_omp_clause (input_location, OMP_CLAUSE_FIRSTPRIVATE); OMP_CLAUSE_DECL (c) = TREE_OPERAND (t, 1); --- libgomp/testsuite/libgomp.c++/pr86539.C (nonexistent) +++ libgomp/testsuite/libgomp.c++/pr86539.C (revision 263014) @@ -0,0 +1,28 @@ +// PR middle-end/86539 + +int a[384]; + +__attribute__((noinline, noclone)) void +foo (int &b, int &c) +{ + #pragma omp taskloop shared (a) collapse(3) + for (int i = 0; i < 1; i++) + for (int *p = &b; p < &c; p++) + for (int j = 0; j < 1; j++) + if (p < &a[128] || p >= &a[256]) + __builtin_abort (); + else + p[0]++; +} + +int +main () +{ + #pragma omp parallel + #pragma omp single + foo (a[128], a[256]); + for (int i = 0; i < 384; i++) + if (a[i] != (i >= 128 && i < 256)) + __builtin_abort (); + return 0; +}
2018-10-12 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-07-17 Jakub Jelinek <ja...@redhat.com> PR middle-end/86542 * omp-low.c (create_task_copyfn): Copy over also fields corresponding to _looptemp_ clauses, other than the first two. * testsuite/libgomp.c++/pr86542.C: New test. --- gcc/omp-low.c (revision 263014) +++ gcc/omp-low.c (revision 263015) @@ -7102,6 +7102,7 @@ create_task_copyfn (gomp_task *task_stmt splay_tree_node n; struct omp_taskcopy_context tcctx; location_t loc = gimple_location (task_stmt); + size_t looptempno = 0; child_fn = gimple_omp_task_copy_fn (task_stmt); child_cfun = DECL_STRUCT_FUNCTION (child_fn); @@ -7215,6 +7216,15 @@ create_task_copyfn (gomp_task *task_stmt t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); append_to_statement_list (t, &list); break; + case OMP_CLAUSE__LOOPTEMP_: + /* Fields for first two _looptemp_ clauses are initialized by + GOMP_taskloop*, the rest are handled like firstprivate. */ + if (looptempno < 2) + { + looptempno++; + break; + } + /* FALLTHRU */ case OMP_CLAUSE_FIRSTPRIVATE: decl = OMP_CLAUSE_DECL (c); if (is_variable_sized (decl)) @@ -7240,7 +7250,10 @@ create_task_copyfn (gomp_task *task_stmt src = decl; dst = build_simple_mem_ref_loc (loc, arg); dst = omp_build_component_ref (dst, f); - t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src); + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE__LOOPTEMP_) + t = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); + else + t = lang_hooks.decls.omp_clause_copy_ctor (c, dst, src); append_to_statement_list (t, &list); break; case OMP_CLAUSE_PRIVATE: --- libgomp/testsuite/libgomp.c++/pr86542.C (nonexistent) +++ libgomp/testsuite/libgomp.c++/pr86542.C (revision 263015) @@ -0,0 +1,37 @@ +// PR middle-end/86542 + +struct S { int s; S (); ~S (); S (const S &); }; +S s; + +S::S () +{ +} + +S::~S () +{ +} + +S::S (const S &x) +{ + s = x.s; +} + +__attribute__((noinline, noclone)) void +foo (int i, int j, int k, S s) +{ + if (i != 0 || j != 0 || k != 0 || s.s != 12) + __builtin_abort (); +} + +int +main () +{ + volatile int inc = 16, jnc = 16, knc = 16; + s.s = 12; + #pragma omp taskloop collapse (3) firstprivate (s) + for (int i = 0; i < 16; i += inc) + for (int j = 0; j < 16; j += jnc) + for (int k = 0; k < 16; k += knc) + foo (i, j, k, s); + return 0; +}
2018-10-12 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-07-24 Jakub Jelinek <ja...@redhat.com> PR middle-end/86627 * expmed.c (expand_divmod): Punt if d == HOST_WIDE_INT_MIN and size > HOST_BITS_PER_WIDE_INT. For size > HOST_BITS_PER_WIDE_INT and abs_d == d, do the power of two handling if profitable. * gcc.target/i386/pr86627.c: New test. --- gcc/expmed.c (revision 263016) +++ gcc/expmed.c (revision 263017) @@ -4314,6 +4314,11 @@ expand_divmod (int rem_flag, enum tree_c HOST_WIDE_INT d = INTVAL (op1); unsigned HOST_WIDE_INT abs_d; + /* Not prepared to handle division/remainder by + 0xffffffffffffffff8000000000000000 etc. */ + if (d == HOST_WIDE_INT_MIN && size > HOST_BITS_PER_WIDE_INT) + break; + /* Since d might be INT_MIN, we have to cast to unsigned HOST_WIDE_INT before negating to avoid undefined signed overflow. */ @@ -4357,9 +4362,7 @@ expand_divmod (int rem_flag, enum tree_c compute_mode) != CODE_FOR_nothing))) ; - else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d) - && (size <= HOST_BITS_PER_WIDE_INT - || abs_d != (unsigned HOST_WIDE_INT) d)) + else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d)) { if (rem_flag) { --- gcc/testsuite/gcc.target/i386/pr86627.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/pr86627.c (revision 263017) @@ -0,0 +1,28 @@ +/* PR middle-end/86627 */ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-not "call\[^\n\r]*__divti3" } } */ + +__int128_t +f1 (__int128_t a) +{ + return a / 2; +} + +__int128_t +f2 (__int128_t a) +{ + return a / -2; +} + +__int128_t +f3 (__int128_t a) +{ + return a / 0x4000000000000000LL; +} + +__int128_t +f4 (__int128_t a) +{ + return a / -0x4000000000000000LL; +}
2018-10-12 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-08-27 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/87065 * combine.c (simplify_if_then_else): Formatting fix. (if_then_else_cond): Guard MULT optimization with SCALAR_INT_MODE_P check. (known_cond): Don't return const_true_rtx for vector modes. Use CONST0_RTX instead of const0_rtx. Formatting fixes. * gcc.target/i386/pr87065.c: New test. --- gcc/combine.c (revision 263872) +++ gcc/combine.c (revision 263873) @@ -6455,7 +6455,7 @@ simplify_if_then_else (rtx x) pc_rtx, pc_rtx, 0, 0, 0); if (reg_mentioned_p (from, false_rtx)) false_rtx = subst (known_cond (copy_rtx (false_rtx), false_code, - from, false_val), + from, false_val), pc_rtx, pc_rtx, 0, 0, 0); SUBST (XEXP (x, 1), swapped ? false_rtx : true_rtx); @@ -9294,6 +9294,7 @@ if_then_else_cond (rtx x, rtx *ptrue, rt if (COMPARISON_P (cond0) && COMPARISON_P (cond1) + && SCALAR_INT_MODE_P (mode) && ((GET_CODE (cond0) == reversed_comparison_code (cond1, NULL) && rtx_equal_p (XEXP (cond0, 0), XEXP (cond1, 0)) && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 1))) @@ -9474,12 +9475,12 @@ known_cond (rtx x, enum rtx_code cond, r if (COMPARISON_P (x)) { if (comparison_dominates_p (cond, code)) - return const_true_rtx; + return VECTOR_MODE_P (GET_MODE (x)) ? x : const_true_rtx; code = reversed_comparison_code (x, NULL); if (code != UNKNOWN && comparison_dominates_p (cond, code)) - return const0_rtx; + return CONST0_RTX (GET_MODE (x)); else return x; } @@ -9522,7 +9523,7 @@ known_cond (rtx x, enum rtx_code cond, r /* We must simplify subreg here, before we lose track of the original inner_mode. */ new_rtx = simplify_subreg (GET_MODE (x), r, - inner_mode, SUBREG_BYTE (x)); + inner_mode, SUBREG_BYTE (x)); if (new_rtx) return new_rtx; else @@ -9547,7 +9548,7 @@ known_cond (rtx x, enum rtx_code cond, r /* We must simplify the zero_extend here, before we lose track of the original inner_mode. */ new_rtx = simplify_unary_operation (ZERO_EXTEND, GET_MODE (x), - r, inner_mode); + r, inner_mode); if (new_rtx) return new_rtx; else --- gcc/testsuite/gcc.target/i386/pr87065.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/pr87065.c (revision 263873) @@ -0,0 +1,22 @@ +/* PR rtl-optimization/87065 */ +/* { dg-do compile } */ +/* { dg-options "-O3 -mxop -mprefer-avx128" } */ + +int a, c, d, e; +short *b; + +void +foo (void) +{ + short *g = b; + int h = 1; + unsigned i; + for (; h <= 1; h++) + g = (short *) &c; + for (; c; c++) + { + for (; i <= 1; i++) + ; + a ^= (a > 0 <= i) + ((e += d) == 0 ?: (*g = 8)); + } +}
2018-10-12 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-09-12 Jakub Jelinek <ja...@redhat.com> PR middle-end/87248 * fold-const.c (fold_ternary_loc) <case COND_EXPR>: Verify also that BIT_AND_EXPR's second operand is a power of two. Formatting fix. * c-c++-common/torture/pr87248.c: New test. --- gcc/fold-const.c (revision 264230) +++ gcc/fold-const.c (revision 264231) @@ -11565,10 +11565,16 @@ fold_ternary_loc (location_t loc, enum t && integer_pow2p (arg1) && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1), - arg1, OEP_ONLY_CONST)) + arg1, OEP_ONLY_CONST) + /* operand_equal_p compares just value, not precision, so e.g. + arg1 could be 8-bit -128 and be power of two, but BIT_AND_EXPR + second operand 32-bit -128, which is not a power of two (or vice + versa. */ + && integer_pow2p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1))) return pedantic_non_lvalue_loc (loc, - fold_convert_loc (loc, type, - TREE_OPERAND (arg0, 0))); + fold_convert_loc (loc, type, + TREE_OPERAND (arg0, + 0))); /* Disable the transformations below for vectors, since fold_binary_op_with_conditional_arg may undo them immediately, --- gcc/testsuite/c-c++-common/torture/pr87248.c (nonexistent) +++ gcc/testsuite/c-c++-common/torture/pr87248.c (revision 264231) @@ -0,0 +1,36 @@ +/* PR middle-end/87248 */ +/* { dg-do run } */ + +void +foo (signed char *p, int q) +{ + *p = q & (-__SCHAR_MAX__ - 1) ? (-__SCHAR_MAX__ - 1) : 0; +} + +int +bar (long long x) +{ + return x & (-__INT_MAX__ - 1) ? (-__INT_MAX__ - 1) : 0; +} + +int +main () +{ +#if __INT_MAX__ > 4 * __SCHAR_MAX__ + signed char a[4]; + foo (a, __SCHAR_MAX__ + 1U); + foo (a + 1, 2 * (__SCHAR_MAX__ + 1U)); + foo (a + 2, -__INT_MAX__ - 1); + foo (a + 3, (__SCHAR_MAX__ + 1U) / 2); + if (a[0] != (-__SCHAR_MAX__ - 1) || a[1] != a[0] || a[2] != a[0] || a[3] != 0) + __builtin_abort (); +#endif +#if __LONG_LONG_MAX__ > 4 * __INT_MAX__ + if (bar (__INT_MAX__ + 1LL) != (-__INT_MAX__ - 1) + || bar (2 * (__INT_MAX__ + 1LL)) != (-__INT_MAX__ - 1) + || bar (-__LONG_LONG_MAX__ - 1) != (-__INT_MAX__ - 1) + || bar ((__INT_MAX__ + 1LL) / 2) != 0) + __builtin_abort (); +#endif + return 0; +}
2018-10-12 Jakub Jelinek <ja...@redhat.com> Backported from mainline 2018-10-10 Jakub Jelinek <ja...@redhat.com> PR target/87550 * config/i386/i386-builtin.def (IX86_BUILTIN_RDPMC): Move from args set to special_args set. * gcc.target/i386/pr87550.c: New test. --- gcc/config/i386/i386-builtin.def (revision 265048) +++ gcc/config/i386/i386-builtin.def (revision 265049) @@ -90,6 +90,7 @@ BDESC_END (PCMPISTR, SPECIAL_ARGS) BDESC_FIRST (special_args, SPECIAL_ARGS, 0, CODE_FOR_nothing, "__builtin_ia32_rdtsc", IX86_BUILTIN_RDTSC, UNKNOWN, (int) UINT64_FTYPE_VOID) BDESC (0, CODE_FOR_nothing, "__builtin_ia32_rdtscp", IX86_BUILTIN_RDTSCP, UNKNOWN, (int) UINT64_FTYPE_PUNSIGNED) +BDESC (0, CODE_FOR_nothing, "__builtin_ia32_rdpmc", IX86_BUILTIN_RDPMC, UNKNOWN, (int) UINT64_FTYPE_INT) BDESC (0, CODE_FOR_pause, "__builtin_ia32_pause", IX86_BUILTIN_PAUSE, UNKNOWN, (int) VOID_FTYPE_VOID) /* 80387 (for use internally for atomic compound assignment). */ @@ -427,7 +428,6 @@ BDESC_END (SPECIAL_ARGS, ARGS) BDESC_FIRST (args, ARGS, 0, CODE_FOR_bsr, "__builtin_ia32_bsrsi", IX86_BUILTIN_BSRSI, UNKNOWN, (int) INT_FTYPE_INT) BDESC (OPTION_MASK_ISA_64BIT, CODE_FOR_bsr_rex64, "__builtin_ia32_bsrdi", IX86_BUILTIN_BSRDI, UNKNOWN, (int) INT64_FTYPE_INT64) -BDESC (0, CODE_FOR_nothing, "__builtin_ia32_rdpmc", IX86_BUILTIN_RDPMC, UNKNOWN, (int) UINT64_FTYPE_INT) BDESC (0, CODE_FOR_rotlqi3, "__builtin_ia32_rolqi", IX86_BUILTIN_ROLQI, UNKNOWN, (int) UINT8_FTYPE_UINT8_INT) BDESC (0, CODE_FOR_rotlhi3, "__builtin_ia32_rolhi", IX86_BUILTIN_ROLHI, UNKNOWN, (int) UINT16_FTYPE_UINT16_INT) BDESC (0, CODE_FOR_rotrqi3, "__builtin_ia32_rorqi", IX86_BUILTIN_RORQI, UNKNOWN, (int) UINT8_FTYPE_UINT8_INT) --- gcc/testsuite/gcc.target/i386/pr87550.c (nonexistent) +++ gcc/testsuite/gcc.target/i386/pr87550.c (revision 265049) @@ -0,0 +1,21 @@ +/* PR target/87550 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +#include <x86intrin.h> + +int +foo (int x) +{ + return __rdtsc () + __rdtsc (); +} + +/* { dg-final { scan-assembler-times "\trdtsc\[\n\r]" 2 } } */ + +int +bar (int x) +{ + return __rdpmc (0) + __rdpmc (0); +} + +/* { dg-final { scan-assembler-times "\trdpmc\[\n\r]" 2 } } */