http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49575
--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> 2011-06-29 19:49:47 UTC --- With firstprivate of course you get a copy of the variable, but it is still a variable. The *.omp_fn* function which is created from the #omp parallel region will load it from parameter's structure and use it: k = .omp_data_i->k; ... D.1646 = (double) k; i.33 = i + (long double) D.1646; temp.34 = pow (D.1646, 2.0e+0); i.36 = i.33 + (long double) temp.34; temp.37 = pow (D.1646, 3.0e+0); i.39 = i.36 + (long double) temp.37; temp.40 = pow (D.1646, 4.0e+0); i.42 = i.39 + (long double) temp.40; temp.43 = pow (D.1646, 5.0e+0); ... but as it doesn't look at the caller, k is variable for it. Without -fopenmp, ccp propagates the 0.7 value to k uses and we end up with: i.32 = i + 6.999999999999999555910790149937383830547332763671875e-1; i.33 = i.32 + 4.89999999999999935607064571740920655429363250732421875e-1; i.34 = i.33 + 3.42999999999999916067139338338165543973445892333984375e-1; i.35 = i.34 + 2.400999999999999523492277830882812850177288055419921875e-1; i.36 = i.35 + 1.680699999999999416644413940957747399806976318359375e-1; i.37 = i.36 + 1.1764899999999996194066653742993366904556751251220703125e-1; i.38 = i.37 + 8.23542999999999636440151107308338396251201629638671875e-2; ... because gcc saw pow (0.7, 2.0e+0), pow (0.7, 3.0e+0); etc. and constant folded that. So, there aren't any pow calls without -fopenmp (wonder why nothing folded even the additions with -ffast-math though). Now, if with -fopenmp we do an interprodecural optimization so that .omp_data_i->k loads in the callee are replaced with what constant value has been stored into that field after constant propagation is performed in the caller, we can again constant propagate the 0.7 down into the pow calls and constant fold them. Of course the testcase doesn't make any sense this way, but the constant propagation accross the parallel region boundary could help real-world OpenMP programs too.