00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #define __STDC_LIMIT_MACROS
00058 #include <stdint.h>
00059 #include <sys/types.h>
00060 #if ! defined(BUILD_OS_DARWIN)
00061 #include <elf.h>
00062 #endif
00063
00064 #include "defs.h"
00065 #include "wn.h"
00066 #include "erbe.h"
00067
00068 #include "symtab.h"
00069
00070 #include "mtypes.h"
00071 #include "wn_util.h"
00072 #include "config_targ.h"
00073 #include "const.h"
00074 #include "cxx_template.h"
00075 #include "cxx_hash.h"
00076 #include "pu_info.h"
00077 #include "omp_lower.h"
00078 #include "srcpos.h"
00079 #include "tracing.h"
00080 #include "lnopt_main.h"
00081 #include "wn_simp.h"
00082 #include "strtab.h"
00083 #include "region_util.h"
00084 #include "config.h"
00085 #include "prompf.h"
00086 #include "anl_driver.h"
00087 #include "cxx_memory.h"
00088 #include "wb_buffer.h"
00089 #include "wb_carray.h"
00090 #include "wb_browser.h"
00091 #include "wb.h"
00092 #include "wb_omp.h"
00093 #include "privatize_common.h"
00094 #include "targ_const.h"
00095 #include "dra_export.h"
00096 #include "be_symtab.h"
00097
00098 #if !defined(BUILD_OS_DARWIN) && !defined(BUILD_SKIP_PROMPF)
00099 #pragma weak Anl_File_Path
00100 #pragma weak New_Construct_Id
00101 #endif
00102
00103
00104
00105
00106
00107 static const mINT32 NUM_HASH_ELEMENTS = 1021;
00108
00109 typedef HASH_TABLE<ST_IDX, BOOL> ST_TO_BOOL_HASH;
00110
00111 typedef enum {
00112 BY_EXPLICIT_CLAUSE,
00113 BY_DEFAULT_CLAUSE,
00114 BY_THREADPRIVATE,
00115 BY_DEFAULT_SHARED,
00116 BY_REDUCTION
00117 } SCOPE_RULE_KIND;
00118
00119
00120
00121
00122
00123
00124 typedef DYN_ARRAY<WN *> WN_LIST;
00125
00126 typedef STACK<WN *> STACK_OF_WN;
00127
00128 typedef STACK<WN_LIST *> WN_LIST_STACK;
00129
00130
00131
00132
00133
00134
00135
00136 DYN_ARRAY<ST*> critical_st;
00137
00138 typedef HASH_TABLE<WN *, BOOL> WN_TO_BOOL_HASH;
00139
00140
00141
00142
00143
00144
00145 static MEM_POOL omp_pool;
00146 static MEM_POOL Omp_Local_Pool;
00147 static WN_MAP Omp_Parent_Map = WN_MAP_UNDEFINED;
00148
00149 WN_TO_BOOL_HASH *Index_Priv_From_OMPL;
00150
00151
00152
00153
00154
00155
00156 #define Set_Parent(wn, p) (WN_MAP_Set(Omp_Parent_Map, wn, (void*) p))
00157 #define Get_Parent(wn) ((WN*) WN_MAP_Get(Omp_Parent_Map, (WN*) wn))
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 static ST *Mem_Ref_To_Var(WN *wn);
00178 static WN_PRAGMA_DEFAULT_KIND
00179 Var_Scope_In_Region(ST *st, WN *pragma_block, SCOPE_RULE_KIND *how,
00180 WN **scope_prag = NULL);
00181 static WN_PRAGMA_DEFAULT_KIND
00182 Var_Scope(ST *st, WN_LIST *pragma_block_list, SCOPE_RULE_KIND *how,
00183 WN **scope_prag = NULL);
00184 static WN *Par_Region_Pragma_Block(WN *wn, BOOL *is_worksharing);
00185 static BOOL Pragmas_For_Par_Region(WN *pragma_blk, BOOL *is_worksharing);
00186 static WN *Translate_OMP_to_MP(WN *pu);
00187 static void
00188 Infer_Reduction_Operators(WN *wn, WN_LIST_STACK *reduction_stack);
00189 static OPERATOR Reduction_Operator(WN *redn_pragma, WN *assign_stmt);
00190 static BOOL ST_is_Index_Var_For_Enclosing_PDO(ST *var_st, WN *wn);
00191 static void Apply_Default_Scopes(WN *pu, WN_LIST *construct_pragma_block_list);
00192 static void
00193 Apply_Par_Region_Default_Scopes(WN *wn, ST_TO_BOOL_HASH *processed,
00194 WN *pragma_block,
00195 WN_LIST *construct_pragma_block_list,
00196 WN_PRAGMA_DEFAULT_KIND defsc);
00197 static void
00198 Privatize_Index_Vars_And_Check_Final_Scopes(
00199 WN *wn, WN_LIST *pragma_block_list, WN *enclosing_pdo,
00200 ST_TO_BOOL_HASH *processed, WN_LIST *nested_constructs,
00201 BOOL top_of_construct);
00202 static mINT32 WN_Find_Linenum(WN *wn);
00203 static BOOL Is_Assumed_Size_Or_Shape_Array(TY *ty);
00204 static BOOL Can_Apply_Default_Private(ST *st, WN *pragma_block);
00205 static BOOL ST_Is_Const(ST *st);
00206 static void OMP_File_Init();
00207 static void Parentize(WN *wn);
00208 static WN *Is_Section_Begin(WN *wn);
00209 static WN *Lower_Master(WN *wn);
00210 static void Lower_Fetch_And_Op(WN *wn);
00211 static void Lower_Atomic(WN *wn);
00212 static void Convert_Section_To_Pdo(WN *sections, WN *pragma);
00213
00214 static TY_IDX Get_Func_Zero_Arg_TY ();
00215 static TY_IDX Get_Func_One_Arg_TY ();
00216 static BOOL Is_Ordered_Do (WN* wn);
00217 static WN *Add_Ordered_XPragmas (WN* wn);
00218 static void Add_Memory_Barriers (WN *wn);
00219 static void Convert_Simple_To_Interleaved (WN *wn);
00220 static void Convert_Just_Chunksize_To_Dynamic (WN *wn);
00221
00222 #ifdef TARG_SL2 //fork_joint
00223 static WN *Is_SL2_Section_Begin(WN *wn);
00224 static void Convert_SL2_Section_To_Pdo(WN *sections, WN *pragma);
00225 #endif
00226
00227
00228
00229
00230
00231
00232 static void OMP_Prompf_Init(WN* func_nd)
00233 {
00234 #ifndef BUILD_SKIP_PROMPF
00235 if (Run_prompf) {
00236 Prompf_Info->Enable();
00237 Prompf_Info->Mark_Omp();
00238 WB_OMP_Set_Prompf_Info(Prompf_Info);
00239 }
00240 #endif
00241 }
00242
00243
00244
00245
00246
00247
00248 static void OMP_Prompf_Finish()
00249 {
00250 #ifndef BUILD_SKIP_PROMPF
00251 if (Run_prompf) {
00252 const char *path = Anl_File_Path();
00253 FILE *fp_anl = fopen(path, "a");
00254 Prompf_Info->Print_Compact(fp_anl, PTL_OMP);
00255 fclose(fp_anl);
00256 Prompf_Info->Disable();
00257 }
00258 #endif
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 #if defined(BUILD_OS_DARWIN)
00270
00271 extern "C" { WN *OMP_Prelower(PU_Info *current_pu, WN *pu); }
00272 #endif
00273
00274 WN *OMP_Prelower(PU_Info *current_pu, WN *pu)
00275 {
00276
00277 static BOOL omp_initialized = FALSE;
00278 if (!omp_initialized) {
00279 OMP_File_Init();
00280 omp_initialized = TRUE;
00281 }
00282
00283 MEM_POOL_Popper popper(&omp_pool);
00284
00285 WN_TO_BOOL_HASH index_priv_set(NUM_HASH_ELEMENTS, &omp_pool);
00286 Index_Priv_From_OMPL = &index_priv_set;
00287
00288
00289 RENAMING_STACK rename_common_stack(&omp_pool);
00290 rename_common_stack.Push(CXX_NEW(RENAMING_SCOPE(NULL, &omp_pool),
00291 &omp_pool));
00292 Rename_Privatized_COMMON(pu, &rename_common_stack);
00293 Is_True(rename_common_stack.Elements() == 1,
00294 ("OMP_Prelower(): rename_common_stack.Elements() != 1"));
00295
00296 # ifdef KEY
00297 RENAMING_SCOPE rename_common(NULL, &omp_pool);
00298 RENAMING_SCOPE rename_common_blk(NULL, &omp_pool);
00299 RENAMING_STACK rename_scope_stack(&omp_pool);
00300 rename_scope_stack.Push(CXX_NEW(RENAMING_SCOPE(NULL, &omp_pool),
00301 &omp_pool));
00302 Rename_Threadprivate_COMMON(pu, pu, pu,
00303 &rename_scope_stack,
00304 &rename_common,
00305 &rename_common_blk);
00306 # endif
00307
00308
00309 Omp_Parent_Map = WN_MAP_Create(&omp_pool);
00310 Set_Parent(pu, NULL);
00311 Parentize(pu);
00312 WB_OMP_Set_Parent_Map(Omp_Parent_Map);
00313 OMP_Prompf_Init(pu);
00314
00315 critical_st.Set_Mem_Pool (&omp_pool);
00316
00317 pu = Translate_OMP_to_MP(pu);
00318 #if defined(TARG_SL2)
00319 if(Cur_PU_Feedback)
00320 Cur_PU_Feedback->Verify("sl2 psection conversion");
00321 #endif
00322
00323 #if defined(TARG_SL) && defined(TARG_SL2)
00324 if(Cur_PU_Feedback)
00325 Cur_PU_Feedback->Verify("sl2 psection conversion");
00326 #endif
00327
00328 FmtAssert (critical_st.Elements() == 0,
00329 ("Mismatch in begin-critical and end-critical pragmas"));
00330 critical_st.Free_array ();
00331
00332 WN_LIST_STACK reduction_stack(&omp_pool);
00333
00334 Infer_Reduction_Operators(pu, &reduction_stack);
00335
00336 WN_LIST pragma_block_list(&omp_pool);
00337 Apply_Default_Scopes(pu, &pragma_block_list);
00338
00339 Is_True(pragma_block_list.Lastidx() < 0,
00340 ("unmatched scope push in Apply_Default_Scopes()"));
00341
00342
00343 ST_TO_BOOL_HASH processed_set(NUM_HASH_ELEMENTS, &omp_pool);
00344 WN_LIST nested_set(&omp_pool);
00345
00346 Privatize_Index_Vars_And_Check_Final_Scopes(
00347 pu, &pragma_block_list, NULL, &processed_set, &nested_set, TRUE);
00348
00349 Is_True(pragma_block_list.Lastidx() < 0,
00350 ("unmatched scope push in "
00351 "Privatize_Index_Vars_And_Check_Final_Scopes()"));
00352
00353 WN_MAP_Delete(Omp_Parent_Map);
00354 OMP_Prompf_Finish();
00355
00356 return pu;
00357 }
00358
00359
00360
00361
00362
00363
00364
00365 static ST *Store_ST(WN *wn)
00366 {
00367 ST *st = NULL;
00368
00369 switch (WN_operator(wn)) {
00370 case OPR_STID:
00371 st = WN_st(wn);
00372 break;
00373
00374 case OPR_ISTORE:
00375 {
00376 WN *kid1 = WN_kid1(wn);
00377
00378 switch (WN_operator(kid1)) {
00379 case OPR_ARRAY:
00380 Is_True(WN_operator(WN_kid0(kid1)) == OPR_LDA ||
00381 WN_operator(WN_kid0(kid1)) == OPR_LDID,
00382 ("expected LDA or LDID as kid0 of ARRAY"));
00383 st = WN_st(WN_kid0(kid1));
00384 break;
00385
00386 case OPR_LDID:
00387 st = WN_st(kid1);
00388
00389 default:
00390 Is_True(0, ("could not find symbol for target of ISTORE"));
00391 }
00392 }
00393 break;
00394
00395 default:
00396 Is_True(0, ("could not find symbol for target of store"));
00397 }
00398
00399 return st;
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409 static ST *Mem_Ref_To_Var(WN *wn)
00410 {
00411 Is_True(wn, ("Mem_Ref_To_Var(): NULL wn argument"));
00412
00413
00414
00415
00416
00417
00418
00419 switch (WN_operator(wn)) {
00420 case OPR_LDA:
00421 case OPR_LDID:
00422 case OPR_STID:
00423 break;
00424 default:
00425 return NULL;
00426 }
00427
00428 ST *retval = WN_st(wn);
00429
00430
00431
00432 if (ST_class(retval) != CLASS_VAR)
00433 return NULL;
00434
00435 return retval;
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 static WN_PRAGMA_DEFAULT_KIND
00456 Var_Scope_In_Region(ST *st, WN *pragma_block, SCOPE_RULE_KIND *how,
00457 WN **scope_prag)
00458 {
00459
00460
00461
00462 ST *split_blk;
00463 ST *common_blk = ST_Source_COMMON_Block(st, &split_blk);
00464
00465 if (ST_is_thread_private(st) ||
00466 (split_blk && ST_is_thread_private(split_blk)) ||
00467 (common_blk && ST_is_thread_private(common_blk))) {
00468 *how = BY_THREADPRIVATE;
00469 return WN_PRAGMA_DEFAULT_PRIVATE;
00470 }
00471
00472
00473 WN_PRAGMA_DEFAULT_KIND defsc = WN_PRAGMA_DEFAULT_UNKNOWN;
00474 BOOL dummy, is_par_region = Pragmas_For_Par_Region(pragma_block, &dummy);
00475
00476 *how = BY_EXPLICIT_CLAUSE;
00477 for (WN *prag = WN_first(pragma_block); prag; prag = WN_next(prag))
00478 if (WN_opcode(prag) == OPC_PRAGMA) {
00479 WN_PRAGMA_ID prag_id = (WN_PRAGMA_ID) WN_pragma(prag);
00480
00481 switch (prag_id) {
00482 case WN_PRAGMA_LOCAL:
00483 case WN_PRAGMA_LASTLOCAL:
00484 case WN_PRAGMA_FIRSTPRIVATE:
00485 case WN_PRAGMA_SHARED:
00486 case WN_PRAGMA_REDUCTION:
00487 {
00488 ST *prag_st = WN_st(prag);
00489
00490 if (prag_st == st || split_blk == prag_st ||
00491 common_blk == prag_st) {
00492 if (prag_id == WN_PRAGMA_SHARED) {
00493 if (scope_prag)
00494 *scope_prag = prag;
00495 return WN_PRAGMA_DEFAULT_SHARED;
00496 } else {
00497 if (prag_id == WN_PRAGMA_REDUCTION)
00498 *how = BY_REDUCTION;
00499 if (scope_prag)
00500 *scope_prag = prag;
00501 return WN_PRAGMA_DEFAULT_PRIVATE;
00502 }
00503 }
00504 }
00505 break;
00506 case WN_PRAGMA_DEFAULT:
00507 defsc = (WN_PRAGMA_DEFAULT_KIND) WN_pragma_arg1(prag);
00508 if (scope_prag)
00509 *scope_prag = prag;
00510 break;
00511 default:
00512 break;
00513 }
00514 }
00515
00516 *how = BY_DEFAULT_CLAUSE;
00517 switch (defsc) {
00518 case WN_PRAGMA_DEFAULT_SHARED:
00519 case WN_PRAGMA_DEFAULT_PRIVATE:
00520 return defsc;
00521 default:
00522 break;
00523 }
00524
00525 if (is_par_region) {
00526 *how = BY_DEFAULT_SHARED;
00527 return WN_PRAGMA_DEFAULT_SHARED;
00528 }
00529
00530 return WN_PRAGMA_DEFAULT_UNKNOWN;
00531 }
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545 static WN_PRAGMA_DEFAULT_KIND
00546 Var_Scope(ST *st, WN_LIST *pragma_block_list, SCOPE_RULE_KIND *how,
00547 WN **scope_prag)
00548 {
00549 WN_PRAGMA_DEFAULT_KIND retval;
00550 *how = BY_DEFAULT_SHARED;
00551
00552 Is_True(pragma_block_list->Lastidx() >= 0,
00553 ("Var_Scope() called outside a parallel construct"));
00554
00555
00556 for (INT idx = pragma_block_list->Lastidx(); idx >= 0; idx--) {
00557 if ((retval = Var_Scope_In_Region(st, (*pragma_block_list)[idx],
00558 how, scope_prag) ) !=
00559 WN_PRAGMA_DEFAULT_UNKNOWN)
00560 break;
00561 }
00562
00563 return retval;
00564 }
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 static WN *Par_Region_Pragma_Block(WN *wn, BOOL *is_worksharing)
00576 {
00577 Is_True(wn, ("Par_Region_Pragma_Block(): NULL wn argument"));
00578
00579 *is_worksharing = FALSE;
00580 if (WN_opcode(wn) != OPC_REGION)
00581 return NULL;
00582
00583 WN *pragma_blk = WN_region_pragmas(wn);
00584
00585 return Pragmas_For_Par_Region(pragma_blk, is_worksharing) ? pragma_blk :
00586 NULL;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 static BOOL Pragmas_For_Par_Region(WN *pragma_blk, BOOL *is_worksharing)
00598 {
00599 Is_True(pragma_blk, ("Pragmas_For_Par_Region(): NULL pragma_blk argument"));
00600
00601 WN *prag = WN_first(pragma_blk);
00602
00603 *is_worksharing = FALSE;
00604
00605 if (!prag)
00606 return FALSE;
00607
00608 switch (WN_pragma(prag)) {
00609 case WN_PRAGMA_PARALLEL_BEGIN:
00610 return TRUE;
00611
00612 case WN_PRAGMA_PARALLEL_DO:
00613 case WN_PRAGMA_DOACROSS:
00614 if (WN_pragma_arg1(prag) != 0)
00615 return FALSE;
00616
00617 *is_worksharing = TRUE;
00618 return TRUE;
00619
00620 case WN_PRAGMA_PDO_BEGIN:
00621 if (WN_pragma_arg1(prag) != 0)
00622 return FALSE;
00623 *is_worksharing = TRUE;
00624 break;
00625
00626 case WN_PRAGMA_SINGLE_PROCESS_BEGIN:
00627 *is_worksharing = TRUE;
00628 break;
00629
00630 default:
00631 break;
00632 }
00633
00634 return FALSE;
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645 static BOOL Is_Assumed_Size_Or_Shape_Array(TY *ty)
00646 {
00647
00648 if (TY_kind(*ty) == KIND_POINTER)
00649 ty = &(Ty_Table[TY_pointed(*ty)]);
00650
00651 if (TY_kind(*ty) != KIND_ARRAY)
00652 return FALSE;
00653
00654
00655
00656
00657 for (INT i = 0; i < TY_AR_ndims (*ty); i++) {
00658
00659
00660 if ((!TY_AR_const_lbnd(*ty, i) && !TY_AR_lbnd_var(*ty, i)) ||
00661 (!TY_AR_const_ubnd(*ty, i) && !TY_AR_ubnd_var(*ty, i)))
00662 return TRUE;
00663 }
00664
00665 return FALSE;
00666 }
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676 static BOOL
00677 Can_Apply_Default_Private(ST *st, WN *pragma_block)
00678 {
00679
00680
00681
00682
00683
00684
00685
00686
00687 if (ST_is_equivalenced(st)) {
00688 ErrMsgLine(EC_MPLOWER_defpriv_equiv, WN_Find_Linenum(pragma_block), st);
00689 return FALSE;
00690 }
00691
00692
00693
00694
00695
00696
00697 TY *ty = &(Ty_Table[ST_type(st)]);
00698
00699
00700 if (Is_Assumed_Size_Or_Shape_Array(ty))
00701 return FALSE;
00702
00703
00704
00705
00706
00707
00708
00709 ST *split_blk, *common_block = ST_Source_COMMON_Block(st, &split_blk);
00710
00711 if (common_block) {
00712
00713 for (WN *prag = WN_first(pragma_block); prag; prag = WN_next(prag))
00714 if (WN_opcode(prag) == OPC_PRAGMA &&
00715 WN_PRAGMA_LOCAL == (WN_PRAGMA_ID) WN_pragma(prag) &&
00716 (split_blk == WN_st(prag) || common_block == WN_st(prag)) )
00717 return FALSE;
00718 }
00719
00720 return TRUE;
00721 }
00722
00723
00724
00725
00726
00727
00728
00729 static BOOL ST_Is_Const(ST *st)
00730 {
00731 TY_IDX ty_idx = ST_type(st);
00732 if (TY_is_const(ty_idx))
00733 return TRUE;
00734
00735 if (TY_kind(ty_idx) != KIND_ARRAY)
00736 return FALSE;
00737
00738 TY_IDX elt_ty_idx = TY_etype(ty_idx);
00739 if (TY_is_const(elt_ty_idx))
00740 return TRUE;
00741
00742 return FALSE;
00743 }
00744
00745
00746
00747
00748
00749
00750
00751 extern BOOL
00752 WN_Store_Target_Matches_Reduction(WN *store, WN *reduction)
00753 {
00754 const OPERATOR store_oper = WN_operator(store);
00755 const OPERATOR reduction_oper = WN_operator(reduction);
00756
00757 Is_True(store_oper == OPR_STID || store_oper == OPR_ISTORE,
00758 ("bad store_oper == %d", store_oper));
00759 Is_True(reduction_oper == OPR_PRAGMA || reduction_oper == OPR_XPRAGMA,
00760 ("bad reduction_oper == %d", reduction_oper));
00761
00762 if (store_oper == OPR_STID && reduction_oper == OPR_PRAGMA &&
00763 WN_st(store) == WN_st(reduction) &&
00764 WN_offset(store) == WN_pragma_arg1(reduction))
00765 return TRUE;
00766
00767 if (store_oper == OPR_ISTORE && reduction_oper == OPR_XPRAGMA &&
00768 WN_Simp_Compare_Trees(WN_kid1(store), WN_kid0(reduction)) == 0)
00769 return TRUE;
00770
00771 return FALSE;
00772 }
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793 static void
00794 Infer_Reduction_Operators(WN *wn, WN_LIST_STACK *reduction_stack)
00795 {
00796 const OPERATOR oper = WN_operator(wn);
00797 WN *recurse_parent = wn;
00798 BOOL do_pop = FALSE, is_worksharing;
00799 WN_LIST *redn_pragmas;
00800
00801 if (oper == OPR_STID || oper == OPR_ISTORE) {
00802 WN *redn_pragma = NULL;
00803 WN_LIST *redn_list;
00804 INT i, j;
00805
00806
00807 for (i = 0; i < reduction_stack->Elements() && !redn_pragma; i++) {
00808 for (j = 0, redn_list = reduction_stack->Top_nth(i);
00809 j < redn_list->Elements(); j++) {
00810 WN *prag = (*redn_list)[j];
00811
00812 if (WN_Store_Target_Matches_Reduction(wn, prag)) {
00813 redn_pragma = prag;
00814 break;
00815 }
00816 }
00817 }
00818
00819 if (redn_pragma) {
00820 OPERATOR redn_oper = Reduction_Operator(redn_pragma, wn);
00821
00822 if (WN_pragma_arg2(redn_pragma) == OPERATOR_UNKNOWN)
00823 WN_pragma_arg2(redn_pragma) = redn_oper;
00824 else if (WN_pragma_arg2(redn_pragma) != redn_oper &&
00825 redn_oper != OPERATOR_UNKNOWN) {
00826
00827
00828
00829
00830
00831 #ifndef KEY
00832
00833
00834
00835 ErrMsgLine(EC_MPLOWER_red_conflict, WN_Find_Linenum(wn),
00836 Store_ST(wn));
00837 #else
00838 DevWarn ("Probably inconsistent reduction operator for variable %s",
00839 ST_name (Store_ST(wn)));
00840 #endif
00841 }
00842 }
00843
00844 recurse_parent = NULL;
00845
00846 } else if (Par_Region_Pragma_Block(wn, &is_worksharing) != NULL ||
00847 is_worksharing) {
00848 redn_pragmas = CXX_NEW(WN_LIST(&omp_pool), &omp_pool);
00849
00850 for (WN *prag = WN_first(WN_region_pragmas(wn)); prag;
00851 prag = WN_next(prag))
00852 if (WN_pragma(prag) == WN_PRAGMA_REDUCTION)
00853 redn_pragmas->AddElement(prag);
00854
00855 reduction_stack->Push(redn_pragmas);
00856 do_pop = TRUE;
00857 recurse_parent = WN_region_body(wn);
00858 }
00859
00860 if (recurse_parent) {
00861 OPCODE rpar_opc = WN_opcode(recurse_parent);
00862
00863 if (!OPCODE_is_leaf(rpar_opc)) {
00864 if (rpar_opc == OPC_BLOCK) {
00865 for (WN *kid = WN_first(recurse_parent); kid; kid = WN_next(kid))
00866 Infer_Reduction_Operators(kid, reduction_stack);
00867 } else {
00868 for (INT kidno = 0; kidno < WN_kid_count(recurse_parent); kidno++) {
00869 WN *kid = WN_kid(recurse_parent, kidno);
00870 if (kid)
00871 Infer_Reduction_Operators(kid, reduction_stack);
00872 }
00873 }
00874 }
00875 }
00876
00877 if (do_pop) {
00878 redn_pragmas = reduction_stack->Pop();
00879 CXX_DELETE(redn_pragmas, &omp_pool);
00880 }
00881 }
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 static OPERATOR Reduction_Operator(WN *redn_pragma, WN *assign_stmt)
00892 {
00893 WN *opnode = WN_kid0(assign_stmt);
00894 OPERATOR oper = WN_operator(opnode);
00895
00896
00897 while (oper == OPR_CVT || oper == OPR_CVTL || oper == OPR_PAREN ||
00898 oper == OPR_TRUNC || oper == OPR_COMPLEX || oper == OPR_REALPART ||
00899 oper == OPR_IMAGPART) {
00900 opnode = WN_kid0(opnode);
00901 oper = WN_operator(opnode);
00902 }
00903
00904 BOOL oper_ok = TRUE;
00905
00906 switch (oper) {
00907 case OPR_LAND:
00908 case OPR_LIOR:
00909 case OPR_EQ:
00910 case OPR_NE:
00911 case OPR_CAND:
00912 case OPR_CIOR:
00913 case OPR_MAX:
00914 case OPR_MIN:
00915 case OPR_ADD:
00916 case OPR_MPY:
00917 case OPR_SUB:
00918 case OPR_BAND:
00919 case OPR_BIOR:
00920 case OPR_BXOR:
00921 case OPR_DIV:
00922 break;
00923 default:
00924 oper_ok = FALSE;
00925 break;
00926 }
00927
00928 if (!oper_ok) {
00929 #ifndef KEY
00930
00931 ErrMsgLine(EC_MPLOWER_red_badop, WN_Find_Linenum(assign_stmt),
00932 Store_ST(assign_stmt));
00933 #endif // !KEY
00934 return OPERATOR_UNKNOWN;
00935 }
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945 return oper;
00946 }
00947
00948
00949
00950
00951
00952
00953
00954 static BOOL ST_is_Index_Var_For_Enclosing_PDO(ST *var_st, WN *wn)
00955 {
00956 for ( ; wn; wn = Get_Parent(wn)) {
00957
00958 BOOL is_worksharing;
00959 (void) Par_Region_Pragma_Block(wn, &is_worksharing);
00960 if (!is_worksharing)
00961 continue;
00962 WN *construct_prag = WN_first(WN_region_pragmas(wn));
00963 switch (WN_pragma(construct_prag)) {
00964 case WN_PRAGMA_PARALLEL_DO:
00965 case WN_PRAGMA_DOACROSS:
00966 case WN_PRAGMA_PDO_BEGIN:
00967 break;
00968 default:
00969 continue;
00970 }
00971
00972
00973 WN *do_wn = WN_first(WN_region_body(wn));
00974 for ( ; do_wn; do_wn = WN_next(do_wn)) {
00975 if (WN_operator(do_wn) == OPR_DO_LOOP &&
00976 var_st == WN_st(WN_index(do_wn)))
00977 return TRUE;
00978 }
00979 }
00980
00981 return FALSE;
00982 }
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995 static BOOL Inside_Region(WN* wn_barrier, WN_PRAGMA_ID pragma_id)
00996 {
00997 for (WN* wn = wn_barrier; wn != NULL; wn = Get_Parent(wn)) {
00998 if (WN_opcode(wn) == OPC_REGION) {
00999 for (WN* wnn = WN_first(WN_region_pragmas(wn)); wnn != NULL;
01000 wnn = WN_next(wnn)) {
01001 if (WN_operator(wnn) == OPR_PRAGMA && WN_pragma(wnn) == pragma_id)
01002 return TRUE;
01003 }
01004 }
01005 }
01006 return FALSE;
01007 }
01008
01009 static BOOL Immed_Inside_Par_Begin(WN* wn_barrier)
01010 {
01011 for (WN* reg = wn_barrier; reg; reg = Get_Parent(reg)) {
01012 if (WN_opcode(reg) == OPC_REGION) {
01013 for (WN* wn = WN_first(WN_region_pragmas(reg)); wn; wn = WN_next(wn)) {
01014 if (WN_operator(wn) == OPR_PRAGMA && WN_pragma_omp(wn)) {
01015 if (WN_pragma(wn) == WN_PRAGMA_PARALLEL_BEGIN) {
01016 return TRUE;
01017 }
01018 if (WN_pragma(wn) == WN_PRAGMA_SINGLE_PROCESS_BEGIN ||
01019 WN_pragma(wn) == WN_PRAGMA_PARALLEL_DO ||
01020 WN_pragma(wn) == WN_PRAGMA_PDO_BEGIN) {
01021 return FALSE;
01022 }
01023 }
01024 }
01025 }
01026 }
01027 return FALSE;
01028 }
01029
01030 static WN *Translate_OMP_to_MP(WN *wn)
01031 {
01032 OPCODE opcode = WN_opcode(wn);
01033 WN *section = Is_Section_Begin(wn);
01034
01035 #ifdef TARG_SL2 //fork_joint
01036 WN* sl2_section = Is_SL2_Section_Begin(wn);
01037 if(sl2_section) {
01038 Convert_SL2_Section_To_Pdo(wn, sl2_section);
01039 }
01040 #endif
01041
01042 if (section) {
01043 Convert_Section_To_Pdo(wn,section);
01044 }
01045
01046
01047
01048 if (WN_operator(wn) == OPR_INTRINSIC_CALL) {
01049 Lower_Fetch_And_Op(wn);
01050 return NULL;
01051 }
01052
01053 if (WN_opcode(wn) == OPC_REGION && RID_TYPE_mp(REGION_get_rid(wn))) {
01054
01055 #ifndef KEY
01056 Add_Memory_Barriers (wn);
01057 #endif
01058
01059
01060 Convert_Simple_To_Interleaved (wn);
01061
01062 Convert_Just_Chunksize_To_Dynamic (wn);
01063 }
01064
01065
01066
01067
01068 if (OPCODE_is_store(opcode)) {
01069 WN *prev = WN_prev(wn);
01070 if (prev && WN_operator(prev) == OPR_PRAGMA) {
01071 if (WN_pragma(prev) == WN_PRAGMA_ATOMIC) {
01072 Lower_Atomic(prev);
01073 return NULL;
01074 }
01075 }
01076 }
01077
01078 if (Is_Ordered_Do(wn)) {
01079 Add_Ordered_XPragmas (wn);
01080 }
01081
01082 if (opcode == OPC_PRAGMA &&
01083 WN_pragma_omp(wn) &&
01084 WN_pragma(wn) == WN_PRAGMA_CRITICAL_SECTION_BEGIN) {
01085
01086
01087 critical_st.AddElement (WN_st(wn));
01088 }
01089
01090 if (opcode == OPC_PRAGMA &&
01091 WN_pragma_omp(wn) &&
01092 WN_pragma(wn) == WN_PRAGMA_BARRIER) {
01093 if (critical_st.Elements() > 0) {
01094 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(wn),
01095 "The C$OMP BARRIER directive cannot be specified within a C$OMP CRITICAL region");
01096 } else if (!Immed_Inside_Par_Begin(wn)) {
01097 if (Inside_Region(wn, WN_PRAGMA_PARALLEL_DO)) {
01098 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(wn),
01099 "The C$OMP BARRIER directive cannot be specified within a C$OMP PARALLEL DO region");
01100 } else if (Inside_Region(wn, WN_PRAGMA_PDO_BEGIN)) {
01101 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(wn),
01102 "The C$OMP BARRIER directive cannot be specified within a C$OMP DO region");
01103 } else if (Inside_Region(wn, WN_PRAGMA_SINGLE_PROCESS_BEGIN)) {
01104 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(wn),
01105 "The C$OMP BARRIER directive cannot be specified within a C$OMP SINGLE region");
01106 }
01107 }
01108 }
01109
01110 if (opcode == OPC_PRAGMA &&
01111 WN_pragma_omp(wn) &&
01112 WN_pragma(wn) == WN_PRAGMA_CRITICAL_SECTION_END) {
01113
01114 FmtAssert (critical_st.Elements() > 0,
01115 ("Encountered an end-critical without a matching critical"));
01116 ST *crit_begin_st = critical_st[critical_st.Lastidx()];
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141 if (crit_begin_st != NULL && WN_st(wn) != NULL) {
01142 FmtAssert (ST_class(WN_st(wn)) == CLASS_CONST, ("non-CONST class"));
01143 FmtAssert (ST_class(crit_begin_st) == CLASS_CONST, ("non-CONST class"));
01144
01145 TCON &wn_tcon = Tcon_Table[ST_tcon(*WN_st(wn))];
01146 TCON &crit_begin_tcon = Tcon_Table[ST_tcon(*crit_begin_st)];
01147 const INT wn_str_len = Targ_String_Length(wn_tcon);
01148 const INT crit_begin_str_len = Targ_String_Length(crit_begin_tcon);
01149
01150 FmtAssert (wn_str_len == crit_begin_str_len, ("length mismatch"));
01151 FmtAssert (strncmp(Targ_String_Address(wn_tcon),
01152 Targ_String_Address(crit_begin_tcon), wn_str_len) ==
01153 0, ("Name on end-critical differs from begin-critical"));
01154 }
01155
01156 if (crit_begin_st == NULL && WN_st(wn) != NULL)
01157 {
01158
01159
01160 WN_st_idx(wn) = ST_st_idx(critical_st[critical_st.Lastidx()]);
01161
01162 }
01163 if (WN_st(wn) == NULL) {
01164
01165 WN_st_idx(wn) = ST_st_idx(critical_st[critical_st.Lastidx()]);
01166 }
01167
01168 critical_st.Decidx ();
01169 }
01170
01171
01172 if (opcode == OPC_BLOCK) {
01173 WN *kid = WN_first(wn);
01174 while (kid) {
01175 WN *next_kid = WN_next(kid);
01176 Translate_OMP_to_MP(kid);
01177 kid = next_kid;
01178 }
01179 } else {
01180 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01181 Translate_OMP_to_MP(WN_kid(wn,kidno));
01182 }
01183 }
01184 return wn;
01185 }
01186
01187
01188
01189
01190
01191
01192
01193 static void Add_Memory_Barriers (WN *wn) {
01194
01195 WN *pwn = WN_first(WN_region_pragmas(wn));
01196 BOOL add_barriers = FALSE;
01197 while (pwn) {
01198 Is_True (WN_opcode(pwn) == OPC_PRAGMA ||
01199 WN_opcode(pwn) == OPC_XPRAGMA,
01200 ("Expected a PRAGMA node in region pragma block"));
01201
01202
01203
01204 if (WN_pragma(pwn) == WN_PRAGMA_PARALLEL_BEGIN ||
01205 (WN_pragma(pwn) == WN_PRAGMA_PDO_BEGIN && WN_pragma_arg1(pwn) == 0) ||
01206 WN_pragma(pwn) == WN_PRAGMA_SINGLE_PROCESS_BEGIN) {
01207 add_barriers = TRUE;
01208 break;
01209 }
01210 pwn = WN_next(pwn);
01211 }
01212 if (add_barriers) {
01213 if (WN_pragma(pwn) == WN_PRAGMA_SINGLE_PROCESS_BEGIN) {
01214
01215 WN_INSERT_BlockBefore (Get_Parent(wn), wn, WN_CreateBarrier(TRUE,0));
01216
01217
01218 WN_INSERT_BlockBefore (WN_region_body(wn), WN_first(WN_region_body(wn)),
01219 WN_CreateBarrier(FALSE,0));
01220
01221 WN_INSERT_BlockAfter (WN_region_body(wn), WN_last(WN_region_body(wn)),
01222 WN_CreateBarrier(TRUE,0));
01223
01224
01225 WN_INSERT_BlockAfter (Get_Parent(wn), wn, WN_CreateBarrier(FALSE,0));
01226 } else {
01227
01228 #ifdef KEY
01229 if (WN_prev(wn) &&
01230 (WN_operator(WN_prev(wn)) != OPR_BACKWARD_BARRIER ||
01231 WN_operator(WN_prev(wn)) != OPR_FORWARD_BARRIER)){
01232 #endif
01233 WN_INSERT_BlockBefore (Get_Parent(wn), wn, WN_CreateBarrier(TRUE,0));
01234 WN_INSERT_BlockBefore (Get_Parent(wn), wn, WN_CreateBarrier(FALSE,0));
01235 }
01236
01237 WN_INSERT_BlockAfter (Get_Parent(wn), wn, WN_CreateBarrier(FALSE,0));
01238 WN_INSERT_BlockAfter (Get_Parent(wn), wn, WN_CreateBarrier(TRUE,0));
01239 }
01240 Parentize (Get_Parent(wn));
01241 }
01242 }
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255 static void Convert_Just_Chunksize_To_Dynamic (WN *wn_region) {
01256
01257 WN* wn_first_pragma = WN_first(WN_region_pragmas(wn_region));
01258 WN* wn_schedtype = NULL;
01259 WN* wn_chunksize = NULL;
01260
01261 for (WN* wn = wn_first_pragma; wn != NULL; wn = WN_next(wn)) {
01262 if (WN_opcode(wn) == OPC_PRAGMA && WN_pragma(wn)==WN_PRAGMA_MPSCHEDTYPE) {
01263 switch (WN_pragma_arg1(wn)) {
01264 case WN_PRAGMA_SCHEDTYPE_SIMPLE:
01265 case WN_PRAGMA_SCHEDTYPE_DYNAMIC:
01266 case WN_PRAGMA_SCHEDTYPE_GSS:
01267 case WN_PRAGMA_SCHEDTYPE_INTERLEAVE:
01268 case WN_PRAGMA_SCHEDTYPE_RUNTIME:
01269 wn_schedtype = wn;
01270 case WN_PRAGMA_SCHEDTYPE_PSEUDOLOWERED:
01271 FmtAssert(TRUE, ("Should not have seen this pragma yet."));
01272 }
01273 }
01274 if (WN_opcode(wn) == OPC_XPRAGMA && WN_pragma(wn) == WN_PRAGMA_CHUNKSIZE)
01275 wn_chunksize = wn;
01276 }
01277 if (wn_chunksize != NULL && wn_schedtype == NULL) {
01278 wn_schedtype = WN_CreatePragma(WN_PRAGMA_MPSCHEDTYPE, (ST_IDX) NULL,
01279 WN_PRAGMA_SCHEDTYPE_DYNAMIC, 0);
01280 WN_INSERT_BlockAfter(WN_region_pragmas(wn_region), wn_first_pragma,
01281 wn_schedtype);
01282 Set_Parent (wn_schedtype, WN_region_pragmas(wn_region));
01283 }
01284 }
01285
01286
01287
01288
01289
01290
01291
01292
01293 static void Convert_Simple_To_Interleaved (WN *wn) {
01294
01295 WN *pragma_wn = WN_first(WN_region_pragmas(wn));
01296 WN *sched_wn = NULL;
01297 WN *chunk_wn = NULL;
01298
01299 if (!WN_pragma_omp(pragma_wn)) return;
01300
01301 while (pragma_wn) {
01302 if (WN_opcode(pragma_wn) == OPC_PRAGMA &&
01303 WN_pragma(pragma_wn) == WN_PRAGMA_MPSCHEDTYPE) {
01304 sched_wn = pragma_wn;
01305 }
01306 if (WN_opcode(pragma_wn) == OPC_XPRAGMA &&
01307 WN_pragma(pragma_wn) == WN_PRAGMA_CHUNKSIZE) {
01308 chunk_wn = pragma_wn;
01309 }
01310 pragma_wn = WN_next(pragma_wn);
01311 }
01312
01313 if (sched_wn &&
01314 WN_pragma_arg1(sched_wn) == WN_PRAGMA_SCHEDTYPE_SIMPLE &&
01315 chunk_wn) {
01316
01317 WN_pragma_arg1(sched_wn) = WN_PRAGMA_SCHEDTYPE_INTERLEAVE;
01318 }
01319 }
01320
01321 static WN * New_Label()
01322 {
01323 LABEL_IDX label;
01324 (void) New_LABEL (CURRENT_SYMTAB, label);
01325 return WN_CreateLabel (label, 0, NULL);
01326 }
01327
01328
01329 static void Convert_Section_To_Pdo(WN *sections, WN *pragma)
01330 {
01331 MEM_POOL_Popper popper(&Omp_Local_Pool);
01332
01333 if ((WN_PRAGMA_ID)WN_pragma(pragma)==WN_PRAGMA_PSECTION_BEGIN) {
01334 WN_pragma(pragma) = WN_PRAGMA_PDO_BEGIN;
01335 } else {
01336 WN_pragma(pragma) = WN_PRAGMA_PARALLEL_DO;
01337 }
01338 WN_pragma_arg1(pragma) = 0;
01339 WN_pragma_arg2(pragma) = 1;
01340 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled())
01341 WN_MAP32_Set(Prompf_Id_Map, pragma, 0);
01342
01343
01344 WN *end_sec = WN_last(WN_region_body(sections));
01345 if (end_sec && WN_opcode(end_sec) == OPC_PRAGMA &&
01346 ((WN_PRAGMA_ID)WN_pragma(end_sec) == WN_PRAGMA_PSECTION_END)) {
01347 WN_Delete(WN_EXTRACT_FromBlock(WN_region_body(sections),end_sec));
01348 }
01349
01350
01351
01352
01353 STACK_OF_WN *sec_stack = CXX_NEW(STACK_OF_WN(&Omp_Local_Pool),
01354 &Omp_Local_Pool);
01355 WN *tmp = WN_first(WN_region_body(sections));
01356
01357
01358 if (!tmp || WN_opcode(tmp) != OPC_PRAGMA ||
01359 ((WN_PRAGMA_ID)WN_pragma(tmp) != WN_PRAGMA_SECTION)) {
01360 WN *label = New_Label();
01361 WN_INSERT_BlockAfter(WN_region_body(sections),NULL,label);
01362 Set_Parent(label,WN_region_body(sections));
01363 sec_stack->Push(label);
01364 if (tmp) {
01365 WN_Set_Linenum(label,WN_Get_Linenum(tmp));
01366 WN_CopyMap(label, WN_MAP_FEEDBACK,tmp);
01367 }
01368 }
01369
01370
01371 while (tmp) {
01372 WN *next = WN_next(tmp);
01373 if (WN_opcode(tmp) == OPC_PRAGMA &&
01374 ((WN_PRAGMA_ID)WN_pragma(tmp) == WN_PRAGMA_SECTION)) {
01375 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
01376 INT section_id = WN_MAP32_Get(Prompf_Id_Map, tmp);
01377 Prompf_Info->OMPL_Eliminate_Section(section_id);
01378 }
01379 WN *label = New_Label();
01380 WN_INSERT_BlockBefore(WN_region_body(sections),tmp,label);
01381 Set_Parent(label,WN_region_body(sections));
01382 sec_stack->Push(label);
01383 if (next) {
01384 WN_Set_Linenum(label,WN_Get_Linenum(next));
01385 WN_CopyMap(label, WN_MAP_FEEDBACK,next);
01386 }
01387 WN_DELETE_FromBlock(WN_region_body(sections),tmp);
01388 }
01389 tmp = next;
01390 }
01391
01392
01393 ST *index_st = MTYPE_To_PREG(MTYPE_I4);
01394 WN_OFFSET index_offset = Create_Preg(MTYPE_I4,"omp_section");
01395 WN *index = WN_CreateIdname(index_offset,index_st);
01396 WN *lb = WN_StidIntoPreg(MTYPE_I4,index_offset, index_st,
01397 WN_CreateIntconst(OPC_I4INTCONST, 0 ));
01398
01399
01400
01401
01402 WN *ub = WN_LE (MTYPE_I4, WN_LdidPreg (MTYPE_I4,index_offset ),
01403 WN_CreateIntconst(OPC_I4INTCONST,sec_stack->Elements()-1));
01404 WN *incr = WN_StidIntoPreg ( MTYPE_I4, index_offset, index_st,
01405 WN_Add(MTYPE_I4, WN_LdidPreg ( MTYPE_I4,index_offset),
01406 WN_CreateIntconst ( OPC_I4INTCONST,(INT64)1 )));
01407 WN *new_do = WN_CreateDO(index,lb,ub,incr,WN_CreateBlock(),NULL);
01408
01409 WN_Set_Linenum(lb,WN_Get_Linenum(sections));
01410 WN_Set_Linenum(incr,WN_Get_Linenum(sections));
01411 WN_Set_Linenum(new_do,WN_Get_Linenum(sections));
01412 if (Cur_PU_Feedback) {
01413 INT32 region_fb = WN_MAP32_Get(WN_MAP_FEEDBACK,sections);
01414 WN_MAP32_Set(WN_MAP_FEEDBACK,new_do,region_fb);
01415 WN_MAP32_Set(WN_MAP_FEEDBACK,lb,region_fb);
01416 WN_MAP32_Set(WN_MAP_FEEDBACK,incr,sec_stack->Elements()*region_fb);
01417 }
01418
01419
01420 WN *comp_goto_block = WN_CreateBlock();
01421 WN *cgoto = WN_CreateCompgoto(sec_stack->Elements(),
01422 WN_LdidPreg ( MTYPE_I4,index_offset),
01423 comp_goto_block,NULL,0);
01424 WN_Set_Linenum(cgoto,WN_Get_Linenum(new_do));
01425 WN_CopyMap(cgoto, WN_MAP_FEEDBACK,new_do);
01426
01427 INT i;
01428 for (i=0; i<sec_stack->Elements(); i++) {
01429 WN *label_goto =
01430 WN_CreateGoto((ST*) NULL,WN_label_number(sec_stack->Bottom_nth(i)));
01431 WN_Set_Linenum(label_goto,WN_Get_Linenum(new_do));
01432 WN_CopyMap(label_goto, WN_MAP_FEEDBACK,new_do);
01433 WN_INSERT_BlockBefore(comp_goto_block,NULL,label_goto);
01434 }
01435 WN_INSERT_BlockAfter(WN_do_body(new_do),NULL,cgoto);
01436 Parentize(new_do);
01437
01438
01439
01440 WN *region_body = WN_region_body(sections);
01441 while (WN_last(region_body)) {
01442 WN *wn = WN_EXTRACT_FromBlock(region_body,WN_last(region_body));
01443 WN_INSERT_BlockAfter(WN_do_body(new_do),cgoto,wn);
01444 Set_Parent(wn,WN_do_body(new_do));
01445 }
01446
01447
01448
01449 WN *exit_label = New_Label();
01450 for (i=1; i<sec_stack->Elements(); i++) {
01451 WN *exit_goto =
01452 WN_CreateGoto((ST*) NULL,WN_label_number(exit_label));
01453 WN_Set_Linenum(exit_goto,WN_Get_Linenum(sec_stack->Bottom_nth(i-1)));
01454 WN_CopyMap(exit_goto, WN_MAP_FEEDBACK,sec_stack->Bottom_nth(i-1));
01455 WN_INSERT_BlockBefore(WN_do_body(new_do),
01456 sec_stack->Bottom_nth(i),exit_goto);
01457 Set_Parent(exit_goto,WN_do_body(new_do));
01458 }
01459 WN_INSERT_BlockBefore(WN_do_body(new_do),NULL,exit_label);
01460 Set_Parent(exit_label,WN_do_body(new_do));
01461 WN_Set_Linenum(exit_label,WN_Get_Linenum(new_do));
01462 WN_CopyMap(exit_label, WN_MAP_FEEDBACK,new_do);
01463
01464
01465 WN_INSERT_BlockAfter(WN_region_body(sections),NULL,new_do);
01466 Set_Parent(new_do,WN_region_body(sections));
01467
01468
01469 if (sec_stack->Elements() >= 9) {
01470 WN *sched_pragma = WN_CreatePragma(WN_PRAGMA_MPSCHEDTYPE,(ST*) 0,
01471 WN_PRAGMA_SCHEDTYPE_DYNAMIC,0);
01472 WN_INSERT_BlockAfter(WN_region_pragmas(sections),pragma,sched_pragma);
01473 Set_Parent(sched_pragma,WN_region_pragmas(sections));
01474 }
01475 #ifdef KEY
01476 else
01477 {
01478
01479 WN *sched_pragma = WN_CreatePragma(WN_PRAGMA_MPSCHEDTYPE,(ST*) 0,
01480 WN_PRAGMA_SCHEDTYPE_SIMPLE,0);
01481 WN_INSERT_BlockAfter(WN_region_pragmas(sections),pragma,sched_pragma);
01482
01483 WN *chunksize = WN_CreateXpragma (WN_PRAGMA_CHUNKSIZE, (ST_IDX)NULL, 1);
01484 WN_kid0 (chunksize) = WN_Intconst (MTYPE_U4, 1);
01485 WN_INSERT_BlockAfter(WN_region_pragmas(sections),sched_pragma,chunksize);
01486
01487 Set_Parent(sched_pragma,WN_region_pragmas(sections));
01488 Set_Parent(chunksize,WN_region_pragmas(sections));
01489 }
01490 #endif // KEY
01491
01492
01493 WN *local_pragma = WN_CreatePragma(WN_PRAGMA_LOCAL, index_st,index_offset,0);
01494 WN_INSERT_BlockAfter(WN_region_pragmas(sections),pragma,local_pragma);
01495 Set_Parent(local_pragma,WN_region_pragmas(sections));
01496
01497 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
01498 INT loop_id = WN_MAP32_Get(Prompf_Id_Map, sections);
01499 FmtAssert(loop_id != 0,
01500 ("Convert_Section_To_Pdo: Expected id on sections"));
01501 WN_MAP32_Set(Prompf_Id_Map, new_do, loop_id);
01502 Prompf_Info->OMPL_Sections_To_Loop(loop_id);
01503 }
01504 }
01505
01506
01507
01508 static WN *Is_Section_Begin(WN *wn)
01509 {
01510 if (WN_opcode(wn) != OPC_REGION) {
01511 return FALSE;
01512 }
01513 WN *pragmas = WN_region_pragmas(wn);
01514 if (pragmas) {
01515 WN *pragma = WN_first(pragmas);
01516 while (pragma) {
01517 if (WN_opcode(pragma) == OPC_PRAGMA) {
01518 if ((WN_PRAGMA_ID)WN_pragma(pragma)==WN_PRAGMA_PSECTION_BEGIN) {
01519 return pragma;
01520 } else if
01521 ((WN_PRAGMA_ID)WN_pragma(pragma)==WN_PRAGMA_PARALLEL_SECTIONS) {
01522 return pragma;
01523 }
01524 }
01525 pragma = WN_next(pragma);
01526 }
01527 }
01528 return NULL;
01529 }
01530
01531
01532
01533 #ifdef TARG_SL2 //fork_joint
01534 static void Convert_SL2_Section_To_Pdo(WN *sections, WN *pragma)
01535 {
01536 MEM_POOL_Popper popper(&Omp_Local_Pool);
01537
01538 WN_pragma_arg1(pragma) = 0;
01539 WN_pragma_arg2(pragma) = 1;
01540
01541
01542 Is_True(WN_opcode(sections) == OPC_REGION, ("expected a region node"));
01543
01544
01545 WN *end_sec = WN_last(WN_region_body(sections));
01546 if (end_sec && WN_opcode(end_sec) == OPC_PRAGMA &&
01547 ((WN_PRAGMA_ID)WN_pragma(end_sec) == WN_PRAGMA_PSECTION_END)) {
01548 WN_Delete(WN_EXTRACT_FromBlock(WN_region_body(sections),end_sec));
01549 }
01550
01551
01552
01553
01554 STACK_OF_WN *sec_stack = CXX_NEW(STACK_OF_WN(&Omp_Local_Pool),
01555 &Omp_Local_Pool);
01556 WN *tmp = WN_first(WN_region_body(sections));
01557 WN* parent = WN_region_body(sections);
01558
01559 BOOL first_region = TRUE;
01560 while (tmp) {
01561 WN *next = WN_next(tmp);
01562 if(WN_opcode(tmp) == OPC_REGION && WN_first(WN_region_pragmas(tmp)) &&
01563 (WN_pragma(WN_first(WN_region_pragmas(tmp))) == WN_PRAGMA_BARRIER))
01564 {
01565
01566
01567 WN_INSERT_BlockAfter(WN_region_body(tmp), WN_last(WN_region_body(tmp)),
01568 WN_Create_Intrinsic (OPR_INTRINSIC_CALL, MTYPE_V, MTYPE_V,
01569 INTRN_C2_JOINT, 0, 0));
01570
01571 WN_DELETE_FromBlock(WN_region_pragmas(tmp), WN_first(WN_region_pragmas(tmp)));
01572
01573 if( first_region )
01574 first_region = FALSE;
01575 else {
01576 if(Cur_PU_Feedback) {
01577 Cur_PU_Feedback->Annot(tmp, FB_EDGE_CALL_OUTGOING, FB_FREQ_ZERO);
01578 Cur_PU_Feedback->FB_reset_in_out_same_node(tmp);
01579 }
01580 }
01581 }
01582
01583
01584 if (WN_opcode(tmp) == OPC_PRAGMA &&
01585 ((WN_PRAGMA_ID)WN_pragma(tmp) == WN_PRAGMA_SL2_SECTION)) {
01586 WN *label = New_Label();
01587 WN_INSERT_BlockBefore(WN_region_body(sections),tmp,label);
01588 Set_Parent(label,WN_region_body(sections));
01589 sec_stack->Push(label);
01590 if (next) {
01591 WN_Set_Linenum(label,WN_Get_Linenum(next));
01592 WN* next_rgn=next;
01593 while(next_rgn!=NULL && WN_operator(next_rgn)!=OPR_REGION) {
01594 next_rgn=WN_next(next_rgn);
01595 }
01596 FmtAssert(next_rgn!=NULL, ("Convert_SL2_Section_To_Pdo: cannot find next region"));
01597 if(Cur_PU_Feedback) {
01598 FB_FREQ fb_into_region = Cur_PU_Feedback->Query(next_rgn, FB_EDGE_CALL_INCOMING);
01599 FB_Info_Invoke fb_label(fb_into_region);
01600 Cur_PU_Feedback->Annot_invoke(label, fb_label);
01601 }
01602 }
01603 WN_DELETE_FromBlock(WN_region_body(sections),tmp);
01604 }
01605 tmp = next;
01606 }
01607
01608
01609 WN_OFFSET index_offset = Create_Preg(MTYPE_I4,"sl2_section");
01610
01611 WN *comp_goto_block = WN_CreateBlock();
01612
01613 WN *cgoto = WN_CreateCompgoto(sec_stack->Elements(),
01614 WN_LdidPreg ( MTYPE_I4,index_offset),
01615 comp_goto_block,NULL,0);
01616
01617
01618 if((WN_PRAGMA_ID) WN_pragma(pragma) == WN_PRAGMA_SL2_MINOR_PSECTION_BEGIN)
01619
01620 {
01621 WN_Set_is_compgoto_for_minor(cgoto);
01622 }
01623 else if((WN_PRAGMA_ID) WN_pragma(pragma) == WN_PRAGMA_SL2_MAJOR_PSECTION_BEGIN )
01624 {
01625 WN_Set_is_compgoto_para(cgoto);
01626 }
01627
01628 WN_Set_Linenum(cgoto,WN_Get_Linenum(sections));
01629
01630
01631
01632 INT i;
01633 for (i=0; i<sec_stack->Elements(); i++) {
01634 WN *label_goto =
01635 WN_CreateGoto((ST*) NULL,WN_label_number(sec_stack->Bottom_nth(i)));
01636 WN_Set_Linenum(label_goto,WN_Get_Linenum(sections));
01637 WN* label=sec_stack->Bottom_nth(i);
01638 WN_CopyMap(label_goto, WN_MAP_FEEDBACK, label);
01639 WN_INSERT_BlockBefore(comp_goto_block,NULL,label_goto);
01640 }
01641
01642 if(Cur_PU_Feedback) {
01643 INT32 cgoto_size = sec_stack->Elements();
01644 FB_Info_Switch fb_info_sw(cgoto_size + 1 );
01645 fb_info_sw[ FB_EDGE_SWITCH_INDEX( FB_EDGE_SWITCH_DEFAULT ) ]= FB_FREQ_UNKNOWN;
01646 for(i=0;i<cgoto_size;i++) {
01647 WN* label=sec_stack->Bottom_nth(i);
01648 FB_Info_Invoke fb_info_iv = Cur_PU_Feedback->Query_invoke( label );
01649 fb_info_sw[ FB_EDGE_SWITCH_INDEX( FB_EDGE_SWITCH( i ) ) ] = fb_info_iv.freq_invoke;
01650 }
01651 Cur_PU_Feedback->Annot_switch(cgoto, fb_info_sw);
01652 }
01653
01654 WN* tmp_block = WN_CreateBlock();
01655 WN_Set_Linenum(tmp_block, WN_Get_Linenum(sections));
01656 WN_INSERT_BlockAfter(tmp_block, NULL, cgoto);
01657
01658
01659 WN *region_body = WN_region_body(sections);
01660 while (WN_last(region_body)) {
01661 WN *wn = WN_EXTRACT_FromBlock(region_body,WN_last(region_body));
01662 WN_INSERT_BlockAfter(tmp_block, cgoto, wn);
01663 Set_Parent(wn, tmp_block);
01664 }
01665
01666
01667
01668 WN *exit_label = New_Label();
01669 for (i=1; i<sec_stack->Elements(); i++) {
01670 WN *exit_goto = WN_CreateGoto((ST*) NULL,WN_label_number(exit_label));
01671 WN_Set_Linenum(exit_goto,WN_Get_Linenum(sec_stack->Bottom_nth(i-1)));
01672 if(Cur_PU_Feedback) {
01673 WN* prev_label=sec_stack->Bottom_nth(i-1);
01674 WN* exit_rgn=WN_next(prev_label);
01675 while(exit_rgn!=NULL && WN_operator(exit_rgn)!=OPR_REGION) {
01676 exit_rgn=WN_next(exit_rgn);
01677 }
01678 FmtAssert(exit_rgn!=NULL, ("Convert_SL2_Section_To_Pdo: cannot find next region"));
01679 if(Cur_PU_Feedback) {
01680 FB_FREQ fb_out_region = Cur_PU_Feedback->Query(exit_rgn, FB_EDGE_CALL_OUTGOING);
01681 FB_Info_Invoke fb_goto(fb_out_region);
01682 Cur_PU_Feedback->Annot_invoke(exit_goto, fb_goto);
01683 }
01684 }
01685 WN_INSERT_BlockBefore(tmp_block,
01686 sec_stack->Bottom_nth(i),exit_goto);
01687 Set_Parent(exit_goto, tmp_block);
01688 }
01689
01690 if(Cur_PU_Feedback)
01691 Cur_PU_Feedback->Annot(exit_label, FB_EDGE_INCOMING,
01692 Cur_PU_Feedback->Query(sections, FB_EDGE_CALL_OUTGOING));
01693
01694 WN_INSERT_BlockBefore(tmp_block, NULL,exit_label);
01695
01696
01697
01698 WN_INSERT_BlockAfter(WN_region_body(sections), NULL, tmp_block);
01699 Parentize(WN_region_body(sections));
01700
01701 }
01702
01703
01704 static WN *Is_SL2_Section_Begin(WN *wn)
01705 {
01706 if (WN_opcode(wn) != OPC_REGION) {
01707 return FALSE;
01708 }
01709 WN *pragmas = WN_region_pragmas(wn);
01710 if (pragmas) {
01711 WN *pragma = WN_first(pragmas);
01712 while (pragma) {
01713 if (WN_opcode(pragma) == OPC_PRAGMA) {
01714 if ((WN_PRAGMA_ID)WN_pragma(pragma)==WN_PRAGMA_SL2_MAJOR_PSECTION_BEGIN
01715 || (WN_PRAGMA_ID) WN_pragma(pragma) == WN_PRAGMA_SL2_MINOR_PSECTION_BEGIN) {
01716 return pragma;
01717 }
01718 }
01719 pragma = WN_next(pragma);
01720 }
01721 }
01722 return NULL;
01723 }
01724 #endif //fork_joint
01725
01726
01727
01728
01729
01730 static ST *Create_Omp_Get_Thread_Num()
01731 {
01732 static ST *result=NULL;
01733 if (result) return result;
01734
01735 TY_IDX func_ty_idx;
01736 TY& func_ty = New_TY(func_ty_idx);
01737
01738 TY_Init (func_ty, 0, KIND_FUNCTION, MTYPE_UNKNOWN,
01739 Save_Str(".omp_get_thread_num_"));
01740
01741 TYLIST_IDX tylist_idx;
01742 TYLIST& tylist = New_TYLIST (tylist_idx);
01743 Set_TY_tylist (func_ty, tylist_idx);
01744 Set_TYLIST_type (tylist, Be_Type_Tbl(MTYPE_I4));
01745 Set_TYLIST_type (New_TYLIST(tylist_idx), 0);
01746
01747 PU_IDX pu_idx;
01748 PU& pu = New_PU(pu_idx);
01749 PU_Init(pu, func_ty_idx, CURRENT_SYMTAB);
01750
01751
01752 result = New_ST (GLOBAL_SYMTAB);
01753 ST_Init (result,
01754 Save_Str("omp_get_thread_num_"),
01755 CLASS_FUNC,
01756 SCLASS_EXTERN,
01757 EXPORT_PREEMPTIBLE,
01758 pu_idx);
01759 return result;
01760 }
01761
01762
01763
01764
01765
01766 static void Atomic_Using_Critical(WN *atomic, WN *store)
01767 {
01768 WN *parent = Get_Parent(atomic);
01769 INT64 line = WN_Get_Linenum(atomic);
01770
01771 char name[25];
01772 switch (WN_desc(store)) {
01773 case MTYPE_I1:
01774 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_I1");
01775 break;
01776 case MTYPE_I2:
01777 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_I2");
01778 break;
01779 case MTYPE_I4:
01780 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_I4");
01781 break;
01782 case MTYPE_I8:
01783 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_I8");
01784 break;
01785 case MTYPE_U1:
01786 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_U1");
01787 break;
01788 case MTYPE_U2:
01789 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_U2");
01790 break;
01791 case MTYPE_U4:
01792 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_U4");
01793 break;
01794 case MTYPE_U8:
01795 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_U8");
01796 break;
01797 case MTYPE_F4:
01798 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_F4");
01799 break;
01800 case MTYPE_F8:
01801 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_F8");
01802 break;
01803 #ifdef TARG_IA64
01804 case MTYPE_F10:
01805 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_F10");
01806 break;
01807 #endif
01808 case MTYPE_FQ:
01809 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_FQ");
01810 break;
01811 case MTYPE_C4:
01812 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_C4");
01813 break;
01814 case MTYPE_C8:
01815 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_C8");
01816 break;
01817 #ifdef TARG_IA64
01818 case MTYPE_C10:
01819 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_C10");
01820 break;
01821 #endif
01822 case MTYPE_CQ:
01823 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_CQ");
01824 break;
01825 default:
01826 sprintf(name,"%s","__OMP_CRITICAL_ATOMIC_??");
01827 break;
01828 }
01829 name[24] = 0;
01830 TCON tc = Host_To_Targ_String ( MTYPE_STRING, name,strlen(name));
01831 ST *string = Gen_String_Sym (&tc, MTYPE_To_TY(MTYPE_STRING), FALSE );
01832 WN *critical1 = WN_CreatePragma(WN_PRAGMA_CRITICAL_SECTION_BEGIN,string,0,0);
01833 WN_set_pragma_compiler_generated(critical1);
01834 WN_set_pragma_omp(critical1);
01835 WN_INSERT_BlockBefore(parent,atomic,critical1);
01836 Set_Parent(critical1,parent);
01837 WN_Set_Linenum(critical1,line);
01838 WN_CopyMap(critical1, WN_MAP_FEEDBACK,atomic);
01839
01840 WN *bb = WN_CreateBarrier(FALSE, 0);
01841 WN_INSERT_BlockBefore(parent,atomic,bb);
01842 Set_Parent(bb,parent);
01843 WN_Set_Linenum(bb,line);
01844 WN_CopyMap(bb, WN_MAP_FEEDBACK,atomic);
01845
01846 WN *fb = WN_CreateBarrier(TRUE, 0);
01847 WN_INSERT_BlockAfter(parent,store,fb);
01848 Set_Parent(fb,parent);
01849 WN_Set_Linenum(fb,line);
01850 WN_CopyMap(fb, WN_MAP_FEEDBACK,atomic);
01851
01852 WN* critical2 = WN_CreatePragma(WN_PRAGMA_CRITICAL_SECTION_END,string,0,0);
01853 WN_set_pragma_compiler_generated(critical2);
01854 WN_set_pragma_omp(critical2);
01855 WN_INSERT_BlockAfter(parent,fb,critical2);
01856 Set_Parent(critical2,parent);
01857 WN_Set_Linenum(critical2,line);
01858 WN_CopyMap(critical2, WN_MAP_FEEDBACK,atomic);
01859
01860 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
01861 INT old_id = WN_MAP32_Get(Prompf_Id_Map, atomic);
01862 WN_MAP32_Set(Prompf_Id_Map, critical1, old_id);
01863 WN_MAP32_Set(Prompf_Id_Map, critical2, old_id);
01864 Prompf_Info->OMPL_Atomic_To_Critical_Section(old_id);
01865 }
01866
01867 WN_DELETE_FromBlock(parent,atomic);
01868 }
01869
01870
01871
01872 static BOOL Direct_Memory(WN *wn1)
01873 {
01874 OPERATOR oper = WN_operator(wn1);
01875 return oper == OPR_LDID || oper == OPR_STID;
01876 }
01877
01878 static BOOL Equiv_Expression(WN *wn1, WN *wn2)
01879 {
01880 if (!WN_Equiv(wn1,wn2)) return FALSE;
01881 for (INT kidno=0; kidno<WN_kid_count(wn1); kidno++) {
01882 if (!Equiv_Expression(WN_kid(wn1,kidno),WN_kid(wn2,kidno))) {
01883 return FALSE;
01884 }
01885 }
01886 return TRUE;
01887 }
01888
01889
01890 static BOOL Same_Location(WN *wn1, WN *wn2)
01891 {
01892 OPCODE opc1 = WN_opcode(wn1);
01893 OPCODE opc2 = WN_opcode(wn2);
01894 if (!OPCODE_is_load(opc1) && !OPCODE_is_store(opc1)) return FALSE;
01895 if (!OPCODE_is_load(opc2) && !OPCODE_is_store(opc2)) return FALSE;
01896 if (WN_offset(wn1) != WN_offset(wn2)) return FALSE;
01897 if (Direct_Memory(wn1)) {
01898 if (!Direct_Memory(wn2)) return FALSE;
01899 return WN_st(wn1) == WN_st(wn2);
01900 }
01901 if (Direct_Memory(wn2)) return FALSE;
01902 WN *addr_kid1, *addr_kid2;
01903 if (OPCODE_is_store(opc1)) {
01904 addr_kid1 = WN_kid1(wn1);
01905 } else {
01906 addr_kid1 = WN_kid0(wn1);
01907 }
01908 if (OPCODE_is_store(opc2)) {
01909 addr_kid2 = WN_kid1(wn2);
01910 } else {
01911 addr_kid2 = WN_kid0(wn2);
01912 }
01913 return Equiv_Expression(addr_kid1,addr_kid2);
01914 }
01915
01916
01917
01918 static WN *Find_Same_Location(WN *loc,WN *wn)
01919 {
01920 if (Same_Location(loc,wn)) {
01921 return wn;
01922 } else {
01923 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01924 WN *tmp;
01925 tmp = Find_Same_Location(loc,WN_kid(wn,kidno));
01926 if (tmp) return tmp;
01927 }
01928 return NULL;
01929 }
01930 }
01931
01932 #ifdef KEY
01933
01934
01935 static WN *Find_Same_Location_And_Parent(WN *loc, WN *wn,
01936 WN ** parent, int * kidnum)
01937 {
01938 if (Same_Location(loc,wn)) {
01939 return wn;
01940 } else {
01941
01942 if (WN_operator (wn) == OPR_BLOCK)
01943 return NULL;
01944 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01945 WN *tmp;
01946 tmp = Find_Same_Location_And_Parent(loc,WN_kid(wn,kidno), parent, kidnum);
01947 if (tmp)
01948 {
01949 if (WN_kid (wn, kidno) == tmp)
01950 {
01951 *kidnum = kidno;
01952 *parent = wn;
01953 }
01954 return tmp;
01955 }
01956 }
01957 return NULL;
01958 }
01959 }
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975 static BOOL format_rhs_atomic_stmt (WN * store)
01976 {
01977 WN * op = WN_kid0 (store);
01978
01979 if (WN_operator (op) != OPR_ADD && WN_operator (op) != OPR_SUB)
01980 return FALSE;
01981
01982
01983 WN * parent;
01984 int kidno;
01985 WN * find = Find_Same_Location_And_Parent (store, op, &parent, &kidno);
01986 FmtAssert (find, ("Invalid atomic operation stmt"));
01987 Is_True (WN_kid (parent, kidno) == find, ("Operand mismatch"));
01988
01989 WN_kid (parent, kidno) = WN_Intconst (WN_rtype (find), 0);
01990
01991 WN * add = WN_Create (OPR_ADD, WN_rtype (op), MTYPE_V, 2);
01992 WN_kid0 (add) = find;
01993 WN_kid1 (add) = op;
01994 WN_kid0 (store) = add;
01995 return TRUE;
01996 }
01997 #endif // KEY
01998
01999
02000
02001
02002
02003
02004 static ST * Create_Local_Symbol (const char* name, TYPE_ID mtype)
02005 {
02006 ST* st = New_ST(CURRENT_SYMTAB);
02007 ST_Init (st,
02008 Save_Str(name),
02009 CLASS_VAR,
02010 SCLASS_AUTO,
02011 EXPORT_LOCAL,
02012 Be_Type_Tbl(mtype));
02013
02014 Set_ST_is_temp_var(st);
02015 return st;
02016 }
02017
02018
02019
02020
02021
02022
02023
02024 static void Update_Private(ST *st, WN *wn)
02025 {
02026
02027
02028
02029
02030 WN_VECTOR wnv(Malloc_Mem_Pool);
02031
02032 WN *tmp = wn;
02033 while (tmp) {
02034 if (WN_opcode(tmp) == OPC_REGION &&
02035 RID_TYPE_mp(REGION_get_rid(tmp))) {
02036 wnv.push_back (tmp);
02037 }
02038 tmp = Get_Parent(tmp);
02039 }
02040
02041 Add_Pragma_To_MP_Regions (&wnv, WN_PRAGMA_LOCAL,
02042 st, 0, Omp_Parent_Map, FALSE);
02043
02044 }
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074 WN *
02075 Atomic_Using_Swap(WN *atomic, WN *store, WN *operation, WN *parent,
02076 Update_Private_Func upf, ST *x2, ST *x3)
02077 {
02078 WN *retblock = WN_CreateBlock();
02079
02080 INT64 line = WN_Get_Linenum(atomic);
02081 OPCODE store_opc = WN_opcode(store);
02082
02083
02084 WN *expr_kid;
02085 WN *var_kid;
02086 WN *bnot=NULL;
02087
02088
02089 if (WN_operator(operation) == OPR_BNOT) {
02090 bnot = operation;
02091 operation = WN_kid0(operation);
02092 }
02093
02094 BOOL unpatterned = FALSE;
02095 if (Same_Location(store,WN_kid0(operation))) {
02096 var_kid = WN_kid0(operation);
02097 expr_kid = WN_kid1(operation);
02098 } else if (WN_kid_count(operation) == 2 &&
02099 Same_Location(store,WN_kid1(operation))) {
02100 var_kid = WN_kid1(operation);
02101 expr_kid = WN_kid0(operation);
02102 } else {
02103 var_kid = Find_Same_Location(store,operation);
02104 if (!var_kid) {
02105 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(atomic),
02106 "OMP ATOMIC: Right hand side not of appropriate form. \n");
02107 return NULL;
02108 }
02109 unpatterned = TRUE;
02110 }
02111
02112
02113 TYPE_ID type = OPCODE_desc(store_opc);
02114 TYPE_ID swap_type;
02115 if (type == MTYPE_I4 || type == MTYPE_U4 || type == MTYPE_F4) {
02116 swap_type = MTYPE_I4;
02117 } else {
02118 Is_True(type == MTYPE_I8 || type == MTYPE_U8 || type == MTYPE_F8,
02119 ("Bad type in Atomic_Using_Swap"));
02120 swap_type = MTYPE_I8;
02121 }
02122
02123
02124 ST *done_st = MTYPE_To_PREG(Boolean_type);
02125 WN_OFFSET done_offset = Create_Preg(Boolean_type,"done");
02126 WN *stid = WN_StidIntoPreg ( Boolean_type, done_offset,done_st,
02127 WN_CreateIntconst(OPCODE_make_op(OPR_INTCONST,Boolean_type,MTYPE_V),0));
02128 WN_INSERT_BlockBefore(retblock, NULL, stid);
02129 WN_Set_Linenum(stid,line);
02130 WN_CopyMap(stid, WN_MAP_FEEDBACK,atomic);
02131
02132
02133 ST *expr_st=NULL;
02134 if (!unpatterned) {
02135 WN *expr_copy = WN_COPY_Tree(expr_kid);
02136 expr_st = Create_Local_Symbol("rhs_tmp",type);
02137 stid = WN_Stid(type,0,expr_st,Be_Type_Tbl(type),
02138 expr_copy);
02139 WN_INSERT_BlockBefore(retblock, NULL, stid);
02140 WN_Set_Linenum(stid,line);
02141 WN_CopyMap(stid, WN_MAP_FEEDBACK,atomic);
02142 if (upf) Update_Private(expr_st,parent);
02143 }
02144
02145
02146 WN *while_wn=WN_CreateWhileDo(WN_LNOT(WN_LdidPreg(Boolean_type,done_offset)),
02147 WN_CreateBlock());
02148 WN_INSERT_BlockBefore(retblock, NULL, while_wn);
02149 WN_Set_Linenum(while_wn,line);
02150 WN_CopyMap(while_wn, WN_MAP_FEEDBACK,atomic);
02151
02152
02153 WN *var_copy = WN_COPY_Tree(var_kid);
02154 #ifdef KEY // bug 5264
02155 if (MTYPE_is_float(type) != MTYPE_is_float(swap_type)) {
02156 #else
02157 if (type != swap_type) {
02158 #endif
02159 var_copy = WN_Tas(swap_type,Be_Type_Tbl(swap_type),var_copy);
02160 }
02161 ST *var_st;
02162 if (!x2) {
02163 var_st = Create_Local_Symbol("var_tmp",swap_type);
02164 } else {
02165 var_st = x2;
02166 }
02167 stid = WN_Stid(swap_type,0,var_st,
02168 Be_Type_Tbl(swap_type),
02169 var_copy);
02170 WN_INSERT_BlockBefore(WN_while_body(while_wn),NULL,stid);
02171 WN_Set_Linenum(stid,line);
02172 WN_CopyMap(stid, WN_MAP_FEEDBACK,atomic);
02173
02174
02175
02176 WN *bar = WN_CreateBarrier(TRUE, 0);
02177 WN_INSERT_BlockAfter(WN_while_body(while_wn),stid,bar);
02178 WN_Set_Linenum(bar,line);
02179 WN_CopyMap(bar, WN_MAP_FEEDBACK,atomic);
02180 bar = WN_CreateBarrier(FALSE, 0);
02181 WN_INSERT_BlockAfter(WN_while_body(while_wn),stid,bar);
02182 WN_Set_Linenum(bar,line);
02183 WN_CopyMap(bar, WN_MAP_FEEDBACK,atomic);
02184
02185 if (upf) Update_Private(var_st,parent);
02186
02187
02188
02189 ST *result_st;
02190 WN *new_op;
02191 if (!x3) {
02192 result_st = Create_Local_Symbol("result_tmp",swap_type);
02193 } else {
02194 result_st = x3;
02195 }
02196 if (!unpatterned) {
02197 new_op = WN_CopyNode(operation);
02198 #ifdef KEY
02199 WN *new_var_kid = WN_Ldid(swap_type, 0, var_st, Be_Type_Tbl(type));
02200 if (MTYPE_is_float(type) != MTYPE_is_float(swap_type))
02201 new_var_kid = WN_Tas(type, Be_Type_Tbl(type), new_var_kid);
02202 #endif
02203
02204 if (expr_kid == WN_kid1(operation)) {
02205 #ifdef KEY // bug 5512
02206 WN_kid0(new_op) = new_var_kid;
02207 #else
02208 WN_kid0(new_op) = WN_COPY_Tree(var_kid);
02209 #endif
02210 WN_kid1(new_op) = WN_Ldid(type,0,expr_st,
02211 Be_Type_Tbl(type));
02212 } else {
02213 Is_True(expr_kid == WN_kid0(operation),("Bad kid in Atomic_Using_Swap"));
02214 #ifdef KEY // bug 5512
02215 WN_kid1(new_op) = new_var_kid;
02216 #else
02217 WN_kid1(new_op) = WN_COPY_Tree(var_kid);
02218 #endif
02219 WN_kid0(new_op) = WN_Ldid(type,0,expr_st,
02220 Be_Type_Tbl(type));
02221 }
02222 if (bnot) {
02223 new_op = WN_Bnot(WN_rtype(bnot),new_op);
02224 }
02225 } else {
02226 new_op = WN_COPY_Tree(operation);
02227 }
02228 #ifdef KEY // bug 5264
02229 if (MTYPE_is_float(type) != MTYPE_is_float(swap_type)) {
02230 #else
02231 if (type != swap_type) {
02232 #endif
02233 new_op = WN_Tas(swap_type,Be_Type_Tbl(swap_type),new_op);
02234 }
02235 stid = WN_Stid(swap_type,0,result_st,
02236 Be_Type_Tbl(swap_type),
02237 new_op);
02238 WN_INSERT_BlockBefore(WN_while_body(while_wn),NULL,stid);
02239 WN_Set_Linenum(stid,line);
02240 if (upf) Update_Private(result_st,parent);
02241
02242 WN *fb = WN_CreateBarrier(TRUE, 0);
02243 WN_INSERT_BlockAfter(WN_while_body(while_wn),stid,fb);
02244 WN_Set_Linenum(fb,line);
02245 WN_CopyMap(fb, WN_MAP_FEEDBACK,atomic);
02246
02247
02248
02249
02250 WN *var_addr;
02251 if (WN_operator(var_kid) == OPR_LDID) {
02252 OPCODE lda_op = OPCODE_make_op(OPR_LDA, Pointer_type, MTYPE_V);
02253 var_addr = WN_CreateLda(lda_op, WN_offset(var_kid),
02254 Make_Pointer_Type(WN_ty(var_kid),FALSE),
02255 WN_st(var_kid));
02256 } else {
02257 var_addr = WN_COPY_Tree(WN_kid0(var_kid));
02258 }
02259 WN *kids[3];
02260 kids[0] = WN_CreateParm(Pointer_type, var_addr,Be_Type_Tbl(Pointer_type),
02261 WN_PARM_BY_REFERENCE);
02262 WN *tmp = WN_Ldid(swap_type,0,var_st, Be_Type_Tbl(swap_type));
02263 kids[1] = WN_CreateParm(swap_type,tmp,Be_Type_Tbl(swap_type),
02264 WN_PARM_BY_VALUE);
02265 tmp = WN_Ldid(swap_type,0,result_st, Be_Type_Tbl(swap_type));
02266 kids[2] = WN_CreateParm(swap_type,tmp,Be_Type_Tbl(swap_type),
02267 WN_PARM_BY_VALUE);
02268
02269 WN *c_s;
02270 if (swap_type == MTYPE_I4) {
02271 c_s=WN_Create_Intrinsic(OPC_U4INTRINSIC_CALL,
02272 INTRN_COMPARE_AND_SWAP_I4,3,kids);
02273 } else {
02274 c_s=WN_Create_Intrinsic(OPC_U8INTRINSIC_CALL,
02275 INTRN_COMPARE_AND_SWAP_I8,3,kids);
02276 }
02277 WN_Set_Call_Parm_Mod(c_s);
02278 WN_Set_Call_Parm_Ref(c_s);
02279 WN_INSERT_BlockBefore(WN_while_body(while_wn),NULL,c_s);
02280 WN_Set_Linenum(c_s,line);
02281 WN_CopyMap(c_s, WN_MAP_FEEDBACK,atomic);
02282
02283
02284 PREG_NUM rreg1, rreg2;
02285 ST* rst = Find_Return_Registers (Pointer_type, &rreg1, &rreg2);
02286 FmtAssert(rreg1 != 0 && rreg2 == 0, ("Bad pointer type ret regs"));
02287 stid = WN_StidIntoPreg ( Boolean_type, done_offset,done_st,
02288 WN_CreateLdid (OPCODE_make_op(OPR_LDID, Pointer_type, Pointer_type),
02289 rreg1, rst, Be_Type_Tbl(Pointer_type)));
02290 WN_INSERT_BlockAfter(WN_while_body(while_wn),c_s,stid);
02291 WN_Set_Linenum(stid,line);
02292 WN_CopyMap(stid, WN_MAP_FEEDBACK,atomic);
02293
02294 WN *bb = WN_CreateBarrier(FALSE, 0);
02295 WN_INSERT_BlockAfter(WN_while_body(while_wn),stid,bb);
02296 WN_Set_Linenum(bb,line);
02297 WN_CopyMap(bb, WN_MAP_FEEDBACK,atomic);
02298
02299 return retblock;
02300 }
02301
02302
02303
02304 WN *Atomic_Direct(WN *atomic, WN *store, WN *operation)
02305 {
02306 WN *retblock = WN_CreateBlock();
02307
02308 INT64 line = WN_Get_Linenum(atomic);
02309 OPCODE store_opc = WN_opcode(store);
02310 OPERATOR oper = WN_operator(operation);
02311
02312
02313 WN *expr_kid;
02314 WN *var_kid;
02315 #ifdef KEY
02316 for (INT i=0; i<2; i++)
02317 {
02318 if (Same_Location(store,WN_kid0(operation))) {
02319 var_kid = WN_kid0(operation);
02320 expr_kid = WN_kid1(operation);
02321 break;
02322 } else if (Same_Location(store,WN_kid1(operation))) {
02323 var_kid = WN_kid1(operation);
02324 expr_kid = WN_kid0(operation);
02325 break;
02326 } else {
02327 BOOL format_ok = format_rhs_atomic_stmt (store);
02328 if (!format_ok)
02329 {
02330 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(atomic),
02331 "OMP ATOMIC: Right hand side not of appropriate form. \n");
02332 return NULL;
02333 }
02334
02335 operation = WN_kid0 (store);
02336 oper = WN_operator (operation);
02337 }
02338 }
02339 #else
02340 if (Same_Location(store,WN_kid0(operation))) {
02341 var_kid = WN_kid0(operation);
02342 expr_kid = WN_kid1(operation);
02343 } else if (Same_Location(store,WN_kid1(operation))) {
02344 var_kid = WN_kid1(operation);
02345 expr_kid = WN_kid0(operation);
02346 } else {
02347 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(atomic),
02348 "OMP ATOMIC: Right hand side not of appropriate form. \n");
02349 return NULL;
02350 }
02351 #endif // KEY
02352
02353 TYPE_ID type = OPCODE_desc(store_opc);
02354 Is_True(type == MTYPE_I4 || type == MTYPE_I8,("Bad type in Atomic_Direct"));
02355
02356
02357
02358 WN *var_addr;
02359 if (WN_operator(var_kid) == OPR_LDID) {
02360 OPCODE lda_op = OPCODE_make_op(OPR_LDA, Pointer_type, MTYPE_V);
02361 var_addr = WN_CreateLda(lda_op, WN_offset(var_kid),
02362 Make_Pointer_Type(WN_ty(var_kid),FALSE),
02363 WN_st(var_kid));
02364 } else {
02365 var_addr = WN_COPY_Tree(WN_kid0(var_kid));
02366 }
02367 WN *kids[2];
02368 kids[0] = WN_CreateParm(Pointer_type,var_addr,Be_Type_Tbl(Pointer_type),
02369 WN_PARM_BY_REFERENCE);
02370 kids[1] = WN_CreateParm(type,WN_COPY_Tree(expr_kid),Be_Type_Tbl(type),
02371 WN_PARM_BY_VALUE);
02372
02373 INTRINSIC intrinsic_type;
02374 if (type == MTYPE_I4) {
02375 switch (oper) {
02376 case OPR_ADD: intrinsic_type = INTRN_FETCH_AND_ADD_I4; break;
02377 case OPR_SUB: intrinsic_type = INTRN_FETCH_AND_SUB_I4; break;
02378 case OPR_BAND: intrinsic_type = INTRN_FETCH_AND_AND_I4; break;
02379 case OPR_BIOR: intrinsic_type = INTRN_FETCH_AND_OR_I4; break;
02380 case OPR_BXOR: intrinsic_type = INTRN_FETCH_AND_XOR_I4; break;
02381 default: Is_True(0,("Bad intrinsic type in Atomic_Direct"));
02382 }
02383 } else {
02384 switch (oper) {
02385 case OPR_ADD: intrinsic_type = INTRN_FETCH_AND_ADD_I8; break;
02386 case OPR_SUB: intrinsic_type = INTRN_FETCH_AND_SUB_I8; break;
02387 case OPR_BAND: intrinsic_type = INTRN_FETCH_AND_AND_I8; break;
02388 case OPR_BIOR: intrinsic_type = INTRN_FETCH_AND_OR_I8; break;
02389 case OPR_BXOR: intrinsic_type = INTRN_FETCH_AND_XOR_I8; break;
02390 default: Is_True(0,("Bad intrinsic type in Atomic_Direct"));
02391 }
02392 }
02393
02394 WN *fetch_and_op;
02395 if (type == MTYPE_I4) {
02396 fetch_and_op=WN_Create_Intrinsic(OPC_I4INTRINSIC_CALL,
02397 intrinsic_type,2,kids);
02398 } else {
02399 fetch_and_op=WN_Create_Intrinsic(OPC_I8INTRINSIC_CALL,
02400 intrinsic_type,2,kids);
02401 }
02402 WN_Set_Call_Parm_Mod(fetch_and_op);
02403 WN_Set_Call_Parm_Ref(fetch_and_op);
02404 WN_INSERT_BlockBefore(retblock, NULL, fetch_and_op);
02405 WN_Set_Linenum(fetch_and_op,line);
02406 WN_CopyMap(atomic, WN_MAP_FEEDBACK,fetch_and_op);
02407
02408 WN *fb = WN_CreateBarrier(TRUE, 0);
02409 WN_INSERT_BlockBefore(retblock, fetch_and_op, fb);
02410 WN_Set_Linenum(fb,line);
02411 WN_CopyMap(fb, WN_MAP_FEEDBACK,atomic);
02412
02413 WN *bb = WN_CreateBarrier(FALSE, 0);
02414 WN_INSERT_BlockAfter(retblock, fetch_and_op, bb);
02415 WN_Set_Linenum(bb,line);
02416 WN_CopyMap(bb, WN_MAP_FEEDBACK,atomic);
02417
02418 return retblock;
02419 }
02420
02421
02422
02423
02424
02425 WN *
02426 Get_ATOMIC_Update_LDA(WN *wn)
02427 {
02428 Is_True(wn, ("NULL wn"));
02429 Is_True(WN_operator(wn) == OPR_INTRINSIC_CALL, ("not an intrinsic call"));
02430
02431 switch (WN_intrinsic(wn)) {
02432
02433 case INTRN_FETCH_AND_ADD_I4:
02434 case INTRN_FETCH_AND_SUB_I4:
02435 case INTRN_FETCH_AND_AND_I4:
02436 case INTRN_FETCH_AND_OR_I4:
02437 case INTRN_FETCH_AND_XOR_I4:
02438 case INTRN_FETCH_AND_ADD_I8:
02439 case INTRN_FETCH_AND_SUB_I8:
02440 case INTRN_FETCH_AND_AND_I8:
02441 case INTRN_FETCH_AND_OR_I8:
02442 case INTRN_FETCH_AND_XOR_I8:
02443
02444 case INTRN_COMPARE_AND_SWAP_I4:
02445 case INTRN_COMPARE_AND_SWAP_I8:
02446 break;
02447 default:
02448 return NULL;
02449 }
02450
02451 WN *parm0 = WN_kid0(wn);
02452 Is_True(parm0 && WN_operator(parm0) == OPR_PARM, ("bad parameter"));
02453 parm0 = WN_kid0(parm0);
02454
02455
02456
02457 if (WN_operator(parm0) == OPR_LDA)
02458 return parm0;
02459 else if (WN_operator(parm0) != OPR_ARRAY)
02460 return NULL;
02461
02462 WN *array_base = WN_kid0(parm0);
02463 if (WN_operator(array_base) == OPR_LDA)
02464 return array_base;
02465
02466 return NULL;
02467 }
02468
02469
02470
02471
02472 static void
02473 Insert_Lowered_Atomic(WN *parent, WN *atomic, WN *atomic_block,
02474 ATOMIC_Lowering_Class alclass)
02475 {
02476 if (!atomic_block) {
02477 WN_DELETE_FromBlock(parent, WN_next(atomic));
02478 WN_DELETE_FromBlock(parent, atomic);
02479 return;
02480 }
02481 Is_True(WN_opcode(atomic_block) == OPC_BLOCK,
02482 ("bad atomic_block"));
02483 for (WN *wn = WN_first(atomic_block); wn; ) {
02484 WN *wn2 = WN_next(wn);
02485 WN_EXTRACT_FromBlock(atomic_block, wn);
02486 Parentize(wn);
02487 Set_Parent(wn, parent);
02488 WN_INSERT_BlockBefore(parent, atomic, wn);
02489 wn = wn2;
02490 }
02491 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
02492 INT old_id = WN_MAP32_Get(Prompf_Id_Map, atomic);
02493 if (alclass == ALCLASS_SWAP)
02494 Prompf_Info->OMPL_Atomic_To_Swap(old_id);
02495 else if (alclass == ALCLASS_DIRECT)
02496 Prompf_Info->OMPL_Atomic_To_FetchAndOp(old_id);
02497 else
02498 Fail_FmtAssertion("bad alclass == %d", (INT) alclass);
02499 }
02500
02501 WN_Delete(atomic_block);
02502 WN_DELETE_FromBlock(parent, WN_next(atomic));
02503 WN_DELETE_FromBlock(parent, atomic);
02504 }
02505
02506
02507 static void Lower_Atomic(WN *atomic)
02508 {
02509 WN *store = WN_next(atomic);
02510
02511 if (OPCODE_is_store(WN_opcode(store)) &&
02512 (!WN_kid_count(WN_kid0(store))) ||
02513 (OPCODE_is_load(WN_opcode(WN_kid0(store))))) {
02514 TYPE_ID store_type = OPCODE_desc(WN_opcode(store));
02515 ErrMsgSrcpos(EC_MPLOWER_Generic_Warning, WN_Get_Linenum(atomic),
02516 "OMP ATOMIC directive simplifies into a store. \n");
02517 switch (store_type) {
02518 case MTYPE_I4: case MTYPE_I8: case MTYPE_I1: case MTYPE_I2:
02519 case MTYPE_U4: case MTYPE_U8: case MTYPE_U1: case MTYPE_U2:
02520 case MTYPE_F4: case MTYPE_F8:
02521 {
02522 WN *parent = Get_Parent(atomic);
02523 WN_DELETE_FromBlock(parent,atomic);
02524 }
02525 break;
02526 default:
02527 Atomic_Using_Critical(atomic, store);
02528 break;
02529 }
02530 return;
02531 }
02532
02533 #ifdef TARG_X8664
02534 if (Is_Target_32bit()){
02535 TYPE_ID store_type = OPCODE_desc(WN_opcode(store));
02536 if (store_type == MTYPE_I8 ||
02537 store_type == MTYPE_U8 ||
02538 store_type == MTYPE_F8) {
02539 Atomic_Using_Critical(atomic, store);
02540 return;
02541 }
02542 }
02543 #endif
02544 ATOMIC_Lowering_Class alclass = WN_ATOMIC_Lowering_Class(atomic);
02545
02546 switch (alclass) {
02547 case ALCLASS_CRITICAL:
02548 Atomic_Using_Critical(atomic, store);
02549 break;
02550 case ALCLASS_SWAP:
02551 case ALCLASS_DIRECT:
02552 {
02553 WN *parent = Get_Parent(atomic);
02554 WN *operation = WN_kid0(WN_next(atomic));
02555 WN *atomic_block =
02556 (alclass == ALCLASS_SWAP) ?
02557 Atomic_Using_Swap(atomic, store, operation,
02558 Get_Parent(atomic), Update_Private) :
02559 Atomic_Direct(atomic, store, operation);
02560
02561 Insert_Lowered_Atomic(parent, atomic, atomic_block, alclass);
02562 }
02563 break;
02564 case ALCLASS_ERROR:
02565
02566 {
02567 WN *parent = Get_Parent(atomic);
02568 WN_DELETE_FromBlock(parent,atomic);
02569 }
02570 break;
02571 default:
02572 Fail_FmtAssertion("invalid ATOMIC_Lowering_Class");
02573 }
02574 }
02575
02576
02577
02578 ATOMIC_Lowering_Class WN_ATOMIC_Lowering_Class(WN *atomic)
02579 {
02580 Is_True(atomic && WN_opcode(atomic) == OPC_PRAGMA &&
02581 WN_pragma(atomic) == WN_PRAGMA_ATOMIC, ("not an ATOMIC"));
02582 WN *store = WN_next(atomic);
02583 Is_True(store, ("nothing after ATOMIC"));
02584
02585 return WN_ATOMIC_STORE_Lowering_Class(store);
02586 }
02587
02588
02589
02590
02591 ATOMIC_Lowering_Class WN_ATOMIC_STORE_Lowering_Class(WN *store)
02592 {
02593 Is_True(store, ("NULL store"));
02594 OPCODE store_opc = WN_opcode(store);
02595 if (!OPCODE_is_store(store_opc)) {
02596 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(store),
02597 "OMP ATOMIC directive not followed by a store. \n");
02598 return ALCLASS_ERROR;
02599 }
02600
02601
02602
02603 WN *operation = WN_kid0(store);
02604 OPERATOR oper = WN_operator(operation);
02605 switch (oper) {
02606 case OPR_ADD: case OPR_LAND: case OPR_MPY: case OPR_SUB: case OPR_DIV:
02607 case OPR_BAND: case OPR_BIOR: case OPR_LIOR: case OPR_BXOR: case OPR_EQ:
02608 case OPR_NE: case OPR_MAX: case OPR_MIN:
02609 case OPR_ASHR: case OPR_LSHR: case OPR_SHL:
02610 case OPR_CVT: case OPR_TAS: case OPR_CVTL: case OPR_TRUNC:
02611 case OPR_REALPART: case OPR_IMAGPART:
02612 #ifdef KEY // bug 8862
02613 case OPR_CAND: case OPR_CIOR:
02614 #endif // KEY
02615 break;
02616 case OPR_BNOT:
02617 if (WN_operator(WN_kid0(operation)) != OPR_BXOR) {
02618 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(store),
02619 "Unsupported operator for OMP ATOMIC. \n");
02620 return ALCLASS_ERROR;
02621 }
02622 break;
02623 default:
02624 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(store),
02625 "Unsupported operator for OMP ATOMIC. \n");
02626 return ALCLASS_ERROR;
02627 }
02628
02629
02630 TYPE_ID store_type = OPCODE_desc(store_opc);
02631 ATOMIC_Lowering_Class alclass;
02632
02633 switch (store_type) {
02634 case MTYPE_U4: case MTYPE_U8: case MTYPE_F4: case MTYPE_F8:
02635 #ifdef TARG_IA32
02636 alclass = ALCLASS_CRITICAL;
02637 #else
02638 alclass = ALCLASS_SWAP;
02639 #endif
02640 break;
02641
02642 #ifdef TARG_IA64
02643 case MTYPE_F10:
02644 alclass = ALCLASS_CRITICAL;
02645 break;
02646
02647 case MTYPE_C10:
02648 #endif
02649 case MTYPE_U1: case MTYPE_U2: case MTYPE_I1: case MTYPE_I2:
02650 case MTYPE_C4: case MTYPE_C8: case MTYPE_CQ: case MTYPE_FQ:
02651 alclass = ALCLASS_CRITICAL;
02652 break;
02653
02654 case MTYPE_I4:
02655 case MTYPE_I8:
02656 switch (oper) {
02657 case OPR_ADD:
02658 case OPR_SUB:
02659 case OPR_BAND:
02660 case OPR_BIOR:
02661 case OPR_BXOR:
02662 #if defined(TARG_IA32)
02663 alclass = ALCLASS_CRITICAL;
02664 #elif defined(TARG_IA64)
02665 alclass = ALCLASS_SWAP;
02666 #else
02667 alclass = ALCLASS_DIRECT;
02668 #endif
02669 break;
02670
02671 default:
02672 #if defined(TARG_IA32)
02673 alclass = ALCLASS_CRITICAL;
02674 #else
02675 alclass = ALCLASS_SWAP;
02676 #endif
02677 break;
02678 }
02679 break;
02680
02681 default:
02682 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(store),
02683 "Unsupported type for OMP ATOMIC. \n");
02684 return ALCLASS_ERROR;
02685 }
02686
02687 return alclass;
02688 }
02689
02690
02691
02692
02693
02694 static WN *Lower_Master(WN *region)
02695 {
02696 if (WN_opcode(region) != OPC_REGION) {
02697 return region;
02698 }
02699 WN *pragmas = WN_region_pragmas(region);
02700 if (pragmas) {
02701 WN *pragma = WN_first(pragmas);
02702 BOOL found_it = FALSE;
02703 while (pragma && !found_it) {
02704 if (WN_opcode(pragma) == OPC_PRAGMA) {
02705 if ((WN_PRAGMA_ID)WN_pragma(pragma)==WN_PRAGMA_MASTER_BEGIN) {
02706 found_it = TRUE;
02707 }
02708 }
02709 pragma = WN_next(pragma);
02710 }
02711 INT pragma_count = 0;
02712 if (!found_it) return region;
02713 for (WN* wn = WN_first(pragmas); wn != NULL; wn = WN_next(wn))
02714 if (WN_opcode(wn) != OPC_PRAGMA
02715 || WN_pragma(wn) != WN_PRAGMA_END_MARKER)
02716 pragma_count++;
02717 if (pragma_count != 1) {
02718 ErrMsgSrcpos(EC_MPLOWER_Generic_Error, WN_Get_Linenum(region),
02719 "OMP MASTER directive can not have subclauses. \n");
02720 }
02721 }
02722
02723
02724
02725
02726 WN *call = WN_Create(OPC_I4CALL,0);
02727 ST *func_st = Create_Omp_Get_Thread_Num();
02728 WN_st_idx(call) = ST_st_idx(func_st);
02729 WN_Set_Linenum(call,WN_Get_Linenum(region));
02730 WN_CopyMap(call, WN_MAP_FEEDBACK,region);
02731 WN *parent = Get_Parent(region);
02732 WN_INSERT_BlockBefore(parent,region,call);
02733 Set_Parent(call,parent);
02734
02735
02736 ST *tmp_st = MTYPE_To_PREG(MTYPE_I4);
02737 WN_OFFSET tmp_offset = Create_Preg(MTYPE_I4,THREAD_NUM_PREG_NAME);
02738 WN *tmp_ldid = WN_LdidPreg(MTYPE_I4,First_Int_Preg_Return_Offset);
02739 WN *tmp_stid = WN_StidIntoPreg ( MTYPE_I4, tmp_offset,tmp_st,tmp_ldid);
02740 Set_Parent(tmp_ldid,tmp_stid);
02741 WN_INSERT_BlockBefore(parent,region,tmp_stid);
02742 Set_Parent(tmp_stid,parent);
02743 WN_Set_Linenum(tmp_stid,WN_Get_Linenum(region));
02744 WN_CopyMap(tmp_stid, WN_MAP_FEEDBACK,region);
02745
02746
02747 WN *test = WN_EQ(MTYPE_I4,WN_LdidPreg(MTYPE_I4,tmp_offset),
02748 WN_CreateIntconst ( OPC_I4INTCONST,(INT64)0 ));
02749 WN *if_wn = WN_CreateIf(test,WN_CreateBlock(),WN_CreateBlock());
02750 Parentize(if_wn);
02751 WN_INSERT_BlockBefore(parent,region,if_wn);
02752 Set_Parent(if_wn,parent);
02753 WN_Set_Linenum(if_wn,WN_Get_Linenum(region));
02754 WN_CopyMap(if_wn, WN_MAP_FEEDBACK,region);
02755
02756
02757 WN *region_body = WN_region_body(region);
02758 while (WN_last(region_body)) {
02759 WN *wn = WN_EXTRACT_FromBlock(region_body,WN_last(region_body));
02760 WN_INSERT_BlockAfter(WN_then(if_wn),NULL,wn);
02761 Set_Parent(wn,WN_then(if_wn));
02762 }
02763 RID_Delete(Current_Map_Tab, region);
02764 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
02765 INT old_id = WN_MAP32_Get(Prompf_Id_Map, region);
02766 Prompf_Info->OMPL_Master_To_If(old_id);
02767 }
02768 WN_DELETE_FromBlock(Get_Parent(region),region);
02769
02770
02771 WN *fb1 = WN_CreateBarrier(TRUE, 0);
02772 WN_Set_Linenum(fb1,WN_Get_Linenum(if_wn));
02773 WN *fb2 = WN_CreateBarrier(TRUE, 0);
02774 WN_Set_Linenum(fb2,WN_Get_Linenum(if_wn));
02775 WN *bb1 = WN_CreateBarrier(FALSE, 0);
02776 WN_Set_Linenum(bb1,WN_Get_Linenum(if_wn));
02777 WN *bb2 = WN_CreateBarrier(FALSE, 0);
02778 WN_Set_Linenum(bb2,WN_Get_Linenum(if_wn));
02779 WN_CopyMap(fb1, WN_MAP_FEEDBACK,if_wn);
02780 WN_CopyMap(bb2, WN_MAP_FEEDBACK,if_wn);
02781 if (WN_first(WN_then(if_wn))) {
02782 WN_CopyMap(fb2, WN_MAP_FEEDBACK,WN_first(WN_then(if_wn)));
02783 WN_CopyMap(bb1, WN_MAP_FEEDBACK,WN_first(WN_then(if_wn)));
02784 } else {
02785 WN_CopyMap(fb2, WN_MAP_FEEDBACK,if_wn);
02786 WN_CopyMap(bb1, WN_MAP_FEEDBACK,if_wn);
02787 }
02788
02789 WN_INSERT_BlockBefore(parent,if_wn,fb1);
02790 Set_Parent(fb1,parent);
02791 WN_INSERT_BlockAfter(WN_then(if_wn),NULL,bb1);
02792 Set_Parent(bb1,WN_then(if_wn));
02793 WN_INSERT_BlockBefore(WN_then(if_wn),NULL,fb2);
02794 Set_Parent(fb2,WN_then(if_wn));
02795 WN_INSERT_BlockAfter(parent,if_wn,bb2);
02796 Set_Parent(bb2,parent);
02797
02798 return if_wn;
02799 }
02800
02801
02802
02803
02804
02805
02806
02807 static BOOL Is_Ordered_Do (WN* wn) {
02808
02809 if (WN_opcode(wn) != OPC_REGION || !RID_TYPE_mp(REGION_get_rid(wn))) {
02810 return FALSE;
02811 }
02812
02813 WN *pragma = WN_first(WN_region_pragmas(wn));
02814 while (pragma) {
02815 if (WN_opcode(pragma) == OPC_PRAGMA &&
02816 WN_pragma_omp(pragma) &&
02817 WN_pragma(pragma) == WN_PRAGMA_ORDERED) {
02818 return TRUE;
02819 }
02820 pragma = WN_next(pragma);
02821 }
02822 return FALSE;
02823 }
02824
02825
02826
02827
02828
02829
02830
02831 static TY_IDX Get_Func_Zero_Arg_TY () {
02832 static TY_IDX func_ty = (TY_IDX) NULL;
02833
02834 if (func_ty == (TY_IDX) NULL) {
02835
02836 TY& ty = New_TY (func_ty);
02837
02838 TYLIST_IDX parm_idx;
02839 New_TYLIST (parm_idx);
02840
02841 Set_TY_tylist (ty, parm_idx);
02842
02843 Tylist_Table [parm_idx] = Be_Type_Tbl(MTYPE_V);
02844
02845
02846 New_TYLIST (parm_idx);
02847 Tylist_Table [parm_idx] = 0;
02848
02849 TY_Init (ty,0,KIND_FUNCTION,MTYPE_UNKNOWN,Save_Str (".mpruntime"));
02850 }
02851 return func_ty;
02852 }
02853
02854
02855
02856
02857
02858
02859
02860 static TY_IDX Get_Func_One_Arg_TY () {
02861 static TY_IDX func_ty = (TY_IDX) NULL;
02862
02863 if (func_ty == (TY_IDX) NULL) {
02864
02865 TY& ty = New_TY(func_ty);
02866 TY_Init (ty,0,KIND_FUNCTION,MTYPE_UNKNOWN,Save_Str (".mpruntime"));
02867 Set_TY_align (func_ty, 1);
02868
02869 TYLIST_IDX parm_idx;
02870 TYLIST& parm_list = New_TYLIST (parm_idx);
02871 Set_TY_tylist (ty, parm_idx);
02872
02873 Set_TYLIST_type(parm_list, Be_Type_Tbl(MTYPE_V));
02874
02875
02876 Set_TYLIST_type(New_TYLIST(parm_idx), Be_Type_Tbl(MTYPE_I8));
02877
02878 Set_TYLIST_type(New_TYLIST(parm_idx), TY_IDX_ZERO);
02879 }
02880 return func_ty;
02881 }
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914 static WN *Add_Ordered_XPragmas (WN* wn) {
02915
02916 static ST *begin_iter_st = NULL;
02917 static ST *end_iter_st = NULL;
02918
02919 if (begin_iter_st == NULL) {
02920
02921
02922 begin_iter_st = New_ST (GLOBAL_SYMTAB);
02923 PU_IDX pu_idx;
02924 PU& pu = New_PU (pu_idx);
02925 PU_Init (pu, Get_Func_One_Arg_TY(), CURRENT_SYMTAB);
02926
02927 ST_Init (begin_iter_st,
02928 Save_Str("__omp_pdo_ordered_begin_iter"),
02929 CLASS_FUNC,
02930 SCLASS_EXTERN,
02931 EXPORT_PREEMPTIBLE,
02932 pu_idx);
02933 }
02934 if (end_iter_st == NULL) {
02935
02936
02937 end_iter_st = New_ST (GLOBAL_SYMTAB);
02938 PU_IDX pu_idx;
02939 PU& pu = New_PU (pu_idx);
02940 PU_Init (pu, Get_Func_One_Arg_TY(), CURRENT_SYMTAB);
02941
02942 ST_Init (end_iter_st,
02943 Save_Str("__omp_pdo_ordered_end_iter"),
02944 CLASS_FUNC,
02945 SCLASS_EXTERN,
02946 EXPORT_PREEMPTIBLE,
02947 pu_idx);
02948 }
02949
02950 WN* do_wn = WN_first(WN_region_body(wn));
02951 while (do_wn) {
02952 if (WN_opcode(do_wn) == OPC_DO_LOOP) break;
02953 do_wn = WN_next(do_wn);
02954 }
02955 FmtAssert (do_wn,("Add_Ordered_XPragmas: Unable to locate parallel loop\n"));
02956
02957 WN *body = WN_do_body(do_wn);
02958
02959
02960 TYPE_ID desc = WN_desc(WN_kid1(do_wn));
02961 TYPE_ID rtype = desc;
02962 rtype = ((rtype == MTYPE_I1 || rtype == MTYPE_I2 || rtype == MTYPE_I4) ?
02963 MTYPE_I8 :
02964 ((rtype == MTYPE_U1 || rtype == MTYPE_U2 || rtype == MTYPE_U4) ?
02965 MTYPE_U8 : rtype));
02966 FmtAssert (rtype == MTYPE_I8 || rtype == MTYPE_U8,
02967 ("Expected integer index variable for parallel ordered do-loop"));
02968 WN *index_wn = WN_RLdid (rtype, desc,
02969 WN_offset(WN_kid1(do_wn)), WN_st(WN_kid1(do_wn)),
02970 ST_type(WN_st(WN_kid1(do_wn))));
02971
02972
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000 WN *lb = WN_COPY_Tree (WN_kid0(WN_start(do_wn)));
03001 WN *xpragma_wn = WN_CreateXpragma (WN_PRAGMA_ORDERED_LOWER_BOUND,
03002 (ST*) NULL, 1);
03003 WN_kid0(xpragma_wn) = lb;
03004 Parentize(xpragma_wn);
03005 WN_INSERT_BlockBefore(WN_region_pragmas(wn), NULL, xpragma_wn);
03006
03007 WN *stride;
03008 if (WN_operator(WN_kid0(WN_kid0(WN_step(do_wn)))) == OPR_LDID &&
03009 WN_st(WN_kid0(WN_kid0(WN_step(do_wn)))) == WN_st(WN_index(do_wn)) &&
03010 WN_offset(WN_kid0(WN_kid0(WN_step(do_wn)))) ==
03011 WN_offset(WN_index(do_wn))) {
03012 stride = WN_COPY_Tree(WN_kid1(WN_kid0(WN_step(do_wn))));
03013 }
03014 else {
03015 stride = WN_COPY_Tree(WN_kid0(WN_kid0(WN_step(do_wn))));
03016 }
03017 xpragma_wn = WN_CreateXpragma (WN_PRAGMA_ORDERED_STRIDE,
03018 (ST*) NULL, 1);
03019 WN_kid0(xpragma_wn) = stride;
03020 Parentize(xpragma_wn);
03021 WN_INSERT_BlockBefore(WN_region_pragmas(wn), NULL, xpragma_wn);
03022
03023 return wn;
03024 }
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041 static void Apply_Default_Scopes(WN *pu, WN_LIST *construct_pragma_block_list)
03042 {
03043 Is_True(pu, ("Apply_Default_Scopes(): NULL pu argument"));
03044
03045
03046 ST_TO_BOOL_HASH *processed = CXX_NEW(ST_TO_BOOL_HASH(NUM_HASH_ELEMENTS,
03047 &omp_pool), &omp_pool);
03048 BOOL dummy;
03049 WN *pragma_block = Par_Region_Pragma_Block(pu, &dummy);
03050
03051 if (pragma_block) {
03052 WN_PRAGMA_DEFAULT_KIND defsc = WN_PRAGMA_DEFAULT_UNKNOWN;
03053 WN *prag;
03054
03055
03056 for (prag = WN_first(pragma_block); prag; prag = WN_next(prag))
03057 if (WN_opcode(prag) == OPC_PRAGMA &&
03058 WN_pragma(prag) == WN_PRAGMA_DEFAULT) {
03059 defsc = (WN_PRAGMA_DEFAULT_KIND) WN_pragma_arg1(prag);
03060 break;
03061 }
03062
03063
03064 construct_pragma_block_list->AddElement(pragma_block);
03065
03066 Apply_Par_Region_Default_Scopes(pu, processed, pragma_block,
03067 construct_pragma_block_list, defsc);
03068 construct_pragma_block_list->Decidx();
03069
03070 if (prag) {
03071 if (Get_Trace(TP_LNOPT2, TT_LNO_OMP_TRANSFORMS))
03072 printf("OMP_Prelower: applied DEFAULT(%s) clause at line %d\n",
03073 (defsc == WN_PRAGMA_DEFAULT_NONE) ? "NONE" :
03074 (defsc == WN_PRAGMA_DEFAULT_PRIVATE) ? "PRIVATE" :
03075 (defsc == WN_PRAGMA_DEFAULT_SHARED) ? "SHARED" : "?????",
03076 WN_Find_Linenum(prag));
03077 Set_Parent(prag, NULL);
03078 WN_DELETE_FromBlock(pragma_block, prag);
03079 }
03080
03081 } else
03082
03083 Apply_Par_Region_Default_Scopes(pu, processed, NULL,
03084 construct_pragma_block_list,
03085 WN_PRAGMA_DEFAULT_UNKNOWN);
03086
03087 CXX_DELETE(processed, &omp_pool);
03088 }
03089
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107
03108
03109
03110 static void
03111 Apply_Par_Region_Default_Scopes(WN *wn, ST_TO_BOOL_HASH *processed,
03112 WN *pragma_block,
03113 WN_LIST *construct_pragma_block_list,
03114 WN_PRAGMA_DEFAULT_KIND defsc)
03115 {
03116 Is_True(wn, ("Apply_Par_Region_Default_Scopes(): NULL wn argument"));
03117
03118 OPCODE opc = WN_opcode(wn);
03119
03120 if (pragma_block) {
03121 ST *var_st = Mem_Ref_To_Var(wn);
03122
03123
03124 if (var_st && !processed->Find(ST_st_idx(var_st))) {
03125 SCOPE_RULE_KIND how;
03126 WN_PRAGMA_DEFAULT_KIND var_scope =
03127 Var_Scope(var_st, construct_pragma_block_list, &how);
03128 BOOL do_enter = TRUE;
03129
03130
03131 Is_True(var_scope != WN_PRAGMA_DEFAULT_UNKNOWN,
03132 ("impossible var_scope for parallel region"));
03133
03134 if (ST_sclass(var_st) == SCLASS_AUTO &&
03135 (var_scope == WN_PRAGMA_DEFAULT_SHARED ||
03136 (var_scope == WN_PRAGMA_DEFAULT_PRIVATE &&
03137 how == BY_REDUCTION) ) ) {
03138
03139
03140
03141 Set_ST_is_shared_auto(*var_st);
03142 }
03143
03144 if (!ST_is_temp_var(var_st)) {
03145
03146
03147
03148 if (how == BY_DEFAULT_SHARED && defsc == WN_PRAGMA_DEFAULT_NONE) {
03149 if (ST_is_Index_Var_For_Enclosing_PDO(var_st, wn)) {
03150
03151 do_enter = FALSE;
03152
03153 } else if (!ST_Is_Const(var_st)) {
03154
03155 ErrMsgLine(EC_MPLOWER_used_noscope, WN_Find_Linenum(pragma_block),
03156 var_st);
03157 }
03158
03159
03160 } else if (how == BY_DEFAULT_CLAUSE) {
03161 switch (var_scope) {
03162 case WN_PRAGMA_DEFAULT_SHARED:
03163 if (Get_Trace(TP_LNOPT2, TT_LNO_OMP_TRANSFORMS))
03164 printf("OMP_Prelower: found DEFAULT(SHARED) at line %d that "
03165 "applies to %s due to use at line %d\n",
03166 WN_Find_Linenum(pragma_block),
03167 ST_name(var_st),
03168 WN_Find_Linenum(wn));
03169 break;
03170 case WN_PRAGMA_DEFAULT_PRIVATE:
03171
03172 if (Can_Apply_Default_Private(var_st, pragma_block)) {
03173
03174 WN *scope_prag = WN_CreatePragma(WN_PRAGMA_LOCAL, var_st, 0, 0);
03175 WN_set_pragma_compiler_generated(scope_prag);
03176
03177 Set_Parent(scope_prag, pragma_block);
03178 WN_INSERT_BlockLast(pragma_block, scope_prag);
03179 if (Get_Trace(TP_LNOPT2, TT_LNO_OMP_TRANSFORMS))
03180 printf("OMP_Prelower: inserting PRIVATE(%s) clause for region "
03181 "starting at line %d due to use at line %d\n",
03182 ST_name(var_st),
03183 WN_Find_Linenum(pragma_block),
03184 WN_Find_Linenum(wn));
03185 }
03186 break;
03187 default:
03188 Is_True(0, ("invalid default scope"));
03189 }
03190 }
03191
03192 }
03193
03194 if (do_enter)
03195 processed->Enter(ST_st_idx(var_st), TRUE);
03196 }
03197 }
03198
03199 BOOL is_worksharing;
03200 WN *pragma_block2 = Par_Region_Pragma_Block(wn, &is_worksharing);
03201 WN *worksharing_pragmas = (!pragma_block2 && is_worksharing) ?
03202 WN_region_pragmas(wn) : NULL;
03203
03204
03205 if (worksharing_pragmas)
03206 construct_pragma_block_list->AddElement(worksharing_pragmas);
03207
03208
03209 if (!OPCODE_is_leaf(opc)) {
03210 if (opc == OPC_BLOCK) {
03211 for (WN *kid = WN_first(wn); kid; kid = WN_next(kid))
03212 Apply_Par_Region_Default_Scopes(kid, processed, pragma_block,
03213 construct_pragma_block_list, defsc);
03214 } else {
03215 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
03216 WN *kid = WN_kid(wn, kidno);
03217 if (kid)
03218 Apply_Par_Region_Default_Scopes(kid, processed, pragma_block,
03219 construct_pragma_block_list, defsc);
03220 }
03221 }
03222 }
03223
03224 if (worksharing_pragmas)
03225 construct_pragma_block_list->Decidx();
03226
03227
03228
03229 if (pragma_block2 && pragma_block2 != pragma_block)
03230 Apply_Default_Scopes(wn, construct_pragma_block_list);
03231 }
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277 static void
03278 Privatize_Index_Vars_And_Check_Final_Scopes(
03279 WN *wn, WN_LIST *pragma_block_list, WN *enclosing_pdo,
03280 ST_TO_BOOL_HASH *processed, WN_LIST *nested_par_regions,
03281 BOOL top_of_construct)
03282 {
03283 Is_True(wn, ("Privatize_Index_Vars_And_Check_Final_Scopes(): "
03284 "NULL wn argument"));
03285
03286 BOOL is_worksharing;
03287 WN *pragma_block = Par_Region_Pragma_Block(wn, &is_worksharing);
03288 BOOL is_par_region = (pragma_block != NULL);
03289 BOOL is_orphaned_pdo =
03290 (pragma_block_list->Elements() == 0 && enclosing_pdo);
03291
03292
03293
03294 if (is_worksharing || is_par_region) {
03295
03296 WN_LIST reprivatizing_pragmas(&omp_pool);
03297
03298 for (WN *prag = WN_first(WN_region_pragmas(wn)); prag;
03299 prag = WN_next(prag)) {
03300 if (WN_opcode(prag) != OPC_PRAGMA)
03301 continue;
03302
03303 SCOPE_RULE_KIND how;
03304 WN_PRAGMA_ID prag_id = (WN_PRAGMA_ID) WN_pragma(prag);
03305 ST *st = WN_st(prag);
03306 WN *scope_prag;
03307
03308 #ifndef KEY
03309
03310
03311 switch (prag_id) {
03312 case WN_PRAGMA_LOCAL:
03313 case WN_PRAGMA_LASTLOCAL:
03314 case WN_PRAGMA_FIRSTPRIVATE:
03315 case WN_PRAGMA_SHARED:
03316 case WN_PRAGMA_REDUCTION:
03317 {
03318 ST *split_blk;
03319 ST *common_blk = ST_Source_COMMON_Block(st, &split_blk);
03320 if (ST_is_thread_private(st) ||
03321 (split_blk && ST_is_thread_private(split_blk)) ||
03322 (common_blk && ST_is_thread_private(common_blk)))
03323 ErrMsgLine(EC_MPLOWER_thrpriv_scope, WN_Find_Linenum(wn), st);
03324 }
03325 break;
03326 default:
03327 break;
03328 }
03329 #endif
03330
03331 if (prag_id == WN_PRAGMA_REDUCTION &&
03332 pragma_block_list->Elements() == 0 && !is_par_region &&
03333 ST_sclass(st) == SCLASS_AUTO) {
03334
03335
03336 ErrMsgLine(EC_MPLOWER_red_of_private, WN_Find_Linenum(wn), st);
03337 }
03338
03339 if (top_of_construct || !is_worksharing || is_par_region ||
03340 pragma_block_list->Elements() == 0)
03341
03342
03343
03344 continue;
03345
03346
03347
03348
03349 switch (prag_id) {
03350 case WN_PRAGMA_LOCAL:
03351 case WN_PRAGMA_LASTLOCAL:
03352 case WN_PRAGMA_FIRSTPRIVATE:
03353 case WN_PRAGMA_REDUCTION:
03354 if (Var_Scope(st, pragma_block_list, &how, &scope_prag) !=
03355 WN_PRAGMA_DEFAULT_PRIVATE)
03356 break;
03357
03358 if (prag_id == WN_PRAGMA_LOCAL &&
03359 Index_Priv_From_OMPL->Find(scope_prag)) {
03360 reprivatizing_pragmas.AddElement(prag);
03361 break;
03362 }
03363
03364 if (WN_pragma(scope_prag) == WN_PRAGMA_LOCAL &&
03365 prag_id == WN_PRAGMA_LOCAL &&
03366 WN_pragma_compiler_generated(scope_prag)
03367 #ifndef KEY
03368
03369 && WN_pragma_compiler_generated(prag)
03370 #endif
03371 )
03372 {
03373 reprivatizing_pragmas.AddElement(prag);
03374 break;
03375 }
03376
03377 ErrMsgLine(prag_id == WN_PRAGMA_REDUCTION ?
03378 EC_MPLOWER_red_of_private : EC_MPLOWER_reprivatization,
03379 WN_Find_Linenum(wn), st);
03380 break;
03381
03382 default:
03383 break;
03384 }
03385 }
03386
03387
03388 for (INT i = 0; i < reprivatizing_pragmas.Elements(); i++) {
03389 Set_Parent(reprivatizing_pragmas[i], NULL);
03390 WN_DELETE_FromBlock(WN_region_pragmas(wn), reprivatizing_pragmas[i]);
03391 }
03392 }
03393
03394 if (is_par_region && !top_of_construct) {
03395 if (WN_pragma_omp(WN_first(pragma_block)))
03396
03397 nested_par_regions->AddElement(wn);
03398 return;
03399 }
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419 if (WN_opcode(wn) == OPC_DO_LOOP &&
03420 (pragma_block_list->Elements() != 0 ||
03421 is_orphaned_pdo)) {
03422 ST *index_st = WN_st(WN_index(wn));
03423
03424
03425 if (!processed->Find(ST_st_idx(index_st))) {
03426 SCOPE_RULE_KIND how;
03427 WN_PRAGMA_DEFAULT_KIND scope = WN_PRAGMA_DEFAULT_UNKNOWN;
03428 BOOL is_index_for_pdo = FALSE;
03429
03430
03431 if (enclosing_pdo)
03432 scope = Var_Scope_In_Region(index_st, enclosing_pdo, &how);
03433 if (!is_orphaned_pdo) {
03434 if (scope == WN_PRAGMA_DEFAULT_UNKNOWN)
03435 scope = Var_Scope(index_st, pragma_block_list, &how);
03436 } else if (scope == WN_PRAGMA_DEFAULT_UNKNOWN) {
03437
03438 how = BY_DEFAULT_SHARED;
03439 scope = WN_PRAGMA_DEFAULT_SHARED;
03440 }
03441 Is_True(scope == WN_PRAGMA_DEFAULT_PRIVATE ||
03442 scope == WN_PRAGMA_DEFAULT_SHARED,
03443 ("impossible value %d for scope", (INT) scope));
03444
03445 if (scope == WN_PRAGMA_DEFAULT_PRIVATE && how == BY_REDUCTION)
03446 ErrMsgLine(EC_MPLOWER_red_badop, WN_Find_Linenum(wn),
03447 index_st);
03448
03449 else if (scope == WN_PRAGMA_DEFAULT_SHARED &&
03450 how != BY_EXPLICIT_CLAUSE) {
03451
03452
03453 if (enclosing_pdo) {
03454
03455 WN *grandparent = Get_Parent(Get_Parent(wn));
03456 Is_True(grandparent, ("no grandparent for wn"));
03457
03458 if (WN_opcode(grandparent) == OPC_REGION &&
03459 WN_region_pragmas(grandparent) == enclosing_pdo)
03460 is_index_for_pdo = TRUE;
03461
03462 #ifdef Is_True_On
03463 if (is_index_for_pdo)
03464
03465 for (WN *prev = WN_prev(wn); prev; prev = WN_prev(prev))
03466 if (WN_opcode(prev) == OPC_DO_LOOP)
03467 Fail_FmtAssertion("multiple DO loops in block for PDO");
03468 #endif
03469 }
03470
03471 if (is_index_for_pdo || !is_orphaned_pdo) {
03472
03473 WN *scope_prag = WN_CreatePragma(WN_PRAGMA_LOCAL, index_st, 0, 0);
03474 WN_set_pragma_compiler_generated(scope_prag);
03475
03476 WN *privatization_region;
03477 if (!is_index_for_pdo || pragma_block_list->Elements() > 1)
03478
03479
03480 privatization_region = (*pragma_block_list)[0];
03481 else
03482 privatization_region = enclosing_pdo;
03483
03484 if (Get_Trace(TP_LNOPT2, TT_LNO_OMP_TRANSFORMS)) {
03485 if (is_index_for_pdo) {
03486 char buff[128];
03487
03488 if (privatization_region == enclosing_pdo)
03489 sprintf(buff, "parallel DO");
03490 else
03491 sprintf(buff, "PARALLEL region starting at line %d",
03492 WN_Find_Linenum(privatization_region));
03493
03494 printf("OMP_Prelower: index variable %s of parallel DO "
03495 "at line %d privatized within %s\n",
03496 ST_name(index_st),
03497 WN_Find_Linenum(enclosing_pdo), buff);
03498 } else {
03499 WN *region_prag = WN_first((*pragma_block_list)
03500 [pragma_block_list->Lastidx()]);
03501 printf("OMP_Prelower: index variable %s of %s DO at "
03502 "line %d privatized within PARALLEL region starting "
03503 "at line %d\n",
03504 ST_name(index_st),
03505 (WN_pragma(region_prag) == WN_PRAGMA_PARALLEL_DO ?
03506 "PARALLEL" : "sequential"),
03507 WN_Find_Linenum(wn),
03508 WN_Find_Linenum(privatization_region));
03509 }
03510 }
03511 Set_Parent(scope_prag, privatization_region);
03512 WN_INSERT_BlockLast(privatization_region, scope_prag);
03513 Index_Priv_From_OMPL->Enter(scope_prag, TRUE);
03514 }
03515 }
03516
03517 if (!is_index_for_pdo)
03518 processed->Enter(ST_st_idx(index_st), TRUE);
03519 }
03520 } else if (WN_opcode(wn) == OPC_REGION) {
03521 WN *first = WN_first(WN_region_pragmas(wn));
03522
03523 if (first && WN_opcode(first) == OPC_PRAGMA &&
03524 WN_pragma(first) == WN_PRAGMA_PDO_BEGIN &&
03525 WN_pragma_arg1(first) == 0) {
03526 if (enclosing_pdo)
03527 Fail_FmtAssertion("Privatize_Index_Vars_And_Check_Final_Scopes(): "
03528 "nested orphaned PDOs!");
03529 enclosing_pdo = WN_region_pragmas(wn);
03530 }
03531 }
03532
03533
03534
03535
03536
03537 WN *recurse_parent = is_par_region ? WN_region_pragmas(wn) : wn;
03538 OPCODE rpar_opc = WN_opcode(recurse_parent);
03539
03540
03541 if (!OPCODE_is_leaf(rpar_opc)) {
03542 if (rpar_opc == OPC_BLOCK) {
03543 for (WN *kid = WN_first(recurse_parent); kid; kid = WN_next(kid))
03544 Privatize_Index_Vars_And_Check_Final_Scopes(kid, pragma_block_list,
03545 is_par_region ? NULL : enclosing_pdo, processed,
03546 nested_par_regions, FALSE);
03547 } else {
03548 for (INT kidno = 0; kidno < WN_kid_count(recurse_parent); kidno++) {
03549 WN *kid = WN_kid(recurse_parent, kidno);
03550 if (kid)
03551 Privatize_Index_Vars_And_Check_Final_Scopes(kid, pragma_block_list,
03552 is_par_region ? NULL : enclosing_pdo, processed,
03553 nested_par_regions, FALSE);
03554 }
03555 }
03556 }
03557
03558
03559
03560 if (top_of_construct) {
03561 for (INT i = 0; i < nested_par_regions->Elements(); i++) {
03562 WN *np = (*nested_par_regions)[i];
03563
03564 ST_TO_BOOL_HASH processed_set(NUM_HASH_ELEMENTS, &omp_pool);
03565 WN_LIST nested_set(&omp_pool);
03566
03567
03568 pragma_block_list->AddElement(WN_region_pragmas(np));
03569
03570
03571 Privatize_Index_Vars_And_Check_Final_Scopes(WN_region_body(np),
03572 pragma_block_list, NULL, &processed_set, &nested_set, TRUE);
03573
03574 pragma_block_list->Decidx();
03575 }
03576
03577 }
03578 }
03579
03580
03581
03582
03583
03584
03585 static mINT32 WN_Find_Linenum(WN *wn)
03586 {
03587 Is_True(wn, ("WN_Find_Linenum(): NULL wn argument"));
03588
03589 mINT32 wn_ln = WN_Get_Linenum(wn);
03590
03591 if (wn_ln != 0)
03592 return wn_ln;
03593
03594 WN *parent = Get_Parent(wn);
03595
03596 if (wn)
03597 return WN_Find_Linenum(parent);
03598 else
03599 return 0;
03600 }
03601
03602
03603
03604
03605
03606
03607 static void OMP_File_Init()
03608 {
03609 MEM_POOL_Initialize(&omp_pool, "OMP Lowering Pool", FALSE);
03610 MEM_POOL_Initialize(&Omp_Local_Pool, "OMP Local Lowering Pool", FALSE);
03611 }
03612
03613
03614
03615
03616
03617
03618 static void Parentize (WN* wn)
03619 {
03620 if (!OPCODE_is_leaf(WN_opcode(wn))) {
03621 if (WN_opcode(wn) == OPC_BLOCK) {
03622 WN *kid = WN_first(wn);
03623 while (kid) {
03624 Set_Parent(kid, wn);
03625 Parentize(kid);
03626 kid = WN_next(kid);
03627 }
03628 } else {
03629 INT kidno;
03630 for (kidno = 0; kidno < WN_kid_count(wn); kidno++) {
03631 WN *kid = WN_kid(wn, kidno);
03632 if (kid) {
03633 Set_Parent(kid, wn);
03634 Parentize(kid);
03635 }
03636 }
03637 }
03638 }
03639 }
03640
03641
03642
03643 static WN *Find_Return_Use(ST *st, PREG_NUM preg, WN *wn)
03644 {
03645 OPCODE opc = WN_opcode(wn);
03646 if (OPCODE_operator(opc) == OPR_LDID &&
03647 WN_st(wn) == st &&
03648 WN_offset(wn) == preg) {
03649 return wn;
03650 }
03651 Is_True(!OPCODE_is_scf(opc),("Return register not next to call "));
03652 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
03653 WN *tmp=Find_Return_Use(st,preg,WN_kid(wn,kidno));
03654 if (tmp) return tmp;
03655 }
03656 if (OPCODE_has_next_prev(opc) && WN_next(wn)) {
03657 return Find_Return_Use(st,preg,WN_next(wn));
03658 }
03659 return NULL;
03660 }
03661
03662
03663
03664
03665
03666
03667
03668 static void Lower_Fetch_And_Op(WN *intrinsic)
03669 {
03670 WN *parent = Get_Parent(intrinsic);
03671 BOOL return_new_val;
03672 OPCODE atomic_op;
03673 switch (WN_intrinsic(intrinsic)) {
03674 case INTRN_MPY_AND_FETCH_I4:
03675 return_new_val = TRUE;
03676 atomic_op = OPC_I4MPY;
03677 break;
03678 case INTRN_MIN_AND_FETCH_I4:
03679 return_new_val = TRUE;
03680 atomic_op = OPC_I4MIN;
03681 break;
03682 case INTRN_MAX_AND_FETCH_I4:
03683 return_new_val = TRUE;
03684 atomic_op = OPC_I4MAX;
03685 break;
03686 case INTRN_MPY_AND_FETCH_I8:
03687 return_new_val = TRUE;
03688 atomic_op = OPC_I8MPY;
03689 break;
03690 case INTRN_MIN_AND_FETCH_I8:
03691 return_new_val = TRUE;
03692 atomic_op = OPC_I8MIN;
03693 break;
03694 case INTRN_MAX_AND_FETCH_I8:
03695 return_new_val = TRUE;
03696 atomic_op = OPC_I8MAX;
03697 break;
03698 case INTRN_ADD_AND_FETCH_F4:
03699 return_new_val = TRUE;
03700 atomic_op = OPC_F4ADD;
03701 break;
03702 case INTRN_SUB_AND_FETCH_F4:
03703 return_new_val = TRUE;
03704 atomic_op = OPC_F4SUB;
03705 break;
03706 case INTRN_MPY_AND_FETCH_F4:
03707 return_new_val = TRUE;
03708 atomic_op = OPC_F4MPY;
03709 break;
03710 case INTRN_MIN_AND_FETCH_F4:
03711 return_new_val = TRUE;
03712 atomic_op = OPC_F4MIN;
03713 break;
03714 case INTRN_MAX_AND_FETCH_F4:
03715 return_new_val = TRUE;
03716 atomic_op = OPC_F4MAX;
03717 break;
03718 case INTRN_ADD_AND_FETCH_F8:
03719 return_new_val = TRUE;
03720 atomic_op = OPC_F8ADD;
03721 break;
03722 case INTRN_SUB_AND_FETCH_F8:
03723 return_new_val = TRUE;
03724 atomic_op = OPC_F8SUB;
03725 break;
03726 case INTRN_MPY_AND_FETCH_F8:
03727 return_new_val = TRUE;
03728 atomic_op = OPC_F8MPY;
03729 break;
03730 case INTRN_MIN_AND_FETCH_F8:
03731 return_new_val = TRUE;
03732 atomic_op = OPC_F8MIN;
03733 break;
03734 case INTRN_MAX_AND_FETCH_F8:
03735 return_new_val = TRUE;
03736 atomic_op = OPC_F8MAX;
03737 break;
03738
03739 case INTRN_FETCH_AND_MPY_I4:
03740 return_new_val = FALSE;
03741 atomic_op = OPC_I4MPY;
03742 break;
03743 case INTRN_FETCH_AND_MIN_I4:
03744 return_new_val = FALSE;
03745 atomic_op = OPC_I4MIN;
03746 break;
03747 case INTRN_FETCH_AND_MAX_I4:
03748 return_new_val = FALSE;
03749 atomic_op = OPC_I4MAX;
03750 break;
03751 case INTRN_FETCH_AND_MPY_I8:
03752 return_new_val = FALSE;
03753 atomic_op = OPC_I8MPY;
03754 break;
03755 case INTRN_FETCH_AND_MIN_I8:
03756 return_new_val = FALSE;
03757 atomic_op = OPC_I8MIN;
03758 break;
03759 case INTRN_FETCH_AND_MAX_I8:
03760 return_new_val = FALSE;
03761 atomic_op = OPC_I8MAX;
03762 break;
03763 case INTRN_FETCH_AND_ADD_F4:
03764 return_new_val = FALSE;
03765 atomic_op = OPC_F4ADD;
03766 break;
03767 case INTRN_FETCH_AND_SUB_F4:
03768 return_new_val = FALSE;
03769 atomic_op = OPC_F4SUB;
03770 break;
03771 case INTRN_FETCH_AND_MPY_F4:
03772 return_new_val = FALSE;
03773 atomic_op = OPC_F4MPY;
03774 break;
03775 case INTRN_FETCH_AND_MIN_F4:
03776 return_new_val = FALSE;
03777 atomic_op = OPC_F4MIN;
03778 break;
03779 case INTRN_FETCH_AND_MAX_F4:
03780 return_new_val = FALSE;
03781 atomic_op = OPC_F4MAX;
03782 break;
03783 case INTRN_FETCH_AND_ADD_F8:
03784 return_new_val = FALSE;
03785 atomic_op = OPC_F8ADD;
03786 break;
03787 case INTRN_FETCH_AND_SUB_F8:
03788 return_new_val = FALSE;
03789 atomic_op = OPC_F8SUB;
03790 break;
03791 case INTRN_FETCH_AND_MPY_F8:
03792 return_new_val = FALSE;
03793 atomic_op = OPC_F8MPY;
03794 break;
03795 case INTRN_FETCH_AND_MIN_F8:
03796 return_new_val = FALSE;
03797 atomic_op = OPC_F8MIN;
03798 break;
03799 case INTRN_FETCH_AND_MAX_F8:
03800 return_new_val = FALSE;
03801 atomic_op = OPC_F8MAX;
03802 break;
03803 default:
03804 return ;
03805 }
03806
03807
03808 WN *var = WN_kid0(WN_kid0(intrinsic));
03809 TYPE_ID type = OPCODE_rtype(atomic_op);
03810
03811 ST *return_st = Create_Local_Symbol("return_val",type);
03812
03813 WN *atomic_pragma = WN_CreatePragma(WN_PRAGMA_ATOMIC, (ST*) 0, 0, 0);
03814 #ifndef BUILD_SKIP_PROMPF
03815 if (Prompf_Info != NULL && Prompf_Info->Is_Enabled()) {
03816 INT new_id = New_Construct_Id();
03817 WN_MAP32_Set(Prompf_Id_Map, atomic_pragma, new_id);
03818 PROMPF_LINES* pl = CXX_NEW(PROMPF_LINES(&PROMPF_pool), &PROMPF_pool);
03819 pl->Add_Lines(intrinsic);
03820 Prompf_Info->OMPL_Fetchop_Atomic(new_id, pl);
03821 }
03822 #endif
03823 WN_set_pragma_omp(atomic_pragma);
03824 WN_INSERT_BlockBefore(parent,intrinsic,atomic_pragma);
03825 Set_Parent(atomic_pragma,parent);
03826 WN_Set_Linenum(atomic_pragma,WN_Get_Linenum(intrinsic));
03827
03828
03829
03830 WN *expr = WN_COPY_Tree(WN_kid0(WN_kid1(intrinsic)));
03831 WN *load_var;
03832 WN *store_var;
03833 if (WN_operator(var) == OPR_LDA) {
03834 load_var = WN_CreateLdid (OPCODE_make_op(OPR_LDID, type, type),
03835 WN_offset(var),WN_st(var), Be_Type_Tbl(type));
03836 store_var = WN_CreateStid(OPCODE_make_op(OPR_STID,MTYPE_V,type),
03837 WN_offset(var),WN_st(var),Be_Type_Tbl(type),
03838 WN_CreateExp2(atomic_op,load_var,expr));
03839 } else {
03840 OPCODE load_opc = OPCODE_make_op(OPR_ILOAD,type,type);
03841 load_var = WN_CreateIload(load_opc, WN_offset(var),
03842 Be_Type_Tbl(type),
03843 Make_Pointer_Type(Be_Type_Tbl(type),FALSE),
03844 WN_COPY_Tree(var));
03845 store_var = WN_CreateIstore(OPCODE_make_op(OPR_ISTORE,MTYPE_V,type),
03846 WN_offset(var),
03847 Make_Pointer_Type(Be_Type_Tbl(type),FALSE),
03848 WN_CreateExp2(atomic_op,load_var,expr),
03849 WN_COPY_Tree(var));
03850
03851 }
03852 Parentize(store_var);
03853 WN_INSERT_BlockBefore(parent,intrinsic,store_var);
03854 Set_Parent(store_var,parent);
03855 WN_Set_Linenum(store_var,WN_Get_Linenum(intrinsic));
03856
03857
03858
03859
03860 PREG_NUM rreg1, rreg2;
03861 ST* rst = Find_Return_Registers (type, &rreg1, &rreg2);
03862 FmtAssert(rreg1 != 0 && rreg2 == 0, ("Bad pointer type ret regs"));
03863 WN *return_use = Find_Return_Use(rst,rreg1,WN_next(intrinsic));
03864 Is_True(return_use,("Couldn't find return register "));
03865 WN *return_parent = Get_Parent(return_use);
03866 INT return_kidno=0;
03867 while (WN_kid(return_parent,return_kidno) != return_use) return_kidno++;
03868 WN_Delete(return_use);
03869
03870 WN_kid(return_parent,return_kidno) =
03871 WN_CreateLdid (OPCODE_make_op(OPR_LDID, type, type),
03872 0, return_st, Be_Type_Tbl(type));
03873
03874 Update_Private(return_st,return_parent);
03875
03876
03877 WN_Delete(WN_EXTRACT_FromBlock(Get_Parent(intrinsic),intrinsic));
03878
03879
03880 WN *store = WN_next(atomic_pragma);
03881 WN *atomic_block = return_new_val ?
03882 Atomic_Using_Swap(atomic_pragma, store, WN_kid0(store), parent,
03883 Update_Private, NULL, return_st) :
03884 Atomic_Using_Swap(atomic_pragma, store, WN_kid0(store), parent,
03885 Update_Private, return_st, NULL);
03886 Insert_Lowered_Atomic(parent, atomic_pragma, atomic_block, ALCLASS_SWAP);
03887 }