GenericOpcodes.td 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469
  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 ptype0:$dst);
  356. let InOperandList = (ins ptype0:$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. // Generic opcode equivalent to the llvm.is_fpclass intrinsic.
  645. def G_IS_FPCLASS: GenericInstruction {
  646. let OutOperandList = (outs type0:$dst);
  647. let InOperandList = (ins type1:$src, unknown:$test);
  648. let hasSideEffects = false;
  649. }
  650. // FMINNUM/FMAXNUM - Perform floating-point minimum or maximum on two
  651. // values.
  652. //
  653. // In the case where a single input is a NaN (either signaling or quiet),
  654. // the non-NaN input is returned.
  655. //
  656. // The return value of (FMINNUM 0.0, -0.0) could be either 0.0 or -0.0.
  657. def G_FMINNUM : 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. def G_FMAXNUM : GenericInstruction {
  664. let OutOperandList = (outs type0:$dst);
  665. let InOperandList = (ins type0:$src1, type0:$src2);
  666. let hasSideEffects = false;
  667. let isCommutable = true;
  668. }
  669. // FMINNUM_IEEE/FMAXNUM_IEEE - Perform floating-point minimum or maximum on
  670. // two values, following the IEEE-754 2008 definition. This differs from
  671. // FMINNUM/FMAXNUM in the handling of signaling NaNs. If one input is a
  672. // signaling NaN, returns a quiet NaN.
  673. def G_FMINNUM_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. def G_FMAXNUM_IEEE : GenericInstruction {
  680. let OutOperandList = (outs type0:$dst);
  681. let InOperandList = (ins type0:$src1, type0:$src2);
  682. let hasSideEffects = false;
  683. let isCommutable = true;
  684. }
  685. // FMINIMUM/FMAXIMUM - NaN-propagating minimum/maximum that also treat -0.0
  686. // as less than 0.0. While FMINNUM_IEEE/FMAXNUM_IEEE follow IEEE 754-2008
  687. // semantics, FMINIMUM/FMAXIMUM follow IEEE 754-2018 draft semantics.
  688. def G_FMINIMUM : 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. def G_FMAXIMUM : GenericInstruction {
  695. let OutOperandList = (outs type0:$dst);
  696. let InOperandList = (ins type0:$src1, type0:$src2);
  697. let hasSideEffects = false;
  698. let isCommutable = true;
  699. }
  700. //------------------------------------------------------------------------------
  701. // Floating Point Binary ops.
  702. //------------------------------------------------------------------------------
  703. // Generic FP addition.
  704. def G_FADD : GenericInstruction {
  705. let OutOperandList = (outs type0:$dst);
  706. let InOperandList = (ins type0:$src1, type0:$src2);
  707. let hasSideEffects = false;
  708. let isCommutable = true;
  709. }
  710. // Generic FP subtraction.
  711. def G_FSUB : GenericInstruction {
  712. let OutOperandList = (outs type0:$dst);
  713. let InOperandList = (ins type0:$src1, type0:$src2);
  714. let hasSideEffects = false;
  715. let isCommutable = false;
  716. }
  717. // Generic FP multiplication.
  718. def G_FMUL : GenericInstruction {
  719. let OutOperandList = (outs type0:$dst);
  720. let InOperandList = (ins type0:$src1, type0:$src2);
  721. let hasSideEffects = false;
  722. let isCommutable = true;
  723. }
  724. // Generic fused multiply-add instruction.
  725. // Behaves like llvm fma intrinsic ie src1 * src2 + src3
  726. def G_FMA : GenericInstruction {
  727. let OutOperandList = (outs type0:$dst);
  728. let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
  729. let hasSideEffects = false;
  730. let isCommutable = false;
  731. }
  732. /// Generic FP multiply and add. Perform a * b + c, while getting the
  733. /// same result as the separately rounded operations, unlike G_FMA.
  734. def G_FMAD : GenericInstruction {
  735. let OutOperandList = (outs type0:$dst);
  736. let InOperandList = (ins type0:$src1, type0:$src2, type0:$src3);
  737. let hasSideEffects = false;
  738. let isCommutable = false;
  739. }
  740. // Generic FP division.
  741. def G_FDIV : GenericInstruction {
  742. let OutOperandList = (outs type0:$dst);
  743. let InOperandList = (ins type0:$src1, type0:$src2);
  744. let hasSideEffects = false;
  745. }
  746. // Generic FP remainder.
  747. def G_FREM : GenericInstruction {
  748. let OutOperandList = (outs type0:$dst);
  749. let InOperandList = (ins type0:$src1, type0:$src2);
  750. let hasSideEffects = false;
  751. }
  752. // Floating point exponentiation.
  753. def G_FPOW : GenericInstruction {
  754. let OutOperandList = (outs type0:$dst);
  755. let InOperandList = (ins type0:$src1, type0:$src2);
  756. let hasSideEffects = false;
  757. }
  758. // Floating point exponentiation, with an integer power.
  759. def G_FPOWI : GenericInstruction {
  760. let OutOperandList = (outs type0:$dst);
  761. let InOperandList = (ins type0:$src0, type1:$src1);
  762. let hasSideEffects = false;
  763. }
  764. // Floating point base-e exponential of a value.
  765. def G_FEXP : GenericInstruction {
  766. let OutOperandList = (outs type0:$dst);
  767. let InOperandList = (ins type0:$src1);
  768. let hasSideEffects = false;
  769. }
  770. // Floating point base-2 exponential of a value.
  771. def G_FEXP2 : GenericInstruction {
  772. let OutOperandList = (outs type0:$dst);
  773. let InOperandList = (ins type0:$src1);
  774. let hasSideEffects = false;
  775. }
  776. // Floating point base-e logarithm of a value.
  777. def G_FLOG : GenericInstruction {
  778. let OutOperandList = (outs type0:$dst);
  779. let InOperandList = (ins type0:$src1);
  780. let hasSideEffects = false;
  781. }
  782. // Floating point base-2 logarithm of a value.
  783. def G_FLOG2 : GenericInstruction {
  784. let OutOperandList = (outs type0:$dst);
  785. let InOperandList = (ins type0:$src1);
  786. let hasSideEffects = false;
  787. }
  788. // Floating point base-10 logarithm of a value.
  789. def G_FLOG10 : GenericInstruction {
  790. let OutOperandList = (outs type0:$dst);
  791. let InOperandList = (ins type0:$src1);
  792. let hasSideEffects = false;
  793. }
  794. // Floating point ceiling of a value.
  795. def G_FCEIL : GenericInstruction {
  796. let OutOperandList = (outs type0:$dst);
  797. let InOperandList = (ins type0:$src1);
  798. let hasSideEffects = false;
  799. }
  800. // Floating point cosine of a value.
  801. def G_FCOS : GenericInstruction {
  802. let OutOperandList = (outs type0:$dst);
  803. let InOperandList = (ins type0:$src1);
  804. let hasSideEffects = false;
  805. }
  806. // Floating point sine of a value.
  807. def G_FSIN : GenericInstruction {
  808. let OutOperandList = (outs type0:$dst);
  809. let InOperandList = (ins type0:$src1);
  810. let hasSideEffects = false;
  811. }
  812. // Floating point square root of a value.
  813. // This returns NaN for negative nonzero values.
  814. // NOTE: Unlike libm sqrt(), this never sets errno. In all other respects it's
  815. // libm-conformant.
  816. def G_FSQRT : GenericInstruction {
  817. let OutOperandList = (outs type0:$dst);
  818. let InOperandList = (ins type0:$src1);
  819. let hasSideEffects = false;
  820. }
  821. // Floating point floor of a value.
  822. def G_FFLOOR : GenericInstruction {
  823. let OutOperandList = (outs type0:$dst);
  824. let InOperandList = (ins type0:$src1);
  825. let hasSideEffects = false;
  826. }
  827. // Floating point round to next integer.
  828. def G_FRINT : GenericInstruction {
  829. let OutOperandList = (outs type0:$dst);
  830. let InOperandList = (ins type0:$src1);
  831. let hasSideEffects = false;
  832. }
  833. // Floating point round to the nearest integer.
  834. def G_FNEARBYINT : GenericInstruction {
  835. let OutOperandList = (outs type0:$dst);
  836. let InOperandList = (ins type0:$src1);
  837. let hasSideEffects = false;
  838. }
  839. //------------------------------------------------------------------------------
  840. // Opcodes for LLVM Intrinsics
  841. //------------------------------------------------------------------------------
  842. def G_INTRINSIC_FPTRUNC_ROUND : GenericInstruction {
  843. let OutOperandList = (outs type0:$dst);
  844. let InOperandList = (ins type1:$src1, i32imm:$round_mode);
  845. let hasSideEffects = false;
  846. }
  847. def G_INTRINSIC_TRUNC : GenericInstruction {
  848. let OutOperandList = (outs type0:$dst);
  849. let InOperandList = (ins type0:$src1);
  850. let hasSideEffects = false;
  851. }
  852. def G_INTRINSIC_ROUND : GenericInstruction {
  853. let OutOperandList = (outs type0:$dst);
  854. let InOperandList = (ins type0:$src1);
  855. let hasSideEffects = false;
  856. }
  857. def G_INTRINSIC_LRINT : GenericInstruction {
  858. let OutOperandList = (outs type0:$dst);
  859. let InOperandList = (ins type1:$src);
  860. let hasSideEffects = false;
  861. }
  862. def G_INTRINSIC_ROUNDEVEN : GenericInstruction {
  863. let OutOperandList = (outs type0:$dst);
  864. let InOperandList = (ins type0:$src1);
  865. let hasSideEffects = false;
  866. }
  867. def G_READCYCLECOUNTER : GenericInstruction {
  868. let OutOperandList = (outs type0:$dst);
  869. let InOperandList = (ins);
  870. let hasSideEffects = true;
  871. }
  872. //------------------------------------------------------------------------------
  873. // Memory ops
  874. //------------------------------------------------------------------------------
  875. // Generic load. Expects a MachineMemOperand in addition to explicit
  876. // operands. If the result size is larger than the memory size, the
  877. // high bits are undefined. If the result is a vector type and larger
  878. // than the memory size, the high elements are undefined (i.e. this is
  879. // not a per-element, vector anyextload)
  880. def G_LOAD : GenericInstruction {
  881. let OutOperandList = (outs type0:$dst);
  882. let InOperandList = (ins ptype1:$addr);
  883. let hasSideEffects = false;
  884. let mayLoad = true;
  885. }
  886. // Generic sign-extended load. Expects a MachineMemOperand in addition to explicit operands.
  887. def G_SEXTLOAD : GenericInstruction {
  888. let OutOperandList = (outs type0:$dst);
  889. let InOperandList = (ins ptype1:$addr);
  890. let hasSideEffects = false;
  891. let mayLoad = true;
  892. }
  893. // Generic zero-extended load. Expects a MachineMemOperand in addition to explicit operands.
  894. def G_ZEXTLOAD : GenericInstruction {
  895. let OutOperandList = (outs type0:$dst);
  896. let InOperandList = (ins ptype1:$addr);
  897. let hasSideEffects = false;
  898. let mayLoad = true;
  899. }
  900. // Generic indexed load. Combines a GEP with a load. $newaddr is set to $base + $offset.
  901. // If $am is 0 (post-indexed), then the value is loaded from $base; if $am is 1 (pre-indexed)
  902. // then the value is loaded from $newaddr.
  903. def G_INDEXED_LOAD : GenericInstruction {
  904. let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
  905. let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
  906. let hasSideEffects = false;
  907. let mayLoad = true;
  908. }
  909. // Same as G_INDEXED_LOAD except that the load performed is sign-extending, as with G_SEXTLOAD.
  910. def G_INDEXED_SEXTLOAD : GenericInstruction {
  911. let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
  912. let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
  913. let hasSideEffects = false;
  914. let mayLoad = true;
  915. }
  916. // Same as G_INDEXED_LOAD except that the load performed is zero-extending, as with G_ZEXTLOAD.
  917. def G_INDEXED_ZEXTLOAD : GenericInstruction {
  918. let OutOperandList = (outs type0:$dst, ptype1:$newaddr);
  919. let InOperandList = (ins ptype1:$base, type2:$offset, unknown:$am);
  920. let hasSideEffects = false;
  921. let mayLoad = true;
  922. }
  923. // Generic store. Expects a MachineMemOperand in addition to explicit operands.
  924. def G_STORE : GenericInstruction {
  925. let OutOperandList = (outs);
  926. let InOperandList = (ins type0:$src, ptype1:$addr);
  927. let hasSideEffects = false;
  928. let mayStore = true;
  929. }
  930. // Combines a store with a GEP. See description of G_INDEXED_LOAD for indexing behaviour.
  931. def G_INDEXED_STORE : GenericInstruction {
  932. let OutOperandList = (outs ptype0:$newaddr);
  933. let InOperandList = (ins type1:$src, ptype0:$base, ptype2:$offset,
  934. unknown:$am);
  935. let hasSideEffects = false;
  936. let mayStore = true;
  937. }
  938. // Generic atomic cmpxchg with internal success check. Expects a
  939. // MachineMemOperand in addition to explicit operands.
  940. def G_ATOMIC_CMPXCHG_WITH_SUCCESS : GenericInstruction {
  941. let OutOperandList = (outs type0:$oldval, type1:$success);
  942. let InOperandList = (ins type2:$addr, type0:$cmpval, type0:$newval);
  943. let hasSideEffects = false;
  944. let mayLoad = true;
  945. let mayStore = true;
  946. }
  947. // Generic atomic cmpxchg. Expects a MachineMemOperand in addition to explicit
  948. // operands.
  949. def G_ATOMIC_CMPXCHG : GenericInstruction {
  950. let OutOperandList = (outs type0:$oldval);
  951. let InOperandList = (ins ptype1:$addr, type0:$cmpval, type0:$newval);
  952. let hasSideEffects = false;
  953. let mayLoad = true;
  954. let mayStore = true;
  955. }
  956. // Generic atomicrmw. Expects a MachineMemOperand in addition to explicit
  957. // operands.
  958. class G_ATOMICRMW_OP : GenericInstruction {
  959. let OutOperandList = (outs type0:$oldval);
  960. let InOperandList = (ins ptype1:$addr, type0:$val);
  961. let hasSideEffects = false;
  962. let mayLoad = true;
  963. let mayStore = true;
  964. }
  965. def G_ATOMICRMW_XCHG : G_ATOMICRMW_OP;
  966. def G_ATOMICRMW_ADD : G_ATOMICRMW_OP;
  967. def G_ATOMICRMW_SUB : G_ATOMICRMW_OP;
  968. def G_ATOMICRMW_AND : G_ATOMICRMW_OP;
  969. def G_ATOMICRMW_NAND : G_ATOMICRMW_OP;
  970. def G_ATOMICRMW_OR : G_ATOMICRMW_OP;
  971. def G_ATOMICRMW_XOR : G_ATOMICRMW_OP;
  972. def G_ATOMICRMW_MAX : G_ATOMICRMW_OP;
  973. def G_ATOMICRMW_MIN : G_ATOMICRMW_OP;
  974. def G_ATOMICRMW_UMAX : G_ATOMICRMW_OP;
  975. def G_ATOMICRMW_UMIN : G_ATOMICRMW_OP;
  976. def G_ATOMICRMW_FADD : G_ATOMICRMW_OP;
  977. def G_ATOMICRMW_FSUB : G_ATOMICRMW_OP;
  978. def G_ATOMICRMW_FMAX : G_ATOMICRMW_OP;
  979. def G_ATOMICRMW_FMIN : G_ATOMICRMW_OP;
  980. def G_ATOMICRMW_UINC_WRAP : G_ATOMICRMW_OP;
  981. def G_ATOMICRMW_UDEC_WRAP : G_ATOMICRMW_OP;
  982. def G_FENCE : GenericInstruction {
  983. let OutOperandList = (outs);
  984. let InOperandList = (ins i32imm:$ordering, i32imm:$scope);
  985. let hasSideEffects = true;
  986. }
  987. //------------------------------------------------------------------------------
  988. // Variadic ops
  989. //------------------------------------------------------------------------------
  990. // Extract a register of the specified size, starting from the block given by
  991. // index. This will almost certainly be mapped to sub-register COPYs after
  992. // register banks have been selected.
  993. def G_EXTRACT : GenericInstruction {
  994. let OutOperandList = (outs type0:$res);
  995. let InOperandList = (ins type1:$src, untyped_imm_0:$offset);
  996. let hasSideEffects = false;
  997. }
  998. // Extract multiple registers specified size, starting from blocks given by
  999. // indexes. This will almost certainly be mapped to sub-register COPYs after
  1000. // register banks have been selected.
  1001. // The output operands are always ordered from lowest bits to highest:
  1002. // %bits_0_7:(s8), %bits_8_15:(s8),
  1003. // %bits_16_23:(s8), %bits_24_31:(s8) = G_UNMERGE_VALUES %0:(s32)
  1004. def G_UNMERGE_VALUES : GenericInstruction {
  1005. let OutOperandList = (outs type0:$dst0, variable_ops);
  1006. let InOperandList = (ins type1:$src);
  1007. let hasSideEffects = false;
  1008. }
  1009. // Insert a smaller register into a larger one at the specified bit-index.
  1010. def G_INSERT : GenericInstruction {
  1011. let OutOperandList = (outs type0:$dst);
  1012. let InOperandList = (ins type0:$src, type1:$op, untyped_imm_0:$offset);
  1013. let hasSideEffects = false;
  1014. }
  1015. // Concatenate multiple registers of the same size into a wider register.
  1016. // The input operands are always ordered from lowest bits to highest:
  1017. // %0:(s32) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8),
  1018. // %bits_16_23:(s8), %bits_24_31:(s8)
  1019. def G_MERGE_VALUES : GenericInstruction {
  1020. let OutOperandList = (outs type0:$dst);
  1021. let InOperandList = (ins type1:$src0, variable_ops);
  1022. let hasSideEffects = false;
  1023. }
  1024. /// Create a vector from multiple scalar registers. No implicit
  1025. /// conversion is performed (i.e. the result element type must be the
  1026. /// same as all source operands)
  1027. def G_BUILD_VECTOR : GenericInstruction {
  1028. let OutOperandList = (outs type0:$dst);
  1029. let InOperandList = (ins type1:$src0, variable_ops);
  1030. let hasSideEffects = false;
  1031. }
  1032. /// Like G_BUILD_VECTOR, but truncates the larger operand types to fit the
  1033. /// destination vector elt type.
  1034. def G_BUILD_VECTOR_TRUNC : GenericInstruction {
  1035. let OutOperandList = (outs type0:$dst);
  1036. let InOperandList = (ins type1:$src0, variable_ops);
  1037. let hasSideEffects = false;
  1038. }
  1039. /// Create a vector by concatenating vectors together.
  1040. def G_CONCAT_VECTORS : GenericInstruction {
  1041. let OutOperandList = (outs type0:$dst);
  1042. let InOperandList = (ins type1:$src0, variable_ops);
  1043. let hasSideEffects = false;
  1044. }
  1045. // Intrinsic without side effects.
  1046. def G_INTRINSIC : GenericInstruction {
  1047. let OutOperandList = (outs);
  1048. let InOperandList = (ins unknown:$intrin, variable_ops);
  1049. let hasSideEffects = false;
  1050. // Conservatively assume this is convergent. If there turnes out to
  1051. // be a need, there should be separate convergent intrinsic opcodes.
  1052. let isConvergent = 1;
  1053. }
  1054. // Intrinsic with side effects.
  1055. def G_INTRINSIC_W_SIDE_EFFECTS : GenericInstruction {
  1056. let OutOperandList = (outs);
  1057. let InOperandList = (ins unknown:$intrin, variable_ops);
  1058. let hasSideEffects = true;
  1059. let mayLoad = true;
  1060. let mayStore = true;
  1061. // Conservatively assume this is convergent. If there turnes out to
  1062. // be a need, there should be separate convergent intrinsic opcodes.
  1063. let isConvergent = true;
  1064. }
  1065. //------------------------------------------------------------------------------
  1066. // Branches.
  1067. //------------------------------------------------------------------------------
  1068. // Generic unconditional branch.
  1069. def G_BR : GenericInstruction {
  1070. let OutOperandList = (outs);
  1071. let InOperandList = (ins unknown:$src1);
  1072. let hasSideEffects = false;
  1073. let isBranch = true;
  1074. let isTerminator = true;
  1075. let isBarrier = true;
  1076. }
  1077. // Generic conditional branch.
  1078. def G_BRCOND : GenericInstruction {
  1079. let OutOperandList = (outs);
  1080. let InOperandList = (ins type0:$tst, unknown:$truebb);
  1081. let hasSideEffects = false;
  1082. let isBranch = true;
  1083. let isTerminator = true;
  1084. }
  1085. // Generic indirect branch.
  1086. def G_BRINDIRECT : GenericInstruction {
  1087. let OutOperandList = (outs);
  1088. let InOperandList = (ins type0:$src1);
  1089. let hasSideEffects = false;
  1090. let isBranch = true;
  1091. let isTerminator = true;
  1092. let isBarrier = true;
  1093. let isIndirectBranch = true;
  1094. }
  1095. // Generic branch to jump table entry
  1096. def G_BRJT : GenericInstruction {
  1097. let OutOperandList = (outs);
  1098. let InOperandList = (ins ptype0:$tbl, unknown:$jti, type1:$idx);
  1099. let hasSideEffects = false;
  1100. let isBranch = true;
  1101. let isTerminator = true;
  1102. let isBarrier = true;
  1103. let isIndirectBranch = true;
  1104. }
  1105. // A marker to signal the following code is an invoke region, that may throw
  1106. // an exception and therefore not return.
  1107. def G_INVOKE_REGION_START : GenericInstruction {
  1108. let OutOperandList = (outs);
  1109. let InOperandList = (ins);
  1110. let isTerminator = true; // This must be a terminator.
  1111. let hasSideEffects = false;
  1112. }
  1113. def G_READ_REGISTER : GenericInstruction {
  1114. let OutOperandList = (outs type0:$dst);
  1115. let InOperandList = (ins unknown:$register);
  1116. let hasSideEffects = true;
  1117. // Assume convergent. It's probably not worth the effort of somehow
  1118. // modeling convergent and nonconvergent register accesses.
  1119. let isConvergent = true;
  1120. }
  1121. def G_WRITE_REGISTER : GenericInstruction {
  1122. let OutOperandList = (outs);
  1123. let InOperandList = (ins unknown:$register, type0:$value);
  1124. let hasSideEffects = true;
  1125. // Assume convergent. It's probably not worth the effort of somehow
  1126. // modeling convergent and nonconvergent register accesses.
  1127. let isConvergent = true;
  1128. }
  1129. //------------------------------------------------------------------------------
  1130. // Vector ops
  1131. //------------------------------------------------------------------------------
  1132. // Generic insertelement.
  1133. def G_INSERT_VECTOR_ELT : GenericInstruction {
  1134. let OutOperandList = (outs type0:$dst);
  1135. let InOperandList = (ins type0:$src, type1:$elt, type2:$idx);
  1136. let hasSideEffects = false;
  1137. }
  1138. // Generic extractelement.
  1139. def G_EXTRACT_VECTOR_ELT : GenericInstruction {
  1140. let OutOperandList = (outs type0:$dst);
  1141. let InOperandList = (ins type1:$src, type2:$idx);
  1142. let hasSideEffects = false;
  1143. }
  1144. // Generic shufflevector.
  1145. //
  1146. // The mask operand should be an IR Constant which exactly matches the
  1147. // corresponding mask for the IR shufflevector instruction.
  1148. def G_SHUFFLE_VECTOR: GenericInstruction {
  1149. let OutOperandList = (outs type0:$dst);
  1150. let InOperandList = (ins type1:$v1, type1:$v2, unknown:$mask);
  1151. let hasSideEffects = false;
  1152. }
  1153. //------------------------------------------------------------------------------
  1154. // Vector reductions
  1155. //------------------------------------------------------------------------------
  1156. class VectorReduction : GenericInstruction {
  1157. let OutOperandList = (outs type0:$dst);
  1158. let InOperandList = (ins type1:$v);
  1159. let hasSideEffects = false;
  1160. }
  1161. def G_VECREDUCE_SEQ_FADD : GenericInstruction {
  1162. let OutOperandList = (outs type0:$dst);
  1163. let InOperandList = (ins type1:$acc, type2:$v);
  1164. let hasSideEffects = false;
  1165. }
  1166. def G_VECREDUCE_SEQ_FMUL : GenericInstruction {
  1167. let OutOperandList = (outs type0:$dst);
  1168. let InOperandList = (ins type1:$acc, type2:$v);
  1169. let hasSideEffects = false;
  1170. }
  1171. def G_VECREDUCE_FADD : VectorReduction;
  1172. def G_VECREDUCE_FMUL : VectorReduction;
  1173. def G_VECREDUCE_FMAX : VectorReduction;
  1174. def G_VECREDUCE_FMIN : VectorReduction;
  1175. def G_VECREDUCE_ADD : VectorReduction;
  1176. def G_VECREDUCE_MUL : VectorReduction;
  1177. def G_VECREDUCE_AND : VectorReduction;
  1178. def G_VECREDUCE_OR : VectorReduction;
  1179. def G_VECREDUCE_XOR : VectorReduction;
  1180. def G_VECREDUCE_SMAX : VectorReduction;
  1181. def G_VECREDUCE_SMIN : VectorReduction;
  1182. def G_VECREDUCE_UMAX : VectorReduction;
  1183. def G_VECREDUCE_UMIN : VectorReduction;
  1184. //------------------------------------------------------------------------------
  1185. // Constrained floating point ops
  1186. //------------------------------------------------------------------------------
  1187. def G_STRICT_FADD : ConstrainedIntruction<G_FADD>;
  1188. def G_STRICT_FSUB : ConstrainedIntruction<G_FSUB>;
  1189. def G_STRICT_FMUL : ConstrainedIntruction<G_FMUL>;
  1190. def G_STRICT_FDIV : ConstrainedIntruction<G_FDIV>;
  1191. def G_STRICT_FREM : ConstrainedIntruction<G_FREM>;
  1192. def G_STRICT_FMA : ConstrainedIntruction<G_FMA>;
  1193. def G_STRICT_FSQRT : ConstrainedIntruction<G_FSQRT>;
  1194. //------------------------------------------------------------------------------
  1195. // Memory intrinsics
  1196. //------------------------------------------------------------------------------
  1197. def G_MEMCPY : GenericInstruction {
  1198. let OutOperandList = (outs);
  1199. let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
  1200. let hasSideEffects = false;
  1201. let mayLoad = true;
  1202. let mayStore = true;
  1203. }
  1204. def G_MEMCPY_INLINE : GenericInstruction {
  1205. let OutOperandList = (outs);
  1206. let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size);
  1207. let hasSideEffects = false;
  1208. let mayLoad = true;
  1209. let mayStore = true;
  1210. }
  1211. def G_MEMMOVE : GenericInstruction {
  1212. let OutOperandList = (outs);
  1213. let InOperandList = (ins ptype0:$dst_addr, ptype1:$src_addr, type2:$size, untyped_imm_0:$tailcall);
  1214. let hasSideEffects = false;
  1215. let mayLoad = true;
  1216. let mayStore = true;
  1217. }
  1218. def G_MEMSET : GenericInstruction {
  1219. let OutOperandList = (outs);
  1220. let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall);
  1221. let hasSideEffects = false;
  1222. let mayStore = true;
  1223. }
  1224. def G_BZERO : GenericInstruction {
  1225. let OutOperandList = (outs);
  1226. let InOperandList = (ins ptype0:$dst_addr, type1:$size, untyped_imm_0:$tailcall);
  1227. let hasSideEffects = false;
  1228. let mayStore = true;
  1229. }
  1230. //------------------------------------------------------------------------------
  1231. // Bitfield extraction.
  1232. //------------------------------------------------------------------------------
  1233. // Generic signed bitfield extraction. The operands are in the range
  1234. // 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
  1235. def G_SBFX : GenericInstruction {
  1236. let OutOperandList = (outs type0:$dst);
  1237. let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
  1238. let hasSideEffects = false;
  1239. }
  1240. // Generic unsigned bitfield extraction. The operands are in the range
  1241. // 0 <= lsb < lsb + width <= src bitwidth, where all values are unsigned.
  1242. def G_UBFX : GenericInstruction {
  1243. let OutOperandList = (outs type0:$dst);
  1244. let InOperandList = (ins type0:$src, type1:$lsb, type1:$width);
  1245. let hasSideEffects = false;
  1246. }
  1247. //------------------------------------------------------------------------------
  1248. // Optimization hints
  1249. //------------------------------------------------------------------------------
  1250. // Asserts that an operation has already been zero-extended from a specific
  1251. // type.
  1252. def G_ASSERT_ZEXT : GenericInstruction {
  1253. let OutOperandList = (outs type0:$dst);
  1254. let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
  1255. let hasSideEffects = false;
  1256. }
  1257. // Asserts that an operation has already been sign-extended from a specific
  1258. // type.
  1259. def G_ASSERT_SEXT : GenericInstruction {
  1260. let OutOperandList = (outs type0:$dst);
  1261. let InOperandList = (ins type0:$src, untyped_imm_0:$sz);
  1262. let hasSideEffects = false;
  1263. }
  1264. // Asserts that a value has at least the given alignment.
  1265. def G_ASSERT_ALIGN : GenericInstruction {
  1266. let OutOperandList = (outs type0:$dst);
  1267. let InOperandList = (ins type0:$src, untyped_imm_0:$align);
  1268. let hasSideEffects = false;
  1269. }