Hi! As the testcases show, not using build_binary_op resulted in sometimes non-promoted arguments, and there were issues with division, where we initially want to use TRUNC_DIV_EXPR, but if the arguments are floating point, change it into RDIV_EXPR instead.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, committed to trunk (backports will follow later, but hopefully soon). 2015-02-04 Jakub Jelinek <ja...@redhat.com> PR c/64824 PR c/64868 gcc/c/ * c-parser.c (c_parser_omp_atomic): Handle RDIV_EXPR. gcc/cp/ * parser.c (cp_parser_omp_atomic): Handle RDIV_EXPR. gcc/c-family/ * c-omp.c (c_finish_omp_atomic): Use TRUNC_DIV_EXPR instead of RDIV_EXPR. Use build_binary_op instead of build2_loc. libgomp/ * testsuite/libgomp.c/pr64824.c: New test. * testsuite/libgomp.c/pr64868.c: New test. * testsuite/libgomp.c++/pr64824.C: New test. * testsuite/libgomp.c++/pr64868.C: New test. --- gcc/c/c-parser.c.jj 2015-02-03 10:33:55.000000000 +0100 +++ gcc/c/c-parser.c 2015-02-04 17:57:50.318652940 +0100 @@ -12611,6 +12611,7 @@ restart: { case MULT_EXPR: case TRUNC_DIV_EXPR: + case RDIV_EXPR: case PLUS_EXPR: case MINUS_EXPR: case LSHIFT_EXPR: --- gcc/cp/parser.c.jj 2015-01-31 10:07:36.000000000 +0100 +++ gcc/cp/parser.c 2015-02-04 18:11:38.761575168 +0100 @@ -29835,6 +29835,7 @@ restart: { case MULT_EXPR: case TRUNC_DIV_EXPR: + case RDIV_EXPR: case PLUS_EXPR: case MINUS_EXPR: case LSHIFT_EXPR: --- gcc/c-family/c-omp.c.jj 2015-01-15 23:39:03.000000000 +0100 +++ gcc/c-family/c-omp.c 2015-02-04 19:08:55.498673461 +0100 @@ -206,6 +206,9 @@ c_finish_omp_atomic (location_t loc, enu return error_mark_node; } + if (opcode == RDIV_EXPR) + opcode = TRUNC_DIV_EXPR; + /* ??? Validate that rhs does not overlap lhs. */ /* Take and save the address of the lhs. From then on we'll reference it @@ -240,7 +243,7 @@ c_finish_omp_atomic (location_t loc, enu to do this, and then take it apart again. */ if (swapped) { - rhs = build2_loc (loc, opcode, TREE_TYPE (lhs), rhs, lhs); + rhs = build_binary_op (loc, opcode, rhs, lhs, 1); opcode = NOP_EXPR; } bool save = in_late_binary_op; --- libgomp/testsuite/libgomp.c/pr64824.c.jj 2015-02-04 20:18:57.061199758 +0100 +++ libgomp/testsuite/libgomp.c/pr64824.c 2015-02-04 20:18:26.509710353 +0100 @@ -0,0 +1,16 @@ +/* PR c/64824 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fopenmp" } */ + +int +main () +{ + long long a; + long long b = 1LL; + int c = 3; +#pragma omp atomic capture + a = b = c << b; + if (b != 6LL || a != 6LL) + __builtin_abort (); + return 0; +} --- libgomp/testsuite/libgomp.c/pr64868.c.jj 2015-02-04 19:46:39.570674828 +0100 +++ libgomp/testsuite/libgomp.c/pr64868.c 2015-02-04 19:46:19.000000000 +0100 @@ -0,0 +1,87 @@ +/* PR c/64868 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fopenmp" } */ + +float f = 2.0f; +double d = 4.0; +long double ld = 8.0L; + +void +foo () +{ +#pragma omp atomic + f = 1.0f / f; +#pragma omp atomic + f = 1 / f; +#pragma omp atomic + f = f / 2.0f; +#pragma omp atomic + f = f / 2; +#pragma omp atomic + f /= 2.0f; +#pragma omp atomic + f /= 2; +#pragma omp atomic + d = 1.0 / d; +#pragma omp atomic + d = 1 / d; +#pragma omp atomic + d = d / 2.0; +#pragma omp atomic + d = d / 2; +#pragma omp atomic + d /= 2.0; +#pragma omp atomic + d /= 2; +#pragma omp atomic + ld = 1.0L / ld; +#pragma omp atomic + ld = 1 / ld; +#pragma omp atomic + ld = ld / 2.0L; +#pragma omp atomic + ld = ld / 2; +#pragma omp atomic + ld /= 2.0L; +#pragma omp atomic + ld /= 2; + if (f != 0.125f || d != 0.25 || ld != 0.5L) + __builtin_abort (); +} + +#ifdef __cplusplus +template <typename T, int N1, int N2> +void +bar () +{ + T v = ::d; +#pragma omp atomic + v *= 16; +#pragma omp atomic + v = 1.0 / v; +#pragma omp atomic + v = N1 / v; +#pragma omp atomic + v = v / 2.0; +#pragma omp atomic + v = v / N2; +#pragma omp atomic + v /= 2.0; +#pragma omp atomic + v /= N2; + if (v != 0.25) + __builtin_abort (); +} +#endif + +int +main () +{ + foo (); +#ifdef __cplusplus + bar<float, 1, 2> (); + bar<double, 1, 2> (); + bar<long double, 1, 2> (); +#endif + return 0; +} --- libgomp/testsuite/libgomp.c++/pr64824.C.jj 2015-02-04 20:19:23.268761761 +0100 +++ libgomp/testsuite/libgomp.c++/pr64824.C 2015-02-04 20:19:19.364827006 +0100 @@ -0,0 +1,5 @@ +// PR c/64824 +// { dg-do run } +// { dg-options "-O2 -fopenmp" } + +#include "../libgomp.c/pr64824.c" --- libgomp/testsuite/libgomp.c++/pr64868.C.jj 2015-02-04 19:47:23.565935798 +0100 +++ libgomp/testsuite/libgomp.c++/pr64868.C 2015-02-04 19:47:16.883048057 +0100 @@ -0,0 +1,5 @@ +// PR c/64868 +// { dg-do run } +// { dg-options "-O2 -fopenmp" } + +#include "../libgomp.c/pr64868.c" Jakub