12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508 |
- /* OpenMP directive translation -- generate GCC trees from gfc_code.
- Copyright (C) 2005-2015 Free Software Foundation, Inc.
- Contributed by Jakub Jelinek <jakub@redhat.com>
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "hash-set.h"
- #include "machmode.h"
- #include "vec.h"
- #include "double-int.h"
- #include "input.h"
- #include "alias.h"
- #include "symtab.h"
- #include "options.h"
- #include "wide-int.h"
- #include "inchash.h"
- #include "tree.h"
- #include "fold-const.h"
- #include "gimple-expr.h"
- #include "gimplify.h" /* For create_tmp_var_raw. */
- #include "stringpool.h"
- #include "gfortran.h"
- #include "diagnostic-core.h" /* For internal_error. */
- #include "trans.h"
- #include "trans-stmt.h"
- #include "trans-types.h"
- #include "trans-array.h"
- #include "trans-const.h"
- #include "arith.h"
- #include "omp-low.h"
- #include "gomp-constants.h"
- int ompws_flags;
- /* True if OpenMP should privatize what this DECL points to rather
- than the DECL itself. */
- bool
- gfc_omp_privatize_by_reference (const_tree decl)
- {
- tree type = TREE_TYPE (decl);
- if (TREE_CODE (type) == REFERENCE_TYPE
- && (!DECL_ARTIFICIAL (decl) || TREE_CODE (decl) == PARM_DECL))
- return true;
- if (TREE_CODE (type) == POINTER_TYPE)
- {
- /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
- that have POINTER_TYPE type and aren't scalar pointers, scalar
- allocatables, Cray pointees or C pointers are supposed to be
- privatized by reference. */
- if (GFC_DECL_GET_SCALAR_POINTER (decl)
- || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
- || GFC_DECL_CRAY_POINTEE (decl)
- || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
- return false;
- if (!DECL_ARTIFICIAL (decl)
- && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
- return true;
- /* Some arrays are expanded as DECL_ARTIFICIAL pointers
- by the frontend. */
- if (DECL_LANG_SPECIFIC (decl)
- && GFC_DECL_SAVED_DESCRIPTOR (decl))
- return true;
- }
- return false;
- }
- /* True if OpenMP sharing attribute of DECL is predetermined. */
- enum omp_clause_default_kind
- gfc_omp_predetermined_sharing (tree decl)
- {
- /* Associate names preserve the association established during ASSOCIATE.
- As they are implemented either as pointers to the selector or array
- descriptor and shouldn't really change in the ASSOCIATE region,
- this decl can be either shared or firstprivate. If it is a pointer,
- use firstprivate, as it is cheaper that way, otherwise make it shared. */
- if (GFC_DECL_ASSOCIATE_VAR_P (decl))
- {
- if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE)
- return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
- else
- return OMP_CLAUSE_DEFAULT_SHARED;
- }
- if (DECL_ARTIFICIAL (decl)
- && ! GFC_DECL_RESULT (decl)
- && ! (DECL_LANG_SPECIFIC (decl)
- && GFC_DECL_SAVED_DESCRIPTOR (decl)))
- return OMP_CLAUSE_DEFAULT_SHARED;
- /* Cray pointees shouldn't be listed in any clauses and should be
- gimplified to dereference of the corresponding Cray pointer.
- Make them all private, so that they are emitted in the debug
- information. */
- if (GFC_DECL_CRAY_POINTEE (decl))
- return OMP_CLAUSE_DEFAULT_PRIVATE;
- /* Assumed-size arrays are predetermined shared. */
- if (TREE_CODE (decl) == PARM_DECL
- && GFC_ARRAY_TYPE_P (TREE_TYPE (decl))
- && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (decl)) == GFC_ARRAY_UNKNOWN
- && GFC_TYPE_ARRAY_UBOUND (TREE_TYPE (decl),
- GFC_TYPE_ARRAY_RANK (TREE_TYPE (decl)) - 1)
- == NULL)
- return OMP_CLAUSE_DEFAULT_SHARED;
- /* Dummy procedures aren't considered variables by OpenMP, thus are
- disallowed in OpenMP clauses. They are represented as PARM_DECLs
- in the middle-end, so return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE here
- to avoid complaining about their uses with default(none). */
- if (TREE_CODE (decl) == PARM_DECL
- && TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == FUNCTION_TYPE)
- return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
- /* COMMON and EQUIVALENCE decls are shared. They
- are only referenced through DECL_VALUE_EXPR of the variables
- contained in them. If those are privatized, they will not be
- gimplified to the COMMON or EQUIVALENCE decls. */
- if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
- return OMP_CLAUSE_DEFAULT_SHARED;
- if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
- return OMP_CLAUSE_DEFAULT_SHARED;
- /* These are either array or derived parameters, or vtables.
- In the former cases, the OpenMP standard doesn't consider them to be
- variables at all (they can't be redefined), but they can nevertheless appear
- in parallel/task regions and for default(none) purposes treat them as shared.
- For vtables likely the same handling is desirable. */
- if (TREE_CODE (decl) == VAR_DECL
- && TREE_READONLY (decl)
- && TREE_STATIC (decl))
- return OMP_CLAUSE_DEFAULT_SHARED;
- return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
- }
- /* Return decl that should be used when reporting DEFAULT(NONE)
- diagnostics. */
- tree
- gfc_omp_report_decl (tree decl)
- {
- if (DECL_ARTIFICIAL (decl)
- && DECL_LANG_SPECIFIC (decl)
- && GFC_DECL_SAVED_DESCRIPTOR (decl))
- return GFC_DECL_SAVED_DESCRIPTOR (decl);
- return decl;
- }
- /* Return true if TYPE has any allocatable components. */
- static bool
- gfc_has_alloc_comps (tree type, tree decl)
- {
- tree field, ftype;
- if (POINTER_TYPE_P (type))
- {
- if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
- type = TREE_TYPE (type);
- else if (GFC_DECL_GET_SCALAR_POINTER (decl))
- return false;
- }
- if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
- type = gfc_get_element_type (type);
- if (TREE_CODE (type) != RECORD_TYPE)
- return false;
- for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
- {
- ftype = TREE_TYPE (field);
- if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
- return true;
- if (GFC_DESCRIPTOR_TYPE_P (ftype)
- && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
- return true;
- if (gfc_has_alloc_comps (ftype, field))
- return true;
- }
- return false;
- }
- /* Return true if DECL in private clause needs
- OMP_CLAUSE_PRIVATE_OUTER_REF on the private clause. */
- bool
- gfc_omp_private_outer_ref (tree decl)
- {
- tree type = TREE_TYPE (decl);
- if (GFC_DESCRIPTOR_TYPE_P (type)
- && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
- return true;
- if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl))
- return true;
- if (gfc_omp_privatize_by_reference (decl))
- type = TREE_TYPE (type);
- if (gfc_has_alloc_comps (type, decl))
- return true;
- return false;
- }
- /* Callback for gfc_omp_unshare_expr. */
- static tree
- gfc_omp_unshare_expr_r (tree *tp, int *walk_subtrees, void *)
- {
- tree t = *tp;
- enum tree_code code = TREE_CODE (t);
- /* Stop at types, decls, constants like copy_tree_r. */
- if (TREE_CODE_CLASS (code) == tcc_type
- || TREE_CODE_CLASS (code) == tcc_declaration
- || TREE_CODE_CLASS (code) == tcc_constant
- || code == BLOCK)
- *walk_subtrees = 0;
- else if (handled_component_p (t)
- || TREE_CODE (t) == MEM_REF)
- {
- *tp = unshare_expr (t);
- *walk_subtrees = 0;
- }
- return NULL_TREE;
- }
- /* Unshare in expr anything that the FE which normally doesn't
- care much about tree sharing (because during gimplification
- everything is unshared) could cause problems with tree sharing
- at omp-low.c time. */
- static tree
- gfc_omp_unshare_expr (tree expr)
- {
- walk_tree (&expr, gfc_omp_unshare_expr_r, NULL, NULL);
- return expr;
- }
- enum walk_alloc_comps
- {
- WALK_ALLOC_COMPS_DTOR,
- WALK_ALLOC_COMPS_DEFAULT_CTOR,
- WALK_ALLOC_COMPS_COPY_CTOR
- };
- /* Handle allocatable components in OpenMP clauses. */
- static tree
- gfc_walk_alloc_comps (tree decl, tree dest, tree var,
- enum walk_alloc_comps kind)
- {
- stmtblock_t block, tmpblock;
- tree type = TREE_TYPE (decl), then_b, tem, field;
- gfc_init_block (&block);
- if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
- {
- if (GFC_DESCRIPTOR_TYPE_P (type))
- {
- gfc_init_block (&tmpblock);
- tem = gfc_full_array_size (&tmpblock, decl,
- GFC_TYPE_ARRAY_RANK (type));
- then_b = gfc_finish_block (&tmpblock);
- gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (then_b));
- tem = gfc_omp_unshare_expr (tem);
- tem = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type, tem,
- gfc_index_one_node);
- }
- else
- {
- if (!TYPE_DOMAIN (type)
- || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
- || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
- || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
- {
- tem = fold_build2 (EXACT_DIV_EXPR, sizetype,
- TYPE_SIZE_UNIT (type),
- TYPE_SIZE_UNIT (TREE_TYPE (type)));
- tem = size_binop (MINUS_EXPR, tem, size_one_node);
- }
- else
- tem = array_type_nelts (type);
- tem = fold_convert (gfc_array_index_type, tem);
- }
- tree nelems = gfc_evaluate_now (tem, &block);
- tree index = gfc_create_var (gfc_array_index_type, "S");
- gfc_init_block (&tmpblock);
- tem = gfc_conv_array_data (decl);
- tree declvar = build_fold_indirect_ref_loc (input_location, tem);
- tree declvref = gfc_build_array_ref (declvar, index, NULL);
- tree destvar, destvref = NULL_TREE;
- if (dest)
- {
- tem = gfc_conv_array_data (dest);
- destvar = build_fold_indirect_ref_loc (input_location, tem);
- destvref = gfc_build_array_ref (destvar, index, NULL);
- }
- gfc_add_expr_to_block (&tmpblock,
- gfc_walk_alloc_comps (declvref, destvref,
- var, kind));
- gfc_loopinfo loop;
- gfc_init_loopinfo (&loop);
- loop.dimen = 1;
- loop.from[0] = gfc_index_zero_node;
- loop.loopvar[0] = index;
- loop.to[0] = nelems;
- gfc_trans_scalarizing_loops (&loop, &tmpblock);
- gfc_add_block_to_block (&block, &loop.pre);
- return gfc_finish_block (&block);
- }
- else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (var))
- {
- decl = build_fold_indirect_ref_loc (input_location, decl);
- if (dest)
- dest = build_fold_indirect_ref_loc (input_location, dest);
- type = TREE_TYPE (decl);
- }
- gcc_assert (TREE_CODE (type) == RECORD_TYPE);
- for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
- {
- tree ftype = TREE_TYPE (field);
- tree declf, destf = NULL_TREE;
- bool has_alloc_comps = gfc_has_alloc_comps (ftype, field);
- if ((!GFC_DESCRIPTOR_TYPE_P (ftype)
- || GFC_TYPE_ARRAY_AKIND (ftype) != GFC_ARRAY_ALLOCATABLE)
- && !GFC_DECL_GET_SCALAR_ALLOCATABLE (field)
- && !has_alloc_comps)
- continue;
- declf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
- decl, field, NULL_TREE);
- if (dest)
- destf = fold_build3_loc (input_location, COMPONENT_REF, ftype,
- dest, field, NULL_TREE);
- tem = NULL_TREE;
- switch (kind)
- {
- case WALK_ALLOC_COMPS_DTOR:
- break;
- case WALK_ALLOC_COMPS_DEFAULT_CTOR:
- if (GFC_DESCRIPTOR_TYPE_P (ftype)
- && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
- {
- gfc_add_modify (&block, unshare_expr (destf),
- unshare_expr (declf));
- tem = gfc_duplicate_allocatable_nocopy
- (destf, declf, ftype,
- GFC_TYPE_ARRAY_RANK (ftype));
- }
- else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
- tem = gfc_duplicate_allocatable_nocopy (destf, declf, ftype, 0);
- break;
- case WALK_ALLOC_COMPS_COPY_CTOR:
- if (GFC_DESCRIPTOR_TYPE_P (ftype)
- && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
- tem = gfc_duplicate_allocatable (destf, declf, ftype,
- GFC_TYPE_ARRAY_RANK (ftype));
- else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
- tem = gfc_duplicate_allocatable (destf, declf, ftype, 0);
- break;
- }
- if (tem)
- gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
- if (has_alloc_comps)
- {
- gfc_init_block (&tmpblock);
- gfc_add_expr_to_block (&tmpblock,
- gfc_walk_alloc_comps (declf, destf,
- field, kind));
- then_b = gfc_finish_block (&tmpblock);
- if (GFC_DESCRIPTOR_TYPE_P (ftype)
- && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
- tem = gfc_conv_descriptor_data_get (unshare_expr (declf));
- else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
- tem = unshare_expr (declf);
- else
- tem = NULL_TREE;
- if (tem)
- {
- tem = fold_convert (pvoid_type_node, tem);
- tem = fold_build2_loc (input_location, NE_EXPR,
- boolean_type_node, tem,
- null_pointer_node);
- then_b = build3_loc (input_location, COND_EXPR, void_type_node,
- tem, then_b,
- build_empty_stmt (input_location));
- }
- gfc_add_expr_to_block (&block, then_b);
- }
- if (kind == WALK_ALLOC_COMPS_DTOR)
- {
- if (GFC_DESCRIPTOR_TYPE_P (ftype)
- && GFC_TYPE_ARRAY_AKIND (ftype) == GFC_ARRAY_ALLOCATABLE)
- {
- tem = gfc_trans_dealloc_allocated (unshare_expr (declf),
- false, NULL);
- gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
- }
- else if (GFC_DECL_GET_SCALAR_ALLOCATABLE (field))
- {
- tem = gfc_call_free (unshare_expr (declf));
- gfc_add_expr_to_block (&block, gfc_omp_unshare_expr (tem));
- }
- }
- }
- return gfc_finish_block (&block);
- }
- /* Return code to initialize DECL with its default constructor, or
- NULL if there's nothing to do. */
- tree
- gfc_omp_clause_default_ctor (tree clause, tree decl, tree outer)
- {
- tree type = TREE_TYPE (decl), size, ptr, cond, then_b, else_b;
- stmtblock_t block, cond_block;
- gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_PRIVATE
- || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LASTPRIVATE
- || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR
- || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION);
- if ((! GFC_DESCRIPTOR_TYPE_P (type)
- || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
- && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
- {
- if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
- {
- gcc_assert (outer);
- gfc_start_block (&block);
- tree tem = gfc_walk_alloc_comps (outer, decl,
- OMP_CLAUSE_DECL (clause),
- WALK_ALLOC_COMPS_DEFAULT_CTOR);
- gfc_add_expr_to_block (&block, tem);
- return gfc_finish_block (&block);
- }
- return NULL_TREE;
- }
- gcc_assert (outer != NULL_TREE);
- /* Allocatable arrays and scalars in PRIVATE clauses need to be set to
- "not currently allocated" allocation status if outer
- array is "not currently allocated", otherwise should be allocated. */
- gfc_start_block (&block);
- gfc_init_block (&cond_block);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- {
- gfc_add_modify (&cond_block, decl, outer);
- tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
- size = gfc_conv_descriptor_ubound_get (decl, rank);
- size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
- size,
- gfc_conv_descriptor_lbound_get (decl, rank));
- size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
- size, gfc_index_one_node);
- if (GFC_TYPE_ARRAY_RANK (type) > 1)
- size = fold_build2_loc (input_location, MULT_EXPR,
- gfc_array_index_type, size,
- gfc_conv_descriptor_stride_get (decl, rank));
- tree esize = fold_convert (gfc_array_index_type,
- TYPE_SIZE_UNIT (gfc_get_element_type (type)));
- size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
- size, esize);
- size = unshare_expr (size);
- size = gfc_evaluate_now (fold_convert (size_type_node, size),
- &cond_block);
- }
- else
- size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
- ptr = gfc_create_var (pvoid_type_node, NULL);
- gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl), ptr);
- else
- gfc_add_modify (&cond_block, unshare_expr (decl),
- fold_convert (TREE_TYPE (decl), ptr));
- if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
- {
- tree tem = gfc_walk_alloc_comps (outer, decl,
- OMP_CLAUSE_DECL (clause),
- WALK_ALLOC_COMPS_DEFAULT_CTOR);
- gfc_add_expr_to_block (&cond_block, tem);
- }
- then_b = gfc_finish_block (&cond_block);
- /* Reduction clause requires allocated ALLOCATABLE. */
- if (OMP_CLAUSE_CODE (clause) != OMP_CLAUSE_REDUCTION)
- {
- gfc_init_block (&cond_block);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- gfc_conv_descriptor_data_set (&cond_block, unshare_expr (decl),
- null_pointer_node);
- else
- gfc_add_modify (&cond_block, unshare_expr (decl),
- build_zero_cst (TREE_TYPE (decl)));
- else_b = gfc_finish_block (&cond_block);
- tree tem = fold_convert (pvoid_type_node,
- GFC_DESCRIPTOR_TYPE_P (type)
- ? gfc_conv_descriptor_data_get (outer) : outer);
- tem = unshare_expr (tem);
- cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- tem, null_pointer_node);
- gfc_add_expr_to_block (&block,
- build3_loc (input_location, COND_EXPR,
- void_type_node, cond, then_b,
- else_b));
- }
- else
- gfc_add_expr_to_block (&block, then_b);
- return gfc_finish_block (&block);
- }
- /* Build and return code for a copy constructor from SRC to DEST. */
- tree
- gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
- {
- tree type = TREE_TYPE (dest), ptr, size, call;
- tree cond, then_b, else_b;
- stmtblock_t block, cond_block;
- gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
- || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
- if ((! GFC_DESCRIPTOR_TYPE_P (type)
- || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
- && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
- {
- if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
- {
- gfc_start_block (&block);
- gfc_add_modify (&block, dest, src);
- tree tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
- WALK_ALLOC_COMPS_COPY_CTOR);
- gfc_add_expr_to_block (&block, tem);
- return gfc_finish_block (&block);
- }
- else
- return build2_v (MODIFY_EXPR, dest, src);
- }
- /* Allocatable arrays in FIRSTPRIVATE clauses need to be allocated
- and copied from SRC. */
- gfc_start_block (&block);
- gfc_init_block (&cond_block);
- gfc_add_modify (&cond_block, dest, src);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- {
- tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
- size = gfc_conv_descriptor_ubound_get (dest, rank);
- size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
- size,
- gfc_conv_descriptor_lbound_get (dest, rank));
- size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
- size, gfc_index_one_node);
- if (GFC_TYPE_ARRAY_RANK (type) > 1)
- size = fold_build2_loc (input_location, MULT_EXPR,
- gfc_array_index_type, size,
- gfc_conv_descriptor_stride_get (dest, rank));
- tree esize = fold_convert (gfc_array_index_type,
- TYPE_SIZE_UNIT (gfc_get_element_type (type)));
- size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
- size, esize);
- size = unshare_expr (size);
- size = gfc_evaluate_now (fold_convert (size_type_node, size),
- &cond_block);
- }
- else
- size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
- ptr = gfc_create_var (pvoid_type_node, NULL);
- gfc_allocate_using_malloc (&cond_block, ptr, size, NULL_TREE);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest), ptr);
- else
- gfc_add_modify (&cond_block, unshare_expr (dest),
- fold_convert (TREE_TYPE (dest), ptr));
- tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
- ? gfc_conv_descriptor_data_get (src) : src;
- srcptr = unshare_expr (srcptr);
- srcptr = fold_convert (pvoid_type_node, srcptr);
- call = build_call_expr_loc (input_location,
- builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
- srcptr, size);
- gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
- if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
- {
- tree tem = gfc_walk_alloc_comps (src, dest,
- OMP_CLAUSE_DECL (clause),
- WALK_ALLOC_COMPS_COPY_CTOR);
- gfc_add_expr_to_block (&cond_block, tem);
- }
- then_b = gfc_finish_block (&cond_block);
- gfc_init_block (&cond_block);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- gfc_conv_descriptor_data_set (&cond_block, unshare_expr (dest),
- null_pointer_node);
- else
- gfc_add_modify (&cond_block, unshare_expr (dest),
- build_zero_cst (TREE_TYPE (dest)));
- else_b = gfc_finish_block (&cond_block);
- cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- unshare_expr (srcptr), null_pointer_node);
- gfc_add_expr_to_block (&block,
- build3_loc (input_location, COND_EXPR,
- void_type_node, cond, then_b, else_b));
- return gfc_finish_block (&block);
- }
- /* Similarly, except use an intrinsic or pointer assignment operator
- instead. */
- tree
- gfc_omp_clause_assign_op (tree clause, tree dest, tree src)
- {
- tree type = TREE_TYPE (dest), ptr, size, call, nonalloc;
- tree cond, then_b, else_b;
- stmtblock_t block, cond_block, cond_block2, inner_block;
- if ((! GFC_DESCRIPTOR_TYPE_P (type)
- || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
- && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
- {
- if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
- {
- gfc_start_block (&block);
- /* First dealloc any allocatable components in DEST. */
- tree tem = gfc_walk_alloc_comps (dest, NULL_TREE,
- OMP_CLAUSE_DECL (clause),
- WALK_ALLOC_COMPS_DTOR);
- gfc_add_expr_to_block (&block, tem);
- /* Then copy over toplevel data. */
- gfc_add_modify (&block, dest, src);
- /* Finally allocate any allocatable components and copy. */
- tem = gfc_walk_alloc_comps (src, dest, OMP_CLAUSE_DECL (clause),
- WALK_ALLOC_COMPS_COPY_CTOR);
- gfc_add_expr_to_block (&block, tem);
- return gfc_finish_block (&block);
- }
- else
- return build2_v (MODIFY_EXPR, dest, src);
- }
- gfc_start_block (&block);
- if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
- {
- then_b = gfc_walk_alloc_comps (dest, NULL_TREE, OMP_CLAUSE_DECL (clause),
- WALK_ALLOC_COMPS_DTOR);
- tree tem = fold_convert (pvoid_type_node,
- GFC_DESCRIPTOR_TYPE_P (type)
- ? gfc_conv_descriptor_data_get (dest) : dest);
- tem = unshare_expr (tem);
- cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- tem, null_pointer_node);
- tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
- then_b, build_empty_stmt (input_location));
- gfc_add_expr_to_block (&block, tem);
- }
- gfc_init_block (&cond_block);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- {
- tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
- size = gfc_conv_descriptor_ubound_get (src, rank);
- size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
- size,
- gfc_conv_descriptor_lbound_get (src, rank));
- size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
- size, gfc_index_one_node);
- if (GFC_TYPE_ARRAY_RANK (type) > 1)
- size = fold_build2_loc (input_location, MULT_EXPR,
- gfc_array_index_type, size,
- gfc_conv_descriptor_stride_get (src, rank));
- tree esize = fold_convert (gfc_array_index_type,
- TYPE_SIZE_UNIT (gfc_get_element_type (type)));
- size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
- size, esize);
- size = unshare_expr (size);
- size = gfc_evaluate_now (fold_convert (size_type_node, size),
- &cond_block);
- }
- else
- size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
- ptr = gfc_create_var (pvoid_type_node, NULL);
- tree destptr = GFC_DESCRIPTOR_TYPE_P (type)
- ? gfc_conv_descriptor_data_get (dest) : dest;
- destptr = unshare_expr (destptr);
- destptr = fold_convert (pvoid_type_node, destptr);
- gfc_add_modify (&cond_block, ptr, destptr);
- nonalloc = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
- destptr, null_pointer_node);
- cond = nonalloc;
- if (GFC_DESCRIPTOR_TYPE_P (type))
- {
- int i;
- for (i = 0; i < GFC_TYPE_ARRAY_RANK (type); i++)
- {
- tree rank = gfc_rank_cst[i];
- tree tem = gfc_conv_descriptor_ubound_get (src, rank);
- tem = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type, tem,
- gfc_conv_descriptor_lbound_get (src, rank));
- tem = fold_build2_loc (input_location, PLUS_EXPR,
- gfc_array_index_type, tem,
- gfc_conv_descriptor_lbound_get (dest, rank));
- tem = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- tem, gfc_conv_descriptor_ubound_get (dest,
- rank));
- cond = fold_build2_loc (input_location, TRUTH_ORIF_EXPR,
- boolean_type_node, cond, tem);
- }
- }
- gfc_init_block (&cond_block2);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- {
- gfc_init_block (&inner_block);
- gfc_allocate_using_malloc (&inner_block, ptr, size, NULL_TREE);
- then_b = gfc_finish_block (&inner_block);
- gfc_init_block (&inner_block);
- gfc_add_modify (&inner_block, ptr,
- gfc_call_realloc (&inner_block, ptr, size));
- else_b = gfc_finish_block (&inner_block);
- gfc_add_expr_to_block (&cond_block2,
- build3_loc (input_location, COND_EXPR,
- void_type_node,
- unshare_expr (nonalloc),
- then_b, else_b));
- gfc_add_modify (&cond_block2, dest, src);
- gfc_conv_descriptor_data_set (&cond_block2, unshare_expr (dest), ptr);
- }
- else
- {
- gfc_allocate_using_malloc (&cond_block2, ptr, size, NULL_TREE);
- gfc_add_modify (&cond_block2, unshare_expr (dest),
- fold_convert (type, ptr));
- }
- then_b = gfc_finish_block (&cond_block2);
- else_b = build_empty_stmt (input_location);
- gfc_add_expr_to_block (&cond_block,
- build3_loc (input_location, COND_EXPR,
- void_type_node, unshare_expr (cond),
- then_b, else_b));
- tree srcptr = GFC_DESCRIPTOR_TYPE_P (type)
- ? gfc_conv_descriptor_data_get (src) : src;
- srcptr = unshare_expr (srcptr);
- srcptr = fold_convert (pvoid_type_node, srcptr);
- call = build_call_expr_loc (input_location,
- builtin_decl_explicit (BUILT_IN_MEMCPY), 3, ptr,
- srcptr, size);
- gfc_add_expr_to_block (&cond_block, fold_convert (void_type_node, call));
- if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
- {
- tree tem = gfc_walk_alloc_comps (src, dest,
- OMP_CLAUSE_DECL (clause),
- WALK_ALLOC_COMPS_COPY_CTOR);
- gfc_add_expr_to_block (&cond_block, tem);
- }
- then_b = gfc_finish_block (&cond_block);
- if (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_COPYIN)
- {
- gfc_init_block (&cond_block);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- gfc_add_expr_to_block (&cond_block,
- gfc_trans_dealloc_allocated (unshare_expr (dest),
- false, NULL));
- else
- {
- destptr = gfc_evaluate_now (destptr, &cond_block);
- gfc_add_expr_to_block (&cond_block, gfc_call_free (destptr));
- gfc_add_modify (&cond_block, unshare_expr (dest),
- build_zero_cst (TREE_TYPE (dest)));
- }
- else_b = gfc_finish_block (&cond_block);
- cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- unshare_expr (srcptr), null_pointer_node);
- gfc_add_expr_to_block (&block,
- build3_loc (input_location, COND_EXPR,
- void_type_node, cond,
- then_b, else_b));
- }
- else
- gfc_add_expr_to_block (&block, then_b);
- return gfc_finish_block (&block);
- }
- static void
- gfc_omp_linear_clause_add_loop (stmtblock_t *block, tree dest, tree src,
- tree add, tree nelems)
- {
- stmtblock_t tmpblock;
- tree desta, srca, index = gfc_create_var (gfc_array_index_type, "S");
- nelems = gfc_evaluate_now (nelems, block);
- gfc_init_block (&tmpblock);
- if (TREE_CODE (TREE_TYPE (dest)) == ARRAY_TYPE)
- {
- desta = gfc_build_array_ref (dest, index, NULL);
- srca = gfc_build_array_ref (src, index, NULL);
- }
- else
- {
- gcc_assert (POINTER_TYPE_P (TREE_TYPE (dest)));
- tree idx = fold_build2 (MULT_EXPR, sizetype,
- fold_convert (sizetype, index),
- TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (dest))));
- desta = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
- TREE_TYPE (dest), dest,
- idx));
- srca = build_fold_indirect_ref (fold_build2 (POINTER_PLUS_EXPR,
- TREE_TYPE (src), src,
- idx));
- }
- gfc_add_modify (&tmpblock, desta,
- fold_build2 (PLUS_EXPR, TREE_TYPE (desta),
- srca, add));
- gfc_loopinfo loop;
- gfc_init_loopinfo (&loop);
- loop.dimen = 1;
- loop.from[0] = gfc_index_zero_node;
- loop.loopvar[0] = index;
- loop.to[0] = nelems;
- gfc_trans_scalarizing_loops (&loop, &tmpblock);
- gfc_add_block_to_block (block, &loop.pre);
- }
- /* Build and return code for a constructor of DEST that initializes
- it to SRC plus ADD (ADD is scalar integer). */
- tree
- gfc_omp_clause_linear_ctor (tree clause, tree dest, tree src, tree add)
- {
- tree type = TREE_TYPE (dest), ptr, size, nelems = NULL_TREE;
- stmtblock_t block;
- gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
- gfc_start_block (&block);
- add = gfc_evaluate_now (add, &block);
- if ((! GFC_DESCRIPTOR_TYPE_P (type)
- || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
- && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
- {
- gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
- if (!TYPE_DOMAIN (type)
- || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE
- || TYPE_MIN_VALUE (TYPE_DOMAIN (type)) == error_mark_node
- || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == error_mark_node)
- {
- nelems = fold_build2 (EXACT_DIV_EXPR, sizetype,
- TYPE_SIZE_UNIT (type),
- TYPE_SIZE_UNIT (TREE_TYPE (type)));
- nelems = size_binop (MINUS_EXPR, nelems, size_one_node);
- }
- else
- nelems = array_type_nelts (type);
- nelems = fold_convert (gfc_array_index_type, nelems);
- gfc_omp_linear_clause_add_loop (&block, dest, src, add, nelems);
- return gfc_finish_block (&block);
- }
- /* Allocatable arrays in LINEAR clauses need to be allocated
- and copied from SRC. */
- gfc_add_modify (&block, dest, src);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- {
- tree rank = gfc_rank_cst[GFC_TYPE_ARRAY_RANK (type) - 1];
- size = gfc_conv_descriptor_ubound_get (dest, rank);
- size = fold_build2_loc (input_location, MINUS_EXPR, gfc_array_index_type,
- size,
- gfc_conv_descriptor_lbound_get (dest, rank));
- size = fold_build2_loc (input_location, PLUS_EXPR, gfc_array_index_type,
- size, gfc_index_one_node);
- if (GFC_TYPE_ARRAY_RANK (type) > 1)
- size = fold_build2_loc (input_location, MULT_EXPR,
- gfc_array_index_type, size,
- gfc_conv_descriptor_stride_get (dest, rank));
- tree esize = fold_convert (gfc_array_index_type,
- TYPE_SIZE_UNIT (gfc_get_element_type (type)));
- nelems = gfc_evaluate_now (unshare_expr (size), &block);
- size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
- nelems, unshare_expr (esize));
- size = gfc_evaluate_now (fold_convert (size_type_node, size),
- &block);
- nelems = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type, nelems,
- gfc_index_one_node);
- }
- else
- size = fold_convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (type)));
- ptr = gfc_create_var (pvoid_type_node, NULL);
- gfc_allocate_using_malloc (&block, ptr, size, NULL_TREE);
- if (GFC_DESCRIPTOR_TYPE_P (type))
- {
- gfc_conv_descriptor_data_set (&block, unshare_expr (dest), ptr);
- tree etype = gfc_get_element_type (type);
- ptr = fold_convert (build_pointer_type (etype), ptr);
- tree srcptr = gfc_conv_descriptor_data_get (unshare_expr (src));
- srcptr = fold_convert (build_pointer_type (etype), srcptr);
- gfc_omp_linear_clause_add_loop (&block, ptr, srcptr, add, nelems);
- }
- else
- {
- gfc_add_modify (&block, unshare_expr (dest),
- fold_convert (TREE_TYPE (dest), ptr));
- ptr = fold_convert (TREE_TYPE (dest), ptr);
- tree dstm = build_fold_indirect_ref (ptr);
- tree srcm = build_fold_indirect_ref (unshare_expr (src));
- gfc_add_modify (&block, dstm,
- fold_build2 (PLUS_EXPR, TREE_TYPE (add), srcm, add));
- }
- return gfc_finish_block (&block);
- }
- /* Build and return code destructing DECL. Return NULL if nothing
- to be done. */
- tree
- gfc_omp_clause_dtor (tree clause, tree decl)
- {
- tree type = TREE_TYPE (decl), tem;
- if ((! GFC_DESCRIPTOR_TYPE_P (type)
- || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)
- && !GFC_DECL_GET_SCALAR_ALLOCATABLE (OMP_CLAUSE_DECL (clause)))
- {
- if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
- return gfc_walk_alloc_comps (decl, NULL_TREE,
- OMP_CLAUSE_DECL (clause),
- WALK_ALLOC_COMPS_DTOR);
- return NULL_TREE;
- }
- if (GFC_DESCRIPTOR_TYPE_P (type))
- /* Allocatable arrays in FIRSTPRIVATE/LASTPRIVATE etc. clauses need
- to be deallocated if they were allocated. */
- tem = gfc_trans_dealloc_allocated (decl, false, NULL);
- else
- tem = gfc_call_free (decl);
- tem = gfc_omp_unshare_expr (tem);
- if (gfc_has_alloc_comps (type, OMP_CLAUSE_DECL (clause)))
- {
- stmtblock_t block;
- tree then_b;
- gfc_init_block (&block);
- gfc_add_expr_to_block (&block,
- gfc_walk_alloc_comps (decl, NULL_TREE,
- OMP_CLAUSE_DECL (clause),
- WALK_ALLOC_COMPS_DTOR));
- gfc_add_expr_to_block (&block, tem);
- then_b = gfc_finish_block (&block);
- tem = fold_convert (pvoid_type_node,
- GFC_DESCRIPTOR_TYPE_P (type)
- ? gfc_conv_descriptor_data_get (decl) : decl);
- tem = unshare_expr (tem);
- tree cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- tem, null_pointer_node);
- tem = build3_loc (input_location, COND_EXPR, void_type_node, cond,
- then_b, build_empty_stmt (input_location));
- }
- return tem;
- }
- void
- gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
- {
- if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
- return;
- tree decl = OMP_CLAUSE_DECL (c);
- tree c2 = NULL_TREE, c3 = NULL_TREE, c4 = NULL_TREE;
- if (POINTER_TYPE_P (TREE_TYPE (decl)))
- {
- if (!gfc_omp_privatize_by_reference (decl)
- && !GFC_DECL_GET_SCALAR_POINTER (decl)
- && !GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
- && !GFC_DECL_CRAY_POINTEE (decl)
- && !GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
- return;
- tree orig_decl = decl;
- c4 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (c4, GOMP_MAP_POINTER);
- OMP_CLAUSE_DECL (c4) = decl;
- OMP_CLAUSE_SIZE (c4) = size_int (0);
- decl = build_fold_indirect_ref (decl);
- OMP_CLAUSE_DECL (c) = decl;
- OMP_CLAUSE_SIZE (c) = NULL_TREE;
- if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
- && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
- || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
- {
- c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
- OMP_CLAUSE_DECL (c3) = unshare_expr (decl);
- OMP_CLAUSE_SIZE (c3) = size_int (0);
- decl = build_fold_indirect_ref (decl);
- OMP_CLAUSE_DECL (c) = decl;
- }
- }
- if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
- {
- stmtblock_t block;
- gfc_start_block (&block);
- tree type = TREE_TYPE (decl);
- tree ptr = gfc_conv_descriptor_data_get (decl);
- ptr = fold_convert (build_pointer_type (char_type_node), ptr);
- ptr = build_fold_indirect_ref (ptr);
- OMP_CLAUSE_DECL (c) = ptr;
- c2 = build_omp_clause (input_location, OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_TO_PSET);
- OMP_CLAUSE_DECL (c2) = decl;
- OMP_CLAUSE_SIZE (c2) = TYPE_SIZE_UNIT (type);
- c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_POINTER);
- OMP_CLAUSE_DECL (c3) = gfc_conv_descriptor_data_get (decl);
- OMP_CLAUSE_SIZE (c3) = size_int (0);
- tree size = create_tmp_var (gfc_array_index_type);
- tree elemsz = TYPE_SIZE_UNIT (gfc_get_element_type (type));
- elemsz = fold_convert (gfc_array_index_type, elemsz);
- if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER
- || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
- {
- stmtblock_t cond_block;
- tree tem, then_b, else_b, zero, cond;
- gfc_init_block (&cond_block);
- tem = gfc_full_array_size (&cond_block, decl,
- GFC_TYPE_ARRAY_RANK (type));
- gfc_add_modify (&cond_block, size, tem);
- gfc_add_modify (&cond_block, size,
- fold_build2 (MULT_EXPR, gfc_array_index_type,
- size, elemsz));
- then_b = gfc_finish_block (&cond_block);
- gfc_init_block (&cond_block);
- zero = build_int_cst (gfc_array_index_type, 0);
- gfc_add_modify (&cond_block, size, zero);
- else_b = gfc_finish_block (&cond_block);
- tem = gfc_conv_descriptor_data_get (decl);
- tem = fold_convert (pvoid_type_node, tem);
- cond = fold_build2_loc (input_location, NE_EXPR,
- boolean_type_node, tem, null_pointer_node);
- gfc_add_expr_to_block (&block, build3_loc (input_location, COND_EXPR,
- void_type_node, cond,
- then_b, else_b));
- }
- else
- {
- gfc_add_modify (&block, size,
- gfc_full_array_size (&block, decl,
- GFC_TYPE_ARRAY_RANK (type)));
- gfc_add_modify (&block, size,
- fold_build2 (MULT_EXPR, gfc_array_index_type,
- size, elemsz));
- }
- OMP_CLAUSE_SIZE (c) = size;
- tree stmt = gfc_finish_block (&block);
- gimplify_and_add (stmt, pre_p);
- }
- tree last = c;
- if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
- OMP_CLAUSE_SIZE (c)
- = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
- : TYPE_SIZE_UNIT (TREE_TYPE (decl));
- if (c2)
- {
- OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (last);
- OMP_CLAUSE_CHAIN (last) = c2;
- last = c2;
- }
- if (c3)
- {
- OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (last);
- OMP_CLAUSE_CHAIN (last) = c3;
- last = c3;
- }
- if (c4)
- {
- OMP_CLAUSE_CHAIN (c4) = OMP_CLAUSE_CHAIN (last);
- OMP_CLAUSE_CHAIN (last) = c4;
- last = c4;
- }
- }
- /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
- disregarded in OpenMP construct, because it is going to be
- remapped during OpenMP lowering. SHARED is true if DECL
- is going to be shared, false if it is going to be privatized. */
- bool
- gfc_omp_disregard_value_expr (tree decl, bool shared)
- {
- if (GFC_DECL_COMMON_OR_EQUIV (decl)
- && DECL_HAS_VALUE_EXPR_P (decl))
- {
- tree value = DECL_VALUE_EXPR (decl);
- if (TREE_CODE (value) == COMPONENT_REF
- && TREE_CODE (TREE_OPERAND (value, 0)) == VAR_DECL
- && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
- {
- /* If variable in COMMON or EQUIVALENCE is privatized, return
- true, as just that variable is supposed to be privatized,
- not the whole COMMON or whole EQUIVALENCE.
- For shared variables in COMMON or EQUIVALENCE, let them be
- gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
- from the same COMMON or EQUIVALENCE just one sharing of the
- whole COMMON or EQUIVALENCE is enough. */
- return ! shared;
- }
- }
- if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
- return ! shared;
- return false;
- }
- /* Return true if DECL that is shared iff SHARED is true should
- be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
- flag set. */
- bool
- gfc_omp_private_debug_clause (tree decl, bool shared)
- {
- if (GFC_DECL_CRAY_POINTEE (decl))
- return true;
- if (GFC_DECL_COMMON_OR_EQUIV (decl)
- && DECL_HAS_VALUE_EXPR_P (decl))
- {
- tree value = DECL_VALUE_EXPR (decl);
- if (TREE_CODE (value) == COMPONENT_REF
- && TREE_CODE (TREE_OPERAND (value, 0)) == VAR_DECL
- && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
- return shared;
- }
- return false;
- }
- /* Register language specific type size variables as potentially OpenMP
- firstprivate variables. */
- void
- gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
- {
- if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
- {
- int r;
- gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
- for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
- {
- omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
- omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
- omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
- }
- omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
- omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
- }
- }
- static inline tree
- gfc_trans_add_clause (tree node, tree tail)
- {
- OMP_CLAUSE_CHAIN (node) = tail;
- return node;
- }
- static tree
- gfc_trans_omp_variable (gfc_symbol *sym, bool declare_simd)
- {
- if (declare_simd)
- {
- int cnt = 0;
- gfc_symbol *proc_sym;
- gfc_formal_arglist *f;
- gcc_assert (sym->attr.dummy);
- proc_sym = sym->ns->proc_name;
- if (proc_sym->attr.entry_master)
- ++cnt;
- if (gfc_return_by_reference (proc_sym))
- {
- ++cnt;
- if (proc_sym->ts.type == BT_CHARACTER)
- ++cnt;
- }
- for (f = gfc_sym_get_dummy_args (proc_sym); f; f = f->next)
- if (f->sym == sym)
- break;
- else if (f->sym)
- ++cnt;
- gcc_assert (f);
- return build_int_cst (integer_type_node, cnt);
- }
- tree t = gfc_get_symbol_decl (sym);
- tree parent_decl;
- int parent_flag;
- bool return_value;
- bool alternate_entry;
- bool entry_master;
- return_value = sym->attr.function && sym->result == sym;
- alternate_entry = sym->attr.function && sym->attr.entry
- && sym->result == sym;
- entry_master = sym->attr.result
- && sym->ns->proc_name->attr.entry_master
- && !gfc_return_by_reference (sym->ns->proc_name);
- parent_decl = current_function_decl
- ? DECL_CONTEXT (current_function_decl) : NULL_TREE;
- if ((t == parent_decl && return_value)
- || (sym->ns && sym->ns->proc_name
- && sym->ns->proc_name->backend_decl == parent_decl
- && (alternate_entry || entry_master)))
- parent_flag = 1;
- else
- parent_flag = 0;
- /* Special case for assigning the return value of a function.
- Self recursive functions must have an explicit return value. */
- if (return_value && (t == current_function_decl || parent_flag))
- t = gfc_get_fake_result_decl (sym, parent_flag);
- /* Similarly for alternate entry points. */
- else if (alternate_entry
- && (sym->ns->proc_name->backend_decl == current_function_decl
- || parent_flag))
- {
- gfc_entry_list *el = NULL;
- for (el = sym->ns->entries; el; el = el->next)
- if (sym == el->sym)
- {
- t = gfc_get_fake_result_decl (sym, parent_flag);
- break;
- }
- }
- else if (entry_master
- && (sym->ns->proc_name->backend_decl == current_function_decl
- || parent_flag))
- t = gfc_get_fake_result_decl (sym, parent_flag);
- return t;
- }
- static tree
- gfc_trans_omp_variable_list (enum omp_clause_code code,
- gfc_omp_namelist *namelist, tree list,
- bool declare_simd)
- {
- for (; namelist != NULL; namelist = namelist->next)
- if (namelist->sym->attr.referenced || declare_simd)
- {
- tree t = gfc_trans_omp_variable (namelist->sym, declare_simd);
- if (t != error_mark_node)
- {
- tree node = build_omp_clause (input_location, code);
- OMP_CLAUSE_DECL (node) = t;
- list = gfc_trans_add_clause (node, list);
- }
- }
- return list;
- }
- struct omp_udr_find_orig_data
- {
- gfc_omp_udr *omp_udr;
- bool omp_orig_seen;
- };
- static int
- omp_udr_find_orig (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
- void *data)
- {
- struct omp_udr_find_orig_data *cd = (struct omp_udr_find_orig_data *) data;
- if ((*e)->expr_type == EXPR_VARIABLE
- && (*e)->symtree->n.sym == cd->omp_udr->omp_orig)
- cd->omp_orig_seen = true;
- return 0;
- }
- static void
- gfc_trans_omp_array_reduction_or_udr (tree c, gfc_omp_namelist *n, locus where)
- {
- gfc_symbol *sym = n->sym;
- gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
- gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
- gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
- gfc_symbol omp_var_copy[4];
- gfc_expr *e1, *e2, *e3, *e4;
- gfc_ref *ref;
- tree decl, backend_decl, stmt, type, outer_decl;
- locus old_loc = gfc_current_locus;
- const char *iname;
- bool t;
- gfc_omp_udr *udr = n->udr ? n->udr->udr : NULL;
- decl = OMP_CLAUSE_DECL (c);
- gfc_current_locus = where;
- type = TREE_TYPE (decl);
- outer_decl = create_tmp_var_raw (type);
- if (TREE_CODE (decl) == PARM_DECL
- && TREE_CODE (type) == REFERENCE_TYPE
- && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (type))
- && GFC_TYPE_ARRAY_AKIND (TREE_TYPE (type)) == GFC_ARRAY_ALLOCATABLE)
- {
- decl = build_fold_indirect_ref (decl);
- type = TREE_TYPE (type);
- }
- /* Create a fake symbol for init value. */
- memset (&init_val_sym, 0, sizeof (init_val_sym));
- init_val_sym.ns = sym->ns;
- init_val_sym.name = sym->name;
- init_val_sym.ts = sym->ts;
- init_val_sym.attr.referenced = 1;
- init_val_sym.declared_at = where;
- init_val_sym.attr.flavor = FL_VARIABLE;
- if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
- backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
- else if (udr->initializer_ns)
- backend_decl = NULL;
- else
- switch (sym->ts.type)
- {
- case BT_LOGICAL:
- case BT_INTEGER:
- case BT_REAL:
- case BT_COMPLEX:
- backend_decl = build_zero_cst (gfc_sym_type (&init_val_sym));
- break;
- default:
- backend_decl = NULL_TREE;
- break;
- }
- init_val_sym.backend_decl = backend_decl;
- /* Create a fake symbol for the outer array reference. */
- outer_sym = *sym;
- if (sym->as)
- outer_sym.as = gfc_copy_array_spec (sym->as);
- outer_sym.attr.dummy = 0;
- outer_sym.attr.result = 0;
- outer_sym.attr.flavor = FL_VARIABLE;
- outer_sym.backend_decl = outer_decl;
- if (decl != OMP_CLAUSE_DECL (c))
- outer_sym.backend_decl = build_fold_indirect_ref (outer_decl);
- /* Create fake symtrees for it. */
- symtree1 = gfc_new_symtree (&root1, sym->name);
- symtree1->n.sym = sym;
- gcc_assert (symtree1 == root1);
- symtree2 = gfc_new_symtree (&root2, sym->name);
- symtree2->n.sym = &init_val_sym;
- gcc_assert (symtree2 == root2);
- symtree3 = gfc_new_symtree (&root3, sym->name);
- symtree3->n.sym = &outer_sym;
- gcc_assert (symtree3 == root3);
- memset (omp_var_copy, 0, sizeof omp_var_copy);
- if (udr)
- {
- omp_var_copy[0] = *udr->omp_out;
- omp_var_copy[1] = *udr->omp_in;
- *udr->omp_out = outer_sym;
- *udr->omp_in = *sym;
- if (udr->initializer_ns)
- {
- omp_var_copy[2] = *udr->omp_priv;
- omp_var_copy[3] = *udr->omp_orig;
- *udr->omp_priv = *sym;
- *udr->omp_orig = outer_sym;
- }
- }
- /* Create expressions. */
- e1 = gfc_get_expr ();
- e1->expr_type = EXPR_VARIABLE;
- e1->where = where;
- e1->symtree = symtree1;
- e1->ts = sym->ts;
- if (sym->attr.dimension)
- {
- e1->ref = ref = gfc_get_ref ();
- ref->type = REF_ARRAY;
- ref->u.ar.where = where;
- ref->u.ar.as = sym->as;
- ref->u.ar.type = AR_FULL;
- ref->u.ar.dimen = 0;
- }
- t = gfc_resolve_expr (e1);
- gcc_assert (t);
- e2 = NULL;
- if (backend_decl != NULL_TREE)
- {
- e2 = gfc_get_expr ();
- e2->expr_type = EXPR_VARIABLE;
- e2->where = where;
- e2->symtree = symtree2;
- e2->ts = sym->ts;
- t = gfc_resolve_expr (e2);
- gcc_assert (t);
- }
- else if (udr->initializer_ns == NULL)
- {
- gcc_assert (sym->ts.type == BT_DERIVED);
- e2 = gfc_default_initializer (&sym->ts);
- gcc_assert (e2);
- t = gfc_resolve_expr (e2);
- gcc_assert (t);
- }
- else if (n->udr->initializer->op == EXEC_ASSIGN)
- {
- e2 = gfc_copy_expr (n->udr->initializer->expr2);
- t = gfc_resolve_expr (e2);
- gcc_assert (t);
- }
- if (udr && udr->initializer_ns)
- {
- struct omp_udr_find_orig_data cd;
- cd.omp_udr = udr;
- cd.omp_orig_seen = false;
- gfc_code_walker (&n->udr->initializer,
- gfc_dummy_code_callback, omp_udr_find_orig, &cd);
- if (cd.omp_orig_seen)
- OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1;
- }
- e3 = gfc_copy_expr (e1);
- e3->symtree = symtree3;
- t = gfc_resolve_expr (e3);
- gcc_assert (t);
- iname = NULL;
- e4 = NULL;
- switch (OMP_CLAUSE_REDUCTION_CODE (c))
- {
- case PLUS_EXPR:
- case MINUS_EXPR:
- e4 = gfc_add (e3, e1);
- break;
- case MULT_EXPR:
- e4 = gfc_multiply (e3, e1);
- break;
- case TRUTH_ANDIF_EXPR:
- e4 = gfc_and (e3, e1);
- break;
- case TRUTH_ORIF_EXPR:
- e4 = gfc_or (e3, e1);
- break;
- case EQ_EXPR:
- e4 = gfc_eqv (e3, e1);
- break;
- case NE_EXPR:
- e4 = gfc_neqv (e3, e1);
- break;
- case MIN_EXPR:
- iname = "min";
- break;
- case MAX_EXPR:
- iname = "max";
- break;
- case BIT_AND_EXPR:
- iname = "iand";
- break;
- case BIT_IOR_EXPR:
- iname = "ior";
- break;
- case BIT_XOR_EXPR:
- iname = "ieor";
- break;
- case ERROR_MARK:
- if (n->udr->combiner->op == EXEC_ASSIGN)
- {
- gfc_free_expr (e3);
- e3 = gfc_copy_expr (n->udr->combiner->expr1);
- e4 = gfc_copy_expr (n->udr->combiner->expr2);
- t = gfc_resolve_expr (e3);
- gcc_assert (t);
- t = gfc_resolve_expr (e4);
- gcc_assert (t);
- }
- break;
- default:
- gcc_unreachable ();
- }
- if (iname != NULL)
- {
- memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
- intrinsic_sym.ns = sym->ns;
- intrinsic_sym.name = iname;
- intrinsic_sym.ts = sym->ts;
- intrinsic_sym.attr.referenced = 1;
- intrinsic_sym.attr.intrinsic = 1;
- intrinsic_sym.attr.function = 1;
- intrinsic_sym.result = &intrinsic_sym;
- intrinsic_sym.declared_at = where;
- symtree4 = gfc_new_symtree (&root4, iname);
- symtree4->n.sym = &intrinsic_sym;
- gcc_assert (symtree4 == root4);
- e4 = gfc_get_expr ();
- e4->expr_type = EXPR_FUNCTION;
- e4->where = where;
- e4->symtree = symtree4;
- e4->value.function.actual = gfc_get_actual_arglist ();
- e4->value.function.actual->expr = e3;
- e4->value.function.actual->next = gfc_get_actual_arglist ();
- e4->value.function.actual->next->expr = e1;
- }
- if (OMP_CLAUSE_REDUCTION_CODE (c) != ERROR_MARK)
- {
- /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
- e1 = gfc_copy_expr (e1);
- e3 = gfc_copy_expr (e3);
- t = gfc_resolve_expr (e4);
- gcc_assert (t);
- }
- /* Create the init statement list. */
- pushlevel ();
- if (e2)
- stmt = gfc_trans_assignment (e1, e2, false, false);
- else
- stmt = gfc_trans_call (n->udr->initializer, false,
- NULL_TREE, NULL_TREE, false);
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
- /* Create the merge statement list. */
- pushlevel ();
- if (e4)
- stmt = gfc_trans_assignment (e3, e4, false, true);
- else
- stmt = gfc_trans_call (n->udr->combiner, false,
- NULL_TREE, NULL_TREE, false);
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
- /* And stick the placeholder VAR_DECL into the clause as well. */
- OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_decl;
- gfc_current_locus = old_loc;
- gfc_free_expr (e1);
- if (e2)
- gfc_free_expr (e2);
- gfc_free_expr (e3);
- if (e4)
- gfc_free_expr (e4);
- free (symtree1);
- free (symtree2);
- free (symtree3);
- free (symtree4);
- if (outer_sym.as)
- gfc_free_array_spec (outer_sym.as);
- if (udr)
- {
- *udr->omp_out = omp_var_copy[0];
- *udr->omp_in = omp_var_copy[1];
- if (udr->initializer_ns)
- {
- *udr->omp_priv = omp_var_copy[2];
- *udr->omp_orig = omp_var_copy[3];
- }
- }
- }
- static tree
- gfc_trans_omp_reduction_list (gfc_omp_namelist *namelist, tree list,
- locus where)
- {
- for (; namelist != NULL; namelist = namelist->next)
- if (namelist->sym->attr.referenced)
- {
- tree t = gfc_trans_omp_variable (namelist->sym, false);
- if (t != error_mark_node)
- {
- tree node = build_omp_clause (where.lb->location,
- OMP_CLAUSE_REDUCTION);
- OMP_CLAUSE_DECL (node) = t;
- switch (namelist->u.reduction_op)
- {
- case OMP_REDUCTION_PLUS:
- OMP_CLAUSE_REDUCTION_CODE (node) = PLUS_EXPR;
- break;
- case OMP_REDUCTION_MINUS:
- OMP_CLAUSE_REDUCTION_CODE (node) = MINUS_EXPR;
- break;
- case OMP_REDUCTION_TIMES:
- OMP_CLAUSE_REDUCTION_CODE (node) = MULT_EXPR;
- break;
- case OMP_REDUCTION_AND:
- OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ANDIF_EXPR;
- break;
- case OMP_REDUCTION_OR:
- OMP_CLAUSE_REDUCTION_CODE (node) = TRUTH_ORIF_EXPR;
- break;
- case OMP_REDUCTION_EQV:
- OMP_CLAUSE_REDUCTION_CODE (node) = EQ_EXPR;
- break;
- case OMP_REDUCTION_NEQV:
- OMP_CLAUSE_REDUCTION_CODE (node) = NE_EXPR;
- break;
- case OMP_REDUCTION_MAX:
- OMP_CLAUSE_REDUCTION_CODE (node) = MAX_EXPR;
- break;
- case OMP_REDUCTION_MIN:
- OMP_CLAUSE_REDUCTION_CODE (node) = MIN_EXPR;
- break;
- case OMP_REDUCTION_IAND:
- OMP_CLAUSE_REDUCTION_CODE (node) = BIT_AND_EXPR;
- break;
- case OMP_REDUCTION_IOR:
- OMP_CLAUSE_REDUCTION_CODE (node) = BIT_IOR_EXPR;
- break;
- case OMP_REDUCTION_IEOR:
- OMP_CLAUSE_REDUCTION_CODE (node) = BIT_XOR_EXPR;
- break;
- case OMP_REDUCTION_USER:
- OMP_CLAUSE_REDUCTION_CODE (node) = ERROR_MARK;
- break;
- default:
- gcc_unreachable ();
- }
- if (namelist->sym->attr.dimension
- || namelist->u.reduction_op == OMP_REDUCTION_USER
- || namelist->sym->attr.allocatable)
- gfc_trans_omp_array_reduction_or_udr (node, namelist, where);
- list = gfc_trans_add_clause (node, list);
- }
- }
- return list;
- }
- static inline tree
- gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr)
- {
- gfc_se se;
- tree result;
- gfc_init_se (&se, NULL );
- gfc_conv_expr (&se, expr);
- gfc_add_block_to_block (block, &se.pre);
- result = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- return result;
- }
- static tree
- gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
- locus where, bool declare_simd = false)
- {
- tree omp_clauses = NULL_TREE, chunk_size, c;
- int list;
- enum omp_clause_code clause_code;
- gfc_se se;
- if (clauses == NULL)
- return NULL_TREE;
- for (list = 0; list < OMP_LIST_NUM; list++)
- {
- gfc_omp_namelist *n = clauses->lists[list];
- if (n == NULL)
- continue;
- switch (list)
- {
- case OMP_LIST_REDUCTION:
- omp_clauses = gfc_trans_omp_reduction_list (n, omp_clauses, where);
- break;
- case OMP_LIST_PRIVATE:
- clause_code = OMP_CLAUSE_PRIVATE;
- goto add_clause;
- case OMP_LIST_SHARED:
- clause_code = OMP_CLAUSE_SHARED;
- goto add_clause;
- case OMP_LIST_FIRSTPRIVATE:
- clause_code = OMP_CLAUSE_FIRSTPRIVATE;
- goto add_clause;
- case OMP_LIST_LASTPRIVATE:
- clause_code = OMP_CLAUSE_LASTPRIVATE;
- goto add_clause;
- case OMP_LIST_COPYIN:
- clause_code = OMP_CLAUSE_COPYIN;
- goto add_clause;
- case OMP_LIST_COPYPRIVATE:
- clause_code = OMP_CLAUSE_COPYPRIVATE;
- goto add_clause;
- case OMP_LIST_UNIFORM:
- clause_code = OMP_CLAUSE_UNIFORM;
- goto add_clause;
- case OMP_LIST_USE_DEVICE:
- clause_code = OMP_CLAUSE_USE_DEVICE;
- goto add_clause;
- case OMP_LIST_DEVICE_RESIDENT:
- clause_code = OMP_CLAUSE_DEVICE_RESIDENT;
- goto add_clause;
- case OMP_LIST_CACHE:
- clause_code = OMP_CLAUSE__CACHE_;
- goto add_clause;
- add_clause:
- omp_clauses
- = gfc_trans_omp_variable_list (clause_code, n, omp_clauses,
- declare_simd);
- break;
- case OMP_LIST_ALIGNED:
- for (; n != NULL; n = n->next)
- if (n->sym->attr.referenced || declare_simd)
- {
- tree t = gfc_trans_omp_variable (n->sym, declare_simd);
- if (t != error_mark_node)
- {
- tree node = build_omp_clause (input_location,
- OMP_CLAUSE_ALIGNED);
- OMP_CLAUSE_DECL (node) = t;
- if (n->expr)
- {
- tree alignment_var;
- if (block == NULL)
- alignment_var = gfc_conv_constant_to_tree (n->expr);
- else
- {
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, n->expr);
- gfc_add_block_to_block (block, &se.pre);
- alignment_var = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- }
- OMP_CLAUSE_ALIGNED_ALIGNMENT (node) = alignment_var;
- }
- omp_clauses = gfc_trans_add_clause (node, omp_clauses);
- }
- }
- break;
- case OMP_LIST_LINEAR:
- {
- gfc_expr *last_step_expr = NULL;
- tree last_step = NULL_TREE;
- for (; n != NULL; n = n->next)
- {
- if (n->expr)
- {
- last_step_expr = n->expr;
- last_step = NULL_TREE;
- }
- if (n->sym->attr.referenced || declare_simd)
- {
- tree t = gfc_trans_omp_variable (n->sym, declare_simd);
- if (t != error_mark_node)
- {
- tree node = build_omp_clause (input_location,
- OMP_CLAUSE_LINEAR);
- OMP_CLAUSE_DECL (node) = t;
- if (last_step_expr && last_step == NULL_TREE)
- {
- if (block == NULL)
- last_step
- = gfc_conv_constant_to_tree (last_step_expr);
- else
- {
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, last_step_expr);
- gfc_add_block_to_block (block, &se.pre);
- last_step = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- }
- }
- OMP_CLAUSE_LINEAR_STEP (node)
- = fold_convert (gfc_typenode_for_spec (&n->sym->ts),
- last_step);
- if (n->sym->attr.dimension || n->sym->attr.allocatable)
- OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
- omp_clauses = gfc_trans_add_clause (node, omp_clauses);
- }
- }
- }
- }
- break;
- case OMP_LIST_DEPEND:
- for (; n != NULL; n = n->next)
- {
- if (!n->sym->attr.referenced)
- continue;
- tree node = build_omp_clause (input_location, OMP_CLAUSE_DEPEND);
- if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
- {
- tree decl = gfc_get_symbol_decl (n->sym);
- if (gfc_omp_privatize_by_reference (decl))
- decl = build_fold_indirect_ref (decl);
- if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
- {
- decl = gfc_conv_descriptor_data_get (decl);
- decl = fold_convert (build_pointer_type (char_type_node),
- decl);
- decl = build_fold_indirect_ref (decl);
- }
- else if (DECL_P (decl))
- TREE_ADDRESSABLE (decl) = 1;
- OMP_CLAUSE_DECL (node) = decl;
- }
- else
- {
- tree ptr;
- gfc_init_se (&se, NULL);
- if (n->expr->ref->u.ar.type == AR_ELEMENT)
- {
- gfc_conv_expr_reference (&se, n->expr);
- ptr = se.expr;
- }
- else
- {
- gfc_conv_expr_descriptor (&se, n->expr);
- ptr = gfc_conv_array_data (se.expr);
- }
- gfc_add_block_to_block (block, &se.pre);
- gfc_add_block_to_block (block, &se.post);
- ptr = fold_convert (build_pointer_type (char_type_node),
- ptr);
- OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
- }
- switch (n->u.depend_op)
- {
- case OMP_DEPEND_IN:
- OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_IN;
- break;
- case OMP_DEPEND_OUT:
- OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_OUT;
- break;
- case OMP_DEPEND_INOUT:
- OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_INOUT;
- break;
- default:
- gcc_unreachable ();
- }
- omp_clauses = gfc_trans_add_clause (node, omp_clauses);
- }
- break;
- case OMP_LIST_MAP:
- for (; n != NULL; n = n->next)
- {
- if (!n->sym->attr.referenced)
- continue;
- tree node = build_omp_clause (input_location, OMP_CLAUSE_MAP);
- tree node2 = NULL_TREE;
- tree node3 = NULL_TREE;
- tree node4 = NULL_TREE;
- tree decl = gfc_get_symbol_decl (n->sym);
- if (DECL_P (decl))
- TREE_ADDRESSABLE (decl) = 1;
- if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
- {
- if (POINTER_TYPE_P (TREE_TYPE (decl))
- && (gfc_omp_privatize_by_reference (decl)
- || GFC_DECL_GET_SCALAR_POINTER (decl)
- || GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
- || GFC_DECL_CRAY_POINTEE (decl)
- || GFC_DESCRIPTOR_TYPE_P
- (TREE_TYPE (TREE_TYPE (decl)))))
- {
- tree orig_decl = decl;
- node4 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
- OMP_CLAUSE_DECL (node4) = decl;
- OMP_CLAUSE_SIZE (node4) = size_int (0);
- decl = build_fold_indirect_ref (decl);
- if (TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE
- && (GFC_DECL_GET_SCALAR_POINTER (orig_decl)
- || GFC_DECL_GET_SCALAR_ALLOCATABLE (orig_decl)))
- {
- node3 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
- OMP_CLAUSE_DECL (node3) = decl;
- OMP_CLAUSE_SIZE (node3) = size_int (0);
- decl = build_fold_indirect_ref (decl);
- }
- }
- if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
- {
- tree type = TREE_TYPE (decl);
- tree ptr = gfc_conv_descriptor_data_get (decl);
- ptr = fold_convert (build_pointer_type (char_type_node),
- ptr);
- ptr = build_fold_indirect_ref (ptr);
- OMP_CLAUSE_DECL (node) = ptr;
- node2 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
- OMP_CLAUSE_DECL (node2) = decl;
- OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
- node3 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
- OMP_CLAUSE_DECL (node3)
- = gfc_conv_descriptor_data_get (decl);
- OMP_CLAUSE_SIZE (node3) = size_int (0);
- /* We have to check for n->sym->attr.dimension because
- of scalar coarrays. */
- if (n->sym->attr.pointer && n->sym->attr.dimension)
- {
- stmtblock_t cond_block;
- tree size
- = gfc_create_var (gfc_array_index_type, NULL);
- tree tem, then_b, else_b, zero, cond;
- gfc_init_block (&cond_block);
- tem
- = gfc_full_array_size (&cond_block, decl,
- GFC_TYPE_ARRAY_RANK (type));
- gfc_add_modify (&cond_block, size, tem);
- then_b = gfc_finish_block (&cond_block);
- gfc_init_block (&cond_block);
- zero = build_int_cst (gfc_array_index_type, 0);
- gfc_add_modify (&cond_block, size, zero);
- else_b = gfc_finish_block (&cond_block);
- tem = gfc_conv_descriptor_data_get (decl);
- tem = fold_convert (pvoid_type_node, tem);
- cond = fold_build2_loc (input_location, NE_EXPR,
- boolean_type_node,
- tem, null_pointer_node);
- gfc_add_expr_to_block (block,
- build3_loc (input_location,
- COND_EXPR,
- void_type_node,
- cond, then_b,
- else_b));
- OMP_CLAUSE_SIZE (node) = size;
- }
- else if (n->sym->attr.dimension)
- OMP_CLAUSE_SIZE (node)
- = gfc_full_array_size (block, decl,
- GFC_TYPE_ARRAY_RANK (type));
- if (n->sym->attr.dimension)
- {
- tree elemsz
- = TYPE_SIZE_UNIT (gfc_get_element_type (type));
- elemsz = fold_convert (gfc_array_index_type, elemsz);
- OMP_CLAUSE_SIZE (node)
- = fold_build2 (MULT_EXPR, gfc_array_index_type,
- OMP_CLAUSE_SIZE (node), elemsz);
- }
- }
- else
- OMP_CLAUSE_DECL (node) = decl;
- }
- else
- {
- tree ptr, ptr2;
- gfc_init_se (&se, NULL);
- if (n->expr->ref->u.ar.type == AR_ELEMENT)
- {
- gfc_conv_expr_reference (&se, n->expr);
- gfc_add_block_to_block (block, &se.pre);
- ptr = se.expr;
- OMP_CLAUSE_SIZE (node)
- = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
- }
- else
- {
- gfc_conv_expr_descriptor (&se, n->expr);
- ptr = gfc_conv_array_data (se.expr);
- tree type = TREE_TYPE (se.expr);
- gfc_add_block_to_block (block, &se.pre);
- OMP_CLAUSE_SIZE (node)
- = gfc_full_array_size (block, se.expr,
- GFC_TYPE_ARRAY_RANK (type));
- tree elemsz
- = TYPE_SIZE_UNIT (gfc_get_element_type (type));
- elemsz = fold_convert (gfc_array_index_type, elemsz);
- OMP_CLAUSE_SIZE (node)
- = fold_build2 (MULT_EXPR, gfc_array_index_type,
- OMP_CLAUSE_SIZE (node), elemsz);
- }
- gfc_add_block_to_block (block, &se.post);
- ptr = fold_convert (build_pointer_type (char_type_node),
- ptr);
- OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
- if (POINTER_TYPE_P (TREE_TYPE (decl))
- && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
- {
- node4 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node4, GOMP_MAP_POINTER);
- OMP_CLAUSE_DECL (node4) = decl;
- OMP_CLAUSE_SIZE (node4) = size_int (0);
- decl = build_fold_indirect_ref (decl);
- }
- ptr = fold_convert (sizetype, ptr);
- if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
- {
- tree type = TREE_TYPE (decl);
- ptr2 = gfc_conv_descriptor_data_get (decl);
- node2 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node2, GOMP_MAP_TO_PSET);
- OMP_CLAUSE_DECL (node2) = decl;
- OMP_CLAUSE_SIZE (node2) = TYPE_SIZE_UNIT (type);
- node3 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
- OMP_CLAUSE_DECL (node3)
- = gfc_conv_descriptor_data_get (decl);
- }
- else
- {
- if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- ptr2 = build_fold_addr_expr (decl);
- else
- {
- gcc_assert (POINTER_TYPE_P (TREE_TYPE (decl)));
- ptr2 = decl;
- }
- node3 = build_omp_clause (input_location,
- OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (node3, GOMP_MAP_POINTER);
- OMP_CLAUSE_DECL (node3) = decl;
- }
- ptr2 = fold_convert (sizetype, ptr2);
- OMP_CLAUSE_SIZE (node3)
- = fold_build2 (MINUS_EXPR, sizetype, ptr, ptr2);
- }
- switch (n->u.map_op)
- {
- case OMP_MAP_ALLOC:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALLOC);
- break;
- case OMP_MAP_TO:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TO);
- break;
- case OMP_MAP_FROM:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FROM);
- break;
- case OMP_MAP_TOFROM:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
- break;
- case OMP_MAP_FORCE_ALLOC:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_ALLOC);
- break;
- case OMP_MAP_FORCE_DEALLOC:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEALLOC);
- break;
- case OMP_MAP_FORCE_TO:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TO);
- break;
- case OMP_MAP_FORCE_FROM:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_FROM);
- break;
- case OMP_MAP_FORCE_TOFROM:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_TOFROM);
- break;
- case OMP_MAP_FORCE_PRESENT:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_PRESENT);
- break;
- case OMP_MAP_FORCE_DEVICEPTR:
- OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_FORCE_DEVICEPTR);
- break;
- default:
- gcc_unreachable ();
- }
- omp_clauses = gfc_trans_add_clause (node, omp_clauses);
- if (node2)
- omp_clauses = gfc_trans_add_clause (node2, omp_clauses);
- if (node3)
- omp_clauses = gfc_trans_add_clause (node3, omp_clauses);
- if (node4)
- omp_clauses = gfc_trans_add_clause (node4, omp_clauses);
- }
- break;
- case OMP_LIST_TO:
- case OMP_LIST_FROM:
- for (; n != NULL; n = n->next)
- {
- if (!n->sym->attr.referenced)
- continue;
- tree node = build_omp_clause (input_location,
- list == OMP_LIST_TO
- ? OMP_CLAUSE_TO : OMP_CLAUSE_FROM);
- if (n->expr == NULL || n->expr->ref->u.ar.type == AR_FULL)
- {
- tree decl = gfc_get_symbol_decl (n->sym);
- if (gfc_omp_privatize_by_reference (decl))
- decl = build_fold_indirect_ref (decl);
- if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
- {
- tree type = TREE_TYPE (decl);
- tree ptr = gfc_conv_descriptor_data_get (decl);
- ptr = fold_convert (build_pointer_type (char_type_node),
- ptr);
- ptr = build_fold_indirect_ref (ptr);
- OMP_CLAUSE_DECL (node) = ptr;
- OMP_CLAUSE_SIZE (node)
- = gfc_full_array_size (block, decl,
- GFC_TYPE_ARRAY_RANK (type));
- tree elemsz
- = TYPE_SIZE_UNIT (gfc_get_element_type (type));
- elemsz = fold_convert (gfc_array_index_type, elemsz);
- OMP_CLAUSE_SIZE (node)
- = fold_build2 (MULT_EXPR, gfc_array_index_type,
- OMP_CLAUSE_SIZE (node), elemsz);
- }
- else
- OMP_CLAUSE_DECL (node) = decl;
- }
- else
- {
- tree ptr;
- gfc_init_se (&se, NULL);
- if (n->expr->ref->u.ar.type == AR_ELEMENT)
- {
- gfc_conv_expr_reference (&se, n->expr);
- ptr = se.expr;
- gfc_add_block_to_block (block, &se.pre);
- OMP_CLAUSE_SIZE (node)
- = TYPE_SIZE_UNIT (TREE_TYPE (ptr));
- }
- else
- {
- gfc_conv_expr_descriptor (&se, n->expr);
- ptr = gfc_conv_array_data (se.expr);
- tree type = TREE_TYPE (se.expr);
- gfc_add_block_to_block (block, &se.pre);
- OMP_CLAUSE_SIZE (node)
- = gfc_full_array_size (block, se.expr,
- GFC_TYPE_ARRAY_RANK (type));
- tree elemsz
- = TYPE_SIZE_UNIT (gfc_get_element_type (type));
- elemsz = fold_convert (gfc_array_index_type, elemsz);
- OMP_CLAUSE_SIZE (node)
- = fold_build2 (MULT_EXPR, gfc_array_index_type,
- OMP_CLAUSE_SIZE (node), elemsz);
- }
- gfc_add_block_to_block (block, &se.post);
- ptr = fold_convert (build_pointer_type (char_type_node),
- ptr);
- OMP_CLAUSE_DECL (node) = build_fold_indirect_ref (ptr);
- }
- omp_clauses = gfc_trans_add_clause (node, omp_clauses);
- }
- break;
- default:
- break;
- }
- }
- if (clauses->if_expr)
- {
- tree if_var;
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, clauses->if_expr);
- gfc_add_block_to_block (block, &se.pre);
- if_var = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_IF);
- OMP_CLAUSE_IF_EXPR (c) = if_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->final_expr)
- {
- tree final_var;
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, clauses->final_expr);
- gfc_add_block_to_block (block, &se.pre);
- final_var = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_FINAL);
- OMP_CLAUSE_FINAL_EXPR (c) = final_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->num_threads)
- {
- tree num_threads;
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, clauses->num_threads);
- gfc_add_block_to_block (block, &se.pre);
- num_threads = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_THREADS);
- OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- chunk_size = NULL_TREE;
- if (clauses->chunk_size)
- {
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, clauses->chunk_size);
- gfc_add_block_to_block (block, &se.pre);
- chunk_size = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- }
- if (clauses->sched_kind != OMP_SCHED_NONE)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_SCHEDULE);
- OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
- switch (clauses->sched_kind)
- {
- case OMP_SCHED_STATIC:
- OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
- break;
- case OMP_SCHED_DYNAMIC:
- OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
- break;
- case OMP_SCHED_GUIDED:
- OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
- break;
- case OMP_SCHED_RUNTIME:
- OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
- break;
- case OMP_SCHED_AUTO:
- OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
- break;
- default:
- gcc_unreachable ();
- }
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_DEFAULT);
- switch (clauses->default_sharing)
- {
- case OMP_DEFAULT_NONE:
- OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
- break;
- case OMP_DEFAULT_SHARED:
- OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
- break;
- case OMP_DEFAULT_PRIVATE:
- OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
- break;
- case OMP_DEFAULT_FIRSTPRIVATE:
- OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
- break;
- default:
- gcc_unreachable ();
- }
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->nowait)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_NOWAIT);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->ordered)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_ORDERED);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->untied)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_UNTIED);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->mergeable)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_MERGEABLE);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->collapse)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_COLLAPSE);
- OMP_CLAUSE_COLLAPSE_EXPR (c)
- = build_int_cst (integer_type_node, clauses->collapse);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->inbranch)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_INBRANCH);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->notinbranch)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_NOTINBRANCH);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- switch (clauses->cancel)
- {
- case OMP_CANCEL_UNKNOWN:
- break;
- case OMP_CANCEL_PARALLEL:
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_PARALLEL);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- break;
- case OMP_CANCEL_SECTIONS:
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_SECTIONS);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- break;
- case OMP_CANCEL_DO:
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_FOR);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- break;
- case OMP_CANCEL_TASKGROUP:
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_TASKGROUP);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- break;
- }
- if (clauses->proc_bind != OMP_PROC_BIND_UNKNOWN)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_PROC_BIND);
- switch (clauses->proc_bind)
- {
- case OMP_PROC_BIND_MASTER:
- OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_MASTER;
- break;
- case OMP_PROC_BIND_SPREAD:
- OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_SPREAD;
- break;
- case OMP_PROC_BIND_CLOSE:
- OMP_CLAUSE_PROC_BIND_KIND (c) = OMP_CLAUSE_PROC_BIND_CLOSE;
- break;
- default:
- gcc_unreachable ();
- }
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->safelen_expr)
- {
- tree safelen_var;
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, clauses->safelen_expr);
- gfc_add_block_to_block (block, &se.pre);
- safelen_var = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_SAFELEN);
- OMP_CLAUSE_SAFELEN_EXPR (c) = safelen_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->simdlen_expr)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_SIMDLEN);
- OMP_CLAUSE_SIMDLEN_EXPR (c)
- = gfc_conv_constant_to_tree (clauses->simdlen_expr);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->num_teams)
- {
- tree num_teams;
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, clauses->num_teams);
- gfc_add_block_to_block (block, &se.pre);
- num_teams = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_TEAMS);
- OMP_CLAUSE_NUM_TEAMS_EXPR (c) = num_teams;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->device)
- {
- tree device;
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, clauses->device);
- gfc_add_block_to_block (block, &se.pre);
- device = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_DEVICE);
- OMP_CLAUSE_DEVICE_ID (c) = device;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->thread_limit)
- {
- tree thread_limit;
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, clauses->thread_limit);
- gfc_add_block_to_block (block, &se.pre);
- thread_limit = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_THREAD_LIMIT);
- OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = thread_limit;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- chunk_size = NULL_TREE;
- if (clauses->dist_chunk_size)
- {
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, clauses->dist_chunk_size);
- gfc_add_block_to_block (block, &se.pre);
- chunk_size = gfc_evaluate_now (se.expr, block);
- gfc_add_block_to_block (block, &se.post);
- }
- if (clauses->dist_sched_kind != OMP_SCHED_NONE)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_DIST_SCHEDULE);
- OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->async)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_ASYNC);
- if (clauses->async_expr)
- OMP_CLAUSE_ASYNC_EXPR (c)
- = gfc_convert_expr_to_tree (block, clauses->async_expr);
- else
- OMP_CLAUSE_ASYNC_EXPR (c) = NULL;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->seq)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_ORDERED);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->independent)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_INDEPENDENT);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->wait_list)
- {
- gfc_expr_list *el;
- for (el = clauses->wait_list; el; el = el->next)
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_WAIT);
- OMP_CLAUSE_DECL (c) = gfc_convert_expr_to_tree (block, el->expr);
- OMP_CLAUSE_CHAIN (c) = omp_clauses;
- omp_clauses = c;
- }
- }
- if (clauses->num_gangs_expr)
- {
- tree num_gangs_var
- = gfc_convert_expr_to_tree (block, clauses->num_gangs_expr);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_GANGS);
- OMP_CLAUSE_NUM_GANGS_EXPR (c) = num_gangs_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->num_workers_expr)
- {
- tree num_workers_var
- = gfc_convert_expr_to_tree (block, clauses->num_workers_expr);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_WORKERS);
- OMP_CLAUSE_NUM_WORKERS_EXPR (c) = num_workers_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->vector_length_expr)
- {
- tree vector_length_var
- = gfc_convert_expr_to_tree (block, clauses->vector_length_expr);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_VECTOR_LENGTH);
- OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = vector_length_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- if (clauses->vector)
- {
- if (clauses->vector_expr)
- {
- tree vector_var
- = gfc_convert_expr_to_tree (block, clauses->vector_expr);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_VECTOR);
- OMP_CLAUSE_VECTOR_EXPR (c) = vector_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- else
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_VECTOR);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- }
- if (clauses->worker)
- {
- if (clauses->worker_expr)
- {
- tree worker_var
- = gfc_convert_expr_to_tree (block, clauses->worker_expr);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_WORKER);
- OMP_CLAUSE_WORKER_EXPR (c) = worker_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- else
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_WORKER);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- }
- if (clauses->gang)
- {
- if (clauses->gang_expr)
- {
- tree gang_var
- = gfc_convert_expr_to_tree (block, clauses->gang_expr);
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_GANG);
- OMP_CLAUSE_GANG_EXPR (c) = gang_var;
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- else
- {
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_GANG);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
- }
- }
- return nreverse (omp_clauses);
- }
- /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
- static tree
- gfc_trans_omp_code (gfc_code *code, bool force_empty)
- {
- tree stmt;
- pushlevel ();
- stmt = gfc_trans_code (code);
- if (TREE_CODE (stmt) != BIND_EXPR)
- {
- if (!IS_EMPTY_STMT (stmt) || force_empty)
- {
- tree block = poplevel (1, 0);
- stmt = build3_v (BIND_EXPR, NULL, stmt, block);
- }
- else
- poplevel (0, 0);
- }
- else
- poplevel (0, 0);
- return stmt;
- }
- /* Trans OpenACC directives. */
- /* parallel, kernels, data and host_data. */
- static tree
- gfc_trans_oacc_construct (gfc_code *code)
- {
- stmtblock_t block;
- tree stmt, oacc_clauses;
- enum tree_code construct_code;
- switch (code->op)
- {
- case EXEC_OACC_PARALLEL:
- construct_code = OACC_PARALLEL;
- break;
- case EXEC_OACC_KERNELS:
- construct_code = OACC_KERNELS;
- break;
- case EXEC_OACC_DATA:
- construct_code = OACC_DATA;
- break;
- case EXEC_OACC_HOST_DATA:
- construct_code = OACC_HOST_DATA;
- break;
- default:
- gcc_unreachable ();
- }
- gfc_start_block (&block);
- oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
- code->loc);
- stmt = gfc_trans_omp_code (code->block->next, true);
- stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
- oacc_clauses);
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- /* update, enter_data, exit_data, cache. */
- static tree
- gfc_trans_oacc_executable_directive (gfc_code *code)
- {
- stmtblock_t block;
- tree stmt, oacc_clauses;
- enum tree_code construct_code;
- switch (code->op)
- {
- case EXEC_OACC_UPDATE:
- construct_code = OACC_UPDATE;
- break;
- case EXEC_OACC_ENTER_DATA:
- construct_code = OACC_ENTER_DATA;
- break;
- case EXEC_OACC_EXIT_DATA:
- construct_code = OACC_EXIT_DATA;
- break;
- case EXEC_OACC_CACHE:
- construct_code = OACC_CACHE;
- break;
- default:
- gcc_unreachable ();
- }
- gfc_start_block (&block);
- oacc_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
- code->loc);
- stmt = build1_loc (input_location, construct_code, void_type_node,
- oacc_clauses);
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_oacc_wait_directive (gfc_code *code)
- {
- stmtblock_t block;
- tree stmt, t;
- vec<tree, va_gc> *args;
- int nparms = 0;
- gfc_expr_list *el;
- gfc_omp_clauses *clauses = code->ext.omp_clauses;
- location_t loc = input_location;
- for (el = clauses->wait_list; el; el = el->next)
- nparms++;
- vec_alloc (args, nparms + 2);
- stmt = builtin_decl_explicit (BUILT_IN_GOACC_WAIT);
- gfc_start_block (&block);
- if (clauses->async_expr)
- t = gfc_convert_expr_to_tree (&block, clauses->async_expr);
- else
- t = build_int_cst (integer_type_node, -2);
- args->quick_push (t);
- args->quick_push (build_int_cst (integer_type_node, nparms));
- for (el = clauses->wait_list; el; el = el->next)
- args->quick_push (gfc_convert_expr_to_tree (&block, el->expr));
- stmt = build_call_expr_loc_vec (loc, stmt, args);
- gfc_add_expr_to_block (&block, stmt);
- vec_free (args);
- return gfc_finish_block (&block);
- }
- static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
- static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
- static tree
- gfc_trans_omp_atomic (gfc_code *code)
- {
- gfc_code *atomic_code = code;
- gfc_se lse;
- gfc_se rse;
- gfc_se vse;
- gfc_expr *expr2, *e;
- gfc_symbol *var;
- stmtblock_t block;
- tree lhsaddr, type, rhs, x;
- enum tree_code op = ERROR_MARK;
- enum tree_code aop = OMP_ATOMIC;
- bool var_on_left = false;
- bool seq_cst = (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SEQ_CST) != 0;
- code = code->block->next;
- gcc_assert (code->op == EXEC_ASSIGN);
- var = code->expr1->symtree->n.sym;
- gfc_init_se (&lse, NULL);
- gfc_init_se (&rse, NULL);
- gfc_init_se (&vse, NULL);
- gfc_start_block (&block);
- expr2 = code->expr2;
- if (expr2->expr_type == EXPR_FUNCTION
- && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
- expr2 = expr2->value.function.actual->expr;
- switch (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
- {
- case GFC_OMP_ATOMIC_READ:
- gfc_conv_expr (&vse, code->expr1);
- gfc_add_block_to_block (&block, &vse.pre);
- gfc_conv_expr (&lse, expr2);
- gfc_add_block_to_block (&block, &lse.pre);
- type = TREE_TYPE (lse.expr);
- lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
- x = build1 (OMP_ATOMIC_READ, type, lhsaddr);
- OMP_ATOMIC_SEQ_CST (x) = seq_cst;
- x = convert (TREE_TYPE (vse.expr), x);
- gfc_add_modify (&block, vse.expr, x);
- gfc_add_block_to_block (&block, &lse.pre);
- gfc_add_block_to_block (&block, &rse.pre);
- return gfc_finish_block (&block);
- case GFC_OMP_ATOMIC_CAPTURE:
- aop = OMP_ATOMIC_CAPTURE_NEW;
- if (expr2->expr_type == EXPR_VARIABLE)
- {
- aop = OMP_ATOMIC_CAPTURE_OLD;
- gfc_conv_expr (&vse, code->expr1);
- gfc_add_block_to_block (&block, &vse.pre);
- gfc_conv_expr (&lse, expr2);
- gfc_add_block_to_block (&block, &lse.pre);
- gfc_init_se (&lse, NULL);
- code = code->next;
- var = code->expr1->symtree->n.sym;
- expr2 = code->expr2;
- if (expr2->expr_type == EXPR_FUNCTION
- && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
- expr2 = expr2->value.function.actual->expr;
- }
- break;
- default:
- break;
- }
- gfc_conv_expr (&lse, code->expr1);
- gfc_add_block_to_block (&block, &lse.pre);
- type = TREE_TYPE (lse.expr);
- lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
- if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
- == GFC_OMP_ATOMIC_WRITE)
- || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
- {
- gfc_conv_expr (&rse, expr2);
- gfc_add_block_to_block (&block, &rse.pre);
- }
- else if (expr2->expr_type == EXPR_OP)
- {
- gfc_expr *e;
- switch (expr2->value.op.op)
- {
- case INTRINSIC_PLUS:
- op = PLUS_EXPR;
- break;
- case INTRINSIC_TIMES:
- op = MULT_EXPR;
- break;
- case INTRINSIC_MINUS:
- op = MINUS_EXPR;
- break;
- case INTRINSIC_DIVIDE:
- if (expr2->ts.type == BT_INTEGER)
- op = TRUNC_DIV_EXPR;
- else
- op = RDIV_EXPR;
- break;
- case INTRINSIC_AND:
- op = TRUTH_ANDIF_EXPR;
- break;
- case INTRINSIC_OR:
- op = TRUTH_ORIF_EXPR;
- break;
- case INTRINSIC_EQV:
- op = EQ_EXPR;
- break;
- case INTRINSIC_NEQV:
- op = NE_EXPR;
- break;
- default:
- gcc_unreachable ();
- }
- e = expr2->value.op.op1;
- if (e->expr_type == EXPR_FUNCTION
- && e->value.function.isym->id == GFC_ISYM_CONVERSION)
- e = e->value.function.actual->expr;
- if (e->expr_type == EXPR_VARIABLE
- && e->symtree != NULL
- && e->symtree->n.sym == var)
- {
- expr2 = expr2->value.op.op2;
- var_on_left = true;
- }
- else
- {
- e = expr2->value.op.op2;
- if (e->expr_type == EXPR_FUNCTION
- && e->value.function.isym->id == GFC_ISYM_CONVERSION)
- e = e->value.function.actual->expr;
- gcc_assert (e->expr_type == EXPR_VARIABLE
- && e->symtree != NULL
- && e->symtree->n.sym == var);
- expr2 = expr2->value.op.op1;
- var_on_left = false;
- }
- gfc_conv_expr (&rse, expr2);
- gfc_add_block_to_block (&block, &rse.pre);
- }
- else
- {
- gcc_assert (expr2->expr_type == EXPR_FUNCTION);
- switch (expr2->value.function.isym->id)
- {
- case GFC_ISYM_MIN:
- op = MIN_EXPR;
- break;
- case GFC_ISYM_MAX:
- op = MAX_EXPR;
- break;
- case GFC_ISYM_IAND:
- op = BIT_AND_EXPR;
- break;
- case GFC_ISYM_IOR:
- op = BIT_IOR_EXPR;
- break;
- case GFC_ISYM_IEOR:
- op = BIT_XOR_EXPR;
- break;
- default:
- gcc_unreachable ();
- }
- e = expr2->value.function.actual->expr;
- gcc_assert (e->expr_type == EXPR_VARIABLE
- && e->symtree != NULL
- && e->symtree->n.sym == var);
- gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
- gfc_add_block_to_block (&block, &rse.pre);
- if (expr2->value.function.actual->next->next != NULL)
- {
- tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
- gfc_actual_arglist *arg;
- gfc_add_modify (&block, accum, rse.expr);
- for (arg = expr2->value.function.actual->next->next; arg;
- arg = arg->next)
- {
- gfc_init_block (&rse.pre);
- gfc_conv_expr (&rse, arg->expr);
- gfc_add_block_to_block (&block, &rse.pre);
- x = fold_build2_loc (input_location, op, TREE_TYPE (accum),
- accum, rse.expr);
- gfc_add_modify (&block, accum, x);
- }
- rse.expr = accum;
- }
- expr2 = expr2->value.function.actual->next->expr;
- }
- lhsaddr = save_expr (lhsaddr);
- if (TREE_CODE (lhsaddr) != SAVE_EXPR
- && (TREE_CODE (lhsaddr) != ADDR_EXPR
- || TREE_CODE (TREE_OPERAND (lhsaddr, 0)) != VAR_DECL))
- {
- /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
- it even after unsharing function body. */
- tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr));
- DECL_CONTEXT (var) = current_function_decl;
- lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr,
- NULL_TREE, NULL_TREE);
- }
- rhs = gfc_evaluate_now (rse.expr, &block);
- if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK)
- == GFC_OMP_ATOMIC_WRITE)
- || (atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_SWAP))
- x = rhs;
- else
- {
- x = convert (TREE_TYPE (rhs),
- build_fold_indirect_ref_loc (input_location, lhsaddr));
- if (var_on_left)
- x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), x, rhs);
- else
- x = fold_build2_loc (input_location, op, TREE_TYPE (rhs), rhs, x);
- }
- if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
- && TREE_CODE (type) != COMPLEX_TYPE)
- x = fold_build1_loc (input_location, REALPART_EXPR,
- TREE_TYPE (TREE_TYPE (rhs)), x);
- gfc_add_block_to_block (&block, &lse.pre);
- gfc_add_block_to_block (&block, &rse.pre);
- if (aop == OMP_ATOMIC)
- {
- x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
- OMP_ATOMIC_SEQ_CST (x) = seq_cst;
- gfc_add_expr_to_block (&block, x);
- }
- else
- {
- if (aop == OMP_ATOMIC_CAPTURE_NEW)
- {
- code = code->next;
- expr2 = code->expr2;
- if (expr2->expr_type == EXPR_FUNCTION
- && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
- expr2 = expr2->value.function.actual->expr;
- gcc_assert (expr2->expr_type == EXPR_VARIABLE);
- gfc_conv_expr (&vse, code->expr1);
- gfc_add_block_to_block (&block, &vse.pre);
- gfc_init_se (&lse, NULL);
- gfc_conv_expr (&lse, expr2);
- gfc_add_block_to_block (&block, &lse.pre);
- }
- x = build2 (aop, type, lhsaddr, convert (type, x));
- OMP_ATOMIC_SEQ_CST (x) = seq_cst;
- x = convert (TREE_TYPE (vse.expr), x);
- gfc_add_modify (&block, vse.expr, x);
- }
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_barrier (void)
- {
- tree decl = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
- return build_call_expr_loc (input_location, decl, 0);
- }
- static tree
- gfc_trans_omp_cancel (gfc_code *code)
- {
- int mask = 0;
- tree ifc = boolean_true_node;
- stmtblock_t block;
- switch (code->ext.omp_clauses->cancel)
- {
- case OMP_CANCEL_PARALLEL: mask = 1; break;
- case OMP_CANCEL_DO: mask = 2; break;
- case OMP_CANCEL_SECTIONS: mask = 4; break;
- case OMP_CANCEL_TASKGROUP: mask = 8; break;
- default: gcc_unreachable ();
- }
- gfc_start_block (&block);
- if (code->ext.omp_clauses->if_expr)
- {
- gfc_se se;
- tree if_var;
- gfc_init_se (&se, NULL);
- gfc_conv_expr (&se, code->ext.omp_clauses->if_expr);
- gfc_add_block_to_block (&block, &se.pre);
- if_var = gfc_evaluate_now (se.expr, &block);
- gfc_add_block_to_block (&block, &se.post);
- tree type = TREE_TYPE (if_var);
- ifc = fold_build2_loc (input_location, NE_EXPR,
- boolean_type_node, if_var,
- build_zero_cst (type));
- }
- tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL);
- tree c_bool_type = TREE_TYPE (TREE_TYPE (decl));
- ifc = fold_convert (c_bool_type, ifc);
- gfc_add_expr_to_block (&block,
- build_call_expr_loc (input_location, decl, 2,
- build_int_cst (integer_type_node,
- mask), ifc));
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_cancellation_point (gfc_code *code)
- {
- int mask = 0;
- switch (code->ext.omp_clauses->cancel)
- {
- case OMP_CANCEL_PARALLEL: mask = 1; break;
- case OMP_CANCEL_DO: mask = 2; break;
- case OMP_CANCEL_SECTIONS: mask = 4; break;
- case OMP_CANCEL_TASKGROUP: mask = 8; break;
- default: gcc_unreachable ();
- }
- tree decl = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT);
- return build_call_expr_loc (input_location, decl, 1,
- build_int_cst (integer_type_node, mask));
- }
- static tree
- gfc_trans_omp_critical (gfc_code *code)
- {
- tree name = NULL_TREE, stmt;
- if (code->ext.omp_name != NULL)
- name = get_identifier (code->ext.omp_name);
- stmt = gfc_trans_code (code->block->next);
- return build2_loc (input_location, OMP_CRITICAL, void_type_node, stmt, name);
- }
- typedef struct dovar_init_d {
- tree var;
- tree init;
- } dovar_init;
- static tree
- gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
- gfc_omp_clauses *do_clauses, tree par_clauses)
- {
- gfc_se se;
- tree dovar, stmt, from, to, step, type, init, cond, incr;
- tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
- stmtblock_t block;
- stmtblock_t body;
- gfc_omp_clauses *clauses = code->ext.omp_clauses;
- int i, collapse = clauses->collapse;
- vec<dovar_init> inits = vNULL;
- dovar_init *di;
- unsigned ix;
- if (collapse <= 0)
- collapse = 1;
- code = code->block->next;
- gcc_assert (code->op == EXEC_DO);
- init = make_tree_vec (collapse);
- cond = make_tree_vec (collapse);
- incr = make_tree_vec (collapse);
- if (pblock == NULL)
- {
- gfc_start_block (&block);
- pblock = █
- }
- omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
- for (i = 0; i < collapse; i++)
- {
- int simple = 0;
- int dovar_found = 0;
- tree dovar_decl;
- if (clauses)
- {
- gfc_omp_namelist *n = NULL;
- if (op != EXEC_OMP_DISTRIBUTE)
- for (n = clauses->lists[(op == EXEC_OMP_SIMD && collapse == 1)
- ? OMP_LIST_LINEAR : OMP_LIST_LASTPRIVATE];
- n != NULL; n = n->next)
- if (code->ext.iterator->var->symtree->n.sym == n->sym)
- break;
- if (n != NULL)
- dovar_found = 1;
- else if (n == NULL && op != EXEC_OMP_SIMD)
- for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
- if (code->ext.iterator->var->symtree->n.sym == n->sym)
- break;
- if (n != NULL)
- dovar_found++;
- }
- /* Evaluate all the expressions in the iterator. */
- gfc_init_se (&se, NULL);
- gfc_conv_expr_lhs (&se, code->ext.iterator->var);
- gfc_add_block_to_block (pblock, &se.pre);
- dovar = se.expr;
- type = TREE_TYPE (dovar);
- gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
- gfc_init_se (&se, NULL);
- gfc_conv_expr_val (&se, code->ext.iterator->start);
- gfc_add_block_to_block (pblock, &se.pre);
- from = gfc_evaluate_now (se.expr, pblock);
- gfc_init_se (&se, NULL);
- gfc_conv_expr_val (&se, code->ext.iterator->end);
- gfc_add_block_to_block (pblock, &se.pre);
- to = gfc_evaluate_now (se.expr, pblock);
- gfc_init_se (&se, NULL);
- gfc_conv_expr_val (&se, code->ext.iterator->step);
- gfc_add_block_to_block (pblock, &se.pre);
- step = gfc_evaluate_now (se.expr, pblock);
- dovar_decl = dovar;
- /* Special case simple loops. */
- if (TREE_CODE (dovar) == VAR_DECL)
- {
- if (integer_onep (step))
- simple = 1;
- else if (tree_int_cst_equal (step, integer_minus_one_node))
- simple = -1;
- }
- else
- dovar_decl
- = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym,
- false);
- /* Loop body. */
- if (simple)
- {
- TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, dovar, from);
- /* The condition should not be folded. */
- TREE_VEC_ELT (cond, i) = build2_loc (input_location, simple > 0
- ? LE_EXPR : GE_EXPR,
- boolean_type_node, dovar, to);
- TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
- type, dovar, step);
- TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
- MODIFY_EXPR,
- type, dovar,
- TREE_VEC_ELT (incr, i));
- }
- else
- {
- /* STEP is not 1 or -1. Use:
- for (count = 0; count < (to + step - from) / step; count++)
- {
- dovar = from + count * step;
- body;
- cycle_label:;
- } */
- tmp = fold_build2_loc (input_location, MINUS_EXPR, type, step, from);
- tmp = fold_build2_loc (input_location, PLUS_EXPR, type, to, tmp);
- tmp = fold_build2_loc (input_location, TRUNC_DIV_EXPR, type, tmp,
- step);
- tmp = gfc_evaluate_now (tmp, pblock);
- count = gfc_create_var (type, "count");
- TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, count,
- build_int_cst (type, 0));
- /* The condition should not be folded. */
- TREE_VEC_ELT (cond, i) = build2_loc (input_location, LT_EXPR,
- boolean_type_node,
- count, tmp);
- TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location, PLUS_EXPR,
- type, count,
- build_int_cst (type, 1));
- TREE_VEC_ELT (incr, i) = fold_build2_loc (input_location,
- MODIFY_EXPR, type, count,
- TREE_VEC_ELT (incr, i));
- /* Initialize DOVAR. */
- tmp = fold_build2_loc (input_location, MULT_EXPR, type, count, step);
- tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
- dovar_init e = {dovar, tmp};
- inits.safe_push (e);
- }
- if (dovar_found == 2
- && op == EXEC_OMP_SIMD
- && collapse == 1
- && !simple)
- {
- for (tmp = omp_clauses; tmp; tmp = OMP_CLAUSE_CHAIN (tmp))
- if (OMP_CLAUSE_CODE (tmp) == OMP_CLAUSE_LINEAR
- && OMP_CLAUSE_DECL (tmp) == dovar)
- {
- OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
- break;
- }
- }
- if (!dovar_found)
- {
- if (op == EXEC_OMP_SIMD)
- {
- if (collapse == 1)
- {
- tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
- OMP_CLAUSE_LINEAR_STEP (tmp) = step;
- OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
- }
- else
- tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
- if (!simple)
- dovar_found = 2;
- }
- else
- tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
- OMP_CLAUSE_DECL (tmp) = dovar_decl;
- omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
- }
- if (dovar_found == 2)
- {
- tree c = NULL;
- tmp = NULL;
- if (!simple)
- {
- /* If dovar is lastprivate, but different counter is used,
- dovar += step needs to be added to
- OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
- will have the value on entry of the last loop, rather
- than value after iterator increment. */
- tmp = gfc_evaluate_now (step, pblock);
- tmp = fold_build2_loc (input_location, PLUS_EXPR, type, dovar,
- tmp);
- tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
- dovar, tmp);
- for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
- && OMP_CLAUSE_DECL (c) == dovar_decl)
- {
- OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp;
- break;
- }
- else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
- && OMP_CLAUSE_DECL (c) == dovar_decl)
- {
- OMP_CLAUSE_LINEAR_STMT (c) = tmp;
- break;
- }
- }
- if (c == NULL && op == EXEC_OMP_DO && par_clauses != NULL)
- {
- for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE
- && OMP_CLAUSE_DECL (c) == dovar_decl)
- {
- tree l = build_omp_clause (input_location,
- OMP_CLAUSE_LASTPRIVATE);
- OMP_CLAUSE_DECL (l) = dovar_decl;
- OMP_CLAUSE_CHAIN (l) = omp_clauses;
- OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp;
- omp_clauses = l;
- OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED);
- break;
- }
- }
- gcc_assert (simple || c != NULL);
- }
- if (!simple)
- {
- if (op != EXEC_OMP_SIMD)
- tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
- else if (collapse == 1)
- {
- tmp = build_omp_clause (input_location, OMP_CLAUSE_LINEAR);
- OMP_CLAUSE_LINEAR_STEP (tmp) = build_int_cst (type, 1);
- OMP_CLAUSE_LINEAR_NO_COPYIN (tmp) = 1;
- OMP_CLAUSE_LINEAR_NO_COPYOUT (tmp) = 1;
- }
- else
- tmp = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE);
- OMP_CLAUSE_DECL (tmp) = count;
- omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
- }
- if (i + 1 < collapse)
- code = code->block->next;
- }
- if (pblock != &block)
- {
- pushlevel ();
- gfc_start_block (&block);
- }
- gfc_start_block (&body);
- FOR_EACH_VEC_ELT (inits, ix, di)
- gfc_add_modify (&body, di->var, di->init);
- inits.release ();
- /* Cycle statement is implemented with a goto. Exit statement must not be
- present for this loop. */
- cycle_label = gfc_build_label_decl (NULL_TREE);
- /* Put these labels where they can be found later. */
- code->cycle_label = cycle_label;
- code->exit_label = NULL_TREE;
- /* Main loop body. */
- tmp = gfc_trans_omp_code (code->block->next, true);
- gfc_add_expr_to_block (&body, tmp);
- /* Label for cycle statements (if needed). */
- if (TREE_USED (cycle_label))
- {
- tmp = build1_v (LABEL_EXPR, cycle_label);
- gfc_add_expr_to_block (&body, tmp);
- }
- /* End of loop body. */
- switch (op)
- {
- case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
- case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
- case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
- case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break;
- default: gcc_unreachable ();
- }
- TREE_TYPE (stmt) = void_type_node;
- OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
- OMP_FOR_CLAUSES (stmt) = omp_clauses;
- OMP_FOR_INIT (stmt) = init;
- OMP_FOR_COND (stmt) = cond;
- OMP_FOR_INCR (stmt) = incr;
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- /* parallel loop and kernels loop. */
- static tree
- gfc_trans_oacc_combined_directive (gfc_code *code)
- {
- stmtblock_t block, *pblock = NULL;
- gfc_omp_clauses construct_clauses, loop_clauses;
- tree stmt, oacc_clauses = NULL_TREE;
- enum tree_code construct_code;
- switch (code->op)
- {
- case EXEC_OACC_PARALLEL_LOOP:
- construct_code = OACC_PARALLEL;
- break;
- case EXEC_OACC_KERNELS_LOOP:
- construct_code = OACC_KERNELS;
- break;
- default:
- gcc_unreachable ();
- }
- gfc_start_block (&block);
- memset (&loop_clauses, 0, sizeof (loop_clauses));
- if (code->ext.omp_clauses != NULL)
- {
- memcpy (&construct_clauses, code->ext.omp_clauses,
- sizeof (construct_clauses));
- loop_clauses.collapse = construct_clauses.collapse;
- loop_clauses.gang = construct_clauses.gang;
- loop_clauses.vector = construct_clauses.vector;
- loop_clauses.worker = construct_clauses.worker;
- loop_clauses.seq = construct_clauses.seq;
- loop_clauses.independent = construct_clauses.independent;
- construct_clauses.collapse = 0;
- construct_clauses.gang = false;
- construct_clauses.vector = false;
- construct_clauses.worker = false;
- construct_clauses.seq = false;
- construct_clauses.independent = false;
- oacc_clauses = gfc_trans_omp_clauses (&block, &construct_clauses,
- code->loc);
- }
- if (!loop_clauses.seq)
- pblock = █
- else
- pushlevel ();
- stmt = gfc_trans_omp_do (code, EXEC_OACC_LOOP, pblock, &loop_clauses, NULL);
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- stmt = build2_loc (input_location, construct_code, void_type_node, stmt,
- oacc_clauses);
- if (code->op == EXEC_OACC_KERNELS_LOOP)
- OACC_KERNELS_COMBINED (stmt) = 1;
- else
- OACC_PARALLEL_COMBINED (stmt) = 1;
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_flush (void)
- {
- tree decl = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
- return build_call_expr_loc (input_location, decl, 0);
- }
- static tree
- gfc_trans_omp_master (gfc_code *code)
- {
- tree stmt = gfc_trans_code (code->block->next);
- if (IS_EMPTY_STMT (stmt))
- return stmt;
- return build1_v (OMP_MASTER, stmt);
- }
- static tree
- gfc_trans_omp_ordered (gfc_code *code)
- {
- return build1_v (OMP_ORDERED, gfc_trans_code (code->block->next));
- }
- static tree
- gfc_trans_omp_parallel (gfc_code *code)
- {
- stmtblock_t block;
- tree stmt, omp_clauses;
- gfc_start_block (&block);
- omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
- code->loc);
- stmt = gfc_trans_omp_code (code->block->next, true);
- stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
- omp_clauses);
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- enum
- {
- GFC_OMP_SPLIT_SIMD,
- GFC_OMP_SPLIT_DO,
- GFC_OMP_SPLIT_PARALLEL,
- GFC_OMP_SPLIT_DISTRIBUTE,
- GFC_OMP_SPLIT_TEAMS,
- GFC_OMP_SPLIT_TARGET,
- GFC_OMP_SPLIT_NUM
- };
- enum
- {
- GFC_OMP_MASK_SIMD = (1 << GFC_OMP_SPLIT_SIMD),
- GFC_OMP_MASK_DO = (1 << GFC_OMP_SPLIT_DO),
- GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
- GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
- GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
- GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET)
- };
- static void
- gfc_split_omp_clauses (gfc_code *code,
- gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM])
- {
- int mask = 0, innermost = 0;
- memset (clausesa, 0, GFC_OMP_SPLIT_NUM * sizeof (gfc_omp_clauses));
- switch (code->op)
- {
- case EXEC_OMP_DISTRIBUTE:
- innermost = GFC_OMP_SPLIT_DISTRIBUTE;
- break;
- case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
- mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
- innermost = GFC_OMP_SPLIT_DO;
- break;
- case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
- mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_PARALLEL
- | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
- innermost = GFC_OMP_SPLIT_SIMD;
- break;
- case EXEC_OMP_DISTRIBUTE_SIMD:
- mask = GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
- innermost = GFC_OMP_SPLIT_SIMD;
- break;
- case EXEC_OMP_DO:
- innermost = GFC_OMP_SPLIT_DO;
- break;
- case EXEC_OMP_DO_SIMD:
- mask = GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
- innermost = GFC_OMP_SPLIT_SIMD;
- break;
- case EXEC_OMP_PARALLEL:
- innermost = GFC_OMP_SPLIT_PARALLEL;
- break;
- case EXEC_OMP_PARALLEL_DO:
- mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
- innermost = GFC_OMP_SPLIT_DO;
- break;
- case EXEC_OMP_PARALLEL_DO_SIMD:
- mask = GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
- innermost = GFC_OMP_SPLIT_SIMD;
- break;
- case EXEC_OMP_SIMD:
- innermost = GFC_OMP_SPLIT_SIMD;
- break;
- case EXEC_OMP_TARGET:
- innermost = GFC_OMP_SPLIT_TARGET;
- break;
- case EXEC_OMP_TARGET_TEAMS:
- mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
- innermost = GFC_OMP_SPLIT_TEAMS;
- break;
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
- mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
- | GFC_OMP_MASK_DISTRIBUTE;
- innermost = GFC_OMP_SPLIT_DISTRIBUTE;
- break;
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
- mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
- | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
- innermost = GFC_OMP_SPLIT_DO;
- break;
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
- | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
- innermost = GFC_OMP_SPLIT_SIMD;
- break;
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
- mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS
- | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
- innermost = GFC_OMP_SPLIT_SIMD;
- break;
- case EXEC_OMP_TEAMS:
- innermost = GFC_OMP_SPLIT_TEAMS;
- break;
- case EXEC_OMP_TEAMS_DISTRIBUTE:
- mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE;
- innermost = GFC_OMP_SPLIT_DISTRIBUTE;
- break;
- case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
- mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
- | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
- innermost = GFC_OMP_SPLIT_DO;
- break;
- case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE
- | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO | GFC_OMP_MASK_SIMD;
- innermost = GFC_OMP_SPLIT_SIMD;
- break;
- case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
- mask = GFC_OMP_MASK_TEAMS | GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
- innermost = GFC_OMP_SPLIT_SIMD;
- break;
- default:
- gcc_unreachable ();
- }
- if (mask == 0)
- {
- clausesa[innermost] = *code->ext.omp_clauses;
- return;
- }
- if (code->ext.omp_clauses != NULL)
- {
- if (mask & GFC_OMP_MASK_TARGET)
- {
- /* First the clauses that are unique to some constructs. */
- clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
- = code->ext.omp_clauses->lists[OMP_LIST_MAP];
- clausesa[GFC_OMP_SPLIT_TARGET].device
- = code->ext.omp_clauses->device;
- }
- if (mask & GFC_OMP_MASK_TEAMS)
- {
- /* First the clauses that are unique to some constructs. */
- clausesa[GFC_OMP_SPLIT_TEAMS].num_teams
- = code->ext.omp_clauses->num_teams;
- clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
- = code->ext.omp_clauses->thread_limit;
- /* Shared and default clauses are allowed on parallel and teams. */
- clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
- = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
- clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
- = code->ext.omp_clauses->default_sharing;
- }
- if (mask & GFC_OMP_MASK_DISTRIBUTE)
- {
- /* First the clauses that are unique to some constructs. */
- clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_sched_kind
- = code->ext.omp_clauses->dist_sched_kind;
- clausesa[GFC_OMP_SPLIT_DISTRIBUTE].dist_chunk_size
- = code->ext.omp_clauses->dist_chunk_size;
- /* Duplicate collapse. */
- clausesa[GFC_OMP_SPLIT_DISTRIBUTE].collapse
- = code->ext.omp_clauses->collapse;
- }
- if (mask & GFC_OMP_MASK_PARALLEL)
- {
- /* First the clauses that are unique to some constructs. */
- clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_COPYIN]
- = code->ext.omp_clauses->lists[OMP_LIST_COPYIN];
- clausesa[GFC_OMP_SPLIT_PARALLEL].num_threads
- = code->ext.omp_clauses->num_threads;
- clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
- = code->ext.omp_clauses->proc_bind;
- /* Shared and default clauses are allowed on parallel and teams. */
- clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
- = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
- clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
- = code->ext.omp_clauses->default_sharing;
- }
- if (mask & GFC_OMP_MASK_DO)
- {
- /* First the clauses that are unique to some constructs. */
- clausesa[GFC_OMP_SPLIT_DO].ordered
- = code->ext.omp_clauses->ordered;
- clausesa[GFC_OMP_SPLIT_DO].sched_kind
- = code->ext.omp_clauses->sched_kind;
- clausesa[GFC_OMP_SPLIT_DO].chunk_size
- = code->ext.omp_clauses->chunk_size;
- clausesa[GFC_OMP_SPLIT_DO].nowait
- = code->ext.omp_clauses->nowait;
- /* Duplicate collapse. */
- clausesa[GFC_OMP_SPLIT_DO].collapse
- = code->ext.omp_clauses->collapse;
- }
- if (mask & GFC_OMP_MASK_SIMD)
- {
- clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
- = code->ext.omp_clauses->safelen_expr;
- clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LINEAR]
- = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
- clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
- = code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
- /* Duplicate collapse. */
- clausesa[GFC_OMP_SPLIT_SIMD].collapse
- = code->ext.omp_clauses->collapse;
- }
- /* Private clause is supported on all constructs but target,
- it is enough to put it on the innermost one. For
- !$ omp do put it on parallel though,
- as that's what we did for OpenMP 3.1. */
- clausesa[innermost == GFC_OMP_SPLIT_DO
- ? (int) GFC_OMP_SPLIT_PARALLEL
- : innermost].lists[OMP_LIST_PRIVATE]
- = code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
- /* Firstprivate clause is supported on all constructs but
- target and simd. Put it on the outermost of those and
- duplicate on parallel. */
- if (mask & GFC_OMP_MASK_TEAMS)
- clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
- = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
- else if (mask & GFC_OMP_MASK_DISTRIBUTE)
- clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_FIRSTPRIVATE]
- = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
- if (mask & GFC_OMP_MASK_PARALLEL)
- clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_FIRSTPRIVATE]
- = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
- else if (mask & GFC_OMP_MASK_DO)
- clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
- = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
- /* Lastprivate is allowed on do and simd. In
- parallel do{, simd} we actually want to put it on
- parallel rather than do. */
- if (mask & GFC_OMP_MASK_PARALLEL)
- clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
- = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
- else if (mask & GFC_OMP_MASK_DO)
- clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_LASTPRIVATE]
- = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
- if (mask & GFC_OMP_MASK_SIMD)
- clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LASTPRIVATE]
- = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
- /* Reduction is allowed on simd, do, parallel and teams.
- Duplicate it on all of them, but omit on do if
- parallel is present. */
- if (mask & GFC_OMP_MASK_TEAMS)
- clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_REDUCTION]
- = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
- if (mask & GFC_OMP_MASK_PARALLEL)
- clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_REDUCTION]
- = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
- else if (mask & GFC_OMP_MASK_DO)
- clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_REDUCTION]
- = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
- if (mask & GFC_OMP_MASK_SIMD)
- clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_REDUCTION]
- = code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
- /* FIXME: This is currently being discussed. */
- if (mask & GFC_OMP_MASK_PARALLEL)
- clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
- = code->ext.omp_clauses->if_expr;
- else
- clausesa[GFC_OMP_SPLIT_TARGET].if_expr
- = code->ext.omp_clauses->if_expr;
- }
- if ((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
- == (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
- clausesa[GFC_OMP_SPLIT_DO].nowait = true;
- }
- static tree
- gfc_trans_omp_do_simd (gfc_code *code, stmtblock_t *pblock,
- gfc_omp_clauses *clausesa, tree omp_clauses)
- {
- stmtblock_t block;
- gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
- tree stmt, body, omp_do_clauses = NULL_TREE;
- if (pblock == NULL)
- gfc_start_block (&block);
- else
- gfc_init_block (&block);
- if (clausesa == NULL)
- {
- clausesa = clausesa_buf;
- gfc_split_omp_clauses (code, clausesa);
- }
- if (flag_openmp)
- omp_do_clauses
- = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DO], code->loc);
- body = gfc_trans_omp_do (code, EXEC_OMP_SIMD, pblock ? pblock : &block,
- &clausesa[GFC_OMP_SPLIT_SIMD], omp_clauses);
- if (pblock == NULL)
- {
- if (TREE_CODE (body) != BIND_EXPR)
- body = build3_v (BIND_EXPR, NULL, body, poplevel (1, 0));
- else
- poplevel (0, 0);
- }
- else if (TREE_CODE (body) != BIND_EXPR)
- body = build3_v (BIND_EXPR, NULL, body, NULL_TREE);
- if (flag_openmp)
- {
- stmt = make_node (OMP_FOR);
- TREE_TYPE (stmt) = void_type_node;
- OMP_FOR_BODY (stmt) = body;
- OMP_FOR_CLAUSES (stmt) = omp_do_clauses;
- }
- else
- stmt = body;
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_parallel_do (gfc_code *code, stmtblock_t *pblock,
- gfc_omp_clauses *clausesa)
- {
- stmtblock_t block, *new_pblock = pblock;
- gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
- tree stmt, omp_clauses = NULL_TREE;
- if (pblock == NULL)
- gfc_start_block (&block);
- else
- gfc_init_block (&block);
- if (clausesa == NULL)
- {
- clausesa = clausesa_buf;
- gfc_split_omp_clauses (code, clausesa);
- }
- omp_clauses
- = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
- code->loc);
- if (pblock == NULL)
- {
- if (!clausesa[GFC_OMP_SPLIT_DO].ordered
- && clausesa[GFC_OMP_SPLIT_DO].sched_kind != OMP_SCHED_STATIC)
- new_pblock = █
- else
- pushlevel ();
- }
- stmt = gfc_trans_omp_do (code, EXEC_OMP_DO, new_pblock,
- &clausesa[GFC_OMP_SPLIT_DO], omp_clauses);
- if (pblock == NULL)
- {
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- }
- else if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
- stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
- omp_clauses);
- OMP_PARALLEL_COMBINED (stmt) = 1;
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_parallel_do_simd (gfc_code *code, stmtblock_t *pblock,
- gfc_omp_clauses *clausesa)
- {
- stmtblock_t block;
- gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
- tree stmt, omp_clauses = NULL_TREE;
- if (pblock == NULL)
- gfc_start_block (&block);
- else
- gfc_init_block (&block);
- if (clausesa == NULL)
- {
- clausesa = clausesa_buf;
- gfc_split_omp_clauses (code, clausesa);
- }
- if (flag_openmp)
- omp_clauses
- = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
- code->loc);
- if (pblock == NULL)
- pushlevel ();
- stmt = gfc_trans_omp_do_simd (code, pblock, clausesa, omp_clauses);
- if (pblock == NULL)
- {
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- }
- else if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, NULL_TREE);
- if (flag_openmp)
- {
- stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
- omp_clauses);
- OMP_PARALLEL_COMBINED (stmt) = 1;
- }
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_parallel_sections (gfc_code *code)
- {
- stmtblock_t block;
- gfc_omp_clauses section_clauses;
- tree stmt, omp_clauses;
- memset (§ion_clauses, 0, sizeof (section_clauses));
- section_clauses.nowait = true;
- gfc_start_block (&block);
- omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
- code->loc);
- pushlevel ();
- stmt = gfc_trans_omp_sections (code, §ion_clauses);
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
- omp_clauses);
- OMP_PARALLEL_COMBINED (stmt) = 1;
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_parallel_workshare (gfc_code *code)
- {
- stmtblock_t block;
- gfc_omp_clauses workshare_clauses;
- tree stmt, omp_clauses;
- memset (&workshare_clauses, 0, sizeof (workshare_clauses));
- workshare_clauses.nowait = true;
- gfc_start_block (&block);
- omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
- code->loc);
- pushlevel ();
- stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
- omp_clauses);
- OMP_PARALLEL_COMBINED (stmt) = 1;
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
- {
- stmtblock_t block, body;
- tree omp_clauses, stmt;
- bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
- gfc_start_block (&block);
- omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
- gfc_init_block (&body);
- for (code = code->block; code; code = code->block)
- {
- /* Last section is special because of lastprivate, so even if it
- is empty, chain it in. */
- stmt = gfc_trans_omp_code (code->next,
- has_lastprivate && code->block == NULL);
- if (! IS_EMPTY_STMT (stmt))
- {
- stmt = build1_v (OMP_SECTION, stmt);
- gfc_add_expr_to_block (&body, stmt);
- }
- }
- stmt = gfc_finish_block (&body);
- stmt = build2_loc (input_location, OMP_SECTIONS, void_type_node, stmt,
- omp_clauses);
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
- {
- tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
- tree stmt = gfc_trans_omp_code (code->block->next, true);
- stmt = build2_loc (input_location, OMP_SINGLE, void_type_node, stmt,
- omp_clauses);
- return stmt;
- }
- static tree
- gfc_trans_omp_task (gfc_code *code)
- {
- stmtblock_t block;
- tree stmt, omp_clauses;
- gfc_start_block (&block);
- omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
- code->loc);
- stmt = gfc_trans_omp_code (code->block->next, true);
- stmt = build2_loc (input_location, OMP_TASK, void_type_node, stmt,
- omp_clauses);
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_taskgroup (gfc_code *code)
- {
- tree stmt = gfc_trans_code (code->block->next);
- return build1_loc (input_location, OMP_TASKGROUP, void_type_node, stmt);
- }
- static tree
- gfc_trans_omp_taskwait (void)
- {
- tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
- return build_call_expr_loc (input_location, decl, 0);
- }
- static tree
- gfc_trans_omp_taskyield (void)
- {
- tree decl = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
- return build_call_expr_loc (input_location, decl, 0);
- }
- static tree
- gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
- {
- stmtblock_t block;
- gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
- tree stmt, omp_clauses = NULL_TREE;
- gfc_start_block (&block);
- if (clausesa == NULL)
- {
- clausesa = clausesa_buf;
- gfc_split_omp_clauses (code, clausesa);
- }
- if (flag_openmp)
- omp_clauses
- = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
- code->loc);
- switch (code->op)
- {
- case EXEC_OMP_DISTRIBUTE:
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
- case EXEC_OMP_TEAMS_DISTRIBUTE:
- /* This is handled in gfc_trans_omp_do. */
- gcc_unreachable ();
- break;
- case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
- case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
- stmt = gfc_trans_omp_parallel_do (code, &block, clausesa);
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- break;
- case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- stmt = gfc_trans_omp_parallel_do_simd (code, &block, clausesa);
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- break;
- case EXEC_OMP_DISTRIBUTE_SIMD:
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
- case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
- stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
- &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- break;
- default:
- gcc_unreachable ();
- }
- if (flag_openmp)
- {
- tree distribute = make_node (OMP_DISTRIBUTE);
- TREE_TYPE (distribute) = void_type_node;
- OMP_FOR_BODY (distribute) = stmt;
- OMP_FOR_CLAUSES (distribute) = omp_clauses;
- stmt = distribute;
- }
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa)
- {
- stmtblock_t block;
- gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
- tree stmt, omp_clauses = NULL_TREE;
- bool combined = true;
- gfc_start_block (&block);
- if (clausesa == NULL)
- {
- clausesa = clausesa_buf;
- gfc_split_omp_clauses (code, clausesa);
- }
- if (flag_openmp)
- omp_clauses
- = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TEAMS],
- code->loc);
- switch (code->op)
- {
- case EXEC_OMP_TARGET_TEAMS:
- case EXEC_OMP_TEAMS:
- stmt = gfc_trans_omp_code (code->block->next, true);
- combined = false;
- break;
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
- case EXEC_OMP_TEAMS_DISTRIBUTE:
- stmt = gfc_trans_omp_do (code, EXEC_OMP_DISTRIBUTE, NULL,
- &clausesa[GFC_OMP_SPLIT_DISTRIBUTE],
- NULL);
- break;
- default:
- stmt = gfc_trans_omp_distribute (code, clausesa);
- break;
- }
- stmt = build2_loc (input_location, OMP_TEAMS, void_type_node, stmt,
- omp_clauses);
- if (combined)
- OMP_TEAMS_COMBINED (stmt) = 1;
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_target (gfc_code *code)
- {
- stmtblock_t block;
- gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
- tree stmt, omp_clauses = NULL_TREE;
- gfc_start_block (&block);
- gfc_split_omp_clauses (code, clausesa);
- if (flag_openmp)
- omp_clauses
- = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
- code->loc);
- if (code->op == EXEC_OMP_TARGET)
- stmt = gfc_trans_omp_code (code->block->next, true);
- else
- {
- pushlevel ();
- stmt = gfc_trans_omp_teams (code, clausesa);
- if (TREE_CODE (stmt) != BIND_EXPR)
- stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
- else
- poplevel (0, 0);
- }
- if (flag_openmp)
- stmt = build2_loc (input_location, OMP_TARGET, void_type_node, stmt,
- omp_clauses);
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_target_data (gfc_code *code)
- {
- stmtblock_t block;
- tree stmt, omp_clauses;
- gfc_start_block (&block);
- omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
- code->loc);
- stmt = gfc_trans_omp_code (code->block->next, true);
- stmt = build2_loc (input_location, OMP_TARGET_DATA, void_type_node, stmt,
- omp_clauses);
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_target_update (gfc_code *code)
- {
- stmtblock_t block;
- tree stmt, omp_clauses;
- gfc_start_block (&block);
- omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
- code->loc);
- stmt = build1_loc (input_location, OMP_TARGET_UPDATE, void_type_node,
- omp_clauses);
- gfc_add_expr_to_block (&block, stmt);
- return gfc_finish_block (&block);
- }
- static tree
- gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
- {
- tree res, tmp, stmt;
- stmtblock_t block, *pblock = NULL;
- stmtblock_t singleblock;
- int saved_ompws_flags;
- bool singleblock_in_progress = false;
- /* True if previous gfc_code in workshare construct is not workshared. */
- bool prev_singleunit;
- code = code->block->next;
- pushlevel ();
- gfc_start_block (&block);
- pblock = █
- ompws_flags = OMPWS_WORKSHARE_FLAG;
- prev_singleunit = false;
- /* Translate statements one by one to trees until we reach
- the end of the workshare construct. Adjacent gfc_codes that
- are a single unit of work are clustered and encapsulated in a
- single OMP_SINGLE construct. */
- for (; code; code = code->next)
- {
- if (code->here != 0)
- {
- res = gfc_trans_label_here (code);
- gfc_add_expr_to_block (pblock, res);
- }
- /* No dependence analysis, use for clauses with wait.
- If this is the last gfc_code, use default omp_clauses. */
- if (code->next == NULL && clauses->nowait)
- ompws_flags |= OMPWS_NOWAIT;
- /* By default, every gfc_code is a single unit of work. */
- ompws_flags |= OMPWS_CURR_SINGLEUNIT;
- ompws_flags &= ~OMPWS_SCALARIZER_WS;
- switch (code->op)
- {
- case EXEC_NOP:
- res = NULL_TREE;
- break;
- case EXEC_ASSIGN:
- res = gfc_trans_assign (code);
- break;
- case EXEC_POINTER_ASSIGN:
- res = gfc_trans_pointer_assign (code);
- break;
- case EXEC_INIT_ASSIGN:
- res = gfc_trans_init_assign (code);
- break;
- case EXEC_FORALL:
- res = gfc_trans_forall (code);
- break;
- case EXEC_WHERE:
- res = gfc_trans_where (code);
- break;
- case EXEC_OMP_ATOMIC:
- res = gfc_trans_omp_directive (code);
- break;
- case EXEC_OMP_PARALLEL:
- case EXEC_OMP_PARALLEL_DO:
- case EXEC_OMP_PARALLEL_SECTIONS:
- case EXEC_OMP_PARALLEL_WORKSHARE:
- case EXEC_OMP_CRITICAL:
- saved_ompws_flags = ompws_flags;
- ompws_flags = 0;
- res = gfc_trans_omp_directive (code);
- ompws_flags = saved_ompws_flags;
- break;
-
- default:
- gfc_internal_error ("gfc_trans_omp_workshare(): Bad statement code");
- }
- gfc_set_backend_locus (&code->loc);
- if (res != NULL_TREE && ! IS_EMPTY_STMT (res))
- {
- if (prev_singleunit)
- {
- if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
- /* Add current gfc_code to single block. */
- gfc_add_expr_to_block (&singleblock, res);
- else
- {
- /* Finish single block and add it to pblock. */
- tmp = gfc_finish_block (&singleblock);
- tmp = build2_loc (input_location, OMP_SINGLE,
- void_type_node, tmp, NULL_TREE);
- gfc_add_expr_to_block (pblock, tmp);
- /* Add current gfc_code to pblock. */
- gfc_add_expr_to_block (pblock, res);
- singleblock_in_progress = false;
- }
- }
- else
- {
- if (ompws_flags & OMPWS_CURR_SINGLEUNIT)
- {
- /* Start single block. */
- gfc_init_block (&singleblock);
- gfc_add_expr_to_block (&singleblock, res);
- singleblock_in_progress = true;
- }
- else
- /* Add the new statement to the block. */
- gfc_add_expr_to_block (pblock, res);
- }
- prev_singleunit = (ompws_flags & OMPWS_CURR_SINGLEUNIT) != 0;
- }
- }
- /* Finish remaining SINGLE block, if we were in the middle of one. */
- if (singleblock_in_progress)
- {
- /* Finish single block and add it to pblock. */
- tmp = gfc_finish_block (&singleblock);
- tmp = build2_loc (input_location, OMP_SINGLE, void_type_node, tmp,
- clauses->nowait
- ? build_omp_clause (input_location, OMP_CLAUSE_NOWAIT)
- : NULL_TREE);
- gfc_add_expr_to_block (pblock, tmp);
- }
- stmt = gfc_finish_block (pblock);
- if (TREE_CODE (stmt) != BIND_EXPR)
- {
- if (!IS_EMPTY_STMT (stmt))
- {
- tree bindblock = poplevel (1, 0);
- stmt = build3_v (BIND_EXPR, NULL, stmt, bindblock);
- }
- else
- poplevel (0, 0);
- }
- else
- poplevel (0, 0);
- if (IS_EMPTY_STMT (stmt) && !clauses->nowait)
- stmt = gfc_trans_omp_barrier ();
- ompws_flags = 0;
- return stmt;
- }
- tree
- gfc_trans_oacc_declare (stmtblock_t *block, gfc_namespace *ns)
- {
- tree oacc_clauses;
- oacc_clauses = gfc_trans_omp_clauses (block, ns->oacc_declare_clauses,
- ns->oacc_declare_clauses->loc);
- return build1_loc (ns->oacc_declare_clauses->loc.lb->location,
- OACC_DECLARE, void_type_node, oacc_clauses);
- }
- tree
- gfc_trans_oacc_directive (gfc_code *code)
- {
- switch (code->op)
- {
- case EXEC_OACC_PARALLEL_LOOP:
- case EXEC_OACC_KERNELS_LOOP:
- return gfc_trans_oacc_combined_directive (code);
- case EXEC_OACC_PARALLEL:
- case EXEC_OACC_KERNELS:
- case EXEC_OACC_DATA:
- case EXEC_OACC_HOST_DATA:
- return gfc_trans_oacc_construct (code);
- case EXEC_OACC_LOOP:
- return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
- NULL);
- case EXEC_OACC_UPDATE:
- case EXEC_OACC_CACHE:
- case EXEC_OACC_ENTER_DATA:
- case EXEC_OACC_EXIT_DATA:
- return gfc_trans_oacc_executable_directive (code);
- case EXEC_OACC_WAIT:
- return gfc_trans_oacc_wait_directive (code);
- default:
- gcc_unreachable ();
- }
- }
- tree
- gfc_trans_omp_directive (gfc_code *code)
- {
- switch (code->op)
- {
- case EXEC_OMP_ATOMIC:
- return gfc_trans_omp_atomic (code);
- case EXEC_OMP_BARRIER:
- return gfc_trans_omp_barrier ();
- case EXEC_OMP_CANCEL:
- return gfc_trans_omp_cancel (code);
- case EXEC_OMP_CANCELLATION_POINT:
- return gfc_trans_omp_cancellation_point (code);
- case EXEC_OMP_CRITICAL:
- return gfc_trans_omp_critical (code);
- case EXEC_OMP_DISTRIBUTE:
- case EXEC_OMP_DO:
- case EXEC_OMP_SIMD:
- return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
- NULL);
- case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
- case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD:
- case EXEC_OMP_DISTRIBUTE_SIMD:
- return gfc_trans_omp_distribute (code, NULL);
- case EXEC_OMP_DO_SIMD:
- return gfc_trans_omp_do_simd (code, NULL, NULL, NULL_TREE);
- case EXEC_OMP_FLUSH:
- return gfc_trans_omp_flush ();
- case EXEC_OMP_MASTER:
- return gfc_trans_omp_master (code);
- case EXEC_OMP_ORDERED:
- return gfc_trans_omp_ordered (code);
- case EXEC_OMP_PARALLEL:
- return gfc_trans_omp_parallel (code);
- case EXEC_OMP_PARALLEL_DO:
- return gfc_trans_omp_parallel_do (code, NULL, NULL);
- case EXEC_OMP_PARALLEL_DO_SIMD:
- return gfc_trans_omp_parallel_do_simd (code, NULL, NULL);
- case EXEC_OMP_PARALLEL_SECTIONS:
- return gfc_trans_omp_parallel_sections (code);
- case EXEC_OMP_PARALLEL_WORKSHARE:
- return gfc_trans_omp_parallel_workshare (code);
- case EXEC_OMP_SECTIONS:
- return gfc_trans_omp_sections (code, code->ext.omp_clauses);
- case EXEC_OMP_SINGLE:
- return gfc_trans_omp_single (code, code->ext.omp_clauses);
- case EXEC_OMP_TARGET:
- case EXEC_OMP_TARGET_TEAMS:
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD:
- return gfc_trans_omp_target (code);
- case EXEC_OMP_TARGET_DATA:
- return gfc_trans_omp_target_data (code);
- case EXEC_OMP_TARGET_UPDATE:
- return gfc_trans_omp_target_update (code);
- case EXEC_OMP_TASK:
- return gfc_trans_omp_task (code);
- case EXEC_OMP_TASKGROUP:
- return gfc_trans_omp_taskgroup (code);
- case EXEC_OMP_TASKWAIT:
- return gfc_trans_omp_taskwait ();
- case EXEC_OMP_TASKYIELD:
- return gfc_trans_omp_taskyield ();
- case EXEC_OMP_TEAMS:
- case EXEC_OMP_TEAMS_DISTRIBUTE:
- case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
- case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
- case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
- return gfc_trans_omp_teams (code, NULL);
- case EXEC_OMP_WORKSHARE:
- return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
- default:
- gcc_unreachable ();
- }
- }
- void
- gfc_trans_omp_declare_simd (gfc_namespace *ns)
- {
- if (ns->entries)
- return;
- gfc_omp_declare_simd *ods;
- for (ods = ns->omp_declare_simd; ods; ods = ods->next)
- {
- tree c = gfc_trans_omp_clauses (NULL, ods->clauses, ods->where, true);
- tree fndecl = ns->proc_name->backend_decl;
- if (c != NULL_TREE)
- c = tree_cons (NULL_TREE, c, NULL_TREE);
- c = build_tree_list (get_identifier ("omp declare simd"), c);
- TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
- DECL_ATTRIBUTES (fndecl) = c;
- }
- }
|