1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971 |
- /* Gimple IR support functions.
- Copyright (C) 2007-2015 Free Software Foundation, Inc.
- Contributed by Aldy Hernandez <aldyh@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 "tm.h"
- #include "target.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 "wide-int.h"
- #include "inchash.h"
- #include "tree.h"
- #include "fold-const.h"
- #include "calls.h"
- #include "stmt.h"
- #include "stor-layout.h"
- #include "hard-reg-set.h"
- #include "predict.h"
- #include "input.h"
- #include "function.h"
- #include "dominance.h"
- #include "cfg.h"
- #include "basic-block.h"
- #include "tree-ssa-alias.h"
- #include "internal-fn.h"
- #include "tree-eh.h"
- #include "gimple-expr.h"
- #include "is-a.h"
- #include "gimple.h"
- #include "gimple-iterator.h"
- #include "gimple-walk.h"
- #include "gimple.h"
- #include "gimplify.h"
- #include "diagnostic.h"
- #include "value-prof.h"
- #include "flags.h"
- #include "alias.h"
- #include "demangle.h"
- #include "langhooks.h"
- #include "bitmap.h"
- #include "stringpool.h"
- #include "tree-ssanames.h"
- #include "ipa-ref.h"
- #include "lto-streamer.h"
- #include "cgraph.h"
- #include "gimple-ssa.h"
- /* All the tuples have their operand vector (if present) at the very bottom
- of the structure. Therefore, the offset required to find the
- operands vector the size of the structure minus the size of the 1
- element tree array at the end (see gimple_ops). */
- #define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) \
- (HAS_TREE_OP ? sizeof (struct STRUCT) - sizeof (tree) : 0),
- EXPORTED_CONST size_t gimple_ops_offset_[] = {
- #include "gsstruct.def"
- };
- #undef DEFGSSTRUCT
- #define DEFGSSTRUCT(SYM, STRUCT, HAS_TREE_OP) sizeof (struct STRUCT),
- static const size_t gsstruct_code_size[] = {
- #include "gsstruct.def"
- };
- #undef DEFGSSTRUCT
- #define DEFGSCODE(SYM, NAME, GSSCODE) NAME,
- const char *const gimple_code_name[] = {
- #include "gimple.def"
- };
- #undef DEFGSCODE
- #define DEFGSCODE(SYM, NAME, GSSCODE) GSSCODE,
- EXPORTED_CONST enum gimple_statement_structure_enum gss_for_code_[] = {
- #include "gimple.def"
- };
- #undef DEFGSCODE
- /* Gimple stats. */
- int gimple_alloc_counts[(int) gimple_alloc_kind_all];
- int gimple_alloc_sizes[(int) gimple_alloc_kind_all];
- /* Keep in sync with gimple.h:enum gimple_alloc_kind. */
- static const char * const gimple_alloc_kind_names[] = {
- "assignments",
- "phi nodes",
- "conditionals",
- "everything else"
- };
- /* Gimple tuple constructors.
- Note: Any constructor taking a ``gimple_seq'' as a parameter, can
- be passed a NULL to start with an empty sequence. */
- /* Set the code for statement G to CODE. */
- static inline void
- gimple_set_code (gimple g, enum gimple_code code)
- {
- g->code = code;
- }
- /* Return the number of bytes needed to hold a GIMPLE statement with
- code CODE. */
- static inline size_t
- gimple_size (enum gimple_code code)
- {
- return gsstruct_code_size[gss_for_code (code)];
- }
- /* Allocate memory for a GIMPLE statement with code CODE and NUM_OPS
- operands. */
- gimple
- gimple_alloc_stat (enum gimple_code code, unsigned num_ops MEM_STAT_DECL)
- {
- size_t size;
- gimple stmt;
- size = gimple_size (code);
- if (num_ops > 0)
- size += sizeof (tree) * (num_ops - 1);
- if (GATHER_STATISTICS)
- {
- enum gimple_alloc_kind kind = gimple_alloc_kind (code);
- gimple_alloc_counts[(int) kind]++;
- gimple_alloc_sizes[(int) kind] += size;
- }
- stmt = ggc_alloc_cleared_gimple_statement_stat (size PASS_MEM_STAT);
- gimple_set_code (stmt, code);
- gimple_set_num_ops (stmt, num_ops);
- /* Do not call gimple_set_modified here as it has other side
- effects and this tuple is still not completely built. */
- stmt->modified = 1;
- gimple_init_singleton (stmt);
- return stmt;
- }
- /* Set SUBCODE to be the code of the expression computed by statement G. */
- static inline void
- gimple_set_subcode (gimple g, unsigned subcode)
- {
- /* We only have 16 bits for the RHS code. Assert that we are not
- overflowing it. */
- gcc_assert (subcode < (1 << 16));
- g->subcode = subcode;
- }
- /* Build a tuple with operands. CODE is the statement to build (which
- must be one of the GIMPLE_WITH_OPS tuples). SUBCODE is the subcode
- for the new tuple. NUM_OPS is the number of operands to allocate. */
- #define gimple_build_with_ops(c, s, n) \
- gimple_build_with_ops_stat (c, s, n MEM_STAT_INFO)
- static gimple
- gimple_build_with_ops_stat (enum gimple_code code, unsigned subcode,
- unsigned num_ops MEM_STAT_DECL)
- {
- gimple s = gimple_alloc_stat (code, num_ops PASS_MEM_STAT);
- gimple_set_subcode (s, subcode);
- return s;
- }
- /* Build a GIMPLE_RETURN statement returning RETVAL. */
- greturn *
- gimple_build_return (tree retval)
- {
- greturn *s
- = as_a <greturn *> (gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK,
- 2));
- if (retval)
- gimple_return_set_retval (s, retval);
- return s;
- }
- /* Reset alias information on call S. */
- void
- gimple_call_reset_alias_info (gcall *s)
- {
- if (gimple_call_flags (s) & ECF_CONST)
- memset (gimple_call_use_set (s), 0, sizeof (struct pt_solution));
- else
- pt_solution_reset (gimple_call_use_set (s));
- if (gimple_call_flags (s) & (ECF_CONST|ECF_PURE|ECF_NOVOPS))
- memset (gimple_call_clobber_set (s), 0, sizeof (struct pt_solution));
- else
- pt_solution_reset (gimple_call_clobber_set (s));
- }
- /* Helper for gimple_build_call, gimple_build_call_valist,
- gimple_build_call_vec and gimple_build_call_from_tree. Build the basic
- components of a GIMPLE_CALL statement to function FN with NARGS
- arguments. */
- static inline gcall *
- gimple_build_call_1 (tree fn, unsigned nargs)
- {
- gcall *s
- = as_a <gcall *> (gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK,
- nargs + 3));
- if (TREE_CODE (fn) == FUNCTION_DECL)
- fn = build_fold_addr_expr (fn);
- gimple_set_op (s, 1, fn);
- gimple_call_set_fntype (s, TREE_TYPE (TREE_TYPE (fn)));
- gimple_call_reset_alias_info (s);
- return s;
- }
- /* Build a GIMPLE_CALL statement to function FN with the arguments
- specified in vector ARGS. */
- gcall *
- gimple_build_call_vec (tree fn, vec<tree> args)
- {
- unsigned i;
- unsigned nargs = args.length ();
- gcall *call = gimple_build_call_1 (fn, nargs);
- for (i = 0; i < nargs; i++)
- gimple_call_set_arg (call, i, args[i]);
- return call;
- }
- /* Build a GIMPLE_CALL statement to function FN. NARGS is the number of
- arguments. The ... are the arguments. */
- gcall *
- gimple_build_call (tree fn, unsigned nargs, ...)
- {
- va_list ap;
- gcall *call;
- unsigned i;
- gcc_assert (TREE_CODE (fn) == FUNCTION_DECL || is_gimple_call_addr (fn));
- call = gimple_build_call_1 (fn, nargs);
- va_start (ap, nargs);
- for (i = 0; i < nargs; i++)
- gimple_call_set_arg (call, i, va_arg (ap, tree));
- va_end (ap);
- return call;
- }
- /* Build a GIMPLE_CALL statement to function FN. NARGS is the number of
- arguments. AP contains the arguments. */
- gcall *
- gimple_build_call_valist (tree fn, unsigned nargs, va_list ap)
- {
- gcall *call;
- unsigned i;
- gcc_assert (TREE_CODE (fn) == FUNCTION_DECL || is_gimple_call_addr (fn));
- call = gimple_build_call_1 (fn, nargs);
- for (i = 0; i < nargs; i++)
- gimple_call_set_arg (call, i, va_arg (ap, tree));
- return call;
- }
- /* Helper for gimple_build_call_internal and gimple_build_call_internal_vec.
- Build the basic components of a GIMPLE_CALL statement to internal
- function FN with NARGS arguments. */
- static inline gcall *
- gimple_build_call_internal_1 (enum internal_fn fn, unsigned nargs)
- {
- gcall *s
- = as_a <gcall *> (gimple_build_with_ops (GIMPLE_CALL, ERROR_MARK,
- nargs + 3));
- s->subcode |= GF_CALL_INTERNAL;
- gimple_call_set_internal_fn (s, fn);
- gimple_call_reset_alias_info (s);
- return s;
- }
- /* Build a GIMPLE_CALL statement to internal function FN. NARGS is
- the number of arguments. The ... are the arguments. */
- gcall *
- gimple_build_call_internal (enum internal_fn fn, unsigned nargs, ...)
- {
- va_list ap;
- gcall *call;
- unsigned i;
- call = gimple_build_call_internal_1 (fn, nargs);
- va_start (ap, nargs);
- for (i = 0; i < nargs; i++)
- gimple_call_set_arg (call, i, va_arg (ap, tree));
- va_end (ap);
- return call;
- }
- /* Build a GIMPLE_CALL statement to internal function FN with the arguments
- specified in vector ARGS. */
- gcall *
- gimple_build_call_internal_vec (enum internal_fn fn, vec<tree> args)
- {
- unsigned i, nargs;
- gcall *call;
- nargs = args.length ();
- call = gimple_build_call_internal_1 (fn, nargs);
- for (i = 0; i < nargs; i++)
- gimple_call_set_arg (call, i, args[i]);
- return call;
- }
- /* Build a GIMPLE_CALL statement from CALL_EXPR T. Note that T is
- assumed to be in GIMPLE form already. Minimal checking is done of
- this fact. */
- gcall *
- gimple_build_call_from_tree (tree t)
- {
- unsigned i, nargs;
- gcall *call;
- tree fndecl = get_callee_fndecl (t);
- gcc_assert (TREE_CODE (t) == CALL_EXPR);
- nargs = call_expr_nargs (t);
- call = gimple_build_call_1 (fndecl ? fndecl : CALL_EXPR_FN (t), nargs);
- for (i = 0; i < nargs; i++)
- gimple_call_set_arg (call, i, CALL_EXPR_ARG (t, i));
- gimple_set_block (call, TREE_BLOCK (t));
- /* Carry all the CALL_EXPR flags to the new GIMPLE_CALL. */
- gimple_call_set_chain (call, CALL_EXPR_STATIC_CHAIN (t));
- gimple_call_set_tail (call, CALL_EXPR_TAILCALL (t));
- gimple_call_set_return_slot_opt (call, CALL_EXPR_RETURN_SLOT_OPT (t));
- if (fndecl
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA
- || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA_WITH_ALIGN))
- gimple_call_set_alloca_for_var (call, CALL_ALLOCA_FOR_VAR_P (t));
- else
- gimple_call_set_from_thunk (call, CALL_FROM_THUNK_P (t));
- gimple_call_set_va_arg_pack (call, CALL_EXPR_VA_ARG_PACK (t));
- gimple_call_set_nothrow (call, TREE_NOTHROW (t));
- gimple_set_no_warning (call, TREE_NO_WARNING (t));
- gimple_call_set_with_bounds (call, CALL_WITH_BOUNDS_P (t));
- return call;
- }
- /* Build a GIMPLE_ASSIGN statement.
- LHS of the assignment.
- RHS of the assignment which can be unary or binary. */
- gassign *
- gimple_build_assign (tree lhs, tree rhs MEM_STAT_DECL)
- {
- enum tree_code subcode;
- tree op1, op2, op3;
- extract_ops_from_tree_1 (rhs, &subcode, &op1, &op2, &op3);
- return gimple_build_assign (lhs, subcode, op1, op2, op3 PASS_MEM_STAT);
- }
- /* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
- OP1, OP2 and OP3. */
- static inline gassign *
- gimple_build_assign_1 (tree lhs, enum tree_code subcode, tree op1,
- tree op2, tree op3 MEM_STAT_DECL)
- {
- unsigned num_ops;
- gassign *p;
- /* Need 1 operand for LHS and 1 or 2 for the RHS (depending on the
- code). */
- num_ops = get_gimple_rhs_num_ops (subcode) + 1;
- p = as_a <gassign *> (
- gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode, num_ops
- PASS_MEM_STAT));
- gimple_assign_set_lhs (p, lhs);
- gimple_assign_set_rhs1 (p, op1);
- if (op2)
- {
- gcc_assert (num_ops > 2);
- gimple_assign_set_rhs2 (p, op2);
- }
- if (op3)
- {
- gcc_assert (num_ops > 3);
- gimple_assign_set_rhs3 (p, op3);
- }
- return p;
- }
- /* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
- OP1, OP2 and OP3. */
- gassign *
- gimple_build_assign (tree lhs, enum tree_code subcode, tree op1,
- tree op2, tree op3 MEM_STAT_DECL)
- {
- return gimple_build_assign_1 (lhs, subcode, op1, op2, op3 PASS_MEM_STAT);
- }
- /* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operands
- OP1 and OP2. */
- gassign *
- gimple_build_assign (tree lhs, enum tree_code subcode, tree op1,
- tree op2 MEM_STAT_DECL)
- {
- return gimple_build_assign_1 (lhs, subcode, op1, op2, NULL_TREE
- PASS_MEM_STAT);
- }
- /* Build a GIMPLE_ASSIGN statement with subcode SUBCODE and operand OP1. */
- gassign *
- gimple_build_assign (tree lhs, enum tree_code subcode, tree op1 MEM_STAT_DECL)
- {
- return gimple_build_assign_1 (lhs, subcode, op1, NULL_TREE, NULL_TREE
- PASS_MEM_STAT);
- }
- /* Build a GIMPLE_COND statement.
- PRED is the condition used to compare LHS and the RHS.
- T_LABEL is the label to jump to if the condition is true.
- F_LABEL is the label to jump to otherwise. */
- gcond *
- gimple_build_cond (enum tree_code pred_code, tree lhs, tree rhs,
- tree t_label, tree f_label)
- {
- gcond *p;
- gcc_assert (TREE_CODE_CLASS (pred_code) == tcc_comparison);
- p = as_a <gcond *> (gimple_build_with_ops (GIMPLE_COND, pred_code, 4));
- gimple_cond_set_lhs (p, lhs);
- gimple_cond_set_rhs (p, rhs);
- gimple_cond_set_true_label (p, t_label);
- gimple_cond_set_false_label (p, f_label);
- return p;
- }
- /* Build a GIMPLE_COND statement from the conditional expression tree
- COND. T_LABEL and F_LABEL are as in gimple_build_cond. */
- gcond *
- gimple_build_cond_from_tree (tree cond, tree t_label, tree f_label)
- {
- enum tree_code code;
- tree lhs, rhs;
- gimple_cond_get_ops_from_tree (cond, &code, &lhs, &rhs);
- return gimple_build_cond (code, lhs, rhs, t_label, f_label);
- }
- /* Set code, lhs, and rhs of a GIMPLE_COND from a suitable
- boolean expression tree COND. */
- void
- gimple_cond_set_condition_from_tree (gcond *stmt, tree cond)
- {
- enum tree_code code;
- tree lhs, rhs;
- gimple_cond_get_ops_from_tree (cond, &code, &lhs, &rhs);
- gimple_cond_set_condition (stmt, code, lhs, rhs);
- }
- /* Build a GIMPLE_LABEL statement for LABEL. */
- glabel *
- gimple_build_label (tree label)
- {
- glabel *p
- = as_a <glabel *> (gimple_build_with_ops (GIMPLE_LABEL, ERROR_MARK, 1));
- gimple_label_set_label (p, label);
- return p;
- }
- /* Build a GIMPLE_GOTO statement to label DEST. */
- ggoto *
- gimple_build_goto (tree dest)
- {
- ggoto *p
- = as_a <ggoto *> (gimple_build_with_ops (GIMPLE_GOTO, ERROR_MARK, 1));
- gimple_goto_set_dest (p, dest);
- return p;
- }
- /* Build a GIMPLE_NOP statement. */
- gimple
- gimple_build_nop (void)
- {
- return gimple_alloc (GIMPLE_NOP, 0);
- }
- /* Build a GIMPLE_BIND statement.
- VARS are the variables in BODY.
- BLOCK is the containing block. */
- gbind *
- gimple_build_bind (tree vars, gimple_seq body, tree block)
- {
- gbind *p = as_a <gbind *> (gimple_alloc (GIMPLE_BIND, 0));
- gimple_bind_set_vars (p, vars);
- if (body)
- gimple_bind_set_body (p, body);
- if (block)
- gimple_bind_set_block (p, block);
- return p;
- }
- /* Helper function to set the simple fields of a asm stmt.
- STRING is a pointer to a string that is the asm blocks assembly code.
- NINPUT is the number of register inputs.
- NOUTPUT is the number of register outputs.
- NCLOBBERS is the number of clobbered registers.
- */
- static inline gasm *
- gimple_build_asm_1 (const char *string, unsigned ninputs, unsigned noutputs,
- unsigned nclobbers, unsigned nlabels)
- {
- gasm *p;
- int size = strlen (string);
- /* ASMs with labels cannot have outputs. This should have been
- enforced by the front end. */
- gcc_assert (nlabels == 0 || noutputs == 0);
- p = as_a <gasm *> (
- gimple_build_with_ops (GIMPLE_ASM, ERROR_MARK,
- ninputs + noutputs + nclobbers + nlabels));
- p->ni = ninputs;
- p->no = noutputs;
- p->nc = nclobbers;
- p->nl = nlabels;
- p->string = ggc_alloc_string (string, size);
- if (GATHER_STATISTICS)
- gimple_alloc_sizes[(int) gimple_alloc_kind (GIMPLE_ASM)] += size;
- return p;
- }
- /* Build a GIMPLE_ASM statement.
- STRING is the assembly code.
- NINPUT is the number of register inputs.
- NOUTPUT is the number of register outputs.
- NCLOBBERS is the number of clobbered registers.
- INPUTS is a vector of the input register parameters.
- OUTPUTS is a vector of the output register parameters.
- CLOBBERS is a vector of the clobbered register parameters.
- LABELS is a vector of destination labels. */
- gasm *
- gimple_build_asm_vec (const char *string, vec<tree, va_gc> *inputs,
- vec<tree, va_gc> *outputs, vec<tree, va_gc> *clobbers,
- vec<tree, va_gc> *labels)
- {
- gasm *p;
- unsigned i;
- p = gimple_build_asm_1 (string,
- vec_safe_length (inputs),
- vec_safe_length (outputs),
- vec_safe_length (clobbers),
- vec_safe_length (labels));
- for (i = 0; i < vec_safe_length (inputs); i++)
- gimple_asm_set_input_op (p, i, (*inputs)[i]);
- for (i = 0; i < vec_safe_length (outputs); i++)
- gimple_asm_set_output_op (p, i, (*outputs)[i]);
- for (i = 0; i < vec_safe_length (clobbers); i++)
- gimple_asm_set_clobber_op (p, i, (*clobbers)[i]);
- for (i = 0; i < vec_safe_length (labels); i++)
- gimple_asm_set_label_op (p, i, (*labels)[i]);
- return p;
- }
- /* Build a GIMPLE_CATCH statement.
- TYPES are the catch types.
- HANDLER is the exception handler. */
- gcatch *
- gimple_build_catch (tree types, gimple_seq handler)
- {
- gcatch *p = as_a <gcatch *> (gimple_alloc (GIMPLE_CATCH, 0));
- gimple_catch_set_types (p, types);
- if (handler)
- gimple_catch_set_handler (p, handler);
- return p;
- }
- /* Build a GIMPLE_EH_FILTER statement.
- TYPES are the filter's types.
- FAILURE is the filter's failure action. */
- geh_filter *
- gimple_build_eh_filter (tree types, gimple_seq failure)
- {
- geh_filter *p = as_a <geh_filter *> (gimple_alloc (GIMPLE_EH_FILTER, 0));
- gimple_eh_filter_set_types (p, types);
- if (failure)
- gimple_eh_filter_set_failure (p, failure);
- return p;
- }
- /* Build a GIMPLE_EH_MUST_NOT_THROW statement. */
- geh_mnt *
- gimple_build_eh_must_not_throw (tree decl)
- {
- geh_mnt *p = as_a <geh_mnt *> (gimple_alloc (GIMPLE_EH_MUST_NOT_THROW, 0));
- gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
- gcc_assert (flags_from_decl_or_type (decl) & ECF_NORETURN);
- gimple_eh_must_not_throw_set_fndecl (p, decl);
- return p;
- }
- /* Build a GIMPLE_EH_ELSE statement. */
- geh_else *
- gimple_build_eh_else (gimple_seq n_body, gimple_seq e_body)
- {
- geh_else *p = as_a <geh_else *> (gimple_alloc (GIMPLE_EH_ELSE, 0));
- gimple_eh_else_set_n_body (p, n_body);
- gimple_eh_else_set_e_body (p, e_body);
- return p;
- }
- /* Build a GIMPLE_TRY statement.
- EVAL is the expression to evaluate.
- CLEANUP is the cleanup expression.
- KIND is either GIMPLE_TRY_CATCH or GIMPLE_TRY_FINALLY depending on
- whether this is a try/catch or a try/finally respectively. */
- gtry *
- gimple_build_try (gimple_seq eval, gimple_seq cleanup,
- enum gimple_try_flags kind)
- {
- gtry *p;
- gcc_assert (kind == GIMPLE_TRY_CATCH || kind == GIMPLE_TRY_FINALLY);
- p = as_a <gtry *> (gimple_alloc (GIMPLE_TRY, 0));
- gimple_set_subcode (p, kind);
- if (eval)
- gimple_try_set_eval (p, eval);
- if (cleanup)
- gimple_try_set_cleanup (p, cleanup);
- return p;
- }
- /* Construct a GIMPLE_WITH_CLEANUP_EXPR statement.
- CLEANUP is the cleanup expression. */
- gimple
- gimple_build_wce (gimple_seq cleanup)
- {
- gimple p = gimple_alloc (GIMPLE_WITH_CLEANUP_EXPR, 0);
- if (cleanup)
- gimple_wce_set_cleanup (p, cleanup);
- return p;
- }
- /* Build a GIMPLE_RESX statement. */
- gresx *
- gimple_build_resx (int region)
- {
- gresx *p
- = as_a <gresx *> (gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0));
- p->region = region;
- return p;
- }
- /* The helper for constructing a gimple switch statement.
- INDEX is the switch's index.
- NLABELS is the number of labels in the switch excluding the default.
- DEFAULT_LABEL is the default label for the switch statement. */
- gswitch *
- gimple_build_switch_nlabels (unsigned nlabels, tree index, tree default_label)
- {
- /* nlabels + 1 default label + 1 index. */
- gcc_checking_assert (default_label);
- gswitch *p = as_a <gswitch *> (gimple_build_with_ops (GIMPLE_SWITCH,
- ERROR_MARK,
- 1 + 1 + nlabels));
- gimple_switch_set_index (p, index);
- gimple_switch_set_default_label (p, default_label);
- return p;
- }
- /* Build a GIMPLE_SWITCH statement.
- INDEX is the switch's index.
- DEFAULT_LABEL is the default label
- ARGS is a vector of labels excluding the default. */
- gswitch *
- gimple_build_switch (tree index, tree default_label, vec<tree> args)
- {
- unsigned i, nlabels = args.length ();
- gswitch *p = gimple_build_switch_nlabels (nlabels, index, default_label);
- /* Copy the labels from the vector to the switch statement. */
- for (i = 0; i < nlabels; i++)
- gimple_switch_set_label (p, i + 1, args[i]);
- return p;
- }
- /* Build a GIMPLE_EH_DISPATCH statement. */
- geh_dispatch *
- gimple_build_eh_dispatch (int region)
- {
- geh_dispatch *p
- = as_a <geh_dispatch *> (
- gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0));
- p->region = region;
- return p;
- }
- /* Build a new GIMPLE_DEBUG_BIND statement.
- VAR is bound to VALUE; block and location are taken from STMT. */
- gdebug *
- gimple_build_debug_bind_stat (tree var, tree value, gimple stmt MEM_STAT_DECL)
- {
- gdebug *p
- = as_a <gdebug *> (gimple_build_with_ops_stat (GIMPLE_DEBUG,
- (unsigned)GIMPLE_DEBUG_BIND, 2
- PASS_MEM_STAT));
- gimple_debug_bind_set_var (p, var);
- gimple_debug_bind_set_value (p, value);
- if (stmt)
- gimple_set_location (p, gimple_location (stmt));
- return p;
- }
- /* Build a new GIMPLE_DEBUG_SOURCE_BIND statement.
- VAR is bound to VALUE; block and location are taken from STMT. */
- gdebug *
- gimple_build_debug_source_bind_stat (tree var, tree value,
- gimple stmt MEM_STAT_DECL)
- {
- gdebug *p
- = as_a <gdebug *> (
- gimple_build_with_ops_stat (GIMPLE_DEBUG,
- (unsigned)GIMPLE_DEBUG_SOURCE_BIND, 2
- PASS_MEM_STAT));
- gimple_debug_source_bind_set_var (p, var);
- gimple_debug_source_bind_set_value (p, value);
- if (stmt)
- gimple_set_location (p, gimple_location (stmt));
- return p;
- }
- /* Build a GIMPLE_OMP_CRITICAL statement.
- BODY is the sequence of statements for which only one thread can execute.
- NAME is optional identifier for this critical block. */
- gomp_critical *
- gimple_build_omp_critical (gimple_seq body, tree name)
- {
- gomp_critical *p
- = as_a <gomp_critical *> (gimple_alloc (GIMPLE_OMP_CRITICAL, 0));
- gimple_omp_critical_set_name (p, name);
- if (body)
- gimple_omp_set_body (p, body);
- return p;
- }
- /* Build a GIMPLE_OMP_FOR statement.
- BODY is sequence of statements inside the for loop.
- KIND is the `for' variant.
- CLAUSES, are any of the construct's clauses.
- COLLAPSE is the collapse count.
- PRE_BODY is the sequence of statements that are loop invariant. */
- gomp_for *
- gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
- gimple_seq pre_body)
- {
- gomp_for *p = as_a <gomp_for *> (gimple_alloc (GIMPLE_OMP_FOR, 0));
- if (body)
- gimple_omp_set_body (p, body);
- gimple_omp_for_set_clauses (p, clauses);
- gimple_omp_for_set_kind (p, kind);
- p->collapse = collapse;
- p->iter = ggc_cleared_vec_alloc<gimple_omp_for_iter> (collapse);
- if (pre_body)
- gimple_omp_for_set_pre_body (p, pre_body);
- return p;
- }
- /* Build a GIMPLE_OMP_PARALLEL statement.
- BODY is sequence of statements which are executed in parallel.
- CLAUSES, are the OMP parallel construct's clauses.
- CHILD_FN is the function created for the parallel threads to execute.
- DATA_ARG are the shared data argument(s). */
- gomp_parallel *
- gimple_build_omp_parallel (gimple_seq body, tree clauses, tree child_fn,
- tree data_arg)
- {
- gomp_parallel *p
- = as_a <gomp_parallel *> (gimple_alloc (GIMPLE_OMP_PARALLEL, 0));
- if (body)
- gimple_omp_set_body (p, body);
- gimple_omp_parallel_set_clauses (p, clauses);
- gimple_omp_parallel_set_child_fn (p, child_fn);
- gimple_omp_parallel_set_data_arg (p, data_arg);
- return p;
- }
- /* Build a GIMPLE_OMP_TASK statement.
- BODY is sequence of statements which are executed by the explicit task.
- CLAUSES, are the OMP parallel construct's clauses.
- CHILD_FN is the function created for the parallel threads to execute.
- DATA_ARG are the shared data argument(s).
- COPY_FN is the optional function for firstprivate initialization.
- ARG_SIZE and ARG_ALIGN are size and alignment of the data block. */
- gomp_task *
- gimple_build_omp_task (gimple_seq body, tree clauses, tree child_fn,
- tree data_arg, tree copy_fn, tree arg_size,
- tree arg_align)
- {
- gomp_task *p = as_a <gomp_task *> (gimple_alloc (GIMPLE_OMP_TASK, 0));
- if (body)
- gimple_omp_set_body (p, body);
- gimple_omp_task_set_clauses (p, clauses);
- gimple_omp_task_set_child_fn (p, child_fn);
- gimple_omp_task_set_data_arg (p, data_arg);
- gimple_omp_task_set_copy_fn (p, copy_fn);
- gimple_omp_task_set_arg_size (p, arg_size);
- gimple_omp_task_set_arg_align (p, arg_align);
- return p;
- }
- /* Build a GIMPLE_OMP_SECTION statement for a sections statement.
- BODY is the sequence of statements in the section. */
- gimple
- gimple_build_omp_section (gimple_seq body)
- {
- gimple p = gimple_alloc (GIMPLE_OMP_SECTION, 0);
- if (body)
- gimple_omp_set_body (p, body);
- return p;
- }
- /* Build a GIMPLE_OMP_MASTER statement.
- BODY is the sequence of statements to be executed by just the master. */
- gimple
- gimple_build_omp_master (gimple_seq body)
- {
- gimple p = gimple_alloc (GIMPLE_OMP_MASTER, 0);
- if (body)
- gimple_omp_set_body (p, body);
- return p;
- }
- /* Build a GIMPLE_OMP_TASKGROUP statement.
- BODY is the sequence of statements to be executed by the taskgroup
- construct. */
- gimple
- gimple_build_omp_taskgroup (gimple_seq body)
- {
- gimple p = gimple_alloc (GIMPLE_OMP_TASKGROUP, 0);
- if (body)
- gimple_omp_set_body (p, body);
- return p;
- }
- /* Build a GIMPLE_OMP_CONTINUE statement.
- CONTROL_DEF is the definition of the control variable.
- CONTROL_USE is the use of the control variable. */
- gomp_continue *
- gimple_build_omp_continue (tree control_def, tree control_use)
- {
- gomp_continue *p
- = as_a <gomp_continue *> (gimple_alloc (GIMPLE_OMP_CONTINUE, 0));
- gimple_omp_continue_set_control_def (p, control_def);
- gimple_omp_continue_set_control_use (p, control_use);
- return p;
- }
- /* Build a GIMPLE_OMP_ORDERED statement.
- BODY is the sequence of statements inside a loop that will executed in
- sequence. */
- gimple
- gimple_build_omp_ordered (gimple_seq body)
- {
- gimple p = gimple_alloc (GIMPLE_OMP_ORDERED, 0);
- if (body)
- gimple_omp_set_body (p, body);
- return p;
- }
- /* Build a GIMPLE_OMP_RETURN statement.
- WAIT_P is true if this is a non-waiting return. */
- gimple
- gimple_build_omp_return (bool wait_p)
- {
- gimple p = gimple_alloc (GIMPLE_OMP_RETURN, 0);
- if (wait_p)
- gimple_omp_return_set_nowait (p);
- return p;
- }
- /* Build a GIMPLE_OMP_SECTIONS statement.
- BODY is a sequence of section statements.
- CLAUSES are any of the OMP sections contsruct's clauses: private,
- firstprivate, lastprivate, reduction, and nowait. */
- gomp_sections *
- gimple_build_omp_sections (gimple_seq body, tree clauses)
- {
- gomp_sections *p
- = as_a <gomp_sections *> (gimple_alloc (GIMPLE_OMP_SECTIONS, 0));
- if (body)
- gimple_omp_set_body (p, body);
- gimple_omp_sections_set_clauses (p, clauses);
- return p;
- }
- /* Build a GIMPLE_OMP_SECTIONS_SWITCH. */
- gimple
- gimple_build_omp_sections_switch (void)
- {
- return gimple_alloc (GIMPLE_OMP_SECTIONS_SWITCH, 0);
- }
- /* Build a GIMPLE_OMP_SINGLE statement.
- BODY is the sequence of statements that will be executed once.
- CLAUSES are any of the OMP single construct's clauses: private, firstprivate,
- copyprivate, nowait. */
- gomp_single *
- gimple_build_omp_single (gimple_seq body, tree clauses)
- {
- gomp_single *p
- = as_a <gomp_single *> (gimple_alloc (GIMPLE_OMP_SINGLE, 0));
- if (body)
- gimple_omp_set_body (p, body);
- gimple_omp_single_set_clauses (p, clauses);
- return p;
- }
- /* Build a GIMPLE_OMP_TARGET statement.
- BODY is the sequence of statements that will be executed.
- KIND is the kind of the region.
- CLAUSES are any of the construct's clauses. */
- gomp_target *
- gimple_build_omp_target (gimple_seq body, int kind, tree clauses)
- {
- gomp_target *p
- = as_a <gomp_target *> (gimple_alloc (GIMPLE_OMP_TARGET, 0));
- if (body)
- gimple_omp_set_body (p, body);
- gimple_omp_target_set_clauses (p, clauses);
- gimple_omp_target_set_kind (p, kind);
- return p;
- }
- /* Build a GIMPLE_OMP_TEAMS statement.
- BODY is the sequence of statements that will be executed.
- CLAUSES are any of the OMP teams construct's clauses. */
- gomp_teams *
- gimple_build_omp_teams (gimple_seq body, tree clauses)
- {
- gomp_teams *p = as_a <gomp_teams *> (gimple_alloc (GIMPLE_OMP_TEAMS, 0));
- if (body)
- gimple_omp_set_body (p, body);
- gimple_omp_teams_set_clauses (p, clauses);
- return p;
- }
- /* Build a GIMPLE_OMP_ATOMIC_LOAD statement. */
- gomp_atomic_load *
- gimple_build_omp_atomic_load (tree lhs, tree rhs)
- {
- gomp_atomic_load *p
- = as_a <gomp_atomic_load *> (gimple_alloc (GIMPLE_OMP_ATOMIC_LOAD, 0));
- gimple_omp_atomic_load_set_lhs (p, lhs);
- gimple_omp_atomic_load_set_rhs (p, rhs);
- return p;
- }
- /* Build a GIMPLE_OMP_ATOMIC_STORE statement.
- VAL is the value we are storing. */
- gomp_atomic_store *
- gimple_build_omp_atomic_store (tree val)
- {
- gomp_atomic_store *p
- = as_a <gomp_atomic_store *> (gimple_alloc (GIMPLE_OMP_ATOMIC_STORE, 0));
- gimple_omp_atomic_store_set_val (p, val);
- return p;
- }
- /* Build a GIMPLE_TRANSACTION statement. */
- gtransaction *
- gimple_build_transaction (gimple_seq body, tree label)
- {
- gtransaction *p
- = as_a <gtransaction *> (gimple_alloc (GIMPLE_TRANSACTION, 0));
- gimple_transaction_set_body (p, body);
- gimple_transaction_set_label (p, label);
- return p;
- }
- /* Build a GIMPLE_PREDICT statement. PREDICT is one of the predictors from
- predict.def, OUTCOME is NOT_TAKEN or TAKEN. */
- gimple
- gimple_build_predict (enum br_predictor predictor, enum prediction outcome)
- {
- gimple p = gimple_alloc (GIMPLE_PREDICT, 0);
- /* Ensure all the predictors fit into the lower bits of the subcode. */
- gcc_assert ((int) END_PREDICTORS <= GF_PREDICT_TAKEN);
- gimple_predict_set_predictor (p, predictor);
- gimple_predict_set_outcome (p, outcome);
- return p;
- }
- #if defined ENABLE_GIMPLE_CHECKING
- /* Complain of a gimple type mismatch and die. */
- void
- gimple_check_failed (const_gimple gs, const char *file, int line,
- const char *function, enum gimple_code code,
- enum tree_code subcode)
- {
- internal_error ("gimple check: expected %s(%s), have %s(%s) in %s, at %s:%d",
- gimple_code_name[code],
- get_tree_code_name (subcode),
- gimple_code_name[gimple_code (gs)],
- gs->subcode > 0
- ? get_tree_code_name ((enum tree_code) gs->subcode)
- : "",
- function, trim_filename (file), line);
- }
- #endif /* ENABLE_GIMPLE_CHECKING */
- /* Link gimple statement GS to the end of the sequence *SEQ_P. If
- *SEQ_P is NULL, a new sequence is allocated. */
- void
- gimple_seq_add_stmt (gimple_seq *seq_p, gimple gs)
- {
- gimple_stmt_iterator si;
- if (gs == NULL)
- return;
- si = gsi_last (*seq_p);
- gsi_insert_after (&si, gs, GSI_NEW_STMT);
- }
- /* Link gimple statement GS to the end of the sequence *SEQ_P. If
- *SEQ_P is NULL, a new sequence is allocated. This function is
- similar to gimple_seq_add_stmt, but does not scan the operands.
- During gimplification, we need to manipulate statement sequences
- before the def/use vectors have been constructed. */
- void
- gimple_seq_add_stmt_without_update (gimple_seq *seq_p, gimple gs)
- {
- gimple_stmt_iterator si;
- if (gs == NULL)
- return;
- si = gsi_last (*seq_p);
- gsi_insert_after_without_update (&si, gs, GSI_NEW_STMT);
- }
- /* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
- NULL, a new sequence is allocated. */
- void
- gimple_seq_add_seq (gimple_seq *dst_p, gimple_seq src)
- {
- gimple_stmt_iterator si;
- if (src == NULL)
- return;
- si = gsi_last (*dst_p);
- gsi_insert_seq_after (&si, src, GSI_NEW_STMT);
- }
- /* Append sequence SRC to the end of sequence *DST_P. If *DST_P is
- NULL, a new sequence is allocated. This function is
- similar to gimple_seq_add_seq, but does not scan the operands. */
- void
- gimple_seq_add_seq_without_update (gimple_seq *dst_p, gimple_seq src)
- {
- gimple_stmt_iterator si;
- if (src == NULL)
- return;
- si = gsi_last (*dst_p);
- gsi_insert_seq_after_without_update (&si, src, GSI_NEW_STMT);
- }
- /* Determine whether to assign a location to the statement GS. */
- static bool
- should_carry_location_p (gimple gs)
- {
- /* Don't emit a line note for a label. We particularly don't want to
- emit one for the break label, since it doesn't actually correspond
- to the beginning of the loop/switch. */
- if (gimple_code (gs) == GIMPLE_LABEL)
- return false;
- return true;
- }
- /* Set the location for gimple statement GS to LOCATION. */
- static void
- annotate_one_with_location (gimple gs, location_t location)
- {
- if (!gimple_has_location (gs)
- && !gimple_do_not_emit_location_p (gs)
- && should_carry_location_p (gs))
- gimple_set_location (gs, location);
- }
- /* Set LOCATION for all the statements after iterator GSI in sequence
- SEQ. If GSI is pointing to the end of the sequence, start with the
- first statement in SEQ. */
- void
- annotate_all_with_location_after (gimple_seq seq, gimple_stmt_iterator gsi,
- location_t location)
- {
- if (gsi_end_p (gsi))
- gsi = gsi_start (seq);
- else
- gsi_next (&gsi);
- for (; !gsi_end_p (gsi); gsi_next (&gsi))
- annotate_one_with_location (gsi_stmt (gsi), location);
- }
- /* Set the location for all the statements in a sequence STMT_P to LOCATION. */
- void
- annotate_all_with_location (gimple_seq stmt_p, location_t location)
- {
- gimple_stmt_iterator i;
- if (gimple_seq_empty_p (stmt_p))
- return;
- for (i = gsi_start (stmt_p); !gsi_end_p (i); gsi_next (&i))
- {
- gimple gs = gsi_stmt (i);
- annotate_one_with_location (gs, location);
- }
- }
- /* Helper function of empty_body_p. Return true if STMT is an empty
- statement. */
- static bool
- empty_stmt_p (gimple stmt)
- {
- if (gimple_code (stmt) == GIMPLE_NOP)
- return true;
- if (gbind *bind_stmt = dyn_cast <gbind *> (stmt))
- return empty_body_p (gimple_bind_body (bind_stmt));
- return false;
- }
- /* Return true if BODY contains nothing but empty statements. */
- bool
- empty_body_p (gimple_seq body)
- {
- gimple_stmt_iterator i;
- if (gimple_seq_empty_p (body))
- return true;
- for (i = gsi_start (body); !gsi_end_p (i); gsi_next (&i))
- if (!empty_stmt_p (gsi_stmt (i))
- && !is_gimple_debug (gsi_stmt (i)))
- return false;
- return true;
- }
- /* Perform a deep copy of sequence SRC and return the result. */
- gimple_seq
- gimple_seq_copy (gimple_seq src)
- {
- gimple_stmt_iterator gsi;
- gimple_seq new_seq = NULL;
- gimple stmt;
- for (gsi = gsi_start (src); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- stmt = gimple_copy (gsi_stmt (gsi));
- gimple_seq_add_stmt (&new_seq, stmt);
- }
- return new_seq;
- }
- /* Return true if calls C1 and C2 are known to go to the same function. */
- bool
- gimple_call_same_target_p (const_gimple c1, const_gimple c2)
- {
- if (gimple_call_internal_p (c1))
- return (gimple_call_internal_p (c2)
- && gimple_call_internal_fn (c1) == gimple_call_internal_fn (c2));
- else
- return (gimple_call_fn (c1) == gimple_call_fn (c2)
- || (gimple_call_fndecl (c1)
- && gimple_call_fndecl (c1) == gimple_call_fndecl (c2)));
- }
- /* Detect flags from a GIMPLE_CALL. This is just like
- call_expr_flags, but for gimple tuples. */
- int
- gimple_call_flags (const_gimple stmt)
- {
- int flags;
- tree decl = gimple_call_fndecl (stmt);
- if (decl)
- flags = flags_from_decl_or_type (decl);
- else if (gimple_call_internal_p (stmt))
- flags = internal_fn_flags (gimple_call_internal_fn (stmt));
- else
- flags = flags_from_decl_or_type (gimple_call_fntype (stmt));
- if (stmt->subcode & GF_CALL_NOTHROW)
- flags |= ECF_NOTHROW;
- return flags;
- }
- /* Return the "fn spec" string for call STMT. */
- static const_tree
- gimple_call_fnspec (const gcall *stmt)
- {
- tree type, attr;
- if (gimple_call_internal_p (stmt))
- return internal_fn_fnspec (gimple_call_internal_fn (stmt));
- type = gimple_call_fntype (stmt);
- if (!type)
- return NULL_TREE;
- attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
- if (!attr)
- return NULL_TREE;
- return TREE_VALUE (TREE_VALUE (attr));
- }
- /* Detects argument flags for argument number ARG on call STMT. */
- int
- gimple_call_arg_flags (const gcall *stmt, unsigned arg)
- {
- const_tree attr = gimple_call_fnspec (stmt);
- if (!attr || 1 + arg >= (unsigned) TREE_STRING_LENGTH (attr))
- return 0;
- switch (TREE_STRING_POINTER (attr)[1 + arg])
- {
- case 'x':
- case 'X':
- return EAF_UNUSED;
- case 'R':
- return EAF_DIRECT | EAF_NOCLOBBER | EAF_NOESCAPE;
- case 'r':
- return EAF_NOCLOBBER | EAF_NOESCAPE;
- case 'W':
- return EAF_DIRECT | EAF_NOESCAPE;
- case 'w':
- return EAF_NOESCAPE;
- case '.':
- default:
- return 0;
- }
- }
- /* Detects return flags for the call STMT. */
- int
- gimple_call_return_flags (const gcall *stmt)
- {
- const_tree attr;
- if (gimple_call_flags (stmt) & ECF_MALLOC)
- return ERF_NOALIAS;
- attr = gimple_call_fnspec (stmt);
- if (!attr || TREE_STRING_LENGTH (attr) < 1)
- return 0;
- switch (TREE_STRING_POINTER (attr)[0])
- {
- case '1':
- case '2':
- case '3':
- case '4':
- return ERF_RETURNS_ARG | (TREE_STRING_POINTER (attr)[0] - '1');
- case 'm':
- return ERF_NOALIAS;
- case '.':
- default:
- return 0;
- }
- }
- /* Return true if GS is a copy assignment. */
- bool
- gimple_assign_copy_p (gimple gs)
- {
- return (gimple_assign_single_p (gs)
- && is_gimple_val (gimple_op (gs, 1)));
- }
- /* Return true if GS is a SSA_NAME copy assignment. */
- bool
- gimple_assign_ssa_name_copy_p (gimple gs)
- {
- return (gimple_assign_single_p (gs)
- && TREE_CODE (gimple_assign_lhs (gs)) == SSA_NAME
- && TREE_CODE (gimple_assign_rhs1 (gs)) == SSA_NAME);
- }
- /* Return true if GS is an assignment with a unary RHS, but the
- operator has no effect on the assigned value. The logic is adapted
- from STRIP_NOPS. This predicate is intended to be used in tuplifying
- instances in which STRIP_NOPS was previously applied to the RHS of
- an assignment.
- NOTE: In the use cases that led to the creation of this function
- and of gimple_assign_single_p, it is typical to test for either
- condition and to proceed in the same manner. In each case, the
- assigned value is represented by the single RHS operand of the
- assignment. I suspect there may be cases where gimple_assign_copy_p,
- gimple_assign_single_p, or equivalent logic is used where a similar
- treatment of unary NOPs is appropriate. */
- bool
- gimple_assign_unary_nop_p (gimple gs)
- {
- return (is_gimple_assign (gs)
- && (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (gs))
- || gimple_assign_rhs_code (gs) == NON_LVALUE_EXPR)
- && gimple_assign_rhs1 (gs) != error_mark_node
- && (TYPE_MODE (TREE_TYPE (gimple_assign_lhs (gs)))
- == TYPE_MODE (TREE_TYPE (gimple_assign_rhs1 (gs)))));
- }
- /* Set BB to be the basic block holding G. */
- void
- gimple_set_bb (gimple stmt, basic_block bb)
- {
- stmt->bb = bb;
- if (gimple_code (stmt) != GIMPLE_LABEL)
- return;
- /* If the statement is a label, add the label to block-to-labels map
- so that we can speed up edge creation for GIMPLE_GOTOs. */
- if (cfun->cfg)
- {
- tree t;
- int uid;
- t = gimple_label_label (as_a <glabel *> (stmt));
- uid = LABEL_DECL_UID (t);
- if (uid == -1)
- {
- unsigned old_len =
- vec_safe_length (label_to_block_map_for_fn (cfun));
- LABEL_DECL_UID (t) = uid = cfun->cfg->last_label_uid++;
- if (old_len <= (unsigned) uid)
- {
- unsigned new_len = 3 * uid / 2 + 1;
- vec_safe_grow_cleared (label_to_block_map_for_fn (cfun),
- new_len);
- }
- }
- (*label_to_block_map_for_fn (cfun))[uid] = bb;
- }
- }
- /* Modify the RHS of the assignment pointed-to by GSI using the
- operands in the expression tree EXPR.
- NOTE: The statement pointed-to by GSI may be reallocated if it
- did not have enough operand slots.
- This function is useful to convert an existing tree expression into
- the flat representation used for the RHS of a GIMPLE assignment.
- It will reallocate memory as needed to expand or shrink the number
- of operand slots needed to represent EXPR.
- NOTE: If you find yourself building a tree and then calling this
- function, you are most certainly doing it the slow way. It is much
- better to build a new assignment or to use the function
- gimple_assign_set_rhs_with_ops, which does not require an
- expression tree to be built. */
- void
- gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *gsi, tree expr)
- {
- enum tree_code subcode;
- tree op1, op2, op3;
- extract_ops_from_tree_1 (expr, &subcode, &op1, &op2, &op3);
- gimple_assign_set_rhs_with_ops (gsi, subcode, op1, op2, op3);
- }
- /* Set the RHS of assignment statement pointed-to by GSI to CODE with
- operands OP1, OP2 and OP3.
- NOTE: The statement pointed-to by GSI may be reallocated if it
- did not have enough operand slots. */
- void
- gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code,
- tree op1, tree op2, tree op3)
- {
- unsigned new_rhs_ops = get_gimple_rhs_num_ops (code);
- gimple stmt = gsi_stmt (*gsi);
- /* If the new CODE needs more operands, allocate a new statement. */
- if (gimple_num_ops (stmt) < new_rhs_ops + 1)
- {
- tree lhs = gimple_assign_lhs (stmt);
- gimple new_stmt = gimple_alloc (gimple_code (stmt), new_rhs_ops + 1);
- memcpy (new_stmt, stmt, gimple_size (gimple_code (stmt)));
- gimple_init_singleton (new_stmt);
- gsi_replace (gsi, new_stmt, true);
- stmt = new_stmt;
- /* The LHS needs to be reset as this also changes the SSA name
- on the LHS. */
- gimple_assign_set_lhs (stmt, lhs);
- }
- gimple_set_num_ops (stmt, new_rhs_ops + 1);
- gimple_set_subcode (stmt, code);
- gimple_assign_set_rhs1 (stmt, op1);
- if (new_rhs_ops > 1)
- gimple_assign_set_rhs2 (stmt, op2);
- if (new_rhs_ops > 2)
- gimple_assign_set_rhs3 (stmt, op3);
- }
- /* Return the LHS of a statement that performs an assignment,
- either a GIMPLE_ASSIGN or a GIMPLE_CALL. Returns NULL_TREE
- for a call to a function that returns no value, or for a
- statement other than an assignment or a call. */
- tree
- gimple_get_lhs (const_gimple stmt)
- {
- enum gimple_code code = gimple_code (stmt);
- if (code == GIMPLE_ASSIGN)
- return gimple_assign_lhs (stmt);
- else if (code == GIMPLE_CALL)
- return gimple_call_lhs (stmt);
- else
- return NULL_TREE;
- }
- /* Set the LHS of a statement that performs an assignment,
- either a GIMPLE_ASSIGN or a GIMPLE_CALL. */
- void
- gimple_set_lhs (gimple stmt, tree lhs)
- {
- enum gimple_code code = gimple_code (stmt);
- if (code == GIMPLE_ASSIGN)
- gimple_assign_set_lhs (stmt, lhs);
- else if (code == GIMPLE_CALL)
- gimple_call_set_lhs (stmt, lhs);
- else
- gcc_unreachable ();
- }
- /* Return a deep copy of statement STMT. All the operands from STMT
- are reallocated and copied using unshare_expr. The DEF, USE, VDEF
- and VUSE operand arrays are set to empty in the new copy. The new
- copy isn't part of any sequence. */
- gimple
- gimple_copy (gimple stmt)
- {
- enum gimple_code code = gimple_code (stmt);
- unsigned num_ops = gimple_num_ops (stmt);
- gimple copy = gimple_alloc (code, num_ops);
- unsigned i;
- /* Shallow copy all the fields from STMT. */
- memcpy (copy, stmt, gimple_size (code));
- gimple_init_singleton (copy);
- /* If STMT has sub-statements, deep-copy them as well. */
- if (gimple_has_substatements (stmt))
- {
- gimple_seq new_seq;
- tree t;
- switch (gimple_code (stmt))
- {
- case GIMPLE_BIND:
- {
- gbind *bind_stmt = as_a <gbind *> (stmt);
- gbind *bind_copy = as_a <gbind *> (copy);
- new_seq = gimple_seq_copy (gimple_bind_body (bind_stmt));
- gimple_bind_set_body (bind_copy, new_seq);
- gimple_bind_set_vars (bind_copy,
- unshare_expr (gimple_bind_vars (bind_stmt)));
- gimple_bind_set_block (bind_copy, gimple_bind_block (bind_stmt));
- }
- break;
- case GIMPLE_CATCH:
- {
- gcatch *catch_stmt = as_a <gcatch *> (stmt);
- gcatch *catch_copy = as_a <gcatch *> (copy);
- new_seq = gimple_seq_copy (gimple_catch_handler (catch_stmt));
- gimple_catch_set_handler (catch_copy, new_seq);
- t = unshare_expr (gimple_catch_types (catch_stmt));
- gimple_catch_set_types (catch_copy, t);
- }
- break;
- case GIMPLE_EH_FILTER:
- {
- geh_filter *eh_filter_stmt = as_a <geh_filter *> (stmt);
- geh_filter *eh_filter_copy = as_a <geh_filter *> (copy);
- new_seq
- = gimple_seq_copy (gimple_eh_filter_failure (eh_filter_stmt));
- gimple_eh_filter_set_failure (eh_filter_copy, new_seq);
- t = unshare_expr (gimple_eh_filter_types (eh_filter_stmt));
- gimple_eh_filter_set_types (eh_filter_copy, t);
- }
- break;
- case GIMPLE_EH_ELSE:
- {
- geh_else *eh_else_stmt = as_a <geh_else *> (stmt);
- geh_else *eh_else_copy = as_a <geh_else *> (copy);
- new_seq = gimple_seq_copy (gimple_eh_else_n_body (eh_else_stmt));
- gimple_eh_else_set_n_body (eh_else_copy, new_seq);
- new_seq = gimple_seq_copy (gimple_eh_else_e_body (eh_else_stmt));
- gimple_eh_else_set_e_body (eh_else_copy, new_seq);
- }
- break;
- case GIMPLE_TRY:
- {
- gtry *try_stmt = as_a <gtry *> (stmt);
- gtry *try_copy = as_a <gtry *> (copy);
- new_seq = gimple_seq_copy (gimple_try_eval (try_stmt));
- gimple_try_set_eval (try_copy, new_seq);
- new_seq = gimple_seq_copy (gimple_try_cleanup (try_stmt));
- gimple_try_set_cleanup (try_copy, new_seq);
- }
- break;
- case GIMPLE_OMP_FOR:
- new_seq = gimple_seq_copy (gimple_omp_for_pre_body (stmt));
- gimple_omp_for_set_pre_body (copy, new_seq);
- t = unshare_expr (gimple_omp_for_clauses (stmt));
- gimple_omp_for_set_clauses (copy, t);
- {
- gomp_for *omp_for_copy = as_a <gomp_for *> (copy);
- omp_for_copy->iter = ggc_vec_alloc<gimple_omp_for_iter>
- ( gimple_omp_for_collapse (stmt));
- }
- for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
- {
- gimple_omp_for_set_cond (copy, i,
- gimple_omp_for_cond (stmt, i));
- gimple_omp_for_set_index (copy, i,
- gimple_omp_for_index (stmt, i));
- t = unshare_expr (gimple_omp_for_initial (stmt, i));
- gimple_omp_for_set_initial (copy, i, t);
- t = unshare_expr (gimple_omp_for_final (stmt, i));
- gimple_omp_for_set_final (copy, i, t);
- t = unshare_expr (gimple_omp_for_incr (stmt, i));
- gimple_omp_for_set_incr (copy, i, t);
- }
- goto copy_omp_body;
- case GIMPLE_OMP_PARALLEL:
- {
- gomp_parallel *omp_par_stmt = as_a <gomp_parallel *> (stmt);
- gomp_parallel *omp_par_copy = as_a <gomp_parallel *> (copy);
- t = unshare_expr (gimple_omp_parallel_clauses (omp_par_stmt));
- gimple_omp_parallel_set_clauses (omp_par_copy, t);
- t = unshare_expr (gimple_omp_parallel_child_fn (omp_par_stmt));
- gimple_omp_parallel_set_child_fn (omp_par_copy, t);
- t = unshare_expr (gimple_omp_parallel_data_arg (omp_par_stmt));
- gimple_omp_parallel_set_data_arg (omp_par_copy, t);
- }
- goto copy_omp_body;
- case GIMPLE_OMP_TASK:
- t = unshare_expr (gimple_omp_task_clauses (stmt));
- gimple_omp_task_set_clauses (copy, t);
- t = unshare_expr (gimple_omp_task_child_fn (stmt));
- gimple_omp_task_set_child_fn (copy, t);
- t = unshare_expr (gimple_omp_task_data_arg (stmt));
- gimple_omp_task_set_data_arg (copy, t);
- t = unshare_expr (gimple_omp_task_copy_fn (stmt));
- gimple_omp_task_set_copy_fn (copy, t);
- t = unshare_expr (gimple_omp_task_arg_size (stmt));
- gimple_omp_task_set_arg_size (copy, t);
- t = unshare_expr (gimple_omp_task_arg_align (stmt));
- gimple_omp_task_set_arg_align (copy, t);
- goto copy_omp_body;
- case GIMPLE_OMP_CRITICAL:
- t = unshare_expr (gimple_omp_critical_name (
- as_a <gomp_critical *> (stmt)));
- gimple_omp_critical_set_name (as_a <gomp_critical *> (copy), t);
- goto copy_omp_body;
- case GIMPLE_OMP_SECTIONS:
- t = unshare_expr (gimple_omp_sections_clauses (stmt));
- gimple_omp_sections_set_clauses (copy, t);
- t = unshare_expr (gimple_omp_sections_control (stmt));
- gimple_omp_sections_set_control (copy, t);
- /* FALLTHRU */
- case GIMPLE_OMP_SINGLE:
- case GIMPLE_OMP_TARGET:
- case GIMPLE_OMP_TEAMS:
- case GIMPLE_OMP_SECTION:
- case GIMPLE_OMP_MASTER:
- case GIMPLE_OMP_TASKGROUP:
- case GIMPLE_OMP_ORDERED:
- copy_omp_body:
- new_seq = gimple_seq_copy (gimple_omp_body (stmt));
- gimple_omp_set_body (copy, new_seq);
- break;
- case GIMPLE_TRANSACTION:
- new_seq = gimple_seq_copy (gimple_transaction_body (
- as_a <gtransaction *> (stmt)));
- gimple_transaction_set_body (as_a <gtransaction *> (copy),
- new_seq);
- break;
- case GIMPLE_WITH_CLEANUP_EXPR:
- new_seq = gimple_seq_copy (gimple_wce_cleanup (stmt));
- gimple_wce_set_cleanup (copy, new_seq);
- break;
- default:
- gcc_unreachable ();
- }
- }
- /* Make copy of operands. */
- for (i = 0; i < num_ops; i++)
- gimple_set_op (copy, i, unshare_expr (gimple_op (stmt, i)));
- if (gimple_has_mem_ops (stmt))
- {
- gimple_set_vdef (copy, gimple_vdef (stmt));
- gimple_set_vuse (copy, gimple_vuse (stmt));
- }
- /* Clear out SSA operand vectors on COPY. */
- if (gimple_has_ops (stmt))
- {
- gimple_set_use_ops (copy, NULL);
- /* SSA operands need to be updated. */
- gimple_set_modified (copy, true);
- }
- return copy;
- }
- /* Return true if statement S has side-effects. We consider a
- statement to have side effects if:
- - It is a GIMPLE_CALL not marked with ECF_PURE or ECF_CONST.
- - Any of its operands are marked TREE_THIS_VOLATILE or TREE_SIDE_EFFECTS. */
- bool
- gimple_has_side_effects (const_gimple s)
- {
- if (is_gimple_debug (s))
- return false;
- /* We don't have to scan the arguments to check for
- volatile arguments, though, at present, we still
- do a scan to check for TREE_SIDE_EFFECTS. */
- if (gimple_has_volatile_ops (s))
- return true;
- if (gimple_code (s) == GIMPLE_ASM
- && gimple_asm_volatile_p (as_a <const gasm *> (s)))
- return true;
- if (is_gimple_call (s))
- {
- int flags = gimple_call_flags (s);
- /* An infinite loop is considered a side effect. */
- if (!(flags & (ECF_CONST | ECF_PURE))
- || (flags & ECF_LOOPING_CONST_OR_PURE))
- return true;
- return false;
- }
- return false;
- }
- /* Helper for gimple_could_trap_p and gimple_assign_rhs_could_trap_p.
- Return true if S can trap. When INCLUDE_MEM is true, check whether
- the memory operations could trap. When INCLUDE_STORES is true and
- S is a GIMPLE_ASSIGN, the LHS of the assignment is also checked. */
- bool
- gimple_could_trap_p_1 (gimple s, bool include_mem, bool include_stores)
- {
- tree t, div = NULL_TREE;
- enum tree_code op;
- if (include_mem)
- {
- unsigned i, start = (is_gimple_assign (s) && !include_stores) ? 1 : 0;
- for (i = start; i < gimple_num_ops (s); i++)
- if (tree_could_trap_p (gimple_op (s, i)))
- return true;
- }
- switch (gimple_code (s))
- {
- case GIMPLE_ASM:
- return gimple_asm_volatile_p (as_a <gasm *> (s));
- case GIMPLE_CALL:
- t = gimple_call_fndecl (s);
- /* Assume that calls to weak functions may trap. */
- if (!t || !DECL_P (t) || DECL_WEAK (t))
- return true;
- return false;
- case GIMPLE_ASSIGN:
- t = gimple_expr_type (s);
- op = gimple_assign_rhs_code (s);
- if (get_gimple_rhs_class (op) == GIMPLE_BINARY_RHS)
- div = gimple_assign_rhs2 (s);
- return (operation_could_trap_p (op, FLOAT_TYPE_P (t),
- (INTEGRAL_TYPE_P (t)
- && TYPE_OVERFLOW_TRAPS (t)),
- div));
- default:
- break;
- }
- return false;
- }
- /* Return true if statement S can trap. */
- bool
- gimple_could_trap_p (gimple s)
- {
- return gimple_could_trap_p_1 (s, true, true);
- }
- /* Return true if RHS of a GIMPLE_ASSIGN S can trap. */
- bool
- gimple_assign_rhs_could_trap_p (gimple s)
- {
- gcc_assert (is_gimple_assign (s));
- return gimple_could_trap_p_1 (s, true, false);
- }
- /* Print debugging information for gimple stmts generated. */
- void
- dump_gimple_statistics (void)
- {
- int i, total_tuples = 0, total_bytes = 0;
- if (! GATHER_STATISTICS)
- {
- fprintf (stderr, "No gimple statistics\n");
- return;
- }
- fprintf (stderr, "\nGIMPLE statements\n");
- fprintf (stderr, "Kind Stmts Bytes\n");
- fprintf (stderr, "---------------------------------------\n");
- for (i = 0; i < (int) gimple_alloc_kind_all; ++i)
- {
- fprintf (stderr, "%-20s %7d %10d\n", gimple_alloc_kind_names[i],
- gimple_alloc_counts[i], gimple_alloc_sizes[i]);
- total_tuples += gimple_alloc_counts[i];
- total_bytes += gimple_alloc_sizes[i];
- }
- fprintf (stderr, "---------------------------------------\n");
- fprintf (stderr, "%-20s %7d %10d\n", "Total", total_tuples, total_bytes);
- fprintf (stderr, "---------------------------------------\n");
- }
- /* Return the number of operands needed on the RHS of a GIMPLE
- assignment for an expression with tree code CODE. */
- unsigned
- get_gimple_rhs_num_ops (enum tree_code code)
- {
- enum gimple_rhs_class rhs_class = get_gimple_rhs_class (code);
- if (rhs_class == GIMPLE_UNARY_RHS || rhs_class == GIMPLE_SINGLE_RHS)
- return 1;
- else if (rhs_class == GIMPLE_BINARY_RHS)
- return 2;
- else if (rhs_class == GIMPLE_TERNARY_RHS)
- return 3;
- else
- gcc_unreachable ();
- }
- #define DEFTREECODE(SYM, STRING, TYPE, NARGS) \
- (unsigned char) \
- ((TYPE) == tcc_unary ? GIMPLE_UNARY_RHS \
- : ((TYPE) == tcc_binary \
- || (TYPE) == tcc_comparison) ? GIMPLE_BINARY_RHS \
- : ((TYPE) == tcc_constant \
- || (TYPE) == tcc_declaration \
- || (TYPE) == tcc_reference) ? GIMPLE_SINGLE_RHS \
- : ((SYM) == TRUTH_AND_EXPR \
- || (SYM) == TRUTH_OR_EXPR \
- || (SYM) == TRUTH_XOR_EXPR) ? GIMPLE_BINARY_RHS \
- : (SYM) == TRUTH_NOT_EXPR ? GIMPLE_UNARY_RHS \
- : ((SYM) == COND_EXPR \
- || (SYM) == WIDEN_MULT_PLUS_EXPR \
- || (SYM) == WIDEN_MULT_MINUS_EXPR \
- || (SYM) == DOT_PROD_EXPR \
- || (SYM) == SAD_EXPR \
- || (SYM) == REALIGN_LOAD_EXPR \
- || (SYM) == VEC_COND_EXPR \
- || (SYM) == VEC_PERM_EXPR \
- || (SYM) == FMA_EXPR) ? GIMPLE_TERNARY_RHS \
- : ((SYM) == CONSTRUCTOR \
- || (SYM) == OBJ_TYPE_REF \
- || (SYM) == ASSERT_EXPR \
- || (SYM) == ADDR_EXPR \
- || (SYM) == WITH_SIZE_EXPR \
- || (SYM) == SSA_NAME) ? GIMPLE_SINGLE_RHS \
- : GIMPLE_INVALID_RHS),
- #define END_OF_BASE_TREE_CODES (unsigned char) GIMPLE_INVALID_RHS,
- const unsigned char gimple_rhs_class_table[] = {
- #include "all-tree.def"
- };
- #undef DEFTREECODE
- #undef END_OF_BASE_TREE_CODES
- /* Canonicalize a tree T for use in a COND_EXPR as conditional. Returns
- a canonicalized tree that is valid for a COND_EXPR or NULL_TREE, if
- we failed to create one. */
- tree
- canonicalize_cond_expr_cond (tree t)
- {
- /* Strip conversions around boolean operations. */
- if (CONVERT_EXPR_P (t)
- && (truth_value_p (TREE_CODE (TREE_OPERAND (t, 0)))
- || TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0)))
- == BOOLEAN_TYPE))
- t = TREE_OPERAND (t, 0);
- /* For !x use x == 0. */
- if (TREE_CODE (t) == TRUTH_NOT_EXPR)
- {
- tree top0 = TREE_OPERAND (t, 0);
- t = build2 (EQ_EXPR, TREE_TYPE (t),
- top0, build_int_cst (TREE_TYPE (top0), 0));
- }
- /* For cmp ? 1 : 0 use cmp. */
- else if (TREE_CODE (t) == COND_EXPR
- && COMPARISON_CLASS_P (TREE_OPERAND (t, 0))
- && integer_onep (TREE_OPERAND (t, 1))
- && integer_zerop (TREE_OPERAND (t, 2)))
- {
- tree top0 = TREE_OPERAND (t, 0);
- t = build2 (TREE_CODE (top0), TREE_TYPE (t),
- TREE_OPERAND (top0, 0), TREE_OPERAND (top0, 1));
- }
- /* For x ^ y use x != y. */
- else if (TREE_CODE (t) == BIT_XOR_EXPR)
- t = build2 (NE_EXPR, TREE_TYPE (t),
- TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
-
- if (is_gimple_condexpr (t))
- return t;
- return NULL_TREE;
- }
- /* Build a GIMPLE_CALL identical to STMT but skipping the arguments in
- the positions marked by the set ARGS_TO_SKIP. */
- gcall *
- gimple_call_copy_skip_args (gcall *stmt, bitmap args_to_skip)
- {
- int i;
- int nargs = gimple_call_num_args (stmt);
- auto_vec<tree> vargs (nargs);
- gcall *new_stmt;
- for (i = 0; i < nargs; i++)
- if (!bitmap_bit_p (args_to_skip, i))
- vargs.quick_push (gimple_call_arg (stmt, i));
- if (gimple_call_internal_p (stmt))
- new_stmt = gimple_build_call_internal_vec (gimple_call_internal_fn (stmt),
- vargs);
- else
- new_stmt = gimple_build_call_vec (gimple_call_fn (stmt), vargs);
- if (gimple_call_lhs (stmt))
- gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt));
- gimple_set_vuse (new_stmt, gimple_vuse (stmt));
- gimple_set_vdef (new_stmt, gimple_vdef (stmt));
- if (gimple_has_location (stmt))
- gimple_set_location (new_stmt, gimple_location (stmt));
- gimple_call_copy_flags (new_stmt, stmt);
- gimple_call_set_chain (new_stmt, gimple_call_chain (stmt));
- gimple_set_modified (new_stmt, true);
- return new_stmt;
- }
- /* Return true if the field decls F1 and F2 are at the same offset.
- This is intended to be used on GIMPLE types only. */
- bool
- gimple_compare_field_offset (tree f1, tree f2)
- {
- if (DECL_OFFSET_ALIGN (f1) == DECL_OFFSET_ALIGN (f2))
- {
- tree offset1 = DECL_FIELD_OFFSET (f1);
- tree offset2 = DECL_FIELD_OFFSET (f2);
- return ((offset1 == offset2
- /* Once gimplification is done, self-referential offsets are
- instantiated as operand #2 of the COMPONENT_REF built for
- each access and reset. Therefore, they are not relevant
- anymore and fields are interchangeable provided that they
- represent the same access. */
- || (TREE_CODE (offset1) == PLACEHOLDER_EXPR
- && TREE_CODE (offset2) == PLACEHOLDER_EXPR
- && (DECL_SIZE (f1) == DECL_SIZE (f2)
- || (TREE_CODE (DECL_SIZE (f1)) == PLACEHOLDER_EXPR
- && TREE_CODE (DECL_SIZE (f2)) == PLACEHOLDER_EXPR)
- || operand_equal_p (DECL_SIZE (f1), DECL_SIZE (f2), 0))
- && DECL_ALIGN (f1) == DECL_ALIGN (f2))
- || operand_equal_p (offset1, offset2, 0))
- && tree_int_cst_equal (DECL_FIELD_BIT_OFFSET (f1),
- DECL_FIELD_BIT_OFFSET (f2)));
- }
- /* Fortran and C do not always agree on what DECL_OFFSET_ALIGN
- should be, so handle differing ones specially by decomposing
- the offset into a byte and bit offset manually. */
- if (tree_fits_shwi_p (DECL_FIELD_OFFSET (f1))
- && tree_fits_shwi_p (DECL_FIELD_OFFSET (f2)))
- {
- unsigned HOST_WIDE_INT byte_offset1, byte_offset2;
- unsigned HOST_WIDE_INT bit_offset1, bit_offset2;
- bit_offset1 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (f1));
- byte_offset1 = (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f1))
- + bit_offset1 / BITS_PER_UNIT);
- bit_offset2 = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (f2));
- byte_offset2 = (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f2))
- + bit_offset2 / BITS_PER_UNIT);
- if (byte_offset1 != byte_offset2)
- return false;
- return bit_offset1 % BITS_PER_UNIT == bit_offset2 % BITS_PER_UNIT;
- }
- return false;
- }
- /* Return a type the same as TYPE except unsigned or
- signed according to UNSIGNEDP. */
- static tree
- gimple_signed_or_unsigned_type (bool unsignedp, tree type)
- {
- tree type1;
- int i;
- type1 = TYPE_MAIN_VARIANT (type);
- if (type1 == signed_char_type_node
- || type1 == char_type_node
- || type1 == unsigned_char_type_node)
- return unsignedp ? unsigned_char_type_node : signed_char_type_node;
- if (type1 == integer_type_node || type1 == unsigned_type_node)
- return unsignedp ? unsigned_type_node : integer_type_node;
- if (type1 == short_integer_type_node || type1 == short_unsigned_type_node)
- return unsignedp ? short_unsigned_type_node : short_integer_type_node;
- if (type1 == long_integer_type_node || type1 == long_unsigned_type_node)
- return unsignedp ? long_unsigned_type_node : long_integer_type_node;
- if (type1 == long_long_integer_type_node
- || type1 == long_long_unsigned_type_node)
- return unsignedp
- ? long_long_unsigned_type_node
- : long_long_integer_type_node;
- for (i = 0; i < NUM_INT_N_ENTS; i ++)
- if (int_n_enabled_p[i]
- && (type1 == int_n_trees[i].unsigned_type
- || type1 == int_n_trees[i].signed_type))
- return unsignedp
- ? int_n_trees[i].unsigned_type
- : int_n_trees[i].signed_type;
- #if HOST_BITS_PER_WIDE_INT >= 64
- if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
- return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
- #endif
- if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node)
- return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
- if (type1 == intSI_type_node || type1 == unsigned_intSI_type_node)
- return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
- if (type1 == intHI_type_node || type1 == unsigned_intHI_type_node)
- return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
- if (type1 == intQI_type_node || type1 == unsigned_intQI_type_node)
- return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
- #define GIMPLE_FIXED_TYPES(NAME) \
- if (type1 == short_ ## NAME ## _type_node \
- || type1 == unsigned_short_ ## NAME ## _type_node) \
- return unsignedp ? unsigned_short_ ## NAME ## _type_node \
- : short_ ## NAME ## _type_node; \
- if (type1 == NAME ## _type_node \
- || type1 == unsigned_ ## NAME ## _type_node) \
- return unsignedp ? unsigned_ ## NAME ## _type_node \
- : NAME ## _type_node; \
- if (type1 == long_ ## NAME ## _type_node \
- || type1 == unsigned_long_ ## NAME ## _type_node) \
- return unsignedp ? unsigned_long_ ## NAME ## _type_node \
- : long_ ## NAME ## _type_node; \
- if (type1 == long_long_ ## NAME ## _type_node \
- || type1 == unsigned_long_long_ ## NAME ## _type_node) \
- return unsignedp ? unsigned_long_long_ ## NAME ## _type_node \
- : long_long_ ## NAME ## _type_node;
- #define GIMPLE_FIXED_MODE_TYPES(NAME) \
- if (type1 == NAME ## _type_node \
- || type1 == u ## NAME ## _type_node) \
- return unsignedp ? u ## NAME ## _type_node \
- : NAME ## _type_node;
- #define GIMPLE_FIXED_TYPES_SAT(NAME) \
- if (type1 == sat_ ## short_ ## NAME ## _type_node \
- || type1 == sat_ ## unsigned_short_ ## NAME ## _type_node) \
- return unsignedp ? sat_ ## unsigned_short_ ## NAME ## _type_node \
- : sat_ ## short_ ## NAME ## _type_node; \
- if (type1 == sat_ ## NAME ## _type_node \
- || type1 == sat_ ## unsigned_ ## NAME ## _type_node) \
- return unsignedp ? sat_ ## unsigned_ ## NAME ## _type_node \
- : sat_ ## NAME ## _type_node; \
- if (type1 == sat_ ## long_ ## NAME ## _type_node \
- || type1 == sat_ ## unsigned_long_ ## NAME ## _type_node) \
- return unsignedp ? sat_ ## unsigned_long_ ## NAME ## _type_node \
- : sat_ ## long_ ## NAME ## _type_node; \
- if (type1 == sat_ ## long_long_ ## NAME ## _type_node \
- || type1 == sat_ ## unsigned_long_long_ ## NAME ## _type_node) \
- return unsignedp ? sat_ ## unsigned_long_long_ ## NAME ## _type_node \
- : sat_ ## long_long_ ## NAME ## _type_node;
- #define GIMPLE_FIXED_MODE_TYPES_SAT(NAME) \
- if (type1 == sat_ ## NAME ## _type_node \
- || type1 == sat_ ## u ## NAME ## _type_node) \
- return unsignedp ? sat_ ## u ## NAME ## _type_node \
- : sat_ ## NAME ## _type_node;
- GIMPLE_FIXED_TYPES (fract);
- GIMPLE_FIXED_TYPES_SAT (fract);
- GIMPLE_FIXED_TYPES (accum);
- GIMPLE_FIXED_TYPES_SAT (accum);
- GIMPLE_FIXED_MODE_TYPES (qq);
- GIMPLE_FIXED_MODE_TYPES (hq);
- GIMPLE_FIXED_MODE_TYPES (sq);
- GIMPLE_FIXED_MODE_TYPES (dq);
- GIMPLE_FIXED_MODE_TYPES (tq);
- GIMPLE_FIXED_MODE_TYPES_SAT (qq);
- GIMPLE_FIXED_MODE_TYPES_SAT (hq);
- GIMPLE_FIXED_MODE_TYPES_SAT (sq);
- GIMPLE_FIXED_MODE_TYPES_SAT (dq);
- GIMPLE_FIXED_MODE_TYPES_SAT (tq);
- GIMPLE_FIXED_MODE_TYPES (ha);
- GIMPLE_FIXED_MODE_TYPES (sa);
- GIMPLE_FIXED_MODE_TYPES (da);
- GIMPLE_FIXED_MODE_TYPES (ta);
- GIMPLE_FIXED_MODE_TYPES_SAT (ha);
- GIMPLE_FIXED_MODE_TYPES_SAT (sa);
- GIMPLE_FIXED_MODE_TYPES_SAT (da);
- GIMPLE_FIXED_MODE_TYPES_SAT (ta);
- /* For ENUMERAL_TYPEs in C++, must check the mode of the types, not
- the precision; they have precision set to match their range, but
- may use a wider mode to match an ABI. If we change modes, we may
- wind up with bad conversions. For INTEGER_TYPEs in C, must check
- the precision as well, so as to yield correct results for
- bit-field types. C++ does not have these separate bit-field
- types, and producing a signed or unsigned variant of an
- ENUMERAL_TYPE may cause other problems as well. */
- if (!INTEGRAL_TYPE_P (type)
- || TYPE_UNSIGNED (type) == unsignedp)
- return type;
- #define TYPE_OK(node) \
- (TYPE_MODE (type) == TYPE_MODE (node) \
- && TYPE_PRECISION (type) == TYPE_PRECISION (node))
- if (TYPE_OK (signed_char_type_node))
- return unsignedp ? unsigned_char_type_node : signed_char_type_node;
- if (TYPE_OK (integer_type_node))
- return unsignedp ? unsigned_type_node : integer_type_node;
- if (TYPE_OK (short_integer_type_node))
- return unsignedp ? short_unsigned_type_node : short_integer_type_node;
- if (TYPE_OK (long_integer_type_node))
- return unsignedp ? long_unsigned_type_node : long_integer_type_node;
- if (TYPE_OK (long_long_integer_type_node))
- return (unsignedp
- ? long_long_unsigned_type_node
- : long_long_integer_type_node);
- for (i = 0; i < NUM_INT_N_ENTS; i ++)
- if (int_n_enabled_p[i]
- && TYPE_MODE (type) == int_n_data[i].m
- && TYPE_PRECISION (type) == int_n_data[i].bitsize)
- return unsignedp
- ? int_n_trees[i].unsigned_type
- : int_n_trees[i].signed_type;
- #if HOST_BITS_PER_WIDE_INT >= 64
- if (TYPE_OK (intTI_type_node))
- return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
- #endif
- if (TYPE_OK (intDI_type_node))
- return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
- if (TYPE_OK (intSI_type_node))
- return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
- if (TYPE_OK (intHI_type_node))
- return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
- if (TYPE_OK (intQI_type_node))
- return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
- #undef GIMPLE_FIXED_TYPES
- #undef GIMPLE_FIXED_MODE_TYPES
- #undef GIMPLE_FIXED_TYPES_SAT
- #undef GIMPLE_FIXED_MODE_TYPES_SAT
- #undef TYPE_OK
- return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
- }
- /* Return an unsigned type the same as TYPE in other respects. */
- tree
- gimple_unsigned_type (tree type)
- {
- return gimple_signed_or_unsigned_type (true, type);
- }
- /* Return a signed type the same as TYPE in other respects. */
- tree
- gimple_signed_type (tree type)
- {
- return gimple_signed_or_unsigned_type (false, type);
- }
- /* Return the typed-based alias set for T, which may be an expression
- or a type. Return -1 if we don't do anything special. */
- alias_set_type
- gimple_get_alias_set (tree t)
- {
- tree u;
- /* Permit type-punning when accessing a union, provided the access
- is directly through the union. For example, this code does not
- permit taking the address of a union member and then storing
- through it. Even the type-punning allowed here is a GCC
- extension, albeit a common and useful one; the C standard says
- that such accesses have implementation-defined behavior. */
- for (u = t;
- TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF;
- u = TREE_OPERAND (u, 0))
- if (TREE_CODE (u) == COMPONENT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
- return 0;
- /* That's all the expressions we handle specially. */
- if (!TYPE_P (t))
- return -1;
- /* For convenience, follow the C standard when dealing with
- character types. Any object may be accessed via an lvalue that
- has character type. */
- if (t == char_type_node
- || t == signed_char_type_node
- || t == unsigned_char_type_node)
- return 0;
- /* Allow aliasing between signed and unsigned variants of the same
- type. We treat the signed variant as canonical. */
- if (TREE_CODE (t) == INTEGER_TYPE && TYPE_UNSIGNED (t))
- {
- tree t1 = gimple_signed_type (t);
- /* t1 == t can happen for boolean nodes which are always unsigned. */
- if (t1 != t)
- return get_alias_set (t1);
- }
- return -1;
- }
- /* Helper for gimple_ior_addresses_taken_1. */
- static bool
- gimple_ior_addresses_taken_1 (gimple, tree addr, tree, void *data)
- {
- bitmap addresses_taken = (bitmap)data;
- addr = get_base_address (addr);
- if (addr
- && DECL_P (addr))
- {
- bitmap_set_bit (addresses_taken, DECL_UID (addr));
- return true;
- }
- return false;
- }
- /* Set the bit for the uid of all decls that have their address taken
- in STMT in the ADDRESSES_TAKEN bitmap. Returns true if there
- were any in this stmt. */
- bool
- gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt)
- {
- return walk_stmt_load_store_addr_ops (stmt, addresses_taken, NULL, NULL,
- gimple_ior_addresses_taken_1);
- }
- /* Return true if TYPE1 and TYPE2 are compatible enough for builtin
- processing. */
- static bool
- validate_type (tree type1, tree type2)
- {
- if (INTEGRAL_TYPE_P (type1)
- && INTEGRAL_TYPE_P (type2))
- ;
- else if (POINTER_TYPE_P (type1)
- && POINTER_TYPE_P (type2))
- ;
- else if (TREE_CODE (type1)
- != TREE_CODE (type2))
- return false;
- return true;
- }
- /* Return true when STMTs arguments and return value match those of FNDECL,
- a decl of a builtin function. */
- bool
- gimple_builtin_call_types_compatible_p (const_gimple stmt, tree fndecl)
- {
- gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN);
- tree ret = gimple_call_lhs (stmt);
- if (ret
- && !validate_type (TREE_TYPE (ret), TREE_TYPE (TREE_TYPE (fndecl))))
- return false;
- tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- unsigned nargs = gimple_call_num_args (stmt);
- for (unsigned i = 0; i < nargs; ++i)
- {
- /* Variadic args follow. */
- if (!targs)
- return true;
- tree arg = gimple_call_arg (stmt, i);
- if (!validate_type (TREE_TYPE (arg), TREE_VALUE (targs)))
- return false;
- targs = TREE_CHAIN (targs);
- }
- if (targs && !VOID_TYPE_P (TREE_VALUE (targs)))
- return false;
- return true;
- }
- /* Return true when STMT is builtins call. */
- bool
- gimple_call_builtin_p (const_gimple stmt)
- {
- tree fndecl;
- if (is_gimple_call (stmt)
- && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
- && DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN)
- return gimple_builtin_call_types_compatible_p (stmt, fndecl);
- return false;
- }
- /* Return true when STMT is builtins call to CLASS. */
- bool
- gimple_call_builtin_p (const_gimple stmt, enum built_in_class klass)
- {
- tree fndecl;
- if (is_gimple_call (stmt)
- && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
- && DECL_BUILT_IN_CLASS (fndecl) == klass)
- return gimple_builtin_call_types_compatible_p (stmt, fndecl);
- return false;
- }
- /* Return true when STMT is builtins call to CODE of CLASS. */
- bool
- gimple_call_builtin_p (const_gimple stmt, enum built_in_function code)
- {
- tree fndecl;
- if (is_gimple_call (stmt)
- && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE
- && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
- && DECL_FUNCTION_CODE (fndecl) == code)
- return gimple_builtin_call_types_compatible_p (stmt, fndecl);
- return false;
- }
- /* Return true if STMT clobbers memory. STMT is required to be a
- GIMPLE_ASM. */
- bool
- gimple_asm_clobbers_memory_p (const gasm *stmt)
- {
- unsigned i;
- for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
- {
- tree op = gimple_asm_clobber_op (stmt, i);
- if (strcmp (TREE_STRING_POINTER (TREE_VALUE (op)), "memory") == 0)
- return true;
- }
- return false;
- }
- /* Dump bitmap SET (assumed to contain VAR_DECLs) to FILE. */
- void
- dump_decl_set (FILE *file, bitmap set)
- {
- if (set)
- {
- bitmap_iterator bi;
- unsigned i;
- fprintf (file, "{ ");
- EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
- {
- fprintf (file, "D.%u", i);
- fprintf (file, " ");
- }
- fprintf (file, "}");
- }
- else
- fprintf (file, "NIL");
- }
- /* Return true when CALL is a call stmt that definitely doesn't
- free any memory or makes it unavailable otherwise. */
- bool
- nonfreeing_call_p (gimple call)
- {
- if (gimple_call_builtin_p (call, BUILT_IN_NORMAL)
- && gimple_call_flags (call) & ECF_LEAF)
- switch (DECL_FUNCTION_CODE (gimple_call_fndecl (call)))
- {
- /* Just in case these become ECF_LEAF in the future. */
- case BUILT_IN_FREE:
- case BUILT_IN_TM_FREE:
- case BUILT_IN_REALLOC:
- case BUILT_IN_STACK_RESTORE:
- return false;
- default:
- return true;
- }
- else if (gimple_call_internal_p (call))
- switch (gimple_call_internal_fn (call))
- {
- case IFN_ABNORMAL_DISPATCHER:
- return true;
- default:
- if (gimple_call_flags (call) & ECF_LEAF)
- return true;
- return false;
- }
- tree fndecl = gimple_call_fndecl (call);
- if (!fndecl)
- return false;
- struct cgraph_node *n = cgraph_node::get (fndecl);
- if (!n)
- return false;
- enum availability availability;
- n = n->function_symbol (&availability);
- if (!n || availability <= AVAIL_INTERPOSABLE)
- return false;
- return n->nonfreeing_fn;
- }
- /* Callback for walk_stmt_load_store_ops.
-
- Return TRUE if OP will dereference the tree stored in DATA, FALSE
- otherwise.
- This routine only makes a superficial check for a dereference. Thus
- it must only be used if it is safe to return a false negative. */
- static bool
- check_loadstore (gimple, tree op, tree, void *data)
- {
- if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
- && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))
- return true;
- return false;
- }
- /* If OP can be inferred to be non-NULL after STMT executes, return true.
- DEREFERENCE is TRUE if we can use a pointer dereference to infer a
- non-NULL range, FALSE otherwise.
- ATTRIBUTE is TRUE if we can use attributes to infer a non-NULL range
- for function arguments and return values. FALSE otherwise. */
- bool
- infer_nonnull_range (gimple stmt, tree op, bool dereference, bool attribute)
- {
- /* We can only assume that a pointer dereference will yield
- non-NULL if -fdelete-null-pointer-checks is enabled. */
- if (!flag_delete_null_pointer_checks
- || !POINTER_TYPE_P (TREE_TYPE (op))
- || gimple_code (stmt) == GIMPLE_ASM)
- return false;
- if (dereference
- && walk_stmt_load_store_ops (stmt, (void *)op,
- check_loadstore, check_loadstore))
- return true;
- if (attribute
- && is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
- {
- tree fntype = gimple_call_fntype (stmt);
- tree attrs = TYPE_ATTRIBUTES (fntype);
- for (; attrs; attrs = TREE_CHAIN (attrs))
- {
- attrs = lookup_attribute ("nonnull", attrs);
- /* If "nonnull" wasn't specified, we know nothing about
- the argument. */
- if (attrs == NULL_TREE)
- return false;
- /* If "nonnull" applies to all the arguments, then ARG
- is non-null if it's in the argument list. */
- if (TREE_VALUE (attrs) == NULL_TREE)
- {
- for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
- {
- if (POINTER_TYPE_P (TREE_TYPE (gimple_call_arg (stmt, i)))
- && operand_equal_p (op, gimple_call_arg (stmt, i), 0))
- return true;
- }
- return false;
- }
- /* Now see if op appears in the nonnull list. */
- for (tree t = TREE_VALUE (attrs); t; t = TREE_CHAIN (t))
- {
- int idx = TREE_INT_CST_LOW (TREE_VALUE (t)) - 1;
- tree arg = gimple_call_arg (stmt, idx);
- if (operand_equal_p (op, arg, 0))
- return true;
- }
- }
- }
- /* If this function is marked as returning non-null, then we can
- infer OP is non-null if it is used in the return statement. */
- if (attribute)
- if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
- if (gimple_return_retval (return_stmt)
- && operand_equal_p (gimple_return_retval (return_stmt), op, 0)
- && lookup_attribute ("returns_nonnull",
- TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
- return true;
- return false;
- }
- /* Compare two case labels. Because the front end should already have
- made sure that case ranges do not overlap, it is enough to only compare
- the CASE_LOW values of each case label. */
- static int
- compare_case_labels (const void *p1, const void *p2)
- {
- const_tree const case1 = *(const_tree const*)p1;
- const_tree const case2 = *(const_tree const*)p2;
- /* The 'default' case label always goes first. */
- if (!CASE_LOW (case1))
- return -1;
- else if (!CASE_LOW (case2))
- return 1;
- else
- return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2));
- }
- /* Sort the case labels in LABEL_VEC in place in ascending order. */
- void
- sort_case_labels (vec<tree> label_vec)
- {
- label_vec.qsort (compare_case_labels);
- }
- /* Prepare a vector of case labels to be used in a GIMPLE_SWITCH statement.
- LABELS is a vector that contains all case labels to look at.
- INDEX_TYPE is the type of the switch index expression. Case labels
- in LABELS are discarded if their values are not in the value range
- covered by INDEX_TYPE. The remaining case label values are folded
- to INDEX_TYPE.
- If a default case exists in LABELS, it is removed from LABELS and
- returned in DEFAULT_CASEP. If no default case exists, but the
- case labels already cover the whole range of INDEX_TYPE, a default
- case is returned pointing to one of the existing case labels.
- Otherwise DEFAULT_CASEP is set to NULL_TREE.
- DEFAULT_CASEP may be NULL, in which case the above comment doesn't
- apply and no action is taken regardless of whether a default case is
- found or not. */
- void
- preprocess_case_label_vec_for_gimple (vec<tree> labels,
- tree index_type,
- tree *default_casep)
- {
- tree min_value, max_value;
- tree default_case = NULL_TREE;
- size_t i, len;
- i = 0;
- min_value = TYPE_MIN_VALUE (index_type);
- max_value = TYPE_MAX_VALUE (index_type);
- while (i < labels.length ())
- {
- tree elt = labels[i];
- tree low = CASE_LOW (elt);
- tree high = CASE_HIGH (elt);
- bool remove_element = FALSE;
- if (low)
- {
- gcc_checking_assert (TREE_CODE (low) == INTEGER_CST);
- gcc_checking_assert (!high || TREE_CODE (high) == INTEGER_CST);
- /* This is a non-default case label, i.e. it has a value.
- See if the case label is reachable within the range of
- the index type. Remove out-of-range case values. Turn
- case ranges into a canonical form (high > low strictly)
- and convert the case label values to the index type.
- NB: The type of gimple_switch_index() may be the promoted
- type, but the case labels retain the original type. */
- if (high)
- {
- /* This is a case range. Discard empty ranges.
- If the bounds or the range are equal, turn this
- into a simple (one-value) case. */
- int cmp = tree_int_cst_compare (high, low);
- if (cmp < 0)
- remove_element = TRUE;
- else if (cmp == 0)
- high = NULL_TREE;
- }
- if (! high)
- {
- /* If the simple case value is unreachable, ignore it. */
- if ((TREE_CODE (min_value) == INTEGER_CST
- && tree_int_cst_compare (low, min_value) < 0)
- || (TREE_CODE (max_value) == INTEGER_CST
- && tree_int_cst_compare (low, max_value) > 0))
- remove_element = TRUE;
- else
- low = fold_convert (index_type, low);
- }
- else
- {
- /* If the entire case range is unreachable, ignore it. */
- if ((TREE_CODE (min_value) == INTEGER_CST
- && tree_int_cst_compare (high, min_value) < 0)
- || (TREE_CODE (max_value) == INTEGER_CST
- && tree_int_cst_compare (low, max_value) > 0))
- remove_element = TRUE;
- else
- {
- /* If the lower bound is less than the index type's
- minimum value, truncate the range bounds. */
- if (TREE_CODE (min_value) == INTEGER_CST
- && tree_int_cst_compare (low, min_value) < 0)
- low = min_value;
- low = fold_convert (index_type, low);
- /* If the upper bound is greater than the index type's
- maximum value, truncate the range bounds. */
- if (TREE_CODE (max_value) == INTEGER_CST
- && tree_int_cst_compare (high, max_value) > 0)
- high = max_value;
- high = fold_convert (index_type, high);
- /* We may have folded a case range to a one-value case. */
- if (tree_int_cst_equal (low, high))
- high = NULL_TREE;
- }
- }
- CASE_LOW (elt) = low;
- CASE_HIGH (elt) = high;
- }
- else
- {
- gcc_assert (!default_case);
- default_case = elt;
- /* The default case must be passed separately to the
- gimple_build_switch routine. But if DEFAULT_CASEP
- is NULL, we do not remove the default case (it would
- be completely lost). */
- if (default_casep)
- remove_element = TRUE;
- }
- if (remove_element)
- labels.ordered_remove (i);
- else
- i++;
- }
- len = i;
- if (!labels.is_empty ())
- sort_case_labels (labels);
- if (default_casep && !default_case)
- {
- /* If the switch has no default label, add one, so that we jump
- around the switch body. If the labels already cover the whole
- range of the switch index_type, add the default label pointing
- to one of the existing labels. */
- if (len
- && TYPE_MIN_VALUE (index_type)
- && TYPE_MAX_VALUE (index_type)
- && tree_int_cst_equal (CASE_LOW (labels[0]),
- TYPE_MIN_VALUE (index_type)))
- {
- tree low, high = CASE_HIGH (labels[len - 1]);
- if (!high)
- high = CASE_LOW (labels[len - 1]);
- if (tree_int_cst_equal (high, TYPE_MAX_VALUE (index_type)))
- {
- for (i = 1; i < len; i++)
- {
- high = CASE_LOW (labels[i]);
- low = CASE_HIGH (labels[i - 1]);
- if (!low)
- low = CASE_LOW (labels[i - 1]);
- if (wi::add (low, 1) != high)
- break;
- }
- if (i == len)
- {
- tree label = CASE_LABEL (labels[0]);
- default_case = build_case_label (NULL_TREE, NULL_TREE,
- label);
- }
- }
- }
- }
- if (default_casep)
- *default_casep = default_case;
- }
- /* Set the location of all statements in SEQ to LOC. */
- void
- gimple_seq_set_location (gimple_seq seq, location_t loc)
- {
- for (gimple_stmt_iterator i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
- gimple_set_location (gsi_stmt (i), loc);
- }
- /* Release SSA_NAMEs in SEQ as well as the GIMPLE statements. */
- void
- gimple_seq_discard (gimple_seq seq)
- {
- gimple_stmt_iterator gsi;
- for (gsi = gsi_start (seq); !gsi_end_p (gsi); )
- {
- gimple stmt = gsi_stmt (gsi);
- gsi_remove (&gsi, true);
- release_defs (stmt);
- ggc_free (stmt);
- }
- }
- /* See if STMT now calls function that takes no parameters and if so, drop
- call arguments. This is used when devirtualization machinery redirects
- to __builtiln_unreacahble or __cxa_pure_virutal. */
- void
- maybe_remove_unused_call_args (struct function *fn, gimple stmt)
- {
- tree decl = gimple_call_fndecl (stmt);
- if (TYPE_ARG_TYPES (TREE_TYPE (decl))
- && TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl))) == void_type_node
- && gimple_call_num_args (stmt))
- {
- gimple_set_num_ops (stmt, 3);
- update_stmt_fn (fn, stmt);
- }
- }
|