GenericOpcodes.td 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443
  1. //===-- GenericOpcodes.td - Opcodes used with GlobalISel ---*- tablegen -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines the generic opcodes used with GlobalISel.
  10. // After instruction selection, these opcodes should not appear.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //------------------------------------------------------------------------------
  14. // Unary ops.
  15. //------------------------------------------------------------------------------
  16. class GenericInstruction : StandardPseudoInstruction {
  17. let isPreISelOpcode = true;
  18. }
  19. // Provide a variant of an instruction with the same operands, but
  20. // different instruction flags. This is intended to provide a
  21. // convenient way to define strict floating point variants of ordinary
  22. // floating point instructions.
  23. class ConstrainedIntruction<GenericInstruction baseInst> :
  24. GenericInstruction {
  25. let OutOperandList = baseInst.OutOperandList;
  26. let InOperandList = baseInst.InOperandList;
  27. let isCommutable = baseInst.isCommutable;
  28. // TODO: Do we need a better way to mark reads from FP mode than
  29. // hasSideEffects?
  30. let hasSideEffects = true;
  31. let mayRaiseFPException = true;
  32. }
  33. // Extend the underlying scalar type of an operation, leaving the high bits
  34. // unspecified.
  35. def G_ANYEXT : GenericInstruction {
  36. let OutOperandList = (outs type0:$dst);
  37. let InOperandList = (ins type1:$src);
  38. let hasSideEffects = false;
  39. }
  40. // Sign extend the underlying scalar type of an operation, copying the sign bit
  41. // into the newly-created space.
  42. def G_SEXT : GenericInstruction {
  43. let OutOperandList = (outs type0:$dst);
  44. let InOperandList = (ins type1:$src);
  45. let hasSideEffects = false;
  46. }
  47. // Sign extend the a value from an arbitrary bit position, copying the sign bit
  48. // into all bits above it. This is equivalent to a shl + ashr pair with an
  49. // appropriate shift amount. $sz is an immediate (MachineOperand::isImm()
  50. // returns true) to allow targets to have some bitwidths legal and others
  51. // lowered. This opcode is particularly useful if the target has sign-extension
  52. // instructions that are cheaper than the constituent shifts as the optimizer is
  53. // able to make decisions on whether it's better to hang on to the G_SEXT_INREG
  54. // or to lower it and optimize the individual shifts.
  55. def G_SEXT_INREG : GenericInstruction {
  56. let OutOperandList = (outs type0:$dst);
  57. let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
  58. let hasSideEffects = false;
  59. }
  60. // Zero extend the underlying scalar type of an operation, putting zero bits
  61. // into the newly-created space.
  62. def G_ZEXT : GenericInstruction {
  63. let OutOperandList = (outs type0:$dst);
  64. let InOperandList = (ins type1:$src);
  65. let hasSideEffects = false;
  66. }
  67. // Truncate the underlying scalar type of an operation. This is equivalent to
  68. // G_EXTRACT for scalar types, but acts elementwise on vectors.
  69. def G_TRUNC : GenericInstruction {
  70. let OutOperandList = (outs type0:$dst);
  71. let InOperandList = (ins type1:$src);
  72. let hasSideEffects = false;
  73. }
  74. def G_IMPLICIT_DEF : GenericInstruction {
  75. let OutOperandList = (outs type0:$dst);
  76. let InOperandList = (ins);
  77. let hasSideEffects = false;
  78. }
  79. def G_PHI : GenericInstruction {
  80. let OutOperandList = (outs type0:$dst);
  81. let InOperandList = (ins variable_ops);
  82. let hasSideEffects = false;
  83. }
  84. def G_FRAME_INDEX : GenericInstruction {
  85. let OutOperandList = (outs type0:$dst);
  86. let InOperandList = (ins unknown:$src2);
  87. let hasSideEffects = false;
  88. }
  89. def G_GLOBAL_VALUE : GenericInstruction {
  90. let OutOperandList = (outs type0:$dst);
  91. let InOperandList = (ins unknown:$src);
  92. let hasSideEffects = false;
  93. }
  94. def G_INTTOPTR : GenericInstruction {
  95. let OutOperandList = (outs type0:$dst);
  96. let InOperandList = (ins type1:$src);
  97. let hasSideEffects = false;
  98. }
  99. def G_PTRTOINT : GenericInstruction {
  100. let OutOperandList = (outs type0:$dst);
  101. let InOperandList = (ins type1:$src);
  102. let hasSideEffects = false;
  103. }
  104. def G_BITCAST : GenericInstruction {
  105. let OutOperandList = (outs type0:$dst);
  106. let InOperandList = (ins type1:$src);
  107. let hasSideEffects = false;
  108. }
  109. // Only supports scalar result types
  110. def G_CONSTANT : GenericInstruction {
  111. let OutOperandList = (outs type0:$dst);
  112. let InOperandList = (ins unknown:$imm);
  113. let hasSideEffects = false;
  114. }
  115. // Only supports scalar result types
  116. def G_FCONSTANT : GenericInstruction {
  117. let OutOperandList = (outs type0:$dst);
  118. let InOperandList = (ins unknown:$imm);
  119. let hasSideEffects = false;
  120. }
  121. def G_VASTART : GenericInstruction {
  122. let OutOperandList = (outs);
  123. let InOperandList = (ins type0:$list);
  124. let hasSideEffects = false;
  125. let mayStore = true;
  126. }
  127. def G_VAARG : GenericInstruction {
  128. let OutOperandList = (outs type0:$val);
  129. let InOperandList = (ins type1:$list, unknown:$align);
  130. let hasSideEffects = false;
  131. let mayLoad = true;
  132. let mayStore = true;
  133. }
  134. def G_CTLZ : GenericInstruction {
  135. let OutOperandList = (outs type0:$dst);
  136. let InOperandList = (ins type1:$src);
  137. let hasSideEffects = false;
  138. }
  139. def G_CTLZ_ZERO_UNDEF : GenericInstruction {
  140. let OutOperandList = (outs type0:$dst);
  141. let InOperandList = (ins type1:$src);
  142. let hasSideEffects = false;
  143. }
  144. def G_CTTZ : GenericInstruction {
  145. let OutOperandList = (outs type0:$dst);
  146. let InOperandList = (ins type1:$src);
  147. let hasSideEffects = false;
  148. }
  149. def G_CTTZ_ZERO_UNDEF : GenericInstruction {
  150. let OutOperandList = (outs type0:$dst);
  151. let InOperandList = (ins type1:$src);
  152. let hasSideEffects = false;
  153. }
  154. def G_CTPOP : GenericInstruction {
  155. let OutOperandList = (outs type0:$dst);
  156. let InOperandList = (ins type1:$src);
  157. let hasSideEffects = false;
  158. }
  159. def G_BSWAP : GenericInstruction {
  160. let OutOperandList = (outs type0:$dst);
  161. let InOperandList = (ins type0:$src);
  162. let hasSideEffects = false;
  163. }
  164. def G_BITREVERSE : GenericInstruction {
  165. let OutOperandList = (outs type0:$dst);
  166. let InOperandList = (ins type0:$src);
  167. let hasSideEffects = false;
  168. }
  169. def G_ADDRSPACE_CAST : GenericInstruction {
  170. let OutOperandList = (outs type0:$dst);
  171. let InOperandList = (ins type1:$src);
  172. let hasSideEffects = false;
  173. }
  174. def G_BLOCK_ADDR : GenericInstruction {
  175. let OutOperandList = (outs type0:$dst);
  176. let InOperandList = (ins unknown:$ba);
  177. let hasSideEffects = false;
  178. }
  179. def G_JUMP_TABLE : GenericInstruction {
  180. let OutOperandList = (outs type0:$dst);
  181. let InOperandList = (ins unknown:$jti);
  182. let hasSideEffects = false;
  183. }
  184. def G_DYN_STACKALLOC : GenericInstruction {
  185. let OutOperandList = (outs ptype0:$dst);
  186. let InOperandList = (ins type1:$size, i32imm:$align);
  187. let hasSideEffects = true;
  188. }
  189. def G_FREEZE : GenericInstruction {
  190. let OutOperandList = (outs type0:$dst);
  191. let InOperandList = (ins type0:$src);
  192. let hasSideEffects = false;
  193. }
  194. def G_LROUND: GenericInstruction {
  195. let OutOperandList = (outs type0:$dst);
  196. let InOperandList = (ins type1:$src);
  197. let hasSideEffects = false;
  198. }
  199. def G_LLROUND: GenericInstruction {
  200. let OutOperandList = (outs type0:$dst);
  201. let InOperandList = (ins type1:$src);
  202. let hasSideEffects = false;
  203. }
  204. //------------------------------------------------------------------------------
  205. // Binary ops.
  206. //------------------------------------------------------------------------------
  207. // Generic addition.
  208. def G_ADD : GenericInstruction {
  209. let OutOperandList = (outs type0:$dst);
  210. let InOperandList = (ins type0:$src1, type0:$src2);
  211. let hasSideEffects = false;
  212. let isCommutable = true;
  213. }
  214. // Generic subtraction.
  215. def G_SUB : GenericInstruction {
  216. let OutOperandList = (outs type0:$dst);
  217. let InOperandList = (ins type0:$src1, type0:$src2);
  218. let hasSideEffects = false;
  219. let isCommutable = false;
  220. }
  221. // Generic multiplication.
  222. def G_MUL : GenericInstruction {
  223. let OutOperandList = (outs type0:$dst);
  224. let InOperandList = (ins type0:$src1, type0:$src2);
  225. let hasSideEffects = false;
  226. let isCommutable = true;
  227. }
  228. // Generic signed division.
  229. def G_SDIV : GenericInstruction {
  230. let OutOperandList = (outs type0:$dst);
  231. let InOperandList = (ins type0:$src1, type0:$src2);
  232. let hasSideEffects = false;
  233. let isCommutable = false;
  234. }
  235. // Generic unsigned division.
  236. def G_UDIV : GenericInstruction {
  237. let OutOperandList = (outs type0:$dst);
  238. let InOperandList = (ins type0:$src1, type0:$src2);
  239. let hasSideEffects = false;
  240. let isCommutable = false;
  241. }
  242. // Generic signed remainder.
  243. def G_SREM : GenericInstruction {
  244. let OutOperandList = (outs type0:$dst);
  245. let InOperandList = (ins type0:$src1, type0:$src2);
  246. let hasSideEffects = false;
  247. let isCommutable = false;
  248. }
  249. // Generic unsigned remainder.
  250. def G_UREM : GenericInstruction {
  251. let OutOperandList = (outs type0:$dst);
  252. let InOperandList = (ins type0:$src1, type0:$src2);
  253. let hasSideEffects = false;
  254. let isCommutable = false;
  255. }
  256. // Generic signed division and remainder.
  257. def G_SDIVREM : GenericInstruction {
  258. let OutOperandList = (outs type0:$div, type0:$rem);
  259. let InOperandList = (ins type0:$src1, type0:$src2);
  260. let hasSideEffects = false;
  261. let isCommutable = false;
  262. }
  263. // Generic unsigned division and remainder.
  264. def G_UDIVREM : GenericInstruction {
  265. let OutOperandList = (outs type0:$div, type0:$rem);
  266. let InOperandList = (ins type0:$src1, type0:$src2);
  267. let hasSideEffects = false;
  268. let isCommutable = false;
  269. }
  270. // Generic bitwise and.
  271. def G_AND : GenericInstruction {
  272. let OutOperandList = (outs type0:$dst);
  273. let InOperandList = (ins type0:$src1, type0:$src2);
  274. let hasSideEffects = false;
  275. let isCommutable = true;
  276. }
  277. // Generic bitwise or.
  278. def G_OR : GenericInstruction {
  279. let OutOperandList = (outs type0:$dst);
  280. let InOperandList = (ins type0:$src1, type0:$src2);
  281. let hasSideEffects = false;
  282. let isCommutable = true;
  283. }
  284. // Generic bitwise xor.
  285. def G_XOR : GenericInstruction {
  286. let OutOperandList = (outs type0:$dst);
  287. let InOperandList = (ins type0:$src1, type0:$src2);
  288. let hasSideEffects = false;
  289. let isCommutable = true;
  290. }
  291. // Generic left-shift.
  292. def G_SHL : GenericInstruction {
  293. let OutOperandList = (outs type0:$dst);
  294. let InOperandList = (ins type0:$src1, type1:$src2);
  295. let hasSideEffects = false;
  296. }
  297. // Generic logical right-shift.
  298. def G_LSHR : GenericInstruction {
  299. let OutOperandList = (outs type0:$dst);
  300. let InOperandList = (ins type0:$src1, type1:$src2);
  301. let hasSideEffects = false;
  302. }
  303. // Generic arithmetic right-shift.
  304. def G_ASHR : GenericInstruction {
  305. let OutOperandList = (outs type0:$dst);
  306. let InOperandList = (ins type0:$src1, type1:$src2);
  307. let hasSideEffects = false;
  308. }
  309. /// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount.
  310. /// fshl(X,Y,Z): (X << (Z % bitwidth)) | (Y >> (bitwidth - (Z % bitwidth)))
  311. def G_FSHL : GenericInstruction {
  312. let OutOperandList = (outs type0:$dst);
  313. let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);
  314. let hasSideEffects = false;
  315. }
  316. /// Funnel 'double' shifts take 3 operands, 2 inputs and the shift amount.
  317. /// fshr(X,Y,Z): (X << (bitwidth - (Z % bitwidth))) | (Y >> (Z % bitwidth))
  318. def G_FSHR : GenericInstruction {
  319. let OutOperandList = (outs type0:$dst);
  320. let InOperandList = (ins type0:$src1, type0:$src2, type1:$src3);
  321. let hasSideEffects = false;
  322. }
  323. /// Rotate bits right.
  324. def G_ROTR : GenericInstruction {
  325. let OutOperandList = (outs type0:$dst);
  326. let InOperandList = (ins type0:$src1, type1:$src2);
  327. let hasSideEffects = false;
  328. }
  329. /// Rotate bits left.
  330. def G_ROTL : GenericInstruction {
  331. let OutOperandList = (outs type0:$dst);
  332. let InOperandList = (ins type0:$src1, type1:$src2);
  333. let hasSideEffects = false;
  334. }
  335. // Generic integer comparison.
  336. def G_ICMP : GenericInstruction {
  337. let OutOperandList = (outs type0:$dst);
  338. let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
  339. let hasSideEffects = false;
  340. }
  341. // Generic floating-point comparison.
  342. def G_FCMP : GenericInstruction {
  343. let OutOperandList = (outs type0:$dst);
  344. let InOperandList = (ins unknown:$tst, type1:$src1, type1:$src2);
  345. let hasSideEffects = false;
  346. }
  347. // Generic select
  348. def G_SELECT : GenericInstruction {
  349. let OutOperandList = (outs type0:$dst);
  350. let InOperandList = (ins type1:$tst, type0:$src1, type0:$src2);
  351. let hasSideEffects = false;
  352. }
  353. // Generic pointer offset.
  354. def G_PTR_ADD : GenericInstruction {
  355. let OutOperandList = (outs type0:$dst);
  356. let InOperandList = (ins type0:$src1, type1:$src2);
  357. let hasSideEffects = false;
  358. }
  359. // Generic pointer mask. type1 should be an integer with the same
  360. // bitwidth as the pointer type.
  361. def G_PTRMASK : GenericInstruction {
  362. let OutOperandList = (outs ptype0:$dst);
  363. let InOperandList = (ins ptype0:$src, type1:$bits);
  364. let hasSideEffects = false;
  365. }
  366. // Generic signed integer minimum.
  367. def G_SMIN : GenericInstruction {
  368. let OutOperandList = (outs type0:$dst);
  369. let InOperandList = (ins type0:$src1, type0:$src2);
  370. let hasSideEffects = false;
  371. let isCommutable = true;
  372. }
  373. // Generic signed integer maximum.
  374. def G_SMAX : GenericInstruction {
  375. let OutOperandList = (outs type0:$dst);
  376. let InOperandList = (ins type0:$src1, type0:$src2);
  377. let hasSideEffects = false;
  378. let isCommutable = true;
  379. }
  380. // Generic unsigned integer minimum.
  381. def G_UMIN : GenericInstruction {
  382. let OutOperandList = (outs type0:$dst);
  383. let InOperandList = (ins type0:$src1, type0:$src2);
  384. let hasSideEffects = false;
  385. let isCommutable = true;
  386. }
  387. // Generic unsigned integer maximum.
  388. def G_UMAX : GenericInstruction {
  389. let OutOperandList = (outs type0:$dst);
  390. let InOperandList = (ins type0:$src1, type0:$src2);
  391. let hasSideEffects = false;
  392. let isCommutable = true;
  393. }
  394. // Generic integer absolute value.
  395. def G_ABS : GenericInstruction {
  396. let OutOperandList = (outs type0:$dst);
  397. let InOperandList = (ins type0:$src);
  398. let hasSideEffects = false;
  399. }
  400. //------------------------------------------------------------------------------
  401. // Overflow ops
  402. //------------------------------------------------------------------------------
  403. // Generic unsigned addition producing a carry flag.
  404. def G_UADDO : GenericInstruction {
  405. let OutOperandList = (outs type0:$dst, type1:$carry_out);
  406. let InOperandList = (ins type0:$src1, type0:$src2);
  407. let hasSideEffects = false;
  408. let isCommutable = true;
  409. }
  410. // Generic unsigned addition consuming and producing a carry flag.
  411. def G_UADDE : GenericInstruction {
  412. let OutOperandList = (outs type0:$dst, type1:$carry_out);
  413. let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
  414. let hasSideEffects = false;
  415. }
  416. // Generic signed addition producing a carry flag.
  417. def G_SADDO : GenericInstruction {
  418. let OutOperandList = (outs type0:$dst, type1:$carry_out);
  419. let InOperandList = (ins type0:$src1, type0:$src2);
  420. let hasSideEffects = false;
  421. let isCommutable = true;
  422. }
  423. // Generic signed addition consuming and producing a carry flag.
  424. def G_SADDE : GenericInstruction {
  425. let OutOperandList = (outs type0:$dst, type1:$carry_out);
  426. let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
  427. let hasSideEffects = false;
  428. }
  429. // Generic unsigned subtraction producing a carry flag.
  430. def G_USUBO : GenericInstruction {
  431. let OutOperandList = (outs type0:$dst, type1:$carry_out);
  432. let InOperandList = (ins type0:$src1, type0:$src2);
  433. let hasSideEffects = false;
  434. }
  435. // Generic unsigned subtraction consuming and producing a carry flag.
  436. def G_USUBE : GenericInstruction {
  437. let OutOperandList = (outs type0:$dst, type1:$carry_out);
  438. let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
  439. let hasSideEffects = false;
  440. }
  441. // Generic signed subtraction producing a carry flag.
  442. def G_SSUBO : GenericInstruction {
  443. let OutOperandList = (outs type0:$dst, type1:$carry_out);
  444. let InOperandList = (ins type0:$src1, type0:$src2);
  445. let hasSideEffects = false;
  446. }
  447. // Generic signed subtraction consuming and producing a carry flag.
  448. def G_SSUBE : GenericInstruction {
  449. let OutOperandList = (outs type0:$dst, type1:$carry_out);
  450. let InOperandList = (ins type0:$src1, type0:$src2, type1:$carry_in);
  451. let hasSideEffects = false;
  452. }
  453. // Generic unsigned multiplication producing a carry flag.
  454. def G_UMULO : GenericInstruction {
  455. let OutOperandList = (outs type0:$dst, type1:$carry_out);
  456. let InOperandList = (ins type0:$src1, type0:$src2);
  457. let hasSideEffects = false;
  458. let isCommutable = true;
  459. }
  460. // Generic signed multiplication producing a carry flag.
  461. def G_SMULO : GenericInstruction {
  462. let OutOperandList = (outs type0:$dst, type1:$carry_out);
  463. let InOperandList = (ins type0:$src1, type0:$src2);
  464. let hasSideEffects = false;
  465. let isCommutable = true;
  466. }
  467. // Multiply two numbers at twice the incoming bit width (unsigned) and return
  468. // the high half of the result.
  469. def G_UMULH : GenericInstruction {
  470. let OutOperandList = (outs type0:$dst);
  471. let InOperandList = (ins type0:$src1, type0:$src2);
  472. let hasSideEffects = false;
  473. let isCommutable = true;
  474. }
  475. // Multiply two numbers at twice the incoming bit width (signed) and return
  476. // the high half of the result.
  477. def G_SMULH : GenericInstruction {
  478. let OutOperandList = (outs type0:$dst);
  479. let InOperandList = (ins type0:$src1, type0:$src2);
  480. let hasSideEffects = false;
  481. let isCommutable = true;
  482. }
  483. //------------------------------------------------------------------------------
  484. // Saturating ops
  485. //------------------------------------------------------------------------------
  486. // Generic saturating unsigned addition.
  487. def G_UADDSAT : GenericInstruction {
  488. let OutOperandList = (outs type0:$dst);
  489. let InOperandList = (ins type0:$src1, type0:$src2);
  490. let hasSideEffects = false;
  491. let isCommutable = true;
  492. }
  493. // Generic saturating signed addition.
  494. def G_SADDSAT : GenericInstruction {
  495. let OutOperandList = (outs type0:$dst);
  496. let InOperandList = (ins type0:$src1, type0:$src2);
  497. let hasSideEffects = false;
  498. let isCommutable = true;
  499. }
  500. // Generic saturating unsigned subtraction.
  501. def G_USUBSAT : GenericInstruction {
  502. let OutOperandList = (outs type0:$dst);
  503. let InOperandList = (ins type0:$src1, type0:$src2);
  504. let hasSideEffects = false;
  505. let isCommutable = false;
  506. }
  507. // Generic saturating signed subtraction.
  508. def G_SSUBSAT : GenericInstruction {
  509. let OutOperandList = (outs type0:$dst);
  510. let InOperandList = (ins type0:$src1, type0:$src2);
  511. let hasSideEffects = false;
  512. let isCommutable = false;
  513. }
  514. // Generic saturating unsigned left shift.
  515. def G_USHLSAT : GenericInstruction {
  516. let OutOperandList = (outs type0:$dst);
  517. let InOperandList = (ins type0:$src1, type1:$src2);
  518. let hasSideEffects = false;
  519. let isCommutable = false;
  520. }
  521. // Generic saturating signed left shift.
  522. def G_SSHLSAT : GenericInstruction {
  523. let OutOperandList = (outs type0:$dst);
  524. let InOperandList = (ins type0:$src1, type1:$src2);
  525. let hasSideEffects = false;
  526. let isCommutable = false;
  527. }
  528. /// RESULT = [US]MULFIX(LHS, RHS, SCALE) - Perform fixed point
  529. /// multiplication on 2 integers with the same width and scale. SCALE
  530. /// represents the scale of both operands as fixed point numbers. This
  531. /// SCALE parameter must be a constant integer. A scale of zero is
  532. /// effectively performing multiplication on 2 integers.
  533. def G_SMULFIX : GenericInstruction {
  534. let OutOperandList = (outs type0:$dst);
  535. let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
  536. let hasSideEffects = false;
  537. let isCommutable = true;
  538. }
  539. def G_UMULFIX : GenericInstruction {
  540. let OutOperandList = (outs type0:$dst);
  541. let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
  542. let hasSideEffects = false;
  543. let isCommutable = true;
  544. }
  545. /// Same as the corresponding unsaturated fixed point instructions, but the
  546. /// result is clamped between the min and max values representable by the
  547. /// bits of the first 2 operands.
  548. def G_SMULFIXSAT : GenericInstruction {
  549. let OutOperandList = (outs type0:$dst);
  550. let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
  551. let hasSideEffects = false;
  552. let isCommutable = true;
  553. }
  554. def G_UMULFIXSAT : GenericInstruction {
  555. let OutOperandList = (outs type0:$dst);
  556. let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
  557. let hasSideEffects = false;
  558. let isCommutable = true;
  559. }
  560. /// RESULT = [US]DIVFIX(LHS, RHS, SCALE) - Perform fixed point division on
  561. /// 2 integers with the same width and scale. SCALE represents the scale
  562. /// of both operands as fixed point numbers. This SCALE parameter must be a
  563. /// constant integer.
  564. def G_SDIVFIX : GenericInstruction {
  565. let OutOperandList = (outs type0:$dst);
  566. let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
  567. let hasSideEffects = false;
  568. let isCommutable = false;
  569. }
  570. def G_UDIVFIX : GenericInstruction {
  571. let OutOperandList = (outs type0:$dst);
  572. let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
  573. let hasSideEffects = false;
  574. let isCommutable = false;
  575. }
  576. /// Same as the corresponding unsaturated fixed point instructions,
  577. /// but the result is clamped between the min and max values
  578. /// representable by the bits of the first 2 operands.
  579. def G_SDIVFIXSAT : GenericInstruction {
  580. let OutOperandList = (outs type0:$dst);
  581. let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
  582. let hasSideEffects = false;
  583. let isCommutable = false;
  584. }
  585. def G_UDIVFIXSAT : GenericInstruction {
  586. let OutOperandList = (outs type0:$dst);
  587. let InOperandList = (ins type0:$src0, type0:$src1, untyped_imm_0:$scale);
  588. let hasSideEffects = false;
  589. let isCommutable = false;
  590. }
  591. //------------------------------------------------------------------------------
  592. // Floating Point Unary Ops.
  593. //------------------------------------------------------------------------------
  594. def G_FNEG : GenericInstruction {
  595. let OutOperandList = (outs type0:$dst);
  596. let InOperandList = (ins type0:$src);
  597. let hasSideEffects = false;
  598. }
  599. def G_FPEXT : GenericInstruction {
  600. let OutOperandList = (outs type0:$dst);
  601. let InOperandList = (ins type1:$src);
  602. let hasSideEffects = false;
  603. }
  604. def G_FPTRUNC : GenericInstruction {
  605. let OutOperandList = (outs type0:$dst);
  606. let InOperandList = (ins type1:$src);
  607. let hasSideEffects = false;
  608. }
  609. def G_FPTOSI : GenericInstruction {
  610. let OutOperandList = (outs type0:$dst);
  611. let InOperandList = (ins type1:$src);
  612. let hasSideEffects = false;
  613. }
  614. def G_FPTOUI : GenericInstruction {
  615. let OutOperandList = (outs type0:$dst);
  616. let InOperandList = (ins type1:$src);
  617. let hasSideEffects = false;
  618. }
  619. def G_SITOFP : GenericInstruction {
  620. let OutOperandList = (outs type0:$dst);
  621. let InOperandList = (ins type1:$src);
  622. let hasSideEffects = false;
  623. }
  624. def G_UITOFP : GenericInstruction {
  625. let OutOperandList = (outs type0:$dst);
  626. let InOperandList = (ins type1:$src);
  627. let hasSideEffects = false;
  628. }
  629. def G_FABS : GenericInstruction {
  630. let OutOperandList = (outs type0:$dst);
  631. let InOperandList = (ins type0:$src);
  632. let hasSideEffects = false;
  633. }
  634. def G_FCOPYSIGN : GenericInstruction {
  635. let OutOperandList = (outs type0:$dst);
  636. let InOperandList = (ins type0:$src0, type1:$src1);
  637. let hasSideEffects = false;
  638. }
  639. def G_FCANONICALIZE : GenericInstruction {
  640. let OutOperandList = (outs type0:$dst);
  641. let InOperandList = (ins type0:$src);
  642. let hasSideEffects = false;
  643. }
  644. // FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
  645. // values.
  646. //
  647. // In the case where a single input is a NaN (either signaling or quiet),
  648. // the non-NaN input is returned.
  649. //
  650. // The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.
  651. def G_FMINNUM : GenericInstruction {
  652. let OutOperandList = (outs type0:$dst);
  653. let InOperandList = (ins type0:$src1, type0:$src2);
  654. let hasSideEffects = false;
  655. let isCommutable = true;
  656. }
  657. def G_FMAXNUM : GenericInstruction {
  658. let OutOperandList = (outs type0:$dst);
  659. let InOperandList = (ins type0:$src1, type0:$src2);
  660. let hasSideEffects = false;
  661. let isCommutable = true;
  662. }
  663. // FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on
  664. // two values, following the IEEE-754 2008 definition. This differs from
  665. // FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a
  666. // signaling NaN, returns a quiet NaN.
  667. def G_FMINNUM_IEEE : GenericInstruction {
  668. let OutOperandList = (outs type0:$dst);
  669. let InOperandList = (ins type0:$src1, type0:$src2);
  670. let hasSideEffects = false;
  671. let isCommutable = true;
  672. }
  673. def G_FMAXNUM_IEEE : GenericInstruction {
  674. let OutOperandList = (outs type0:$dst);
  675. let InOperandList = (ins type0:$src1, type0:$src2);
  676. let hasSideEffects = false;
  677. let isCommutable = true;
  678. }
  679. // FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0
  680. // as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008
  681. // semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics.
  682. def G_FMINIMUM : GenericInstruction {
  683. let OutOperandList = (outs type0:$dst);
  684. let InOperandList = (ins type0:$src1, type0:$src2);
  685. let hasSideEffects = false;
  686. let isCommutable = true;
  687. }
  688. def G_FMAXIMUM : GenericInstruction {
  689. let OutOperandList = (outs type0:$dst);
  690. let InOperandList = (ins type0:$src1, type0:$src2);
  691. let hasSideEffects = false;
  692. let isCommutable = true;
  693. }
  694. //------------------------------------------------------------------------------
  695. // Floating Point Binary ops.
  696. //------------------------------------------------------------------------------
  697. // Generic FP addition.
  698. def G_FADD : GenericInstruction {
  699. let OutOperandList = (outs type0:$dst);
  700. let InOperandList = (ins type0:$src1, type0:$src2);
  701. let hasSideEffects = false;
  702. let isCommutable = true;
  703. }
  704. // Generic FP subtraction.
  705. def G_FSUB : GenericInstruction {
  706. let OutOperandList = (outs type0:$dst);
  707. let InOperandList = (ins type0:$src1, type0:$src2);
  708. let hasSideEffects = false;
  709. let isCommutable = false;
  710. }
  711. // Generic FP multiplication.
  712. def G_FMUL : GenericInstruction {
  713. let OutOperandList = (outs type0:$dst);
  714. let InOperandList = (ins type0:$src1, type0:$src2);
  715. let hasSideEffects = false;
  716. let isCommutable = true;
  717. }
  718. // Generic fused multiply-add instruction.
  719. // Behaves like llvm fma intrinsic ie src1 * src2 + src3
  720. def G_FMA : GenericInstruction {
  721. let OutOperandList = (outs type0:$dst);
  722. let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
  723. let hasSideEffects = false;
  724. let isCommutable = false;
  725. }
  726. /// Generic FP multiply and add. Perform a * b + c, while getting the
  727. /// same result as the separately rounded operations, unlike G_FMA.
  728. def G_FMAD : GenericInstruction {
  729. let OutOperandList = (outs type0:$dst);
  730. let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
  731. let hasSideEffects = false;
  732. let isCommutable = false;
  733. }
  734. // Generic FP division.
  735. def G_FDIV : GenericInstruction {
  736. let OutOperandList = (outs type0:$dst);
  737. let InOperandList = (ins type0:$src1, type0:$src2);
  738. let hasSideEffects = false;
  739. }
  740. // Generic FP remainder.
  741. def G_FREM : GenericInstruction {
  742. let OutOperandList = (outs type0:$dst);
  743. let InOperandList = (ins type0:$src1, type0:$src2);
  744. let hasSideEffects = false;
  745. }
  746. // Floating point exponentiation.
  747. def G_FPOW : GenericInstruction {
  748. let OutOperandList = (outs type0:$dst);
  749. let InOperandList = (ins type0:$src1, type0:$src2);
  750. let hasSideEffects = false;
  751. }
  752. // Floating point exponentiation, with an integer power.
  753. def G_FPOWI : GenericInstruction {
  754. let OutOperandList = (outs type0:$dst);
  755. let InOperandList = (ins type0:$src0, type1:$src1);
  756. let hasSideEffects = false;
  757. }
  758. // Floating point base-e exponential of a value.
  759. def G_FEXP : GenericInstruction {
  760. let OutOperandList = (outs type0:$dst);
  761. let InOperandList = (ins type0:$src1);
  762. let hasSideEffects = false;
  763. }
  764. // Floating point base-2 exponential of a value.
  765. def G_FEXP2 : GenericInstruction {
  766. let OutOperandList = (outs type0:$dst);
  767. let InOperandList = (ins type0:$src1);
  768. let hasSideEffects = false;
  769. }
  770. // Floating point base-e logarithm of a value.
  771. def G_FLOG : GenericInstruction {
  772. let OutOperandList = (outs type0:$dst);
  773. let InOperandList = (ins type0:$src1);
  774. let hasSideEffects = false;
  775. }
  776. // Floating point base-2 logarithm of a value.
  777. def G_FLOG2 : GenericInstruction {
  778. let OutOperandList = (outs type0:$dst);
  779. let InOperandList = (ins type0:$src1);
  780. let hasSideEffects = false;
  781. }
  782. // Floating point base-10 logarithm of a value.
  783. def G_FLOG10 : GenericInstruction {
  784. let OutOperandList = (outs type0:$dst);
  785. let InOperandList = (ins type0:$src1);
  786. let hasSideEffects = false;
  787. }
  788. // Floating point ceiling of a value.
  789. def G_FCEIL : GenericInstruction {
  790. let OutOperandList = (outs type0:$dst);
  791. let InOperandList = (ins type0:$src1);
  792. let hasSideEffects = false;
  793. }
  794. // Floating point cosine of a value.
  795. def G_FCOS : GenericInstruction {
  796. let OutOperandList = (outs type0:$dst);
  797. let InOperandList = (ins type0:$src1);
  798. let hasSideEffects = false;
  799. }
  800. // Floating point sine of a value.
  801. def G_FSIN : GenericInstruction {
  802. let OutOperandList = (outs type0:$dst);
  803. let InOperandList = (ins type0:$src1);
  804. let hasSideEffects = false;
  805. }
  806. // Floating point square root of a value.
  807. // This returns NaN for negative nonzero values.
  808. // NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's
  809. // libm-conformant.
  810. def G_FSQRT : GenericInstruction {
  811. let OutOperandList = (outs type0:$dst);
  812. let InOperandList = (ins type0:$src1);
  813. let hasSideEffects = false;
  814. }
  815. // Floating point floor of a value.
  816. def G_FFLOOR : GenericInstruction {
  817. let OutOperandList = (outs type0:$dst);
  818. let InOperandList = (ins type0:$src1);
  819. let hasSideEffects = false;
  820. }
  821. // Floating point round to next integer.
  822. def G_FRINT : GenericInstruction {
  823. let OutOperandList = (outs type0:$dst);
  824. let InOperandList = (ins type0:$src1);
  825. let hasSideEffects = false;
  826. }
  827. // Floating point round to the nearest integer.
  828. def G_FNEARBYINT : GenericInstruction {
  829. let OutOperandList = (outs type0:$dst);
  830. let InOperandList = (ins type0:$src1);
  831. let hasSideEffects = false;
  832. }
  833. //------------------------------------------------------------------------------
  834. // Opcodes for LLVM Intrinsics
  835. //------------------------------------------------------------------------------
  836. def G_INTRINSIC_TRUNC : GenericInstruction {
  837. let OutOperandList = (outs type0:$dst);
  838. let InOperandList = (ins type0:$src1);
  839. let hasSideEffects = false;
  840. }
  841. def G_INTRINSIC_ROUND : GenericInstruction {
  842. let OutOperandList = (outs type0:$dst);
  843. let InOperandList = (ins type0:$src1);
  844. let hasSideEffects = false;
  845. }
  846. def G_INTRINSIC_LRINT : GenericInstruction {
  847. let OutOperandList = (outs type0:$dst);
  848. let InOperandList = (ins type1:$src);
  849. let hasSideEffects = false;
  850. }
  851. def G_INTRINSIC_ROUNDEVEN : GenericInstruction {
  852. let OutOperandList = (outs type0:$dst);
  853. let InOperandList = (ins type0:$src1);
  854. let hasSideEffects = false;
  855. }
  856. def G_READCYCLECOUNTER : GenericInstruction {
  857. let OutOperandList = (outs type0:$dst);
  858. let InOperandList = (ins);
  859. let hasSideEffects = true;
  860. }
  861. //------------------------------------------------------------------------------
  862. // Memory ops
  863. //------------------------------------------------------------------------------
  864. // Generic load. Expects a MachineMemOperand in addition to explicit
  865. // operands. If the result size is larger than the memory size, the
  866. // high bits are undefined. If the result is a vector type and larger
  867. // than the memory size, the high elements are undefined (i.e. this is
  868. // not a per-element, vector anyextload)
  869. def G_LOAD : GenericInstruction {
  870. let OutOperandList = (outs type0:$dst);
  871. let InOperandList = (ins ptype1:$addr);
  872. let hasSideEffects = false;
  873. let mayLoad = true;
  874. }
  875. // Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
  876. def G_SEXTLOAD : GenericInstruction {
  877. let OutOperandList = (outs type0:$dst);
  878. let InOperandList = (ins ptype1:$addr);
  879. let hasSideEffects = false;
  880. let mayLoad = true;
  881. }
  882. // Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
  883. def G_ZEXTLOAD : GenericInstruction {
  884. let OutOperandList = (outs type0:$dst);
  885. let InOperandList = (ins ptype1:$addr);
  886. let hasSideEffects = false;
  887. let mayLoad = true;
  888. }
  889. // Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
  890. // If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
  891. // then the value is loaded from $newaddr.
  892. def G_INDEXED_LOAD : GenericInstruction {
  893. let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
  894. let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
  895. let hasSideEffects = false;
  896. let mayLoad = true;
  897. }
  898. // Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
  899. def G_INDEXED_SEXTLOAD : GenericInstruction {
  900. let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
  901. let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
  902. let hasSideEffects = false;
  903. let mayLoad = true;
  904. }
  905. // Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
  906. def G_INDEXED_ZEXTLOAD : GenericInstruction {
  907. let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
  908. let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
  909. let hasSideEffects = false;
  910. let mayLoad = true;
  911. }
  912. // Generic store. Expects a MachineMemOperand in addition to explicit operands.
  913. def G_STORE : GenericInstruction {
  914. let OutOperandList = (outs);
  915. let InOperandList = (ins type0:$src, ptype1:$addr);
  916. let hasSideEffects = false;
  917. let mayStore = true;
  918. }
  919. // Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
  920. def G_INDEXED_STORE : GenericInstruction {
  921. let OutOperandList = (outs ptype0:$newaddr);
  922. let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
  923. unknown:$am);
  924. let hasSideEffects = false;
  925. let mayStore = true;
  926. }
  927. // Generic atomic cmpxchg with internal success check. Expects a
  928. // MachineMemOperand in addition to explicit operands.
  929. def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
  930. let OutOperandList = (outs type0:$oldval, type1:$success);
  931. let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
  932. let hasSideEffects = false;
  933. let mayLoad = true;
  934. let mayStore = true;
  935. }
  936. // Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
  937. // operands.
  938. def G_ATOMIC_CMPXCHG : GenericInstruction {
  939. let OutOperandList = (outs type0:$oldval);
  940. let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
  941. let hasSideEffects = false;
  942. let mayLoad = true;
  943. let mayStore = true;
  944. }
  945. // Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
  946. // operands.
  947. class G_ATOMICRMW_OP : GenericInstruction {
  948. let OutOperandList = (outs type0:$oldval);
  949. let InOperandList = (ins ptype1:$addr, type0:$val);
  950. let hasSideEffects = false;
  951. let mayLoad = true;
  952. let mayStore = true;
  953. }
  954. def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
  955. def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
  956. def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
  957. def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
  958. def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
  959. def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
  960. def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
  961. def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
  962. def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
  963. def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
  964. def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
  965. def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
  966. def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
  967. def G_FENCE : GenericInstruction {
  968. let OutOperandList = (outs);
  969. let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
  970. let hasSideEffects = true;
  971. }
  972. //------------------------------------------------------------------------------
  973. // Variadic ops
  974. //------------------------------------------------------------------------------
  975. // Extract a register of the specified size, starting from the block given by
  976. // index. This will almost certainly be mapped to sub-register COPYs after
  977. // register banks have been selected.
  978. def G_EXTRACT : GenericInstruction {
  979. let OutOperandList = (outs type0:$res);
  980. let InOperandList = (ins type1:$src, untyped_imm_0:$offset);
  981. let hasSideEffects = false;
  982. }
  983. // Extract multiple registers specified size, starting from blocks given by
  984. // indexes. This will almost certainly be mapped to sub-register COPYs after
  985. // register banks have been selected.
  986. // The output operands are always ordered from lowest bits to highest:
  987. // %bits_0_7:(s8), %bits_8_15:(s8),
  988. // %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
  989. def G_UNMERGE_VALUES : GenericInstruction {
  990. let OutOperandList = (outs type0:$dst0, variable_ops);
  991. let InOperandList = (ins type1:$src);
  992. let hasSideEffects = false;
  993. }
  994. // Insert a smaller register into a larger one at the specified bit-index.
  995. def G_INSERT : GenericInstruction {
  996. let OutOperandList = (outs type0:$dst);
  997. let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset);
  998. let hasSideEffects = false;
  999. }
  1000. // Concatenate multiple registers of the same size into a wider register.
  1001. // The input operands are always ordered from lowest bits to highest:
  1002. // %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
  1003. // %bits_16_23:(s8), %bits_24_31:(s8)
  1004. def G_MERGE_VALUES : GenericInstruction {
  1005. let OutOperandList = (outs type0:$dst);
  1006. let InOperandList = (ins type1:$src0, variable_ops);
  1007. let hasSideEffects = false;
  1008. }
  1009. /// Create a vector from multiple scalar registers. No implicit
  1010. /// conversion is performed (i.e. the result element type must be the
  1011. /// same as all source operands)
  1012. def G_BUILD_VECTOR : GenericInstruction {
  1013. let OutOperandList = (outs type0:$dst);
  1014. let InOperandList = (ins type1:$src0, variable_ops);
  1015. let hasSideEffects = false;
  1016. }
  1017. /// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
  1018. /// destination vector elt type.
  1019. def G_BUILD_VECTOR_TRUNC : GenericInstruction {
  1020. let OutOperandList = (outs type0:$dst);
  1021. let InOperandList = (ins type1:$src0, variable_ops);
  1022. let hasSideEffects = false;
  1023. }
  1024. /// Create a vector by concatenating vectors together.
  1025. def G_CONCAT_VECTORS : GenericInstruction {
  1026. let OutOperandList = (outs type0:$dst);
  1027. let InOperandList = (ins type1:$src0, variable_ops);
  1028. let hasSideEffects = false;
  1029. }
  1030. // Intrinsic without side effects.
  1031. def G_INTRINSIC : GenericInstruction {
  1032. let OutOperandList = (outs);
  1033. let InOperandList = (ins unknown:$intrin, variable_ops);
  1034. let hasSideEffects = false;
  1035. // Conservatively assume this is convergent. If there turnes out to
  1036. // be a need, there should be separate convergent intrinsic opcodes.
  1037. let isConvergent = 1;
  1038. }
  1039. // Intrinsic with side effects.
  1040. def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
  1041. let OutOperandList = (outs);
  1042. let InOperandList = (ins unknown:$intrin, variable_ops);
  1043. let hasSideEffects = true;
  1044. let mayLoad = true;
  1045. let mayStore = true;
  1046. // Conservatively assume this is convergent. If there turnes out to
  1047. // be a need, there should be separate convergent intrinsic opcodes.
  1048. let isConvergent = true;
  1049. }
  1050. //------------------------------------------------------------------------------
  1051. // Branches.
  1052. //------------------------------------------------------------------------------
  1053. // Generic unconditional branch.
  1054. def G_BR : GenericInstruction {
  1055. let OutOperandList = (outs);
  1056. let InOperandList = (ins unknown:$src1);
  1057. let hasSideEffects = false;
  1058. let isBranch = true;
  1059. let isTerminator = true;
  1060. let isBarrier = true;
  1061. }
  1062. // Generic conditional branch.
  1063. def G_BRCOND : GenericInstruction {
  1064. let OutOperandList = (outs);
  1065. let InOperandList = (ins type0:$tst, unknown:$truebb);
  1066. let hasSideEffects = false;
  1067. let isBranch = true;
  1068. let isTerminator = true;
  1069. }
  1070. // Generic indirect branch.
  1071. def G_BRINDIRECT : GenericInstruction {
  1072. let OutOperandList = (outs);
  1073. let InOperandList = (ins type0:$src1);
  1074. let hasSideEffects = false;
  1075. let isBranch = true;
  1076. let isTerminator = true;
  1077. let isBarrier = true;
  1078. let isIndirectBranch = true;
  1079. }
  1080. // Generic branch to jump table entry
  1081. def G_BRJT : GenericInstruction {
  1082. let OutOperandList = (outs);
  1083. let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
  1084. let hasSideEffects = false;
  1085. let isBranch = true;
  1086. let isTerminator = true;
  1087. let isBarrier = true;
  1088. let isIndirectBranch = true;
  1089. }
  1090. def G_READ_REGISTER : GenericInstruction {
  1091. let OutOperandList = (outs type0:$dst);
  1092. let InOperandList = (ins unknown:$register);
  1093. let hasSideEffects = true;
  1094. // Assume convergent. It's probably not worth the effort of somehow
  1095. // modeling convergent and nonconvergent register accesses.
  1096. let isConvergent = true;
  1097. }
  1098. def G_WRITE_REGISTER : GenericInstruction {
  1099. let OutOperandList = (outs);
  1100. let InOperandList = (ins unknown:$register, type0:$value);
  1101. let hasSideEffects = true;
  1102. // Assume convergent. It's probably not worth the effort of somehow
  1103. // modeling convergent and nonconvergent register accesses.
  1104. let isConvergent = true;
  1105. }
  1106. //------------------------------------------------------------------------------
  1107. // Vector ops
  1108. //------------------------------------------------------------------------------
  1109. // Generic insertelement.
  1110. def G_INSERT_VECTOR_ELT : GenericInstruction {
  1111. let OutOperandList = (outs type0:$dst);
  1112. let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
  1113. let hasSideEffects = false;
  1114. }
  1115. // Generic extractelement.
  1116. def G_EXTRACT_VECTOR_ELT : GenericInstruction {
  1117. let OutOperandList = (outs type0:$dst);
  1118. let InOperandList = (ins type1:$src, type2:$idx);
  1119. let hasSideEffects = false;
  1120. }
  1121. // Generic shufflevector.
  1122. //
  1123. // The mask operand should be an IR Constant which exactly matches the
  1124. // corresponding mask for the IR shufflevector instruction.
  1125. def G_SHUFFLE_VECTOR: GenericInstruction {
  1126. let OutOperandList = (outs type0:$dst);
  1127. let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
  1128. let hasSideEffects = false;
  1129. }
  1130. //------------------------------------------------------------------------------
  1131. // Vector reductions
  1132. //------------------------------------------------------------------------------
  1133. class VectorReduction : GenericInstruction {
  1134. let OutOperandList = (outs type0:$dst);
  1135. let InOperandList = (ins type1:$v);
  1136. let hasSideEffects = false;
  1137. }
  1138. def G_VECREDUCE_SEQ_FADD : GenericInstruction {
  1139. let OutOperandList = (outs type0:$dst);
  1140. let InOperandList = (ins type1:$acc, type2:$v);
  1141. let hasSideEffects = false;
  1142. }
  1143. def G_VECREDUCE_SEQ_FMUL : GenericInstruction {
  1144. let OutOperandList = (outs type0:$dst);
  1145. let InOperandList = (ins type1:$acc, type2:$v);
  1146. let hasSideEffects = false;
  1147. }
  1148. def G_VECREDUCE_FADD : VectorReduction;
  1149. def G_VECREDUCE_FMUL : VectorReduction;
  1150. def G_VECREDUCE_FMAX : VectorReduction;
  1151. def G_VECREDUCE_FMIN : VectorReduction;
  1152. def G_VECREDUCE_ADD : VectorReduction;
  1153. def G_VECREDUCE_MUL : VectorReduction;
  1154. def G_VECREDUCE_AND : VectorReduction;
  1155. def G_VECREDUCE_OR : VectorReduction;
  1156. def G_VECREDUCE_XOR : VectorReduction;
  1157. def G_VECREDUCE_SMAX : VectorReduction;
  1158. def G_VECREDUCE_SMIN : VectorReduction;
  1159. def G_VECREDUCE_UMAX : VectorReduction;
  1160. def G_VECREDUCE_UMIN : VectorReduction;
  1161. //------------------------------------------------------------------------------
  1162. // Constrained floating point ops
  1163. //------------------------------------------------------------------------------
  1164. def G_STRICT_FADD : ConstrainedIntruction<G_FADD>;
  1165. def G_STRICT_FSUB : ConstrainedIntruction<G_FSUB>;
  1166. def G_STRICT_FMUL : ConstrainedIntruction<G_FMUL>;
  1167. def G_STRICT_FDIV : ConstrainedIntruction<G_FDIV>;
  1168. def G_STRICT_FREM : ConstrainedIntruction<G_FREM>;
  1169. def G_STRICT_FMA : ConstrainedIntruction<G_FMA>;
  1170. def G_STRICT_FSQRT : ConstrainedIntruction<G_FSQRT>;
  1171. //------------------------------------------------------------------------------
  1172. // Memory intrinsics
  1173. //------------------------------------------------------------------------------
  1174. def G_MEMCPY : GenericInstruction {
  1175. let OutOperandList = (outs);
  1176. let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
  1177. let hasSideEffects = false;
  1178. let mayLoad = true;
  1179. let mayStore = true;
  1180. }
  1181. def G_MEMCPY_INLINE : GenericInstruction {
  1182. let OutOperandList = (outs);
  1183. let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size);
  1184. let hasSideEffects = false;
  1185. let mayLoad = true;
  1186. let mayStore = true;
  1187. }
  1188. def G_MEMMOVE : GenericInstruction {
  1189. let OutOperandList = (outs);
  1190. let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
  1191. let hasSideEffects = false;
  1192. let mayLoad = true;
  1193. let mayStore = true;
  1194. }
  1195. def G_MEMSET : GenericInstruction {
  1196. let OutOperandList = (outs);
  1197. let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall);
  1198. let hasSideEffects = false;
  1199. let mayStore = true;
  1200. }
  1201. def G_BZERO : GenericInstruction {
  1202. let OutOperandList = (outs);
  1203. let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall);
  1204. let hasSideEffects = false;
  1205. let mayStore = true;
  1206. }
  1207. //------------------------------------------------------------------------------
  1208. // Bitfield extraction.
  1209. //------------------------------------------------------------------------------
  1210. // Generic signed bitfield extraction. The operands are in the range
  1211. // 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
  1212. def G_SBFX : GenericInstruction {
  1213. let OutOperandList = (outs type0:$dst);
  1214. let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
  1215. let hasSideEffects = false;
  1216. }
  1217. // Generic unsigned bitfield extraction. The operands are in the range
  1218. // 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
  1219. def G_UBFX : GenericInstruction {
  1220. let OutOperandList = (outs type0:$dst);
  1221. let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
  1222. let hasSideEffects = false;
  1223. }
  1224. //------------------------------------------------------------------------------
  1225. // Optimization hints
  1226. //------------------------------------------------------------------------------
  1227. // Asserts that an operation has already been zero-extended from a specific
  1228. // type.
  1229. def G_ASSERT_ZEXT : GenericInstruction {
  1230. let OutOperandList = (outs type0:$dst);
  1231. let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
  1232. let hasSideEffects = false;
  1233. }
  1234. // Asserts that an operation has already been sign-extended from a specific
  1235. // type.
  1236. def G_ASSERT_SEXT : GenericInstruction {
  1237. let OutOperandList = (outs type0:$dst);
  1238. let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
  1239. let hasSideEffects = false;
  1240. }
  1241. // Asserts that a value has at least the given alignment.
  1242. def G_ASSERT_ALIGN : GenericInstruction {
  1243. let OutOperandList = (outs type0:$dst);
  1244. let InOperandList = (ins type0:$src, untyped_imm_0:$align);
  1245. let hasSideEffects = false;
  1246. }