aarch64-builtins.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521
  1. /* Builtins' description for AArch64 SIMD architecture.
  2. Copyright (C) 2011-2015 Free Software Foundation, Inc.
  3. Contributed by ARM Ltd.
  4. This file is part of GCC.
  5. GCC is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3, or (at your option)
  8. any later version.
  9. GCC is distributed in the hope that it will be useful, but
  10. WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GCC; see the file COPYING3. If not see
  15. <http://www.gnu.org/licenses/>. */
  16. #include "config.h"
  17. #include "system.h"
  18. #include "coretypes.h"
  19. #include "tm.h"
  20. #include "rtl.h"
  21. #include "hash-set.h"
  22. #include "machmode.h"
  23. #include "vec.h"
  24. #include "double-int.h"
  25. #include "input.h"
  26. #include "alias.h"
  27. #include "symtab.h"
  28. #include "wide-int.h"
  29. #include "inchash.h"
  30. #include "tree.h"
  31. #include "fold-const.h"
  32. #include "stor-layout.h"
  33. #include "stringpool.h"
  34. #include "calls.h"
  35. #include "hashtab.h"
  36. #include "hard-reg-set.h"
  37. #include "function.h"
  38. #include "flags.h"
  39. #include "statistics.h"
  40. #include "real.h"
  41. #include "fixed-value.h"
  42. #include "insn-config.h"
  43. #include "expmed.h"
  44. #include "dojump.h"
  45. #include "explow.h"
  46. #include "emit-rtl.h"
  47. #include "varasm.h"
  48. #include "stmt.h"
  49. #include "expr.h"
  50. #include "tm_p.h"
  51. #include "recog.h"
  52. #include "langhooks.h"
  53. #include "diagnostic-core.h"
  54. #include "insn-codes.h"
  55. #include "optabs.h"
  56. #include "hash-table.h"
  57. #include "ggc.h"
  58. #include "predict.h"
  59. #include "dominance.h"
  60. #include "cfg.h"
  61. #include "cfgrtl.h"
  62. #include "cfganal.h"
  63. #include "lcm.h"
  64. #include "cfgbuild.h"
  65. #include "cfgcleanup.h"
  66. #include "basic-block.h"
  67. #include "tree-ssa-alias.h"
  68. #include "internal-fn.h"
  69. #include "gimple-fold.h"
  70. #include "tree-eh.h"
  71. #include "gimple-expr.h"
  72. #include "is-a.h"
  73. #include "gimple.h"
  74. #include "gimple-iterator.h"
  75. #define v8qi_UP V8QImode
  76. #define v4hi_UP V4HImode
  77. #define v2si_UP V2SImode
  78. #define v2sf_UP V2SFmode
  79. #define v1df_UP V1DFmode
  80. #define di_UP DImode
  81. #define df_UP DFmode
  82. #define v16qi_UP V16QImode
  83. #define v8hi_UP V8HImode
  84. #define v4si_UP V4SImode
  85. #define v4sf_UP V4SFmode
  86. #define v2di_UP V2DImode
  87. #define v2df_UP V2DFmode
  88. #define ti_UP TImode
  89. #define ei_UP EImode
  90. #define oi_UP OImode
  91. #define ci_UP CImode
  92. #define xi_UP XImode
  93. #define si_UP SImode
  94. #define sf_UP SFmode
  95. #define hi_UP HImode
  96. #define qi_UP QImode
  97. #define UP(X) X##_UP
  98. #define SIMD_MAX_BUILTIN_ARGS 5
  99. enum aarch64_type_qualifiers
  100. {
  101. /* T foo. */
  102. qualifier_none = 0x0,
  103. /* unsigned T foo. */
  104. qualifier_unsigned = 0x1, /* 1 << 0 */
  105. /* const T foo. */
  106. qualifier_const = 0x2, /* 1 << 1 */
  107. /* T *foo. */
  108. qualifier_pointer = 0x4, /* 1 << 2 */
  109. /* Used when expanding arguments if an operand could
  110. be an immediate. */
  111. qualifier_immediate = 0x8, /* 1 << 3 */
  112. qualifier_maybe_immediate = 0x10, /* 1 << 4 */
  113. /* void foo (...). */
  114. qualifier_void = 0x20, /* 1 << 5 */
  115. /* Some patterns may have internal operands, this qualifier is an
  116. instruction to the initialisation code to skip this operand. */
  117. qualifier_internal = 0x40, /* 1 << 6 */
  118. /* Some builtins should use the T_*mode* encoded in a simd_builtin_datum
  119. rather than using the type of the operand. */
  120. qualifier_map_mode = 0x80, /* 1 << 7 */
  121. /* qualifier_pointer | qualifier_map_mode */
  122. qualifier_pointer_map_mode = 0x84,
  123. /* qualifier_const | qualifier_pointer | qualifier_map_mode */
  124. qualifier_const_pointer_map_mode = 0x86,
  125. /* Polynomial types. */
  126. qualifier_poly = 0x100,
  127. /* Lane indices - must be in range, and flipped for bigendian. */
  128. qualifier_lane_index = 0x200
  129. };
  130. typedef struct
  131. {
  132. const char *name;
  133. machine_mode mode;
  134. const enum insn_code code;
  135. unsigned int fcode;
  136. enum aarch64_type_qualifiers *qualifiers;
  137. } aarch64_simd_builtin_datum;
  138. static enum aarch64_type_qualifiers
  139. aarch64_types_unop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  140. = { qualifier_none, qualifier_none };
  141. #define TYPES_UNOP (aarch64_types_unop_qualifiers)
  142. static enum aarch64_type_qualifiers
  143. aarch64_types_unopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  144. = { qualifier_unsigned, qualifier_unsigned };
  145. #define TYPES_UNOPU (aarch64_types_unopu_qualifiers)
  146. static enum aarch64_type_qualifiers
  147. aarch64_types_binop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  148. = { qualifier_none, qualifier_none, qualifier_maybe_immediate };
  149. #define TYPES_BINOP (aarch64_types_binop_qualifiers)
  150. static enum aarch64_type_qualifiers
  151. aarch64_types_binopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  152. = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned };
  153. #define TYPES_BINOPU (aarch64_types_binopu_qualifiers)
  154. static enum aarch64_type_qualifiers
  155. aarch64_types_binop_uus_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  156. = { qualifier_unsigned, qualifier_unsigned, qualifier_none };
  157. #define TYPES_BINOP_UUS (aarch64_types_binop_uus_qualifiers)
  158. static enum aarch64_type_qualifiers
  159. aarch64_types_binop_ssu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  160. = { qualifier_none, qualifier_none, qualifier_unsigned };
  161. #define TYPES_BINOP_SSU (aarch64_types_binop_ssu_qualifiers)
  162. static enum aarch64_type_qualifiers
  163. aarch64_types_binopp_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  164. = { qualifier_poly, qualifier_poly, qualifier_poly };
  165. #define TYPES_BINOPP (aarch64_types_binopp_qualifiers)
  166. static enum aarch64_type_qualifiers
  167. aarch64_types_ternop_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  168. = { qualifier_none, qualifier_none, qualifier_none, qualifier_none };
  169. #define TYPES_TERNOP (aarch64_types_ternop_qualifiers)
  170. static enum aarch64_type_qualifiers
  171. aarch64_types_ternop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  172. = { qualifier_none, qualifier_none, qualifier_none, qualifier_lane_index };
  173. #define TYPES_TERNOP_LANE (aarch64_types_ternop_lane_qualifiers)
  174. static enum aarch64_type_qualifiers
  175. aarch64_types_ternopu_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  176. = { qualifier_unsigned, qualifier_unsigned,
  177. qualifier_unsigned, qualifier_unsigned };
  178. #define TYPES_TERNOPU (aarch64_types_ternopu_qualifiers)
  179. static enum aarch64_type_qualifiers
  180. aarch64_types_quadop_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  181. = { qualifier_none, qualifier_none, qualifier_none,
  182. qualifier_none, qualifier_lane_index };
  183. #define TYPES_QUADOP_LANE (aarch64_types_quadop_lane_qualifiers)
  184. static enum aarch64_type_qualifiers
  185. aarch64_types_binop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  186. = { qualifier_none, qualifier_none, qualifier_immediate };
  187. #define TYPES_GETREG (aarch64_types_binop_imm_qualifiers)
  188. #define TYPES_SHIFTIMM (aarch64_types_binop_imm_qualifiers)
  189. static enum aarch64_type_qualifiers
  190. aarch64_types_shift_to_unsigned_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  191. = { qualifier_unsigned, qualifier_none, qualifier_immediate };
  192. #define TYPES_SHIFTIMM_USS (aarch64_types_shift_to_unsigned_qualifiers)
  193. static enum aarch64_type_qualifiers
  194. aarch64_types_unsigned_shift_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  195. = { qualifier_unsigned, qualifier_unsigned, qualifier_immediate };
  196. #define TYPES_USHIFTIMM (aarch64_types_unsigned_shift_qualifiers)
  197. static enum aarch64_type_qualifiers
  198. aarch64_types_ternop_imm_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  199. = { qualifier_none, qualifier_none, qualifier_none, qualifier_immediate };
  200. #define TYPES_SETREG (aarch64_types_ternop_imm_qualifiers)
  201. #define TYPES_SHIFTINSERT (aarch64_types_ternop_imm_qualifiers)
  202. #define TYPES_SHIFTACC (aarch64_types_ternop_imm_qualifiers)
  203. static enum aarch64_type_qualifiers
  204. aarch64_types_unsigned_shiftacc_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  205. = { qualifier_unsigned, qualifier_unsigned, qualifier_unsigned,
  206. qualifier_immediate };
  207. #define TYPES_USHIFTACC (aarch64_types_unsigned_shiftacc_qualifiers)
  208. static enum aarch64_type_qualifiers
  209. aarch64_types_combine_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  210. = { qualifier_none, qualifier_none, qualifier_none };
  211. #define TYPES_COMBINE (aarch64_types_combine_qualifiers)
  212. static enum aarch64_type_qualifiers
  213. aarch64_types_load1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  214. = { qualifier_none, qualifier_const_pointer_map_mode };
  215. #define TYPES_LOAD1 (aarch64_types_load1_qualifiers)
  216. #define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers)
  217. static enum aarch64_type_qualifiers
  218. aarch64_types_loadstruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  219. = { qualifier_none, qualifier_const_pointer_map_mode,
  220. qualifier_none, qualifier_none };
  221. #define TYPES_LOADSTRUCT_LANE (aarch64_types_loadstruct_lane_qualifiers)
  222. static enum aarch64_type_qualifiers
  223. aarch64_types_bsl_p_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  224. = { qualifier_poly, qualifier_unsigned,
  225. qualifier_poly, qualifier_poly };
  226. #define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers)
  227. static enum aarch64_type_qualifiers
  228. aarch64_types_bsl_s_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  229. = { qualifier_none, qualifier_unsigned,
  230. qualifier_none, qualifier_none };
  231. #define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers)
  232. static enum aarch64_type_qualifiers
  233. aarch64_types_bsl_u_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  234. = { qualifier_unsigned, qualifier_unsigned,
  235. qualifier_unsigned, qualifier_unsigned };
  236. #define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers)
  237. /* The first argument (return type) of a store should be void type,
  238. which we represent with qualifier_void. Their first operand will be
  239. a DImode pointer to the location to store to, so we must use
  240. qualifier_map_mode | qualifier_pointer to build a pointer to the
  241. element type of the vector. */
  242. static enum aarch64_type_qualifiers
  243. aarch64_types_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  244. = { qualifier_void, qualifier_pointer_map_mode, qualifier_none };
  245. #define TYPES_STORE1 (aarch64_types_store1_qualifiers)
  246. #define TYPES_STORESTRUCT (aarch64_types_store1_qualifiers)
  247. static enum aarch64_type_qualifiers
  248. aarch64_types_storestruct_lane_qualifiers[SIMD_MAX_BUILTIN_ARGS]
  249. = { qualifier_void, qualifier_pointer_map_mode,
  250. qualifier_none, qualifier_none };
  251. #define TYPES_STORESTRUCT_LANE (aarch64_types_storestruct_lane_qualifiers)
  252. #define CF0(N, X) CODE_FOR_aarch64_##N##X
  253. #define CF1(N, X) CODE_FOR_##N##X##1
  254. #define CF2(N, X) CODE_FOR_##N##X##2
  255. #define CF3(N, X) CODE_FOR_##N##X##3
  256. #define CF4(N, X) CODE_FOR_##N##X##4
  257. #define CF10(N, X) CODE_FOR_##N##X
  258. #define VAR1(T, N, MAP, A) \
  259. {#N #A, UP (A), CF##MAP (N, A), 0, TYPES_##T},
  260. #define VAR2(T, N, MAP, A, B) \
  261. VAR1 (T, N, MAP, A) \
  262. VAR1 (T, N, MAP, B)
  263. #define VAR3(T, N, MAP, A, B, C) \
  264. VAR2 (T, N, MAP, A, B) \
  265. VAR1 (T, N, MAP, C)
  266. #define VAR4(T, N, MAP, A, B, C, D) \
  267. VAR3 (T, N, MAP, A, B, C) \
  268. VAR1 (T, N, MAP, D)
  269. #define VAR5(T, N, MAP, A, B, C, D, E) \
  270. VAR4 (T, N, MAP, A, B, C, D) \
  271. VAR1 (T, N, MAP, E)
  272. #define VAR6(T, N, MAP, A, B, C, D, E, F) \
  273. VAR5 (T, N, MAP, A, B, C, D, E) \
  274. VAR1 (T, N, MAP, F)
  275. #define VAR7(T, N, MAP, A, B, C, D, E, F, G) \
  276. VAR6 (T, N, MAP, A, B, C, D, E, F) \
  277. VAR1 (T, N, MAP, G)
  278. #define VAR8(T, N, MAP, A, B, C, D, E, F, G, H) \
  279. VAR7 (T, N, MAP, A, B, C, D, E, F, G) \
  280. VAR1 (T, N, MAP, H)
  281. #define VAR9(T, N, MAP, A, B, C, D, E, F, G, H, I) \
  282. VAR8 (T, N, MAP, A, B, C, D, E, F, G, H) \
  283. VAR1 (T, N, MAP, I)
  284. #define VAR10(T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
  285. VAR9 (T, N, MAP, A, B, C, D, E, F, G, H, I) \
  286. VAR1 (T, N, MAP, J)
  287. #define VAR11(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
  288. VAR10 (T, N, MAP, A, B, C, D, E, F, G, H, I, J) \
  289. VAR1 (T, N, MAP, K)
  290. #define VAR12(T, N, MAP, A, B, C, D, E, F, G, H, I, J, K, L) \
  291. VAR11 (T, N, MAP, A, B, C, D, E, F, G, H, I, J, K) \
  292. VAR1 (T, N, MAP, L)
  293. #include "aarch64-builtin-iterators.h"
  294. static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = {
  295. #include "aarch64-simd-builtins.def"
  296. };
  297. /* There's only 8 CRC32 builtins. Probably not worth their own .def file. */
  298. #define AARCH64_CRC32_BUILTINS \
  299. CRC32_BUILTIN (crc32b, QI) \
  300. CRC32_BUILTIN (crc32h, HI) \
  301. CRC32_BUILTIN (crc32w, SI) \
  302. CRC32_BUILTIN (crc32x, DI) \
  303. CRC32_BUILTIN (crc32cb, QI) \
  304. CRC32_BUILTIN (crc32ch, HI) \
  305. CRC32_BUILTIN (crc32cw, SI) \
  306. CRC32_BUILTIN (crc32cx, DI)
  307. typedef struct
  308. {
  309. const char *name;
  310. machine_mode mode;
  311. const enum insn_code icode;
  312. unsigned int fcode;
  313. } aarch64_crc_builtin_datum;
  314. #define CRC32_BUILTIN(N, M) \
  315. AARCH64_BUILTIN_##N,
  316. #undef VAR1
  317. #define VAR1(T, N, MAP, A) \
  318. AARCH64_SIMD_BUILTIN_##T##_##N##A,
  319. enum aarch64_builtins
  320. {
  321. AARCH64_BUILTIN_MIN,
  322. AARCH64_BUILTIN_GET_FPCR,
  323. AARCH64_BUILTIN_SET_FPCR,
  324. AARCH64_BUILTIN_GET_FPSR,
  325. AARCH64_BUILTIN_SET_FPSR,
  326. AARCH64_SIMD_BUILTIN_BASE,
  327. AARCH64_SIMD_BUILTIN_LANE_CHECK,
  328. #include "aarch64-simd-builtins.def"
  329. /* The first enum element which is based on an insn_data pattern. */
  330. AARCH64_SIMD_PATTERN_START = AARCH64_SIMD_BUILTIN_LANE_CHECK + 1,
  331. AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_PATTERN_START
  332. + ARRAY_SIZE (aarch64_simd_builtin_data) - 1,
  333. AARCH64_CRC32_BUILTIN_BASE,
  334. AARCH64_CRC32_BUILTINS
  335. AARCH64_CRC32_BUILTIN_MAX,
  336. AARCH64_BUILTIN_MAX
  337. };
  338. #undef CRC32_BUILTIN
  339. #define CRC32_BUILTIN(N, M) \
  340. {"__builtin_aarch64_"#N, M##mode, CODE_FOR_aarch64_##N, AARCH64_BUILTIN_##N},
  341. static aarch64_crc_builtin_datum aarch64_crc_builtin_data[] = {
  342. AARCH64_CRC32_BUILTINS
  343. };
  344. #undef CRC32_BUILTIN
  345. static GTY(()) tree aarch64_builtin_decls[AARCH64_BUILTIN_MAX];
  346. #define NUM_DREG_TYPES 6
  347. #define NUM_QREG_TYPES 6
  348. /* Internal scalar builtin types. These types are used to support
  349. neon intrinsic builtins. They are _not_ user-visible types. Therefore
  350. the mangling for these types are implementation defined. */
  351. const char *aarch64_scalar_builtin_types[] = {
  352. "__builtin_aarch64_simd_qi",
  353. "__builtin_aarch64_simd_hi",
  354. "__builtin_aarch64_simd_si",
  355. "__builtin_aarch64_simd_sf",
  356. "__builtin_aarch64_simd_di",
  357. "__builtin_aarch64_simd_df",
  358. "__builtin_aarch64_simd_poly8",
  359. "__builtin_aarch64_simd_poly16",
  360. "__builtin_aarch64_simd_poly64",
  361. "__builtin_aarch64_simd_poly128",
  362. "__builtin_aarch64_simd_ti",
  363. "__builtin_aarch64_simd_uqi",
  364. "__builtin_aarch64_simd_uhi",
  365. "__builtin_aarch64_simd_usi",
  366. "__builtin_aarch64_simd_udi",
  367. "__builtin_aarch64_simd_ei",
  368. "__builtin_aarch64_simd_oi",
  369. "__builtin_aarch64_simd_ci",
  370. "__builtin_aarch64_simd_xi",
  371. NULL
  372. };
  373. #define ENTRY(E, M, Q, G) E,
  374. enum aarch64_simd_type
  375. {
  376. #include "aarch64-simd-builtin-types.def"
  377. ARM_NEON_H_TYPES_LAST
  378. };
  379. #undef ENTRY
  380. struct aarch64_simd_type_info
  381. {
  382. enum aarch64_simd_type type;
  383. /* Internal type name. */
  384. const char *name;
  385. /* Internal type name(mangled). The mangled names conform to the
  386. AAPCS64 (see "Procedure Call Standard for the ARM 64-bit Architecture",
  387. Appendix A). To qualify for emission with the mangled names defined in
  388. that document, a vector type must not only be of the correct mode but also
  389. be of the correct internal AdvSIMD vector type (e.g. __Int8x8_t); these
  390. types are registered by aarch64_init_simd_builtin_types (). In other
  391. words, vector types defined in other ways e.g. via vector_size attribute
  392. will get default mangled names. */
  393. const char *mangle;
  394. /* Internal type. */
  395. tree itype;
  396. /* Element type. */
  397. tree eltype;
  398. /* Machine mode the internal type maps to. */
  399. enum machine_mode mode;
  400. /* Qualifiers. */
  401. enum aarch64_type_qualifiers q;
  402. };
  403. #define ENTRY(E, M, Q, G) \
  404. {E, "__" #E, #G "__" #E, NULL_TREE, NULL_TREE, M##mode, qualifier_##Q},
  405. static struct aarch64_simd_type_info aarch64_simd_types [] = {
  406. #include "aarch64-simd-builtin-types.def"
  407. };
  408. #undef ENTRY
  409. static tree aarch64_simd_intOI_type_node = NULL_TREE;
  410. static tree aarch64_simd_intEI_type_node = NULL_TREE;
  411. static tree aarch64_simd_intCI_type_node = NULL_TREE;
  412. static tree aarch64_simd_intXI_type_node = NULL_TREE;
  413. static const char *
  414. aarch64_mangle_builtin_scalar_type (const_tree type)
  415. {
  416. int i = 0;
  417. while (aarch64_scalar_builtin_types[i] != NULL)
  418. {
  419. const char *name = aarch64_scalar_builtin_types[i];
  420. if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
  421. && DECL_NAME (TYPE_NAME (type))
  422. && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))), name))
  423. return aarch64_scalar_builtin_types[i];
  424. i++;
  425. }
  426. return NULL;
  427. }
  428. static const char *
  429. aarch64_mangle_builtin_vector_type (const_tree type)
  430. {
  431. int i;
  432. int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
  433. for (i = 0; i < nelts; i++)
  434. if (aarch64_simd_types[i].mode == TYPE_MODE (type)
  435. && TYPE_NAME (type)
  436. && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
  437. && DECL_NAME (TYPE_NAME (type))
  438. && !strcmp
  439. (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))),
  440. aarch64_simd_types[i].name))
  441. return aarch64_simd_types[i].mangle;
  442. return NULL;
  443. }
  444. const char *
  445. aarch64_mangle_builtin_type (const_tree type)
  446. {
  447. const char *mangle;
  448. /* Walk through all the AArch64 builtins types tables to filter out the
  449. incoming type. */
  450. if ((mangle = aarch64_mangle_builtin_vector_type (type))
  451. || (mangle = aarch64_mangle_builtin_scalar_type (type)))
  452. return mangle;
  453. return NULL;
  454. }
  455. static tree
  456. aarch64_simd_builtin_std_type (enum machine_mode mode,
  457. enum aarch64_type_qualifiers q)
  458. {
  459. #define QUAL_TYPE(M) \
  460. ((q == qualifier_none) ? int##M##_type_node : unsigned_int##M##_type_node);
  461. switch (mode)
  462. {
  463. case QImode:
  464. return QUAL_TYPE (QI);
  465. case HImode:
  466. return QUAL_TYPE (HI);
  467. case SImode:
  468. return QUAL_TYPE (SI);
  469. case DImode:
  470. return QUAL_TYPE (DI);
  471. case TImode:
  472. return QUAL_TYPE (TI);
  473. case OImode:
  474. return aarch64_simd_intOI_type_node;
  475. case EImode:
  476. return aarch64_simd_intEI_type_node;
  477. case CImode:
  478. return aarch64_simd_intCI_type_node;
  479. case XImode:
  480. return aarch64_simd_intXI_type_node;
  481. case SFmode:
  482. return float_type_node;
  483. case DFmode:
  484. return double_type_node;
  485. default:
  486. gcc_unreachable ();
  487. }
  488. #undef QUAL_TYPE
  489. }
  490. static tree
  491. aarch64_lookup_simd_builtin_type (enum machine_mode mode,
  492. enum aarch64_type_qualifiers q)
  493. {
  494. int i;
  495. int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
  496. /* Non-poly scalar modes map to standard types not in the table. */
  497. if (q != qualifier_poly && !VECTOR_MODE_P (mode))
  498. return aarch64_simd_builtin_std_type (mode, q);
  499. for (i = 0; i < nelts; i++)
  500. if (aarch64_simd_types[i].mode == mode
  501. && aarch64_simd_types[i].q == q)
  502. return aarch64_simd_types[i].itype;
  503. return NULL_TREE;
  504. }
  505. static tree
  506. aarch64_simd_builtin_type (enum machine_mode mode,
  507. bool unsigned_p, bool poly_p)
  508. {
  509. if (poly_p)
  510. return aarch64_lookup_simd_builtin_type (mode, qualifier_poly);
  511. else if (unsigned_p)
  512. return aarch64_lookup_simd_builtin_type (mode, qualifier_unsigned);
  513. else
  514. return aarch64_lookup_simd_builtin_type (mode, qualifier_none);
  515. }
  516. static void
  517. aarch64_init_simd_builtin_types (void)
  518. {
  519. int i;
  520. int nelts = sizeof (aarch64_simd_types) / sizeof (aarch64_simd_types[0]);
  521. tree tdecl;
  522. /* Init all the element types built by the front-end. */
  523. aarch64_simd_types[Int8x8_t].eltype = intQI_type_node;
  524. aarch64_simd_types[Int8x16_t].eltype = intQI_type_node;
  525. aarch64_simd_types[Int16x4_t].eltype = intHI_type_node;
  526. aarch64_simd_types[Int16x8_t].eltype = intHI_type_node;
  527. aarch64_simd_types[Int32x2_t].eltype = intSI_type_node;
  528. aarch64_simd_types[Int32x4_t].eltype = intSI_type_node;
  529. aarch64_simd_types[Int64x1_t].eltype = intDI_type_node;
  530. aarch64_simd_types[Int64x2_t].eltype = intDI_type_node;
  531. aarch64_simd_types[Uint8x8_t].eltype = unsigned_intQI_type_node;
  532. aarch64_simd_types[Uint8x16_t].eltype = unsigned_intQI_type_node;
  533. aarch64_simd_types[Uint16x4_t].eltype = unsigned_intHI_type_node;
  534. aarch64_simd_types[Uint16x8_t].eltype = unsigned_intHI_type_node;
  535. aarch64_simd_types[Uint32x2_t].eltype = unsigned_intSI_type_node;
  536. aarch64_simd_types[Uint32x4_t].eltype = unsigned_intSI_type_node;
  537. aarch64_simd_types[Uint64x1_t].eltype = unsigned_intDI_type_node;
  538. aarch64_simd_types[Uint64x2_t].eltype = unsigned_intDI_type_node;
  539. /* Poly types are a world of their own. */
  540. aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
  541. build_distinct_type_copy (unsigned_intQI_type_node);
  542. aarch64_simd_types[Poly16_t].eltype = aarch64_simd_types[Poly16_t].itype =
  543. build_distinct_type_copy (unsigned_intHI_type_node);
  544. aarch64_simd_types[Poly64_t].eltype = aarch64_simd_types[Poly64_t].itype =
  545. build_distinct_type_copy (unsigned_intDI_type_node);
  546. aarch64_simd_types[Poly128_t].eltype = aarch64_simd_types[Poly128_t].itype =
  547. build_distinct_type_copy (unsigned_intTI_type_node);
  548. /* Init poly vector element types with scalar poly types. */
  549. aarch64_simd_types[Poly8x8_t].eltype = aarch64_simd_types[Poly8_t].itype;
  550. aarch64_simd_types[Poly8x16_t].eltype = aarch64_simd_types[Poly8_t].itype;
  551. aarch64_simd_types[Poly16x4_t].eltype = aarch64_simd_types[Poly16_t].itype;
  552. aarch64_simd_types[Poly16x8_t].eltype = aarch64_simd_types[Poly16_t].itype;
  553. aarch64_simd_types[Poly64x1_t].eltype = aarch64_simd_types[Poly64_t].itype;
  554. aarch64_simd_types[Poly64x2_t].eltype = aarch64_simd_types[Poly64_t].itype;
  555. /* Continue with standard types. */
  556. aarch64_simd_types[Float32x2_t].eltype = float_type_node;
  557. aarch64_simd_types[Float32x4_t].eltype = float_type_node;
  558. aarch64_simd_types[Float64x1_t].eltype = double_type_node;
  559. aarch64_simd_types[Float64x2_t].eltype = double_type_node;
  560. for (i = 0; i < nelts; i++)
  561. {
  562. tree eltype = aarch64_simd_types[i].eltype;
  563. enum machine_mode mode = aarch64_simd_types[i].mode;
  564. if (aarch64_simd_types[i].itype == NULL)
  565. aarch64_simd_types[i].itype =
  566. build_distinct_type_copy
  567. (build_vector_type (eltype, GET_MODE_NUNITS (mode)));
  568. tdecl = add_builtin_type (aarch64_simd_types[i].name,
  569. aarch64_simd_types[i].itype);
  570. TYPE_NAME (aarch64_simd_types[i].itype) = tdecl;
  571. SET_TYPE_STRUCTURAL_EQUALITY (aarch64_simd_types[i].itype);
  572. }
  573. #define AARCH64_BUILD_SIGNED_TYPE(mode) \
  574. make_signed_type (GET_MODE_PRECISION (mode));
  575. aarch64_simd_intOI_type_node = AARCH64_BUILD_SIGNED_TYPE (OImode);
  576. aarch64_simd_intEI_type_node = AARCH64_BUILD_SIGNED_TYPE (EImode);
  577. aarch64_simd_intCI_type_node = AARCH64_BUILD_SIGNED_TYPE (CImode);
  578. aarch64_simd_intXI_type_node = AARCH64_BUILD_SIGNED_TYPE (XImode);
  579. #undef AARCH64_BUILD_SIGNED_TYPE
  580. tdecl = add_builtin_type
  581. ("__builtin_aarch64_simd_ei" , aarch64_simd_intEI_type_node);
  582. TYPE_NAME (aarch64_simd_intEI_type_node) = tdecl;
  583. tdecl = add_builtin_type
  584. ("__builtin_aarch64_simd_oi" , aarch64_simd_intOI_type_node);
  585. TYPE_NAME (aarch64_simd_intOI_type_node) = tdecl;
  586. tdecl = add_builtin_type
  587. ("__builtin_aarch64_simd_ci" , aarch64_simd_intCI_type_node);
  588. TYPE_NAME (aarch64_simd_intCI_type_node) = tdecl;
  589. tdecl = add_builtin_type
  590. ("__builtin_aarch64_simd_xi" , aarch64_simd_intXI_type_node);
  591. TYPE_NAME (aarch64_simd_intXI_type_node) = tdecl;
  592. }
  593. static void
  594. aarch64_init_simd_builtin_scalar_types (void)
  595. {
  596. /* Define typedefs for all the standard scalar types. */
  597. (*lang_hooks.types.register_builtin_type) (intQI_type_node,
  598. "__builtin_aarch64_simd_qi");
  599. (*lang_hooks.types.register_builtin_type) (intHI_type_node,
  600. "__builtin_aarch64_simd_hi");
  601. (*lang_hooks.types.register_builtin_type) (intSI_type_node,
  602. "__builtin_aarch64_simd_si");
  603. (*lang_hooks.types.register_builtin_type) (float_type_node,
  604. "__builtin_aarch64_simd_sf");
  605. (*lang_hooks.types.register_builtin_type) (intDI_type_node,
  606. "__builtin_aarch64_simd_di");
  607. (*lang_hooks.types.register_builtin_type) (double_type_node,
  608. "__builtin_aarch64_simd_df");
  609. (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
  610. "__builtin_aarch64_simd_poly8");
  611. (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
  612. "__builtin_aarch64_simd_poly16");
  613. (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
  614. "__builtin_aarch64_simd_poly64");
  615. (*lang_hooks.types.register_builtin_type) (unsigned_intTI_type_node,
  616. "__builtin_aarch64_simd_poly128");
  617. (*lang_hooks.types.register_builtin_type) (intTI_type_node,
  618. "__builtin_aarch64_simd_ti");
  619. /* Unsigned integer types for various mode sizes. */
  620. (*lang_hooks.types.register_builtin_type) (unsigned_intQI_type_node,
  621. "__builtin_aarch64_simd_uqi");
  622. (*lang_hooks.types.register_builtin_type) (unsigned_intHI_type_node,
  623. "__builtin_aarch64_simd_uhi");
  624. (*lang_hooks.types.register_builtin_type) (unsigned_intSI_type_node,
  625. "__builtin_aarch64_simd_usi");
  626. (*lang_hooks.types.register_builtin_type) (unsigned_intDI_type_node,
  627. "__builtin_aarch64_simd_udi");
  628. }
  629. static void
  630. aarch64_init_simd_builtins (void)
  631. {
  632. unsigned int i, fcode = AARCH64_SIMD_PATTERN_START;
  633. aarch64_init_simd_builtin_types ();
  634. /* Strong-typing hasn't been implemented for all AdvSIMD builtin intrinsics.
  635. Therefore we need to preserve the old __builtin scalar types. It can be
  636. removed once all the intrinsics become strongly typed using the qualifier
  637. system. */
  638. aarch64_init_simd_builtin_scalar_types ();
  639. tree lane_check_fpr = build_function_type_list (void_type_node,
  640. size_type_node,
  641. size_type_node,
  642. intSI_type_node,
  643. NULL);
  644. aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_LANE_CHECK] =
  645. add_builtin_function ("__builtin_aarch64_im_lane_boundsi", lane_check_fpr,
  646. AARCH64_SIMD_BUILTIN_LANE_CHECK, BUILT_IN_MD,
  647. NULL, NULL_TREE);
  648. for (i = 0; i < ARRAY_SIZE (aarch64_simd_builtin_data); i++, fcode++)
  649. {
  650. bool print_type_signature_p = false;
  651. char type_signature[SIMD_MAX_BUILTIN_ARGS] = { 0 };
  652. aarch64_simd_builtin_datum *d = &aarch64_simd_builtin_data[i];
  653. char namebuf[60];
  654. tree ftype = NULL;
  655. tree fndecl = NULL;
  656. d->fcode = fcode;
  657. /* We must track two variables here. op_num is
  658. the operand number as in the RTL pattern. This is
  659. required to access the mode (e.g. V4SF mode) of the
  660. argument, from which the base type can be derived.
  661. arg_num is an index in to the qualifiers data, which
  662. gives qualifiers to the type (e.g. const unsigned).
  663. The reason these two variables may differ by one is the
  664. void return type. While all return types take the 0th entry
  665. in the qualifiers array, there is no operand for them in the
  666. RTL pattern. */
  667. int op_num = insn_data[d->code].n_operands - 1;
  668. int arg_num = d->qualifiers[0] & qualifier_void
  669. ? op_num + 1
  670. : op_num;
  671. tree return_type = void_type_node, args = void_list_node;
  672. tree eltype;
  673. /* Build a function type directly from the insn_data for this
  674. builtin. The build_function_type () function takes care of
  675. removing duplicates for us. */
  676. for (; op_num >= 0; arg_num--, op_num--)
  677. {
  678. machine_mode op_mode = insn_data[d->code].operand[op_num].mode;
  679. enum aarch64_type_qualifiers qualifiers = d->qualifiers[arg_num];
  680. if (qualifiers & qualifier_unsigned)
  681. {
  682. type_signature[arg_num] = 'u';
  683. print_type_signature_p = true;
  684. }
  685. else if (qualifiers & qualifier_poly)
  686. {
  687. type_signature[arg_num] = 'p';
  688. print_type_signature_p = true;
  689. }
  690. else
  691. type_signature[arg_num] = 's';
  692. /* Skip an internal operand for vget_{low, high}. */
  693. if (qualifiers & qualifier_internal)
  694. continue;
  695. /* Some builtins have different user-facing types
  696. for certain arguments, encoded in d->mode. */
  697. if (qualifiers & qualifier_map_mode)
  698. op_mode = d->mode;
  699. /* For pointers, we want a pointer to the basic type
  700. of the vector. */
  701. if (qualifiers & qualifier_pointer && VECTOR_MODE_P (op_mode))
  702. op_mode = GET_MODE_INNER (op_mode);
  703. eltype = aarch64_simd_builtin_type
  704. (op_mode,
  705. (qualifiers & qualifier_unsigned) != 0,
  706. (qualifiers & qualifier_poly) != 0);
  707. gcc_assert (eltype != NULL);
  708. /* Add qualifiers. */
  709. if (qualifiers & qualifier_const)
  710. eltype = build_qualified_type (eltype, TYPE_QUAL_CONST);
  711. if (qualifiers & qualifier_pointer)
  712. eltype = build_pointer_type (eltype);
  713. /* If we have reached arg_num == 0, we are at a non-void
  714. return type. Otherwise, we are still processing
  715. arguments. */
  716. if (arg_num == 0)
  717. return_type = eltype;
  718. else
  719. args = tree_cons (NULL_TREE, eltype, args);
  720. }
  721. ftype = build_function_type (return_type, args);
  722. gcc_assert (ftype != NULL);
  723. if (print_type_signature_p)
  724. snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s_%s",
  725. d->name, type_signature);
  726. else
  727. snprintf (namebuf, sizeof (namebuf), "__builtin_aarch64_%s",
  728. d->name);
  729. fndecl = add_builtin_function (namebuf, ftype, fcode, BUILT_IN_MD,
  730. NULL, NULL_TREE);
  731. aarch64_builtin_decls[fcode] = fndecl;
  732. }
  733. }
  734. static void
  735. aarch64_init_crc32_builtins ()
  736. {
  737. tree usi_type = aarch64_simd_builtin_std_type (SImode, qualifier_unsigned);
  738. unsigned int i = 0;
  739. for (i = 0; i < ARRAY_SIZE (aarch64_crc_builtin_data); ++i)
  740. {
  741. aarch64_crc_builtin_datum* d = &aarch64_crc_builtin_data[i];
  742. tree argtype = aarch64_simd_builtin_std_type (d->mode,
  743. qualifier_unsigned);
  744. tree ftype = build_function_type_list (usi_type, usi_type, argtype, NULL_TREE);
  745. tree fndecl = add_builtin_function (d->name, ftype, d->fcode,
  746. BUILT_IN_MD, NULL, NULL_TREE);
  747. aarch64_builtin_decls[d->fcode] = fndecl;
  748. }
  749. }
  750. void
  751. aarch64_init_builtins (void)
  752. {
  753. tree ftype_set_fpr
  754. = build_function_type_list (void_type_node, unsigned_type_node, NULL);
  755. tree ftype_get_fpr
  756. = build_function_type_list (unsigned_type_node, NULL);
  757. aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR]
  758. = add_builtin_function ("__builtin_aarch64_get_fpcr", ftype_get_fpr,
  759. AARCH64_BUILTIN_GET_FPCR, BUILT_IN_MD, NULL, NULL_TREE);
  760. aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR]
  761. = add_builtin_function ("__builtin_aarch64_set_fpcr", ftype_set_fpr,
  762. AARCH64_BUILTIN_SET_FPCR, BUILT_IN_MD, NULL, NULL_TREE);
  763. aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR]
  764. = add_builtin_function ("__builtin_aarch64_get_fpsr", ftype_get_fpr,
  765. AARCH64_BUILTIN_GET_FPSR, BUILT_IN_MD, NULL, NULL_TREE);
  766. aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR]
  767. = add_builtin_function ("__builtin_aarch64_set_fpsr", ftype_set_fpr,
  768. AARCH64_BUILTIN_SET_FPSR, BUILT_IN_MD, NULL, NULL_TREE);
  769. if (TARGET_SIMD)
  770. aarch64_init_simd_builtins ();
  771. if (TARGET_CRC32)
  772. aarch64_init_crc32_builtins ();
  773. }
  774. tree
  775. aarch64_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
  776. {
  777. if (code >= AARCH64_BUILTIN_MAX)
  778. return error_mark_node;
  779. return aarch64_builtin_decls[code];
  780. }
  781. typedef enum
  782. {
  783. SIMD_ARG_COPY_TO_REG,
  784. SIMD_ARG_CONSTANT,
  785. SIMD_ARG_LANE_INDEX,
  786. SIMD_ARG_STOP
  787. } builtin_simd_arg;
  788. static rtx
  789. aarch64_simd_expand_args (rtx target, int icode, int have_retval,
  790. tree exp, builtin_simd_arg *args)
  791. {
  792. rtx pat;
  793. rtx op[SIMD_MAX_BUILTIN_ARGS + 1]; /* First element for result operand. */
  794. int opc = 0;
  795. if (have_retval)
  796. {
  797. machine_mode tmode = insn_data[icode].operand[0].mode;
  798. if (!target
  799. || GET_MODE (target) != tmode
  800. || !(*insn_data[icode].operand[0].predicate) (target, tmode))
  801. target = gen_reg_rtx (tmode);
  802. op[opc++] = target;
  803. }
  804. for (;;)
  805. {
  806. builtin_simd_arg thisarg = args[opc - have_retval];
  807. if (thisarg == SIMD_ARG_STOP)
  808. break;
  809. else
  810. {
  811. tree arg = CALL_EXPR_ARG (exp, opc - have_retval);
  812. enum machine_mode mode = insn_data[icode].operand[opc].mode;
  813. op[opc] = expand_normal (arg);
  814. switch (thisarg)
  815. {
  816. case SIMD_ARG_COPY_TO_REG:
  817. if (POINTER_TYPE_P (TREE_TYPE (arg)))
  818. op[opc] = convert_memory_address (Pmode, op[opc]);
  819. /*gcc_assert (GET_MODE (op[opc]) == mode); */
  820. if (!(*insn_data[icode].operand[opc].predicate)
  821. (op[opc], mode))
  822. op[opc] = copy_to_mode_reg (mode, op[opc]);
  823. break;
  824. case SIMD_ARG_LANE_INDEX:
  825. /* Must be a previous operand into which this is an index. */
  826. gcc_assert (opc > 0);
  827. if (CONST_INT_P (op[opc]))
  828. {
  829. machine_mode vmode = insn_data[icode].operand[opc - 1].mode;
  830. aarch64_simd_lane_bounds (op[opc],
  831. 0, GET_MODE_NUNITS (vmode), exp);
  832. /* Keep to GCC-vector-extension lane indices in the RTL. */
  833. op[opc] = GEN_INT (ENDIAN_LANE_N (vmode, INTVAL (op[opc])));
  834. }
  835. /* Fall through - if the lane index isn't a constant then
  836. the next case will error. */
  837. case SIMD_ARG_CONSTANT:
  838. if (!(*insn_data[icode].operand[opc].predicate)
  839. (op[opc], mode))
  840. {
  841. error ("%Kargument %d must be a constant immediate",
  842. exp, opc + 1 - have_retval);
  843. return const0_rtx;
  844. }
  845. break;
  846. case SIMD_ARG_STOP:
  847. gcc_unreachable ();
  848. }
  849. opc++;
  850. }
  851. }
  852. switch (opc)
  853. {
  854. case 1:
  855. pat = GEN_FCN (icode) (op[0]);
  856. break;
  857. case 2:
  858. pat = GEN_FCN (icode) (op[0], op[1]);
  859. break;
  860. case 3:
  861. pat = GEN_FCN (icode) (op[0], op[1], op[2]);
  862. break;
  863. case 4:
  864. pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
  865. break;
  866. case 5:
  867. pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4]);
  868. break;
  869. case 6:
  870. pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3], op[4], op[5]);
  871. break;
  872. default:
  873. gcc_unreachable ();
  874. }
  875. if (!pat)
  876. return NULL_RTX;
  877. emit_insn (pat);
  878. return target;
  879. }
  880. /* Expand an AArch64 AdvSIMD builtin(intrinsic). */
  881. rtx
  882. aarch64_simd_expand_builtin (int fcode, tree exp, rtx target)
  883. {
  884. if (fcode == AARCH64_SIMD_BUILTIN_LANE_CHECK)
  885. {
  886. rtx totalsize = expand_normal (CALL_EXPR_ARG (exp, 0));
  887. rtx elementsize = expand_normal (CALL_EXPR_ARG (exp, 1));
  888. if (CONST_INT_P (totalsize) && CONST_INT_P (elementsize)
  889. && UINTVAL (elementsize) != 0
  890. && UINTVAL (totalsize) != 0)
  891. {
  892. rtx lane_idx = expand_normal (CALL_EXPR_ARG (exp, 2));
  893. if (CONST_INT_P (lane_idx))
  894. aarch64_simd_lane_bounds (lane_idx, 0,
  895. UINTVAL (totalsize)
  896. / UINTVAL (elementsize),
  897. exp);
  898. else
  899. error ("%Klane index must be a constant immediate", exp);
  900. }
  901. else
  902. error ("%Ktotal size and element size must be a non-zero constant immediate", exp);
  903. /* Don't generate any RTL. */
  904. return const0_rtx;
  905. }
  906. aarch64_simd_builtin_datum *d =
  907. &aarch64_simd_builtin_data[fcode - AARCH64_SIMD_PATTERN_START];
  908. enum insn_code icode = d->code;
  909. builtin_simd_arg args[SIMD_MAX_BUILTIN_ARGS + 1];
  910. int num_args = insn_data[d->code].n_operands;
  911. int is_void = 0;
  912. int k;
  913. is_void = !!(d->qualifiers[0] & qualifier_void);
  914. num_args += is_void;
  915. for (k = 1; k < num_args; k++)
  916. {
  917. /* We have four arrays of data, each indexed in a different fashion.
  918. qualifiers - element 0 always describes the function return type.
  919. operands - element 0 is either the operand for return value (if
  920. the function has a non-void return type) or the operand for the
  921. first argument.
  922. expr_args - element 0 always holds the first argument.
  923. args - element 0 is always used for the return type. */
  924. int qualifiers_k = k;
  925. int operands_k = k - is_void;
  926. int expr_args_k = k - 1;
  927. if (d->qualifiers[qualifiers_k] & qualifier_lane_index)
  928. args[k] = SIMD_ARG_LANE_INDEX;
  929. else if (d->qualifiers[qualifiers_k] & qualifier_immediate)
  930. args[k] = SIMD_ARG_CONSTANT;
  931. else if (d->qualifiers[qualifiers_k] & qualifier_maybe_immediate)
  932. {
  933. rtx arg
  934. = expand_normal (CALL_EXPR_ARG (exp,
  935. (expr_args_k)));
  936. /* Handle constants only if the predicate allows it. */
  937. bool op_const_int_p =
  938. (CONST_INT_P (arg)
  939. && (*insn_data[icode].operand[operands_k].predicate)
  940. (arg, insn_data[icode].operand[operands_k].mode));
  941. args[k] = op_const_int_p ? SIMD_ARG_CONSTANT : SIMD_ARG_COPY_TO_REG;
  942. }
  943. else
  944. args[k] = SIMD_ARG_COPY_TO_REG;
  945. }
  946. args[k] = SIMD_ARG_STOP;
  947. /* The interface to aarch64_simd_expand_args expects a 0 if
  948. the function is void, and a 1 if it is not. */
  949. return aarch64_simd_expand_args
  950. (target, icode, !is_void, exp, &args[1]);
  951. }
  952. rtx
  953. aarch64_crc32_expand_builtin (int fcode, tree exp, rtx target)
  954. {
  955. rtx pat;
  956. aarch64_crc_builtin_datum *d
  957. = &aarch64_crc_builtin_data[fcode - (AARCH64_CRC32_BUILTIN_BASE + 1)];
  958. enum insn_code icode = d->icode;
  959. tree arg0 = CALL_EXPR_ARG (exp, 0);
  960. tree arg1 = CALL_EXPR_ARG (exp, 1);
  961. rtx op0 = expand_normal (arg0);
  962. rtx op1 = expand_normal (arg1);
  963. machine_mode tmode = insn_data[icode].operand[0].mode;
  964. machine_mode mode0 = insn_data[icode].operand[1].mode;
  965. machine_mode mode1 = insn_data[icode].operand[2].mode;
  966. if (! target
  967. || GET_MODE (target) != tmode
  968. || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
  969. target = gen_reg_rtx (tmode);
  970. gcc_assert ((GET_MODE (op0) == mode0 || GET_MODE (op0) == VOIDmode)
  971. && (GET_MODE (op1) == mode1 || GET_MODE (op1) == VOIDmode));
  972. if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
  973. op0 = copy_to_mode_reg (mode0, op0);
  974. if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
  975. op1 = copy_to_mode_reg (mode1, op1);
  976. pat = GEN_FCN (icode) (target, op0, op1);
  977. if (!pat)
  978. return NULL_RTX;
  979. emit_insn (pat);
  980. return target;
  981. }
  982. /* Expand an expression EXP that calls a built-in function,
  983. with result going to TARGET if that's convenient. */
  984. rtx
  985. aarch64_expand_builtin (tree exp,
  986. rtx target,
  987. rtx subtarget ATTRIBUTE_UNUSED,
  988. machine_mode mode ATTRIBUTE_UNUSED,
  989. int ignore ATTRIBUTE_UNUSED)
  990. {
  991. tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
  992. int fcode = DECL_FUNCTION_CODE (fndecl);
  993. int icode;
  994. rtx pat, op0;
  995. tree arg0;
  996. switch (fcode)
  997. {
  998. case AARCH64_BUILTIN_GET_FPCR:
  999. case AARCH64_BUILTIN_SET_FPCR:
  1000. case AARCH64_BUILTIN_GET_FPSR:
  1001. case AARCH64_BUILTIN_SET_FPSR:
  1002. if ((fcode == AARCH64_BUILTIN_GET_FPCR)
  1003. || (fcode == AARCH64_BUILTIN_GET_FPSR))
  1004. {
  1005. icode = (fcode == AARCH64_BUILTIN_GET_FPSR) ?
  1006. CODE_FOR_get_fpsr : CODE_FOR_get_fpcr;
  1007. target = gen_reg_rtx (SImode);
  1008. pat = GEN_FCN (icode) (target);
  1009. }
  1010. else
  1011. {
  1012. target = NULL_RTX;
  1013. icode = (fcode == AARCH64_BUILTIN_SET_FPSR) ?
  1014. CODE_FOR_set_fpsr : CODE_FOR_set_fpcr;
  1015. arg0 = CALL_EXPR_ARG (exp, 0);
  1016. op0 = expand_normal (arg0);
  1017. pat = GEN_FCN (icode) (op0);
  1018. }
  1019. emit_insn (pat);
  1020. return target;
  1021. }
  1022. if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX)
  1023. return aarch64_simd_expand_builtin (fcode, exp, target);
  1024. else if (fcode >= AARCH64_CRC32_BUILTIN_BASE && fcode <= AARCH64_CRC32_BUILTIN_MAX)
  1025. return aarch64_crc32_expand_builtin (fcode, exp, target);
  1026. gcc_unreachable ();
  1027. }
  1028. tree
  1029. aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in)
  1030. {
  1031. machine_mode in_mode, out_mode;
  1032. int in_n, out_n;
  1033. if (TREE_CODE (type_out) != VECTOR_TYPE
  1034. || TREE_CODE (type_in) != VECTOR_TYPE)
  1035. return NULL_TREE;
  1036. out_mode = TYPE_MODE (TREE_TYPE (type_out));
  1037. out_n = TYPE_VECTOR_SUBPARTS (type_out);
  1038. in_mode = TYPE_MODE (TREE_TYPE (type_in));
  1039. in_n = TYPE_VECTOR_SUBPARTS (type_in);
  1040. #undef AARCH64_CHECK_BUILTIN_MODE
  1041. #define AARCH64_CHECK_BUILTIN_MODE(C, N) 1
  1042. #define AARCH64_FIND_FRINT_VARIANT(N) \
  1043. (AARCH64_CHECK_BUILTIN_MODE (2, D) \
  1044. ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \
  1045. : (AARCH64_CHECK_BUILTIN_MODE (4, S) \
  1046. ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \
  1047. : (AARCH64_CHECK_BUILTIN_MODE (2, S) \
  1048. ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \
  1049. : NULL_TREE)))
  1050. if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
  1051. {
  1052. enum built_in_function fn = DECL_FUNCTION_CODE (fndecl);
  1053. switch (fn)
  1054. {
  1055. #undef AARCH64_CHECK_BUILTIN_MODE
  1056. #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
  1057. (out_mode == N##Fmode && out_n == C \
  1058. && in_mode == N##Fmode && in_n == C)
  1059. case BUILT_IN_FLOOR:
  1060. case BUILT_IN_FLOORF:
  1061. return AARCH64_FIND_FRINT_VARIANT (floor);
  1062. case BUILT_IN_CEIL:
  1063. case BUILT_IN_CEILF:
  1064. return AARCH64_FIND_FRINT_VARIANT (ceil);
  1065. case BUILT_IN_TRUNC:
  1066. case BUILT_IN_TRUNCF:
  1067. return AARCH64_FIND_FRINT_VARIANT (btrunc);
  1068. case BUILT_IN_ROUND:
  1069. case BUILT_IN_ROUNDF:
  1070. return AARCH64_FIND_FRINT_VARIANT (round);
  1071. case BUILT_IN_NEARBYINT:
  1072. case BUILT_IN_NEARBYINTF:
  1073. return AARCH64_FIND_FRINT_VARIANT (nearbyint);
  1074. case BUILT_IN_SQRT:
  1075. case BUILT_IN_SQRTF:
  1076. return AARCH64_FIND_FRINT_VARIANT (sqrt);
  1077. #undef AARCH64_CHECK_BUILTIN_MODE
  1078. #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
  1079. (out_mode == SImode && out_n == C \
  1080. && in_mode == N##Imode && in_n == C)
  1081. case BUILT_IN_CLZ:
  1082. {
  1083. if (AARCH64_CHECK_BUILTIN_MODE (4, S))
  1084. return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_clzv4si];
  1085. return NULL_TREE;
  1086. }
  1087. case BUILT_IN_CTZ:
  1088. {
  1089. if (AARCH64_CHECK_BUILTIN_MODE (2, S))
  1090. return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv2si];
  1091. else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
  1092. return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_ctzv4si];
  1093. return NULL_TREE;
  1094. }
  1095. #undef AARCH64_CHECK_BUILTIN_MODE
  1096. #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
  1097. (out_mode == N##Imode && out_n == C \
  1098. && in_mode == N##Fmode && in_n == C)
  1099. case BUILT_IN_LFLOOR:
  1100. case BUILT_IN_LFLOORF:
  1101. case BUILT_IN_LLFLOOR:
  1102. case BUILT_IN_IFLOORF:
  1103. {
  1104. enum aarch64_builtins builtin;
  1105. if (AARCH64_CHECK_BUILTIN_MODE (2, D))
  1106. builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di;
  1107. else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
  1108. builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si;
  1109. else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
  1110. builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si;
  1111. else
  1112. return NULL_TREE;
  1113. return aarch64_builtin_decls[builtin];
  1114. }
  1115. case BUILT_IN_LCEIL:
  1116. case BUILT_IN_LCEILF:
  1117. case BUILT_IN_LLCEIL:
  1118. case BUILT_IN_ICEILF:
  1119. {
  1120. enum aarch64_builtins builtin;
  1121. if (AARCH64_CHECK_BUILTIN_MODE (2, D))
  1122. builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di;
  1123. else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
  1124. builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si;
  1125. else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
  1126. builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si;
  1127. else
  1128. return NULL_TREE;
  1129. return aarch64_builtin_decls[builtin];
  1130. }
  1131. case BUILT_IN_LROUND:
  1132. case BUILT_IN_IROUNDF:
  1133. {
  1134. enum aarch64_builtins builtin;
  1135. if (AARCH64_CHECK_BUILTIN_MODE (2, D))
  1136. builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di;
  1137. else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
  1138. builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si;
  1139. else if (AARCH64_CHECK_BUILTIN_MODE (2, S))
  1140. builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si;
  1141. else
  1142. return NULL_TREE;
  1143. return aarch64_builtin_decls[builtin];
  1144. }
  1145. case BUILT_IN_BSWAP16:
  1146. #undef AARCH64_CHECK_BUILTIN_MODE
  1147. #define AARCH64_CHECK_BUILTIN_MODE(C, N) \
  1148. (out_mode == N##Imode && out_n == C \
  1149. && in_mode == N##Imode && in_n == C)
  1150. if (AARCH64_CHECK_BUILTIN_MODE (4, H))
  1151. return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOPU_bswapv4hi];
  1152. else if (AARCH64_CHECK_BUILTIN_MODE (8, H))
  1153. return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOPU_bswapv8hi];
  1154. else
  1155. return NULL_TREE;
  1156. case BUILT_IN_BSWAP32:
  1157. if (AARCH64_CHECK_BUILTIN_MODE (2, S))
  1158. return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOPU_bswapv2si];
  1159. else if (AARCH64_CHECK_BUILTIN_MODE (4, S))
  1160. return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOPU_bswapv4si];
  1161. else
  1162. return NULL_TREE;
  1163. case BUILT_IN_BSWAP64:
  1164. if (AARCH64_CHECK_BUILTIN_MODE (2, D))
  1165. return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOPU_bswapv2di];
  1166. else
  1167. return NULL_TREE;
  1168. default:
  1169. return NULL_TREE;
  1170. }
  1171. }
  1172. return NULL_TREE;
  1173. }
  1174. #undef VAR1
  1175. #define VAR1(T, N, MAP, A) \
  1176. case AARCH64_SIMD_BUILTIN_##T##_##N##A:
  1177. tree
  1178. aarch64_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args,
  1179. bool ignore ATTRIBUTE_UNUSED)
  1180. {
  1181. int fcode = DECL_FUNCTION_CODE (fndecl);
  1182. tree type = TREE_TYPE (TREE_TYPE (fndecl));
  1183. switch (fcode)
  1184. {
  1185. BUILTIN_VDQF (UNOP, abs, 2)
  1186. return fold_build1 (ABS_EXPR, type, args[0]);
  1187. break;
  1188. VAR1 (UNOP, floatv2si, 2, v2sf)
  1189. VAR1 (UNOP, floatv4si, 2, v4sf)
  1190. VAR1 (UNOP, floatv2di, 2, v2df)
  1191. return fold_build1 (FLOAT_EXPR, type, args[0]);
  1192. default:
  1193. break;
  1194. }
  1195. return NULL_TREE;
  1196. }
  1197. bool
  1198. aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi)
  1199. {
  1200. bool changed = false;
  1201. gimple stmt = gsi_stmt (*gsi);
  1202. tree call = gimple_call_fn (stmt);
  1203. tree fndecl;
  1204. gimple new_stmt = NULL;
  1205. if (call)
  1206. {
  1207. fndecl = gimple_call_fndecl (stmt);
  1208. if (fndecl)
  1209. {
  1210. int fcode = DECL_FUNCTION_CODE (fndecl);
  1211. int nargs = gimple_call_num_args (stmt);
  1212. tree *args = (nargs > 0
  1213. ? gimple_call_arg_ptr (stmt, 0)
  1214. : &error_mark_node);
  1215. /* We use gimple's REDUC_(PLUS|MIN|MAX)_EXPRs for float, signed int
  1216. and unsigned int; it will distinguish according to the types of
  1217. the arguments to the __builtin. */
  1218. switch (fcode)
  1219. {
  1220. BUILTIN_VALL (UNOP, reduc_plus_scal_, 10)
  1221. new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
  1222. REDUC_PLUS_EXPR, args[0]);
  1223. break;
  1224. BUILTIN_VDQIF (UNOP, reduc_smax_scal_, 10)
  1225. BUILTIN_VDQ_BHSI (UNOPU, reduc_umax_scal_, 10)
  1226. new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
  1227. REDUC_MAX_EXPR, args[0]);
  1228. break;
  1229. BUILTIN_VDQIF (UNOP, reduc_smin_scal_, 10)
  1230. BUILTIN_VDQ_BHSI (UNOPU, reduc_umin_scal_, 10)
  1231. new_stmt = gimple_build_assign (gimple_call_lhs (stmt),
  1232. REDUC_MIN_EXPR, args[0]);
  1233. break;
  1234. default:
  1235. break;
  1236. }
  1237. }
  1238. }
  1239. if (new_stmt)
  1240. {
  1241. gsi_replace (gsi, new_stmt, true);
  1242. changed = true;
  1243. }
  1244. return changed;
  1245. }
  1246. void
  1247. aarch64_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
  1248. {
  1249. const unsigned AARCH64_FE_INVALID = 1;
  1250. const unsigned AARCH64_FE_DIVBYZERO = 2;
  1251. const unsigned AARCH64_FE_OVERFLOW = 4;
  1252. const unsigned AARCH64_FE_UNDERFLOW = 8;
  1253. const unsigned AARCH64_FE_INEXACT = 16;
  1254. const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT = (AARCH64_FE_INVALID
  1255. | AARCH64_FE_DIVBYZERO
  1256. | AARCH64_FE_OVERFLOW
  1257. | AARCH64_FE_UNDERFLOW
  1258. | AARCH64_FE_INEXACT);
  1259. const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT = 8;
  1260. tree fenv_cr, fenv_sr, get_fpcr, set_fpcr, mask_cr, mask_sr;
  1261. tree ld_fenv_cr, ld_fenv_sr, masked_fenv_cr, masked_fenv_sr, hold_fnclex_cr;
  1262. tree hold_fnclex_sr, new_fenv_var, reload_fenv, restore_fnenv, get_fpsr, set_fpsr;
  1263. tree update_call, atomic_feraiseexcept, hold_fnclex, masked_fenv, ld_fenv;
  1264. /* Generate the equivalence of :
  1265. unsigned int fenv_cr;
  1266. fenv_cr = __builtin_aarch64_get_fpcr ();
  1267. unsigned int fenv_sr;
  1268. fenv_sr = __builtin_aarch64_get_fpsr ();
  1269. Now set all exceptions to non-stop
  1270. unsigned int mask_cr
  1271. = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT);
  1272. unsigned int masked_cr;
  1273. masked_cr = fenv_cr & mask_cr;
  1274. And clear all exception flags
  1275. unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT;
  1276. unsigned int masked_cr;
  1277. masked_sr = fenv_sr & mask_sr;
  1278. __builtin_aarch64_set_cr (masked_cr);
  1279. __builtin_aarch64_set_sr (masked_sr); */
  1280. fenv_cr = create_tmp_var (unsigned_type_node);
  1281. fenv_sr = create_tmp_var (unsigned_type_node);
  1282. get_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR];
  1283. set_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR];
  1284. get_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR];
  1285. set_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR];
  1286. mask_cr = build_int_cst (unsigned_type_node,
  1287. ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT));
  1288. mask_sr = build_int_cst (unsigned_type_node,
  1289. ~(AARCH64_FE_ALL_EXCEPT));
  1290. ld_fenv_cr = build2 (MODIFY_EXPR, unsigned_type_node,
  1291. fenv_cr, build_call_expr (get_fpcr, 0));
  1292. ld_fenv_sr = build2 (MODIFY_EXPR, unsigned_type_node,
  1293. fenv_sr, build_call_expr (get_fpsr, 0));
  1294. masked_fenv_cr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_cr, mask_cr);
  1295. masked_fenv_sr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_sr, mask_sr);
  1296. hold_fnclex_cr = build_call_expr (set_fpcr, 1, masked_fenv_cr);
  1297. hold_fnclex_sr = build_call_expr (set_fpsr, 1, masked_fenv_sr);
  1298. hold_fnclex = build2 (COMPOUND_EXPR, void_type_node, hold_fnclex_cr,
  1299. hold_fnclex_sr);
  1300. masked_fenv = build2 (COMPOUND_EXPR, void_type_node, masked_fenv_cr,
  1301. masked_fenv_sr);
  1302. ld_fenv = build2 (COMPOUND_EXPR, void_type_node, ld_fenv_cr, ld_fenv_sr);
  1303. *hold = build2 (COMPOUND_EXPR, void_type_node,
  1304. build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv),
  1305. hold_fnclex);
  1306. /* Store the value of masked_fenv to clear the exceptions:
  1307. __builtin_aarch64_set_fpsr (masked_fenv_sr); */
  1308. *clear = build_call_expr (set_fpsr, 1, masked_fenv_sr);
  1309. /* Generate the equivalent of :
  1310. unsigned int new_fenv_var;
  1311. new_fenv_var = __builtin_aarch64_get_fpsr ();
  1312. __builtin_aarch64_set_fpsr (fenv_sr);
  1313. __atomic_feraiseexcept (new_fenv_var); */
  1314. new_fenv_var = create_tmp_var (unsigned_type_node);
  1315. reload_fenv = build2 (MODIFY_EXPR, unsigned_type_node,
  1316. new_fenv_var, build_call_expr (get_fpsr, 0));
  1317. restore_fnenv = build_call_expr (set_fpsr, 1, fenv_sr);
  1318. atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
  1319. update_call = build_call_expr (atomic_feraiseexcept, 1,
  1320. fold_convert (integer_type_node, new_fenv_var));
  1321. *update = build2 (COMPOUND_EXPR, void_type_node,
  1322. build2 (COMPOUND_EXPR, void_type_node,
  1323. reload_fenv, restore_fnenv), update_call);
  1324. }
  1325. #undef AARCH64_CHECK_BUILTIN_MODE
  1326. #undef AARCH64_FIND_FRINT_VARIANT
  1327. #undef CF0
  1328. #undef CF1
  1329. #undef CF2
  1330. #undef CF3
  1331. #undef CF4
  1332. #undef CF10
  1333. #undef VAR1
  1334. #undef VAR2
  1335. #undef VAR3
  1336. #undef VAR4
  1337. #undef VAR5
  1338. #undef VAR6
  1339. #undef VAR7
  1340. #undef VAR8
  1341. #undef VAR9
  1342. #undef VAR10
  1343. #undef VAR11
  1344. #include "gt-aarch64-builtins.h"