Skip to main content

cranelift_codegen_meta/shared/
instructions.rs

1#![expect(non_snake_case, reason = "DSL style here")]
2
3use crate::cdsl::instructions::{
4    AllInstructions, InstructionBuilder as Inst, InstructionGroupBuilder,
5};
6use crate::cdsl::operands::Operand;
7use crate::cdsl::types::{LaneType, ValueType};
8use crate::cdsl::typevar::{Interval, TypeSetBuilder, TypeVar};
9use crate::shared::formats::Formats;
10use crate::shared::types;
11use crate::shared::{entities::EntityRefs, immediates::Immediates};
12
13#[inline(never)]
14fn define_control_flow(
15    ig: &mut InstructionGroupBuilder,
16    formats: &Formats,
17    imm: &Immediates,
18    entities: &EntityRefs,
19) {
20    ig.push(
21        Inst::new(
22            "jump",
23            r#"
24        Jump.
25
26        Unconditionally jump to a basic block, passing the specified
27        block arguments. The number and types of arguments must match the
28        destination block.
29        "#,
30            &formats.jump,
31        )
32        .operands_in(&[Operand::new("block_call", &entities.block_call)
33            .with_doc("Destination basic block, with its arguments provided")])
34        .branches(),
35    );
36
37    let ScalarTruthy = &TypeVar::new(
38        "ScalarTruthy",
39        "A scalar truthy type",
40        TypeSetBuilder::new().ints(Interval::All).build(),
41    );
42
43    ig.push(
44        Inst::new(
45            "brif",
46            r#"
47        Conditional branch when cond is non-zero.
48
49        Take the ``then`` branch when ``c != 0``, and the ``else`` branch otherwise.
50        "#,
51            &formats.brif,
52        )
53        .operands_in(&[
54            Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
55            Operand::new("block_then", &entities.block_then).with_doc("Then block"),
56            Operand::new("block_else", &entities.block_else).with_doc("Else block"),
57        ])
58        .branches(),
59    );
60
61    {
62        let _i32 = &TypeVar::new(
63            "i32",
64            "A 32 bit scalar integer type",
65            TypeSetBuilder::new().ints(32..32).build(),
66        );
67
68        ig.push(
69            Inst::new(
70                "br_table",
71                r#"
72        Indirect branch via jump table.
73
74        Use ``x`` as an unsigned index into the jump table ``JT``. If a jump
75        table entry is found, branch to the corresponding block. If no entry was
76        found or the index is out-of-bounds, branch to the default block of the
77        table.
78
79        Note that this branch instruction can't pass arguments to the targeted
80        blocks. Split critical edges as needed to work around this.
81
82        Do not confuse this with "tables" in WebAssembly. ``br_table`` is for
83        jump tables with destinations within the current function only -- think
84        of a ``match`` in Rust or a ``switch`` in C.  If you want to call a
85        function in a dynamic library, that will typically use
86        ``call_indirect``.
87        "#,
88                &formats.branch_table,
89            )
90            .operands_in(&[
91                Operand::new("x", _i32).with_doc("i32 index into jump table"),
92                Operand::new("JT", &entities.jump_table),
93            ])
94            .branches(),
95        );
96    }
97
98    let iAddr = &TypeVar::new(
99        "iAddr",
100        "An integer address type",
101        TypeSetBuilder::new().ints(32..64).build(),
102    );
103
104    ig.push(
105        Inst::new(
106            "debugtrap",
107            r#"
108        Encodes an assembly debug trap.
109        "#,
110            &formats.nullary,
111        )
112        .other_side_effects()
113        .can_load()
114        .can_store(),
115    );
116
117    ig.push(
118        Inst::new(
119            "trap",
120            r#"
121        Terminate execution unconditionally.
122        "#,
123            &formats.trap,
124        )
125        .operands_in(&[Operand::new("code", &imm.trapcode)])
126        .can_trap()
127        .terminates_block(),
128    );
129
130    ig.push(
131        Inst::new(
132            "trapz",
133            r#"
134        Trap when zero.
135
136        if ``c`` is non-zero, execution continues at the following instruction.
137        "#,
138            &formats.cond_trap,
139        )
140        .operands_in(&[
141            Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
142            Operand::new("code", &imm.trapcode),
143        ])
144        .can_trap()
145        // When one `trapz` dominates another `trapz` and they have identical
146        // conditions and trap codes, it is safe to deduplicate them (like GVN,
147        // although there is not actually any value being numbered). Either the
148        // first `trapz` raised a trap and execution halted, or it didn't and
149        // therefore the dominated `trapz` will not raise a trap either.
150        .side_effects_idempotent(),
151    );
152
153    ig.push(
154        Inst::new(
155            "trapnz",
156            r#"
157        Trap when non-zero.
158
159        If ``c`` is zero, execution continues at the following instruction.
160        "#,
161            &formats.cond_trap,
162        )
163        .operands_in(&[
164            Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
165            Operand::new("code", &imm.trapcode),
166        ])
167        .can_trap()
168        // See the above comment for `trapz` and idempotent side effects.
169        .side_effects_idempotent(),
170    );
171
172    ig.push(
173        Inst::new(
174            "return",
175            r#"
176        Return from the function.
177
178        Unconditionally transfer control to the calling function, passing the
179        provided return values. The list of return values must match the
180        function signature's return types.
181        "#,
182            &formats.multiary,
183        )
184        .operands_in(&[Operand::new("rvals", &entities.varargs).with_doc("return values")])
185        .returns(),
186    );
187
188    ig.push(
189        Inst::new(
190            "call",
191            r#"
192        Direct function call.
193
194        Call a function which has been declared in the preamble. The argument
195        types must match the function's signature.
196        "#,
197            &formats.call,
198        )
199        .operands_in(&[
200            Operand::new("FN", &entities.func_ref)
201                .with_doc("function to call, declared by `function`"),
202            Operand::new("args", &entities.varargs).with_doc("call arguments"),
203        ])
204        .operands_out(&[Operand::new("rvals", &entities.varargs).with_doc("return values")])
205        .call(),
206    );
207
208    ig.push(
209        Inst::new(
210            "call_indirect",
211            r#"
212        Indirect function call.
213
214        Call the function pointed to by `callee` with the given arguments. The
215        called function must match the specified signature.
216
217        Note that this is different from WebAssembly's ``call_indirect``; the
218        callee is a native address, rather than a table index. For WebAssembly,
219        `table_addr` and `load` are used to obtain a native address
220        from a table.
221        "#,
222            &formats.call_indirect,
223        )
224        .operands_in(&[
225            Operand::new("SIG", &entities.sig_ref).with_doc("function signature"),
226            Operand::new("callee", iAddr).with_doc("address of function to call"),
227            Operand::new("args", &entities.varargs).with_doc("call arguments"),
228        ])
229        .operands_out(&[Operand::new("rvals", &entities.varargs).with_doc("return values")])
230        .call(),
231    );
232
233    ig.push(
234        Inst::new(
235            "return_call",
236            r#"
237        Direct tail call.
238
239        Tail call a function which has been declared in the preamble. The
240        argument types must match the function's signature, the caller and
241        callee calling conventions must be the same, and must be a calling
242        convention that supports tail calls.
243
244        This instruction is a block terminator.
245        "#,
246            &formats.call,
247        )
248        .operands_in(&[
249            Operand::new("FN", &entities.func_ref)
250                .with_doc("function to call, declared by `function`"),
251            Operand::new("args", &entities.varargs).with_doc("call arguments"),
252        ])
253        .returns()
254        .call(),
255    );
256
257    ig.push(
258        Inst::new(
259            "return_call_indirect",
260            r#"
261        Indirect tail call.
262
263        Call the function pointed to by `callee` with the given arguments. The
264        argument types must match the function's signature, the caller and
265        callee calling conventions must be the same, and must be a calling
266        convention that supports tail calls.
267
268        This instruction is a block terminator.
269
270        Note that this is different from WebAssembly's ``tail_call_indirect``;
271        the callee is a native address, rather than a table index. For
272        WebAssembly, `table_addr` and `load` are used to obtain a native address
273        from a table.
274        "#,
275            &formats.call_indirect,
276        )
277        .operands_in(&[
278            Operand::new("SIG", &entities.sig_ref).with_doc("function signature"),
279            Operand::new("callee", iAddr).with_doc("address of function to call"),
280            Operand::new("args", &entities.varargs).with_doc("call arguments"),
281        ])
282        .returns()
283        .call(),
284    );
285
286    ig.push(
287        Inst::new(
288            "func_addr",
289            r#"
290        Get the address of a function.
291
292        Compute the absolute address of a function declared in the preamble.
293        The returned address can be used as a ``callee`` argument to
294        `call_indirect`. This is also a method for calling functions that
295        are too far away to be addressable by a direct `call`
296        instruction.
297        "#,
298            &formats.func_addr,
299        )
300        .operands_in(&[Operand::new("FN", &entities.func_ref)
301            .with_doc("function to call, declared by `function`")])
302        .operands_out(&[Operand::new("addr", iAddr)]),
303    );
304
305    ig.push(
306        Inst::new(
307            "try_call",
308            r#"
309        Call a function, catching the specified exceptions.
310
311        Call the function pointed to by `callee` with the given arguments. On
312        normal return, branch to the first target, with function returns
313        available as `retN` block arguments. On exceptional return,
314        look up the thrown exception tag in the provided exception table;
315        if the tag matches one of the targets, branch to the matching
316        target with the exception payloads available as `exnN` block arguments.
317        If no tag matches, then propagate the exception up the stack.
318
319        It is the Cranelift embedder's responsibility to define the meaning
320        of tags: they are accepted by this instruction and passed through
321        to unwind metadata tables in Cranelift's output. Actual unwinding is
322        outside the purview of the core Cranelift compiler.
323
324        Payload values on exception are passed in fixed register(s) that are
325        defined by the platform and ABI. See the documentation on `CallConv`
326        for details.
327        "#,
328            &formats.try_call,
329        )
330        .operands_in(&[
331            Operand::new("callee", &entities.func_ref)
332                .with_doc("function to call, declared by `function`"),
333            Operand::new("args", &entities.varargs).with_doc("call arguments"),
334            Operand::new("ET", &entities.exception_table).with_doc("exception table"),
335        ])
336        .call()
337        .branches(),
338    );
339
340    ig.push(
341        Inst::new(
342            "try_call_indirect",
343            r#"
344        Call a function, catching the specified exceptions.
345
346        Call the function pointed to by `callee` with the given arguments. On
347        normal return, branch to the first target, with function returns
348        available as `retN` block arguments. On exceptional return,
349        look up the thrown exception tag in the provided exception table;
350        if the tag matches one of the targets, branch to the matching
351        target with the exception payloads available as `exnN` block arguments.
352        If no tag matches, then propagate the exception up the stack.
353
354        It is the Cranelift embedder's responsibility to define the meaning
355        of tags: they are accepted by this instruction and passed through
356        to unwind metadata tables in Cranelift's output. Actual unwinding is
357        outside the purview of the core Cranelift compiler.
358
359        Payload values on exception are passed in fixed register(s) that are
360        defined by the platform and ABI. See the documentation on `CallConv`
361        for details.
362        "#,
363            &formats.try_call_indirect,
364        )
365        .operands_in(&[
366            Operand::new("callee", iAddr).with_doc("address of function to call"),
367            Operand::new("args", &entities.varargs).with_doc("call arguments"),
368            Operand::new("ET", &entities.exception_table).with_doc("exception table"),
369        ])
370        .call()
371        .branches(),
372    );
373
374    ig.push(
375        Inst::new(
376            "interrupt_poll",
377            r#"
378        Load from a memory location to possibly trigger a resumeable
379        interruption.
380
381        This sequence of operations captures the semantics:
382            - register A := context
383            - Reserve register B as scratch space.
384            - register C := load_ptr
385            - _ := memory\[load_ptr\]
386            - result := register C
387
388        Exact choices of registers are ISA-specific; see each backend's
389        `get_operands` for the registers and the reasoning behind them.
390
391        In addition, at codegen time, the address of the load instruction is
392        recorded in the binary's trap table.
393
394        This instruction aids in implementing virtual-memory-triggered
395        interrupts, with the load trapping if the loaded location is
396        inaccessible. The trap handler can then take further action, first using
397        the trap table to confirm that this instruction was the cause. The
398        handler can receive further arbitrary input in `context`. It can use the
399        second reserved register as scratch space: for example, to record the
400        original resumption address so it can arrange to "return to" a
401        trampoline first, which can ultimately then jump to the original
402        address. (Such gymnastics are necessary on platforms where signal
403        handlers cannot push stack frames directly.) It is expected that
404        execution will ultimately resume at the load, re-running it; care must
405        be taken to ensure it succeeds the second time, lest the whole process
406        repeat. This is where the output `next_load_ptr` comes in, carrying a
407        new location to load from. All current implementations (x64 and aarch64)
408        pin `load_ptr` and `next_load_ptr` to the same register so a move from
409        the latter to the former does not even need to be emitted.
410        "#,
411            &formats.int_add_trap,
412        )
413        .operands_in(&[
414            Operand::new("load_ptr", iAddr).with_doc("memory location to load from"),
415            Operand::new("context", iAddr)
416                .with_doc("arbitrary address-sized context to place into a known register"),
417            Operand::new("code", &imm.trapcode)
418                .with_doc("trap code to record at the load's address"),
419        ])
420        .operands_out(&[
421            Operand::new("next_load_ptr", iAddr).with_doc("memory location to load from next time")
422        ])
423        // As with `stack_switch`, this instruction is a call, in that "it
424        // continues execution elsewhere". See reasoning at
425        // https://github.com/bytecodealliance/wasmtime/pull/9078#issuecomment-2273869774.
426        .call()
427        .can_load()
428        // It may transfer control to something that may store. Declaring this
429        // makes us a memory fence.
430        .can_store()
431        // The universe of possible side effects is wide open. Control may never
432        // even return to this point. When this instruction is used to trigger
433        // preemption, we certainly do not want it hoisted or deduplicated via
434        // GVN.
435        .other_side_effects(),
436        // If `load` is not `can_trap()`, this isn't either.
437        //
438        // This cannot use `side_effects_idempotent()`: its purpose is to allow
439        // deduplication or LICM of redundant instructions. The decision made by
440        // `interrupt_poll` (implicitly, via trap) is determined by the flags on
441        // the page of memory loaded, which change at runtime, outside the
442        // purview of the compiler. Thus, the tuple formed by the instruction
443        // and its input operands is not sufficient to decide redundancy.
444    );
445}
446
447#[inline(never)]
448fn define_simd_lane_access(
449    ig: &mut InstructionGroupBuilder,
450    formats: &Formats,
451    imm: &Immediates,
452    _: &EntityRefs,
453) {
454    let TxN = &TypeVar::new(
455        "TxN",
456        "A SIMD vector type",
457        TypeSetBuilder::new()
458            .ints(Interval::All)
459            .floats(Interval::All)
460            .simd_lanes(Interval::All)
461            .dynamic_simd_lanes(Interval::All)
462            .includes_scalars(false)
463            .build(),
464    );
465
466    ig.push(
467        Inst::new(
468            "splat",
469            r#"
470        Vector splat.
471
472        Return a vector whose lanes are all ``x``.
473        "#,
474            &formats.unary,
475        )
476        .operands_in(&[Operand::new("x", &TxN.lane_of()).with_doc("Value to splat to all lanes")])
477        .operands_out(&[Operand::new("a", TxN)]),
478    );
479
480    let I8x16 = &TypeVar::new(
481        "I8x16",
482        "A SIMD vector type consisting of 16 lanes of 8-bit integers",
483        TypeSetBuilder::new()
484            .ints(8..8)
485            .simd_lanes(16..16)
486            .includes_scalars(false)
487            .build(),
488    );
489
490    ig.push(
491        Inst::new(
492            "swizzle",
493            r#"
494        Vector swizzle.
495
496        Returns a new vector with byte-width lanes selected from the lanes of the first input
497        vector ``x`` specified in the second input vector ``s``. The indices ``i`` in range
498        ``[0, 15]`` select the ``i``-th element of ``x``. For indices outside of the range the
499        resulting lane is 0. Note that this operates on byte-width lanes.
500        "#,
501            &formats.binary,
502        )
503        .operands_in(&[
504            Operand::new("x", I8x16).with_doc("Vector to modify by re-arranging lanes"),
505            Operand::new("y", I8x16).with_doc("Mask for re-arranging lanes"),
506        ])
507        .operands_out(&[Operand::new("a", I8x16)]),
508    );
509
510    ig.push(
511        Inst::new(
512            "x86_pshufb",
513            r#"
514        A vector swizzle lookalike which has the semantics of `pshufb` on x64.
515
516        This instruction will permute the 8-bit lanes of `x` with the indices
517        specified in `y`. Each lane in the mask, `y`, uses the bottom four
518        bits for selecting the lane from `x` unless the most significant bit
519        is set, in which case the lane is zeroed. The output vector will have
520        the following contents when the element of `y` is in these ranges:
521
522        * `[0, 127]` -> `x[y[i] % 16]`
523        * `[128, 255]` -> 0
524        "#,
525            &formats.binary,
526        )
527        .operands_in(&[
528            Operand::new("x", I8x16).with_doc("Vector to modify by re-arranging lanes"),
529            Operand::new("y", I8x16).with_doc("Mask for re-arranging lanes"),
530        ])
531        .operands_out(&[Operand::new("a", I8x16)]),
532    );
533
534    ig.push(
535        Inst::new(
536            "insertlane",
537            r#"
538        Insert ``y`` as lane ``Idx`` in x.
539
540        The lane index, ``Idx``, is an immediate value, not an SSA value. It
541        must indicate a valid lane index for the type of ``x``.
542        "#,
543            &formats.ternary_imm8,
544        )
545        .operands_in(&[
546            Operand::new("x", TxN).with_doc("The vector to modify"),
547            Operand::new("y", &TxN.lane_of()).with_doc("New lane value"),
548            Operand::new("Idx", &imm.uimm8).with_doc("Lane index"),
549        ])
550        .operands_out(&[Operand::new("a", TxN)]),
551    );
552
553    ig.push(
554        Inst::new(
555            "extractlane",
556            r#"
557        Extract lane ``Idx`` from ``x``.
558
559        The lane index, ``Idx``, is an immediate value, not an SSA value. It
560        must indicate a valid lane index for the type of ``x``. Note that the upper bits of ``a``
561        may or may not be zeroed depending on the ISA but the type system should prevent using
562        ``a`` as anything other than the extracted value.
563        "#,
564            &formats.binary_imm8,
565        )
566        .operands_in(&[
567            Operand::new("x", TxN),
568            Operand::new("Idx", &imm.uimm8).with_doc("Lane index"),
569        ])
570        .operands_out(&[Operand::new("a", &TxN.lane_of())]),
571    );
572}
573
574#[inline(never)]
575fn define_simd_arithmetic(
576    ig: &mut InstructionGroupBuilder,
577    formats: &Formats,
578    _: &Immediates,
579    _: &EntityRefs,
580) {
581    let Int = &TypeVar::new(
582        "Int",
583        "A scalar or vector integer type",
584        TypeSetBuilder::new()
585            .ints(Interval::All)
586            .simd_lanes(Interval::All)
587            .build(),
588    );
589
590    ig.push(
591        Inst::new(
592            "smin",
593            r#"
594        Signed integer minimum.
595        "#,
596            &formats.binary,
597        )
598        .operands_in(&[Operand::new("x", Int), Operand::new("y", Int)])
599        .operands_out(&[Operand::new("a", Int)]),
600    );
601
602    ig.push(
603        Inst::new(
604            "umin",
605            r#"
606        Unsigned integer minimum.
607        "#,
608            &formats.binary,
609        )
610        .operands_in(&[Operand::new("x", Int), Operand::new("y", Int)])
611        .operands_out(&[Operand::new("a", Int)]),
612    );
613
614    ig.push(
615        Inst::new(
616            "smax",
617            r#"
618        Signed integer maximum.
619        "#,
620            &formats.binary,
621        )
622        .operands_in(&[Operand::new("x", Int), Operand::new("y", Int)])
623        .operands_out(&[Operand::new("a", Int)]),
624    );
625
626    ig.push(
627        Inst::new(
628            "umax",
629            r#"
630        Unsigned integer maximum.
631        "#,
632            &formats.binary,
633        )
634        .operands_in(&[Operand::new("x", Int), Operand::new("y", Int)])
635        .operands_out(&[Operand::new("a", Int)]),
636    );
637
638    let IxN = &TypeVar::new(
639        "IxN",
640        "A SIMD vector type containing integers",
641        TypeSetBuilder::new()
642            .ints(Interval::All)
643            .simd_lanes(Interval::All)
644            .includes_scalars(false)
645            .build(),
646    );
647
648    ig.push(
649        Inst::new(
650            "avg_round",
651            r#"
652        Unsigned average with rounding: `a := (x + y + 1) // 2`
653
654        The addition does not lose any information (such as from overflow).
655        "#,
656            &formats.binary,
657        )
658        .operands_in(&[Operand::new("x", IxN), Operand::new("y", IxN)])
659        .operands_out(&[Operand::new("a", IxN)]),
660    );
661
662    ig.push(
663        Inst::new(
664            "uadd_sat",
665            r#"
666        Add with unsigned saturation.
667
668        This is similar to `iadd` but the operands are interpreted as unsigned integers and their
669        summed result, instead of wrapping, will be saturated to the highest unsigned integer for
670        the controlling type (e.g. `0xFF` for i8).
671        "#,
672            &formats.binary,
673        )
674        .operands_in(&[Operand::new("x", IxN), Operand::new("y", IxN)])
675        .operands_out(&[Operand::new("a", IxN)]),
676    );
677
678    ig.push(
679        Inst::new(
680            "sadd_sat",
681            r#"
682        Add with signed saturation.
683
684        This is similar to `iadd` but the operands are interpreted as signed integers and their
685        summed result, instead of wrapping, will be saturated to the lowest or highest
686        signed integer for the controlling type (e.g. `0x80` or `0x7F` for i8). For example,
687        since an `sadd_sat.i8` of `0x70` and `0x70` is greater than `0x7F`, the result will be
688        clamped to `0x7F`.
689        "#,
690            &formats.binary,
691        )
692        .operands_in(&[Operand::new("x", IxN), Operand::new("y", IxN)])
693        .operands_out(&[Operand::new("a", IxN)]),
694    );
695
696    ig.push(
697        Inst::new(
698            "usub_sat",
699            r#"
700        Subtract with unsigned saturation.
701
702        This is similar to `isub` but the operands are interpreted as unsigned integers and their
703        difference, instead of wrapping, will be saturated to the lowest unsigned integer for
704        the controlling type (e.g. `0x00` for i8).
705        "#,
706            &formats.binary,
707        )
708        .operands_in(&[Operand::new("x", IxN), Operand::new("y", IxN)])
709        .operands_out(&[Operand::new("a", IxN)]),
710    );
711
712    ig.push(
713        Inst::new(
714            "ssub_sat",
715            r#"
716        Subtract with signed saturation.
717
718        This is similar to `isub` but the operands are interpreted as signed integers and their
719        difference, instead of wrapping, will be saturated to the lowest or highest
720        signed integer for the controlling type (e.g. `0x80` or `0x7F` for i8).
721        "#,
722            &formats.binary,
723        )
724        .operands_in(&[Operand::new("x", IxN), Operand::new("y", IxN)])
725        .operands_out(&[Operand::new("a", IxN)]),
726    );
727}
728
729pub(crate) fn define(
730    all_instructions: &mut AllInstructions,
731    formats: &Formats,
732    imm: &Immediates,
733    entities: &EntityRefs,
734) {
735    let mut ig = InstructionGroupBuilder::new(all_instructions);
736
737    define_control_flow(&mut ig, formats, imm, entities);
738    define_simd_lane_access(&mut ig, formats, imm, entities);
739    define_simd_arithmetic(&mut ig, formats, imm, entities);
740
741    // Operand kind shorthands.
742    let i8: &TypeVar = &ValueType::from(LaneType::from(types::Int::I8)).into();
743    let f16_: &TypeVar = &ValueType::from(LaneType::from(types::Float::F16)).into();
744    let f32_: &TypeVar = &ValueType::from(LaneType::from(types::Float::F32)).into();
745    let f64_: &TypeVar = &ValueType::from(LaneType::from(types::Float::F64)).into();
746    let f128_: &TypeVar = &ValueType::from(LaneType::from(types::Float::F128)).into();
747
748    // Starting definitions.
749    let Int = &TypeVar::new(
750        "Int",
751        "A scalar or vector integer type",
752        TypeSetBuilder::new()
753            .ints(Interval::All)
754            .simd_lanes(Interval::All)
755            .dynamic_simd_lanes(Interval::All)
756            .build(),
757    );
758
759    let NarrowInt = &TypeVar::new(
760        "NarrowInt",
761        "An integer type of width up to `i64`",
762        TypeSetBuilder::new().ints(8..64).build(),
763    );
764
765    let ScalarTruthy = &TypeVar::new(
766        "ScalarTruthy",
767        "A scalar truthy type",
768        TypeSetBuilder::new().ints(Interval::All).build(),
769    );
770
771    let iB = &TypeVar::new(
772        "iB",
773        "A scalar integer type",
774        TypeSetBuilder::new().ints(Interval::All).build(),
775    );
776
777    let iSwappable = &TypeVar::new(
778        "iSwappable",
779        "A multi byte scalar integer type",
780        TypeSetBuilder::new().ints(16..128).build(),
781    );
782
783    let iAddr = &TypeVar::new(
784        "iAddr",
785        "An integer address type",
786        TypeSetBuilder::new().ints(32..64).build(),
787    );
788
789    let TxN = &TypeVar::new(
790        "TxN",
791        "A SIMD vector type",
792        TypeSetBuilder::new()
793            .ints(Interval::All)
794            .floats(Interval::All)
795            .simd_lanes(Interval::All)
796            .includes_scalars(false)
797            .build(),
798    );
799    let Any = &TypeVar::new(
800        "Any",
801        "Any integer, float, or reference scalar or vector type",
802        TypeSetBuilder::new()
803            .ints(Interval::All)
804            .floats(Interval::All)
805            .simd_lanes(Interval::All)
806            .includes_scalars(true)
807            .build(),
808    );
809
810    let Mem = &TypeVar::new(
811        "Mem",
812        "Any type that can be stored in memory",
813        TypeSetBuilder::new()
814            .ints(Interval::All)
815            .floats(Interval::All)
816            .simd_lanes(Interval::All)
817            .dynamic_simd_lanes(Interval::All)
818            .build(),
819    );
820
821    let MemTo = &TypeVar::copy_from(Mem, "MemTo".to_string());
822
823    ig.push(
824        Inst::new(
825            "load",
826            r#"
827        Load from memory at ``p + Offset``.
828
829        This is a polymorphic instruction that can load any value type which
830        has a memory representation.
831        "#,
832            &formats.load,
833        )
834        .operands_in(&[
835            Operand::new("MemFlags", &imm.memflags),
836            Operand::new("p", iAddr),
837            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
838        ])
839        .operands_out(&[Operand::new("a", Mem).with_doc("Value loaded")])
840        .can_load(),
841    );
842
843    ig.push(
844        Inst::new(
845            "store",
846            r#"
847        Store ``x`` to memory at ``p + Offset``.
848
849        This is a polymorphic instruction that can store any value type with a
850        memory representation.
851        "#,
852            &formats.store,
853        )
854        .operands_in(&[
855            Operand::new("MemFlags", &imm.memflags),
856            Operand::new("x", Mem).with_doc("Value to be stored"),
857            Operand::new("p", iAddr),
858            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
859        ])
860        .can_store(),
861    );
862
863    let iExt8 = &TypeVar::new(
864        "iExt8",
865        "An integer type with more than 8 bits",
866        TypeSetBuilder::new().ints(16..64).build(),
867    );
868
869    ig.push(
870        Inst::new(
871            "uload8",
872            r#"
873        Load 8 bits from memory at ``p + Offset`` and zero-extend.
874
875        This is equivalent to ``load.i8`` followed by ``uextend``.
876        "#,
877            &formats.load,
878        )
879        .operands_in(&[
880            Operand::new("MemFlags", &imm.memflags),
881            Operand::new("p", iAddr),
882            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
883        ])
884        .operands_out(&[Operand::new("a", iExt8)])
885        .can_load(),
886    );
887
888    ig.push(
889        Inst::new(
890            "sload8",
891            r#"
892        Load 8 bits from memory at ``p + Offset`` and sign-extend.
893
894        This is equivalent to ``load.i8`` followed by ``sextend``.
895        "#,
896            &formats.load,
897        )
898        .operands_in(&[
899            Operand::new("MemFlags", &imm.memflags),
900            Operand::new("p", iAddr),
901            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
902        ])
903        .operands_out(&[Operand::new("a", iExt8)])
904        .can_load(),
905    );
906
907    ig.push(
908        Inst::new(
909            "istore8",
910            r#"
911        Store the low 8 bits of ``x`` to memory at ``p + Offset``.
912
913        This is equivalent to ``ireduce.i8`` followed by ``store.i8``.
914        "#,
915            &formats.store,
916        )
917        .operands_in(&[
918            Operand::new("MemFlags", &imm.memflags),
919            Operand::new("x", iExt8),
920            Operand::new("p", iAddr),
921            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
922        ])
923        .can_store(),
924    );
925
926    let iExt16 = &TypeVar::new(
927        "iExt16",
928        "An integer type with more than 16 bits",
929        TypeSetBuilder::new().ints(32..64).build(),
930    );
931
932    ig.push(
933        Inst::new(
934            "uload16",
935            r#"
936        Load 16 bits from memory at ``p + Offset`` and zero-extend.
937
938        This is equivalent to ``load.i16`` followed by ``uextend``.
939        "#,
940            &formats.load,
941        )
942        .operands_in(&[
943            Operand::new("MemFlags", &imm.memflags),
944            Operand::new("p", iAddr),
945            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
946        ])
947        .operands_out(&[Operand::new("a", iExt16)])
948        .can_load(),
949    );
950
951    ig.push(
952        Inst::new(
953            "sload16",
954            r#"
955        Load 16 bits from memory at ``p + Offset`` and sign-extend.
956
957        This is equivalent to ``load.i16`` followed by ``sextend``.
958        "#,
959            &formats.load,
960        )
961        .operands_in(&[
962            Operand::new("MemFlags", &imm.memflags),
963            Operand::new("p", iAddr),
964            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
965        ])
966        .operands_out(&[Operand::new("a", iExt16)])
967        .can_load(),
968    );
969
970    ig.push(
971        Inst::new(
972            "istore16",
973            r#"
974        Store the low 16 bits of ``x`` to memory at ``p + Offset``.
975
976        This is equivalent to ``ireduce.i16`` followed by ``store.i16``.
977        "#,
978            &formats.store,
979        )
980        .operands_in(&[
981            Operand::new("MemFlags", &imm.memflags),
982            Operand::new("x", iExt16),
983            Operand::new("p", iAddr),
984            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
985        ])
986        .can_store(),
987    );
988
989    let iExt32 = &TypeVar::new(
990        "iExt32",
991        "An integer type with more than 32 bits",
992        TypeSetBuilder::new().ints(64..64).build(),
993    );
994
995    ig.push(
996        Inst::new(
997            "uload32",
998            r#"
999        Load 32 bits from memory at ``p + Offset`` and zero-extend.
1000
1001        This is equivalent to ``load.i32`` followed by ``uextend``.
1002        "#,
1003            &formats.load,
1004        )
1005        .operands_in(&[
1006            Operand::new("MemFlags", &imm.memflags),
1007            Operand::new("p", iAddr),
1008            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1009        ])
1010        .operands_out(&[Operand::new("a", iExt32)])
1011        .can_load(),
1012    );
1013
1014    ig.push(
1015        Inst::new(
1016            "sload32",
1017            r#"
1018        Load 32 bits from memory at ``p + Offset`` and sign-extend.
1019
1020        This is equivalent to ``load.i32`` followed by ``sextend``.
1021        "#,
1022            &formats.load,
1023        )
1024        .operands_in(&[
1025            Operand::new("MemFlags", &imm.memflags),
1026            Operand::new("p", iAddr),
1027            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1028        ])
1029        .operands_out(&[Operand::new("a", iExt32)])
1030        .can_load(),
1031    );
1032
1033    ig.push(
1034        Inst::new(
1035            "istore32",
1036            r#"
1037        Store the low 32 bits of ``x`` to memory at ``p + Offset``.
1038
1039        This is equivalent to ``ireduce.i32`` followed by ``store.i32``.
1040        "#,
1041            &formats.store,
1042        )
1043        .operands_in(&[
1044            Operand::new("MemFlags", &imm.memflags),
1045            Operand::new("x", iExt32),
1046            Operand::new("p", iAddr),
1047            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1048        ])
1049        .can_store(),
1050    );
1051    ig.push(
1052        Inst::new(
1053            "stack_switch",
1054            r#"
1055        Suspends execution of the current stack and resumes execution of another
1056        one.
1057
1058        The target stack to switch to is identified by the data stored at
1059        ``load_context_ptr``. Before switching, this instruction stores
1060        analogous information about the
1061        current (i.e., original) stack at ``store_context_ptr``, to
1062        enabled switching back to the original stack at a later point.
1063
1064        The size, alignment and layout of the information stored at
1065        ``load_context_ptr`` and ``store_context_ptr`` is platform-dependent.
1066        The instruction assumes that ``load_context_ptr`` and
1067        ``store_context_ptr`` are valid pointers to memory with said layout and
1068        alignment, and does not perform any checks on these pointers or the data
1069        stored there.
1070
1071        The instruction is experimental and only supported on x64 Linux at the
1072        moment.
1073
1074        When switching from a stack A to a stack B, one of the following cases
1075        must apply:
1076        1. Stack B was previously suspended using a ``stack_switch`` instruction.
1077        2. Stack B is a newly initialized stack. The necessary initialization is
1078        platform-dependent and will generally involve running some kind of
1079        trampoline to start execution of a function on the new stack.
1080
1081        In both cases, the ``in_payload`` argument of the ``stack_switch``
1082        instruction executed on A is passed to stack B. In the first case above,
1083        it will be the result value of the earlier ``stack_switch`` instruction
1084        executed on stack B. In the second case, the value will be accessible to
1085        the trampoline in a platform-dependent register.
1086
1087        The pointers ``load_context_ptr`` and ``store_context_ptr`` are allowed
1088        to be equal; the instruction ensures that all data is loaded from the
1089        former before writing to the latter.
1090
1091        Stack switching is one-shot in the sense that each ``stack_switch``
1092        operation effectively consumes the context identified by
1093        ``load_context_ptr``. In other words, performing two ``stack_switches``
1094        using the same ``load_context_ptr`` causes undefined behavior, unless
1095        the context at ``load_context_ptr`` is overwritten by another
1096        `stack_switch` in between.
1097        "#,
1098            &formats.ternary,
1099        )
1100        .operands_in(&[
1101            Operand::new("store_context_ptr", iAddr),
1102            Operand::new("load_context_ptr", iAddr),
1103            Operand::new("in_payload0", iAddr),
1104        ])
1105        .operands_out(&[Operand::new("out_payload0", iAddr)])
1106        .other_side_effects()
1107        .can_load()
1108        .can_store()
1109        .call(),
1110    );
1111
1112    let I16x8 = &TypeVar::new(
1113        "I16x8",
1114        "A SIMD vector with exactly 8 lanes of 16-bit values",
1115        TypeSetBuilder::new()
1116            .ints(16..16)
1117            .simd_lanes(8..8)
1118            .includes_scalars(false)
1119            .build(),
1120    );
1121
1122    ig.push(
1123        Inst::new(
1124            "uload8x8",
1125            r#"
1126        Load an 8x8 vector (64 bits) from memory at ``p + Offset`` and zero-extend into an i16x8
1127        vector.
1128        "#,
1129            &formats.load,
1130        )
1131        .operands_in(&[
1132            Operand::new("MemFlags", &imm.memflags),
1133            Operand::new("p", iAddr),
1134            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1135        ])
1136        .operands_out(&[Operand::new("a", I16x8).with_doc("Value loaded")])
1137        .can_load(),
1138    );
1139
1140    ig.push(
1141        Inst::new(
1142            "sload8x8",
1143            r#"
1144        Load an 8x8 vector (64 bits) from memory at ``p + Offset`` and sign-extend into an i16x8
1145        vector.
1146        "#,
1147            &formats.load,
1148        )
1149        .operands_in(&[
1150            Operand::new("MemFlags", &imm.memflags),
1151            Operand::new("p", iAddr),
1152            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1153        ])
1154        .operands_out(&[Operand::new("a", I16x8).with_doc("Value loaded")])
1155        .can_load(),
1156    );
1157
1158    let I32x4 = &TypeVar::new(
1159        "I32x4",
1160        "A SIMD vector with exactly 4 lanes of 32-bit values",
1161        TypeSetBuilder::new()
1162            .ints(32..32)
1163            .simd_lanes(4..4)
1164            .includes_scalars(false)
1165            .build(),
1166    );
1167
1168    ig.push(
1169        Inst::new(
1170            "uload16x4",
1171            r#"
1172        Load a 16x4 vector (64 bits) from memory at ``p + Offset`` and zero-extend into an i32x4
1173        vector.
1174        "#,
1175            &formats.load,
1176        )
1177        .operands_in(&[
1178            Operand::new("MemFlags", &imm.memflags),
1179            Operand::new("p", iAddr),
1180            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1181        ])
1182        .operands_out(&[Operand::new("a", I32x4).with_doc("Value loaded")])
1183        .can_load(),
1184    );
1185
1186    ig.push(
1187        Inst::new(
1188            "sload16x4",
1189            r#"
1190        Load a 16x4 vector (64 bits) from memory at ``p + Offset`` and sign-extend into an i32x4
1191        vector.
1192        "#,
1193            &formats.load,
1194        )
1195        .operands_in(&[
1196            Operand::new("MemFlags", &imm.memflags),
1197            Operand::new("p", iAddr),
1198            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1199        ])
1200        .operands_out(&[Operand::new("a", I32x4).with_doc("Value loaded")])
1201        .can_load(),
1202    );
1203
1204    let I64x2 = &TypeVar::new(
1205        "I64x2",
1206        "A SIMD vector with exactly 2 lanes of 64-bit values",
1207        TypeSetBuilder::new()
1208            .ints(64..64)
1209            .simd_lanes(2..2)
1210            .includes_scalars(false)
1211            .build(),
1212    );
1213
1214    ig.push(
1215        Inst::new(
1216            "uload32x2",
1217            r#"
1218        Load an 32x2 vector (64 bits) from memory at ``p + Offset`` and zero-extend into an i64x2
1219        vector.
1220        "#,
1221            &formats.load,
1222        )
1223        .operands_in(&[
1224            Operand::new("MemFlags", &imm.memflags),
1225            Operand::new("p", iAddr),
1226            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1227        ])
1228        .operands_out(&[Operand::new("a", I64x2).with_doc("Value loaded")])
1229        .can_load(),
1230    );
1231
1232    ig.push(
1233        Inst::new(
1234            "sload32x2",
1235            r#"
1236        Load a 32x2 vector (64 bits) from memory at ``p + Offset`` and sign-extend into an i64x2
1237        vector.
1238        "#,
1239            &formats.load,
1240        )
1241        .operands_in(&[
1242            Operand::new("MemFlags", &imm.memflags),
1243            Operand::new("p", iAddr),
1244            Operand::new("Offset", &imm.offset32).with_doc("Byte offset from base address"),
1245        ])
1246        .operands_out(&[Operand::new("a", I64x2).with_doc("Value loaded")])
1247        .can_load(),
1248    );
1249
1250    ig.push(
1251        Inst::new(
1252            "stack_addr",
1253            r#"
1254        Get the address of a stack slot.
1255
1256        Compute the absolute address of a byte in a stack slot. The offset must
1257        refer to a byte inside the stack slot:
1258        `0 <= Offset < sizeof(SS)`.
1259        "#,
1260            &formats.stack_addr,
1261        )
1262        .operands_in(&[
1263            Operand::new("SS", &entities.stack_slot),
1264            Operand::new("Offset", &imm.offset32).with_doc("In-bounds offset into stack slot"),
1265        ])
1266        .operands_out(&[Operand::new("addr", iAddr)]),
1267    );
1268
1269    ig.push(
1270        Inst::new(
1271            "dynamic_stack_addr",
1272            r#"
1273        Get the address of a dynamic stack slot.
1274
1275        Compute the absolute address of the first byte of a dynamic stack slot.
1276        "#,
1277            &formats.dynamic_stack_addr,
1278        )
1279        .operands_in(&[Operand::new("DSS", &entities.dynamic_stack_slot)])
1280        .operands_out(&[Operand::new("addr", iAddr)]),
1281    );
1282
1283    ig.push(
1284        Inst::new(
1285            "symbol_value",
1286            r#"
1287        Compute the value of global GV, which is a symbolic value.
1288        "#,
1289            &formats.unary_global_value,
1290        )
1291        .operands_in(&[Operand::new("GV", &entities.global_value)])
1292        .operands_out(&[Operand::new("a", Mem).with_doc("Value loaded")]),
1293    );
1294
1295    ig.push(
1296        Inst::new(
1297            "tls_value",
1298            r#"
1299        Compute the value of global GV, which is a TLS (thread local storage) value.
1300        "#,
1301            &formats.unary_global_value,
1302        )
1303        .operands_in(&[Operand::new("GV", &entities.global_value)])
1304        .operands_out(&[Operand::new("a", Mem).with_doc("Value loaded")]),
1305    );
1306
1307    // Note this instruction is marked as having other side-effects, so GVN won't try to hoist it,
1308    // which would result in it being subject to spilling. While not hoisting would generally hurt
1309    // performance, since a computed value used many times may need to be regenerated before each
1310    // use, it is not the case here: this instruction doesn't generate any code.  That's because,
1311    // by definition the pinned register is never used by the register allocator, but is written to
1312    // and read explicitly and exclusively by set_pinned_reg and get_pinned_reg.
1313    ig.push(
1314        Inst::new(
1315            "get_pinned_reg",
1316            r#"
1317            Gets the content of the pinned register, when it's enabled.
1318        "#,
1319            &formats.nullary,
1320        )
1321        .operands_out(&[Operand::new("addr", iAddr)])
1322        .other_side_effects(),
1323    );
1324
1325    ig.push(
1326        Inst::new(
1327            "set_pinned_reg",
1328            r#"
1329        Sets the content of the pinned register, when it's enabled.
1330        "#,
1331            &formats.unary,
1332        )
1333        .operands_in(&[Operand::new("addr", iAddr)])
1334        .other_side_effects(),
1335    );
1336
1337    ig.push(
1338        Inst::new(
1339            "get_frame_pointer",
1340            r#"
1341        Get the address in the frame pointer register.
1342
1343        Usage of this instruction requires setting `preserve_frame_pointers` to `true`.
1344        "#,
1345            &formats.nullary,
1346        )
1347        .operands_out(&[Operand::new("addr", iAddr)]),
1348    );
1349
1350    ig.push(
1351        Inst::new(
1352            "get_stack_pointer",
1353            r#"
1354        Get the address in the stack pointer register.
1355        "#,
1356            &formats.nullary,
1357        )
1358        .operands_out(&[Operand::new("addr", iAddr)]),
1359    );
1360
1361    ig.push(
1362        Inst::new(
1363            "get_return_address",
1364            r#"
1365        Get the PC where this function will transfer control to when it returns.
1366
1367        Usage of this instruction requires setting `preserve_frame_pointers` to `true`.
1368        "#,
1369            &formats.nullary,
1370        )
1371        .operands_out(&[Operand::new("addr", iAddr)]),
1372    );
1373
1374    ig.push(
1375        Inst::new(
1376            "get_exception_handler_address",
1377            r#"
1378        Get the handler PC for the given exceptional edge for an
1379        exception return from the given `try_call`-terminated block.
1380
1381        This instruction provides the PC for the handler resume point,
1382        as defined by the exception-handling aspect of the given
1383        callee ABI, for a return from the given calling block.  It can
1384        be used when the exception unwind mechanism requires manual
1385        plumbing for this information which must be set up before the call
1386        itself: for example, if the resume address needs to be stored in
1387        some context structure for a runtime to resume to on error.
1388
1389        The given caller block must end in a `try_call` and the given
1390        exception-handling block must be one of its exceptional
1391        successors in the associated exception-handling table. The
1392        returned PC is *only* valid to resume to when the `try_call`
1393        is on the stack having called the callee; in other words, when
1394        a normal exception unwinder might otherwise resume to that
1395        handler.
1396        "#,
1397            &formats.exception_handler_address,
1398        )
1399        .operands_in(&[
1400            Operand::new("block", &entities.raw_block),
1401            Operand::new("index", &imm.imm64),
1402        ])
1403        .operands_out(&[Operand::new("addr", iAddr)]),
1404    );
1405
1406    ig.push(
1407        Inst::new(
1408            "iconst",
1409            r#"
1410        Integer constant.
1411
1412        Create a scalar integer SSA value with an immediate constant value, or
1413        an integer vector where all the lanes have the same value.
1414        "#,
1415            &formats.unary_imm,
1416        )
1417        .operands_in(&[Operand::new("N", &imm.imm64)])
1418        .operands_out(&[
1419            Operand::new("a", NarrowInt).with_doc("A constant integer scalar or vector value")
1420        ]),
1421    );
1422
1423    ig.push(
1424        Inst::new(
1425            "f16const",
1426            r#"
1427        Floating point constant.
1428
1429        Create a `f16` SSA value with an immediate constant value.
1430        "#,
1431            &formats.unary_ieee16,
1432        )
1433        .operands_in(&[Operand::new("N", &imm.ieee16)])
1434        .operands_out(&[Operand::new("a", f16_).with_doc("A constant f16 scalar value")]),
1435    );
1436
1437    ig.push(
1438        Inst::new(
1439            "f32const",
1440            r#"
1441        Floating point constant.
1442
1443        Create a `f32` SSA value with an immediate constant value.
1444        "#,
1445            &formats.unary_ieee32,
1446        )
1447        .operands_in(&[Operand::new("N", &imm.ieee32)])
1448        .operands_out(&[Operand::new("a", f32_).with_doc("A constant f32 scalar value")]),
1449    );
1450
1451    ig.push(
1452        Inst::new(
1453            "f64const",
1454            r#"
1455        Floating point constant.
1456
1457        Create a `f64` SSA value with an immediate constant value.
1458        "#,
1459            &formats.unary_ieee64,
1460        )
1461        .operands_in(&[Operand::new("N", &imm.ieee64)])
1462        .operands_out(&[Operand::new("a", f64_).with_doc("A constant f64 scalar value")]),
1463    );
1464
1465    ig.push(
1466        Inst::new(
1467            "f128const",
1468            r#"
1469        Floating point constant.
1470
1471        Create a `f128` SSA value with an immediate constant value.
1472        "#,
1473            &formats.unary_const,
1474        )
1475        .operands_in(&[Operand::new("N", &entities.pool_constant)])
1476        .operands_out(&[Operand::new("a", f128_).with_doc("A constant f128 scalar value")]),
1477    );
1478
1479    ig.push(
1480        Inst::new(
1481            "vconst",
1482            r#"
1483        SIMD vector constant.
1484
1485        Construct a vector with the given immediate bytes.
1486        "#,
1487            &formats.unary_const,
1488        )
1489        .operands_in(&[Operand::new("N", &entities.pool_constant)
1490            .with_doc("The 16 immediate bytes of a 128-bit vector")])
1491        .operands_out(&[Operand::new("a", TxN).with_doc("A constant vector value")]),
1492    );
1493
1494    let Tx16 = &TypeVar::new(
1495        "Tx16",
1496        "A SIMD vector with exactly 16 lanes of 8-bit values; eventually this may support other \
1497         lane counts and widths",
1498        TypeSetBuilder::new()
1499            .ints(8..8)
1500            .simd_lanes(16..16)
1501            .includes_scalars(false)
1502            .build(),
1503    );
1504
1505    ig.push(
1506        Inst::new(
1507            "shuffle",
1508            r#"
1509        SIMD vector shuffle.
1510
1511        Shuffle two vectors using the given immediate bytes. For each of the 16 bytes of the
1512        immediate, a value i of 0-15 selects the i-th element of the first vector and a value i of
1513        16-31 selects the (i-16)th element of the second vector. Immediate values outside of the
1514        0-31 range are not valid.
1515        "#,
1516            &formats.shuffle,
1517        )
1518        .operands_in(&[
1519            Operand::new("a", Tx16).with_doc("A vector value"),
1520            Operand::new("b", Tx16).with_doc("A vector value"),
1521            Operand::new("mask", &entities.uimm128)
1522                .with_doc("The 16 immediate bytes used for selecting the elements to shuffle"),
1523        ])
1524        .operands_out(&[Operand::new("a", Tx16).with_doc("A vector value")]),
1525    );
1526
1527    ig.push(Inst::new(
1528        "nop",
1529        r#"
1530        Just a dummy instruction.
1531
1532        Note: this doesn't compile to a machine code nop.
1533        "#,
1534        &formats.nullary,
1535    ));
1536
1537    ig.push(
1538        Inst::new(
1539            "select",
1540            r#"
1541        Conditional select.
1542
1543        This instruction selects whole values. Use `bitselect` to choose each
1544        bit according to a mask.
1545        "#,
1546            &formats.ternary,
1547        )
1548        .operands_in(&[
1549            Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
1550            Operand::new("x", Any).with_doc("Value to use when `c` is true"),
1551            Operand::new("y", Any).with_doc("Value to use when `c` is false"),
1552        ])
1553        .operands_out(&[Operand::new("a", Any)]),
1554    );
1555
1556    ig.push(
1557        Inst::new(
1558            "select_spectre_guard",
1559            r#"
1560            Conditional select intended for Spectre guards.
1561
1562            This operation is semantically equivalent to a select instruction.
1563            However, this instruction prohibits all speculation on the
1564            controlling value when determining which input to use as the result.
1565            As such, it is suitable for use in Spectre guards.
1566
1567            For example, on a target which may speculatively execute branches,
1568            the lowering of this instruction is guaranteed to not conditionally
1569            branch. Instead it will typically lower to a conditional move
1570            instruction. (No Spectre-vulnerable processors are known to perform
1571            value speculation on conditional move instructions.)
1572
1573            Ensure that the instruction you're trying to protect from Spectre
1574            attacks has a data dependency on the result of this instruction.
1575            That prevents an out-of-order CPU from evaluating that instruction
1576            until the result of this one is known, which in turn will be blocked
1577            until the controlling value is known.
1578
1579            Typical usage is to use a bounds-check as the controlling value,
1580            and select between either a null pointer if the bounds-check
1581            fails, or an in-bounds address otherwise, so that dereferencing
1582            the resulting address with a load or store instruction will trap if
1583            the bounds-check failed. When this instruction is used in this way,
1584            any microarchitectural side effects of the memory access will only
1585            occur after the bounds-check finishes, which ensures that no Spectre
1586            vulnerability will exist.
1587
1588            Optimization opportunities for this instruction are limited compared
1589            to a normal select instruction, but it is allowed to be replaced
1590            by other values which are functionally equivalent as long as doing
1591            so does not introduce any new opportunities to speculate on the
1592            controlling value.
1593            "#,
1594            &formats.ternary,
1595        )
1596        .operands_in(&[
1597            Operand::new("c", ScalarTruthy).with_doc("Controlling value to test"),
1598            Operand::new("x", Any).with_doc("Value to use when `c` is true"),
1599            Operand::new("y", Any).with_doc("Value to use when `c` is false"),
1600        ])
1601        .operands_out(&[Operand::new("a", Any)]),
1602    );
1603
1604    ig.push(
1605        Inst::new(
1606            "bitselect",
1607            r#"
1608        Conditional select of bits.
1609
1610        For each bit in `c`, this instruction selects the corresponding bit from `x` if the bit
1611        in `c` is 1 and the corresponding bit from `y` if the bit in `c` is 0. See also:
1612        `select`.
1613        "#,
1614            &formats.ternary,
1615        )
1616        .operands_in(&[
1617            Operand::new("c", Any).with_doc("Controlling value to test"),
1618            Operand::new("x", Any).with_doc("Value to use when `c` is true"),
1619            Operand::new("y", Any).with_doc("Value to use when `c` is false"),
1620        ])
1621        .operands_out(&[Operand::new("a", Any)]),
1622    );
1623
1624    ig.push(
1625        Inst::new(
1626            "blendv",
1627            r#"
1628        A bitselect-lookalike instruction except with the semantics of
1629        `blendv`-related instructions on x86.
1630
1631        This instruction will use the top bit of each lane in `c`, the condition
1632        mask. If the bit is 1 then the corresponding lane from `x` is chosen.
1633        Otherwise the corresponding lane from `y` is chosen.
1634
1635            "#,
1636            &formats.ternary,
1637        )
1638        .operands_in(&[
1639            Operand::new("c", Any).with_doc("Controlling value to test"),
1640            Operand::new("x", Any).with_doc("Value to use when `c` is true"),
1641            Operand::new("y", Any).with_doc("Value to use when `c` is false"),
1642        ])
1643        .operands_out(&[Operand::new("a", Any)]),
1644    );
1645
1646    ig.push(
1647        Inst::new(
1648            "vany_true",
1649            r#"
1650        Reduce a vector to a scalar boolean.
1651
1652        Return a scalar boolean true if any lane in ``a`` is non-zero, false otherwise.
1653        "#,
1654            &formats.unary,
1655        )
1656        .operands_in(&[Operand::new("a", TxN)])
1657        .operands_out(&[Operand::new("s", i8)]),
1658    );
1659
1660    ig.push(
1661        Inst::new(
1662            "vall_true",
1663            r#"
1664        Reduce a vector to a scalar boolean.
1665
1666        Return a scalar boolean true if all lanes in ``i`` are non-zero, false otherwise.
1667        "#,
1668            &formats.unary,
1669        )
1670        .operands_in(&[Operand::new("a", TxN)])
1671        .operands_out(&[Operand::new("s", i8)]),
1672    );
1673
1674    ig.push(
1675        Inst::new(
1676            "vhigh_bits",
1677            r#"
1678        Reduce a vector to a scalar integer.
1679
1680        Return a scalar integer, consisting of the concatenation of the most significant bit
1681        of each lane of ``a``.
1682        "#,
1683            &formats.unary,
1684        )
1685        .operands_in(&[Operand::new("a", TxN)])
1686        .operands_out(&[Operand::new("x", NarrowInt)]),
1687    );
1688
1689    ig.push(
1690        Inst::new(
1691            "icmp",
1692            r#"
1693        Integer comparison.
1694
1695        The condition code determines if the operands are interpreted as signed
1696        or unsigned integers.
1697
1698        | Signed | Unsigned | Condition             |
1699        |--------|----------|-----------------------|
1700        | eq     | eq       | Equal                 |
1701        | ne     | ne       | Not equal             |
1702        | slt    | ult      | Less than             |
1703        | sge    | uge      | Greater than or equal |
1704        | sgt    | ugt      | Greater than          |
1705        | sle    | ule      | Less than or equal    |
1706
1707        When this instruction compares integer vectors, it returns a vector of
1708        lane-wise comparisons.
1709
1710        When comparing scalars, the result is:
1711            - `1` if the condition holds.
1712            - `0` if the condition does not hold.
1713
1714        When comparing vectors, the result is:
1715            - `-1` (i.e. all ones) in each lane where the condition holds.
1716            - `0` in each lane where the condition does not hold.
1717        "#,
1718            &formats.int_compare,
1719        )
1720        .operands_in(&[
1721            Operand::new("Cond", &imm.intcc),
1722            Operand::new("x", Int),
1723            Operand::new("y", Int),
1724        ])
1725        .operands_out(&[Operand::new("a", &Int.as_truthy())])
1726        .inst_builder_imm_method(true),
1727    );
1728
1729    ig.push(
1730        Inst::new(
1731            "iadd",
1732            r#"
1733        Wrapping integer addition: `a := x + y \pmod{2^B}`.
1734
1735        This instruction does not depend on the signed/unsigned interpretation
1736        of the operands.
1737        "#,
1738            &formats.binary,
1739        )
1740        .operands_in(&[Operand::new("x", Int), Operand::new("y", Int)])
1741        .operands_out(&[Operand::new("a", Int)])
1742        .inst_builder_imm_method(true),
1743    );
1744
1745    ig.push(
1746        Inst::new(
1747            "isub",
1748            r#"
1749        Wrapping integer subtraction: `a := x - y \pmod{2^B}`.
1750
1751        This instruction does not depend on the signed/unsigned interpretation
1752        of the operands.
1753        "#,
1754            &formats.binary,
1755        )
1756        .operands_in(&[Operand::new("x", Int), Operand::new("y", Int)])
1757        .operands_out(&[Operand::new("a", Int)]),
1758    );
1759
1760    ig.push(
1761        Inst::new(
1762            "ineg",
1763            r#"
1764        Integer negation: `a := -x \pmod{2^B}`.
1765        "#,
1766            &formats.unary,
1767        )
1768        .operands_in(&[Operand::new("x", Int)])
1769        .operands_out(&[Operand::new("a", Int)]),
1770    );
1771
1772    ig.push(
1773        Inst::new(
1774            "iabs",
1775            r#"
1776        Integer absolute value with wrapping: `a := |x|`.
1777        "#,
1778            &formats.unary,
1779        )
1780        .operands_in(&[Operand::new("x", Int)])
1781        .operands_out(&[Operand::new("a", Int)]),
1782    );
1783
1784    ig.push(
1785        Inst::new(
1786            "imul",
1787            r#"
1788        Wrapping integer multiplication: `a := x y \pmod{2^B}`.
1789
1790        This instruction does not depend on the signed/unsigned interpretation
1791        of the operands.
1792
1793        Polymorphic over all integer types (vector and scalar).
1794        "#,
1795            &formats.binary,
1796        )
1797        .operands_in(&[Operand::new("x", Int), Operand::new("y", Int)])
1798        .operands_out(&[Operand::new("a", Int)])
1799        .inst_builder_imm_method(true),
1800    );
1801
1802    ig.push(
1803        Inst::new(
1804            "umulhi",
1805            r#"
1806        Unsigned integer multiplication, producing the high half of a
1807        double-length result.
1808
1809        Polymorphic over all integer types (vector and scalar).
1810        "#,
1811            &formats.binary,
1812        )
1813        .operands_in(&[Operand::new("x", Int), Operand::new("y", Int)])
1814        .operands_out(&[Operand::new("a", Int)]),
1815    );
1816
1817    ig.push(
1818        Inst::new(
1819            "smulhi",
1820            r#"
1821        Signed integer multiplication, producing the high half of a
1822        double-length result.
1823
1824        Polymorphic over all integer types (vector and scalar).
1825        "#,
1826            &formats.binary,
1827        )
1828        .operands_in(&[Operand::new("x", Int), Operand::new("y", Int)])
1829        .operands_out(&[Operand::new("a", Int)]),
1830    );
1831
1832    let I16or32 = &TypeVar::new(
1833        "I16or32",
1834        "A vector integer type with 16- or 32-bit numbers",
1835        TypeSetBuilder::new().ints(16..32).simd_lanes(4..8).build(),
1836    );
1837
1838    ig.push(
1839        Inst::new(
1840            "sqmul_round_sat",
1841            r#"
1842        Fixed-point multiplication of numbers in the QN format, where N + 1
1843        is the number bitwidth:
1844        `a := signed_saturate((x * y + (1 << (Q - 1))) >> Q)`
1845
1846        Polymorphic over all integer vector types with 16- or 32-bit numbers.
1847        "#,
1848            &formats.binary,
1849        )
1850        .operands_in(&[Operand::new("x", I16or32), Operand::new("y", I16or32)])
1851        .operands_out(&[Operand::new("a", I16or32)]),
1852    );
1853
1854    ig.push(
1855        Inst::new(
1856            "x86_pmulhrsw",
1857            r#"
1858        A similar instruction to `sqmul_round_sat` except with the semantics
1859        of x86's `pmulhrsw` instruction.
1860
1861        This is the same as `sqmul_round_sat` except when both input lanes are
1862        `i16::MIN`.
1863        "#,
1864            &formats.binary,
1865        )
1866        .operands_in(&[Operand::new("x", I16or32), Operand::new("y", I16or32)])
1867        .operands_out(&[Operand::new("a", I16or32)]),
1868    );
1869
1870    // Integer division and remainder are scalar-only; most
1871    // hardware does not directly support vector integer division.
1872
1873    ig.push(
1874        Inst::new(
1875            "udiv",
1876            r#"
1877        Unsigned integer division: `a := \lfloor {x \over y} \rfloor`.
1878
1879        This operation traps if the divisor is zero.
1880        "#,
1881            &formats.binary,
1882        )
1883        .operands_in(&[Operand::new("x", iB), Operand::new("y", iB)])
1884        .operands_out(&[Operand::new("a", iB)])
1885        .can_trap()
1886        .side_effects_idempotent()
1887        .inst_builder_imm_method(true),
1888    );
1889
1890    ig.push(
1891        Inst::new(
1892            "sdiv",
1893            r#"
1894        Signed integer division rounded toward zero: `a := sign(xy)
1895        \lfloor {|x| \over |y|}\rfloor`.
1896
1897        This operation traps if the divisor is zero, or if the result is not
1898        representable in `B` bits two's complement. This only happens
1899        when `x = -2^{B-1}, y = -1`.
1900        "#,
1901            &formats.binary,
1902        )
1903        .operands_in(&[Operand::new("x", iB), Operand::new("y", iB)])
1904        .operands_out(&[Operand::new("a", iB)])
1905        .can_trap()
1906        .side_effects_idempotent()
1907        .inst_builder_imm_method(true),
1908    );
1909
1910    ig.push(
1911        Inst::new(
1912            "urem",
1913            r#"
1914        Unsigned integer remainder.
1915
1916        This operation traps if the divisor is zero.
1917        "#,
1918            &formats.binary,
1919        )
1920        .operands_in(&[Operand::new("x", iB), Operand::new("y", iB)])
1921        .operands_out(&[Operand::new("a", iB)])
1922        .can_trap()
1923        .side_effects_idempotent()
1924        .inst_builder_imm_method(true),
1925    );
1926
1927    ig.push(
1928        Inst::new(
1929            "srem",
1930            r#"
1931        Signed integer remainder. The result has the sign of the dividend.
1932
1933        This operation traps if the divisor is zero.
1934        "#,
1935            &formats.binary,
1936        )
1937        .operands_in(&[Operand::new("x", iB), Operand::new("y", iB)])
1938        .operands_out(&[Operand::new("a", iB)])
1939        .can_trap()
1940        .side_effects_idempotent()
1941        .inst_builder_imm_method(true),
1942    );
1943
1944    ig.push(
1945        Inst::new(
1946            "sadd_overflow_cin",
1947            r#"
1948        Add signed integers with carry in and overflow out.
1949
1950        Same as `sadd_overflow` with an additional carry input. The `c_in` type
1951        is interpreted as 1 if it's nonzero or 0 if it's zero.
1952        "#,
1953            &formats.ternary,
1954        )
1955        .operands_in(&[
1956            Operand::new("x", iB),
1957            Operand::new("y", iB),
1958            Operand::new("c_in", i8).with_doc("Input carry flag"),
1959        ])
1960        .operands_out(&[
1961            Operand::new("a", iB),
1962            Operand::new("c_out", i8).with_doc("Output carry flag"),
1963        ]),
1964    );
1965
1966    ig.push(
1967        Inst::new(
1968            "uadd_overflow_cin",
1969            r#"
1970        Add unsigned integers with carry in and overflow out.
1971
1972        Same as `uadd_overflow` with an additional carry input. The `c_in` type
1973        is interpreted as 1 if it's nonzero or 0 if it's zero.
1974        "#,
1975            &formats.ternary,
1976        )
1977        .operands_in(&[
1978            Operand::new("x", iB),
1979            Operand::new("y", iB),
1980            Operand::new("c_in", i8).with_doc("Input carry flag"),
1981        ])
1982        .operands_out(&[
1983            Operand::new("a", iB),
1984            Operand::new("c_out", i8).with_doc("Output carry flag"),
1985        ]),
1986    );
1987
1988    {
1989        let of_out = Operand::new("of", i8).with_doc("Overflow flag");
1990        ig.push(
1991            Inst::new(
1992                "uadd_overflow",
1993                r#"
1994            Add integers unsigned with overflow out.
1995            ``of`` is set when the addition overflowed.
1996            ```text
1997                a &= x + y \pmod 2^B \\
1998                of &= x+y >= 2^B
1999            ```
2000            Polymorphic over all scalar integer types, but does not support vector
2001            types.
2002            "#,
2003                &formats.binary,
2004            )
2005            .operands_in(&[Operand::new("x", iB), Operand::new("y", iB)])
2006            .operands_out(&[Operand::new("a", iB), of_out.clone()]),
2007        );
2008
2009        ig.push(
2010            Inst::new(
2011                "sadd_overflow",
2012                r#"
2013            Add integers signed with overflow out.
2014            ``of`` is set when the addition over- or underflowed.
2015            Polymorphic over all scalar integer types, but does not support vector
2016            types.
2017            "#,
2018                &formats.binary,
2019            )
2020            .operands_in(&[Operand::new("x", iB), Operand::new("y", iB)])
2021            .operands_out(&[Operand::new("a", iB), of_out.clone()]),
2022        );
2023
2024        ig.push(
2025            Inst::new(
2026                "usub_overflow",
2027                r#"
2028            Subtract integers unsigned with overflow out.
2029            ``of`` is set when the subtraction underflowed.
2030            ```text
2031                a &= x - y \pmod 2^B \\
2032                of &= x - y < 0
2033            ```
2034            Polymorphic over all scalar integer types, but does not support vector
2035            types.
2036            "#,
2037                &formats.binary,
2038            )
2039            .operands_in(&[Operand::new("x", iB), Operand::new("y", iB)])
2040            .operands_out(&[Operand::new("a", iB), of_out.clone()]),
2041        );
2042
2043        ig.push(
2044            Inst::new(
2045                "ssub_overflow",
2046                r#"
2047            Subtract integers signed with overflow out.
2048            ``of`` is set when the subtraction over- or underflowed.
2049            Polymorphic over all scalar integer types, but does not support vector
2050            types.
2051            "#,
2052                &formats.binary,
2053            )
2054            .operands_in(&[Operand::new("x", iB), Operand::new("y", iB)])
2055            .operands_out(&[Operand::new("a", iB), of_out.clone()]),
2056        );
2057
2058        {
2059            let NarrowScalar = &TypeVar::new(
2060                "NarrowScalar",
2061                "A scalar integer type up to 64 bits",
2062                TypeSetBuilder::new().ints(8..64).build(),
2063            );
2064
2065            ig.push(
2066                Inst::new(
2067                    "umul_overflow",
2068                    r#"
2069                Multiply integers unsigned with overflow out.
2070                ``of`` is set when the multiplication overflowed.
2071                ```text
2072                    a &= x * y \pmod 2^B \\
2073                    of &= x * y > 2^B
2074                ```
2075                Polymorphic over all scalar integer types except i128, but does not support vector
2076                types.
2077                "#,
2078                    &formats.binary,
2079                )
2080                .operands_in(&[
2081                    Operand::new("x", NarrowScalar),
2082                    Operand::new("y", NarrowScalar),
2083                ])
2084                .operands_out(&[Operand::new("a", NarrowScalar), of_out.clone()]),
2085            );
2086
2087            ig.push(
2088                Inst::new(
2089                    "smul_overflow",
2090                    r#"
2091                Multiply integers signed with overflow out.
2092                ``of`` is set when the multiplication over- or underflowed.
2093                Polymorphic over all scalar integer types except i128, but does not support vector
2094                types.
2095                "#,
2096                    &formats.binary,
2097                )
2098                .operands_in(&[
2099                    Operand::new("x", NarrowScalar),
2100                    Operand::new("y", NarrowScalar),
2101                ])
2102                .operands_out(&[Operand::new("a", NarrowScalar), of_out.clone()]),
2103            );
2104        }
2105    }
2106
2107    let i32_64 = &TypeVar::new(
2108        "i32_64",
2109        "A 32 or 64-bit scalar integer type",
2110        TypeSetBuilder::new().ints(32..64).build(),
2111    );
2112
2113    ig.push(
2114        Inst::new(
2115            "uadd_overflow_trap",
2116            r#"
2117        Unsigned addition of x and y, trapping if the result overflows.
2118
2119        Accepts 32 or 64-bit integers, and does not support vector types.
2120        "#,
2121            &formats.int_add_trap,
2122        )
2123        .operands_in(&[
2124            Operand::new("x", i32_64),
2125            Operand::new("y", i32_64),
2126            Operand::new("code", &imm.trapcode),
2127        ])
2128        .operands_out(&[Operand::new("a", i32_64)])
2129        .can_trap()
2130        .side_effects_idempotent(),
2131    );
2132
2133    ig.push(
2134        Inst::new(
2135            "ssub_overflow_bin",
2136            r#"
2137        Subtract signed integers with borrow in and overflow out.
2138
2139        Same as `ssub_overflow` with an additional borrow input. The `b_in` type
2140        is interpreted as 1 if it's nonzero or 0 if it's zero. The computation
2141        performed here is `x - (y + (b_in != 0))`.
2142        "#,
2143            &formats.ternary,
2144        )
2145        .operands_in(&[
2146            Operand::new("x", iB),
2147            Operand::new("y", iB),
2148            Operand::new("b_in", i8).with_doc("Input borrow flag"),
2149        ])
2150        .operands_out(&[
2151            Operand::new("a", iB),
2152            Operand::new("b_out", i8).with_doc("Output borrow flag"),
2153        ]),
2154    );
2155
2156    ig.push(
2157        Inst::new(
2158            "usub_overflow_bin",
2159            r#"
2160        Subtract unsigned integers with borrow in and overflow out.
2161
2162        Same as `usub_overflow` with an additional borrow input. The `b_in` type
2163        is interpreted as 1 if it's nonzero or 0 if it's zero. The computation
2164        performed here is `x - (y + (b_in != 0))`.
2165        "#,
2166            &formats.ternary,
2167        )
2168        .operands_in(&[
2169            Operand::new("x", iB),
2170            Operand::new("y", iB),
2171            Operand::new("b_in", i8).with_doc("Input borrow flag"),
2172        ])
2173        .operands_out(&[
2174            Operand::new("a", iB),
2175            Operand::new("b_out", i8).with_doc("Output borrow flag"),
2176        ]),
2177    );
2178
2179    let bits = &TypeVar::new(
2180        "bits",
2181        "Any integer, float, or vector type",
2182        TypeSetBuilder::new()
2183            .ints(Interval::All)
2184            .floats(Interval::All)
2185            .simd_lanes(Interval::All)
2186            .includes_scalars(true)
2187            .build(),
2188    );
2189
2190    ig.push(
2191        Inst::new(
2192            "band",
2193            r#"
2194        Bitwise and.
2195        "#,
2196            &formats.binary,
2197        )
2198        .operands_in(&[Operand::new("x", bits), Operand::new("y", bits)])
2199        .operands_out(&[Operand::new("a", bits)])
2200        .inst_builder_imm_method(true),
2201    );
2202
2203    ig.push(
2204        Inst::new(
2205            "bor",
2206            r#"
2207        Bitwise or.
2208        "#,
2209            &formats.binary,
2210        )
2211        .operands_in(&[Operand::new("x", bits), Operand::new("y", bits)])
2212        .operands_out(&[Operand::new("a", bits)])
2213        .inst_builder_imm_method(true),
2214    );
2215
2216    ig.push(
2217        Inst::new(
2218            "bxor",
2219            r#"
2220        Bitwise xor.
2221        "#,
2222            &formats.binary,
2223        )
2224        .operands_in(&[Operand::new("x", bits), Operand::new("y", bits)])
2225        .operands_out(&[Operand::new("a", bits)])
2226        .inst_builder_imm_method(true),
2227    );
2228
2229    ig.push(
2230        Inst::new(
2231            "bnot",
2232            r#"
2233        Bitwise not.
2234        "#,
2235            &formats.unary,
2236        )
2237        .operands_in(&[Operand::new("x", bits)])
2238        .operands_out(&[Operand::new("a", bits)]),
2239    );
2240
2241    ig.push(
2242        Inst::new(
2243            "rotl",
2244            r#"
2245        Rotate left.
2246
2247        Rotate the bits in ``x`` by ``y`` places.
2248        "#,
2249            &formats.binary,
2250        )
2251        .operands_in(&[
2252            Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2253            Operand::new("y", iB).with_doc("Number of bits to shift"),
2254        ])
2255        .operands_out(&[Operand::new("a", Int)])
2256        .inst_builder_imm_method(true),
2257    );
2258
2259    ig.push(
2260        Inst::new(
2261            "rotr",
2262            r#"
2263        Rotate right.
2264
2265        Rotate the bits in ``x`` by ``y`` places.
2266        "#,
2267            &formats.binary,
2268        )
2269        .operands_in(&[
2270            Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2271            Operand::new("y", iB).with_doc("Number of bits to shift"),
2272        ])
2273        .operands_out(&[Operand::new("a", Int)])
2274        .inst_builder_imm_method(true),
2275    );
2276
2277    ig.push(
2278        Inst::new(
2279            "ishl",
2280            r#"
2281        Integer shift left. Shift the bits in ``x`` towards the MSB by ``y``
2282        places. Shift in zero bits to the LSB.
2283
2284        The shift amount is masked to the size of ``x``.
2285
2286        When shifting a B-bits integer type, this instruction computes:
2287
2288        ```text
2289            s &:= y \pmod B,
2290            a &:= x \cdot 2^s \pmod{2^B}.
2291        ```
2292        "#,
2293            &formats.binary,
2294        )
2295        .operands_in(&[
2296            Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2297            Operand::new("y", iB).with_doc("Number of bits to shift"),
2298        ])
2299        .operands_out(&[Operand::new("a", Int)])
2300        .inst_builder_imm_method(true),
2301    );
2302
2303    ig.push(
2304        Inst::new(
2305            "ushr",
2306            r#"
2307        Unsigned shift right. Shift bits in ``x`` towards the LSB by ``y``
2308        places, shifting in zero bits to the MSB. Also called a *logical
2309        shift*.
2310
2311        The shift amount is masked to the size of ``x``.
2312
2313        When shifting a B-bits integer type, this instruction computes:
2314
2315        ```text
2316            s &:= y \pmod B,
2317            a &:= \lfloor x \cdot 2^{-s} \rfloor.
2318        ```
2319        "#,
2320            &formats.binary,
2321        )
2322        .operands_in(&[
2323            Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2324            Operand::new("y", iB).with_doc("Number of bits to shift"),
2325        ])
2326        .operands_out(&[Operand::new("a", Int)])
2327        .inst_builder_imm_method(true),
2328    );
2329
2330    ig.push(
2331        Inst::new(
2332            "sshr",
2333            r#"
2334        Signed shift right. Shift bits in ``x`` towards the LSB by ``y``
2335        places, shifting in sign bits to the MSB. Also called an *arithmetic
2336        shift*.
2337
2338        The shift amount is masked to the size of ``x``.
2339        "#,
2340            &formats.binary,
2341        )
2342        .operands_in(&[
2343            Operand::new("x", Int).with_doc("Scalar or vector value to shift"),
2344            Operand::new("y", iB).with_doc("Number of bits to shift"),
2345        ])
2346        .operands_out(&[Operand::new("a", Int)])
2347        .inst_builder_imm_method(true),
2348    );
2349
2350    ig.push(
2351        Inst::new(
2352            "bitrev",
2353            r#"
2354        Reverse the bits of a integer.
2355
2356        Reverses the bits in ``x``.
2357        "#,
2358            &formats.unary,
2359        )
2360        .operands_in(&[Operand::new("x", iB)])
2361        .operands_out(&[Operand::new("a", iB)]),
2362    );
2363
2364    ig.push(
2365        Inst::new(
2366            "clz",
2367            r#"
2368        Count leading zero bits.
2369
2370        Starting from the MSB in ``x``, count the number of zero bits before
2371        reaching the first one bit. When ``x`` is zero, returns the size of x
2372        in bits.
2373        "#,
2374            &formats.unary,
2375        )
2376        .operands_in(&[Operand::new("x", iB)])
2377        .operands_out(&[Operand::new("a", iB)]),
2378    );
2379
2380    ig.push(
2381        Inst::new(
2382            "cls",
2383            r#"
2384        Count leading sign bits.
2385
2386        Starting from the MSB after the sign bit in ``x``, count the number of
2387        consecutive bits identical to the sign bit. When ``x`` is 0 or -1,
2388        returns one less than the size of x in bits.
2389        "#,
2390            &formats.unary,
2391        )
2392        .operands_in(&[Operand::new("x", iB)])
2393        .operands_out(&[Operand::new("a", iB)]),
2394    );
2395
2396    ig.push(
2397        Inst::new(
2398            "ctz",
2399            r#"
2400        Count trailing zeros.
2401
2402        Starting from the LSB in ``x``, count the number of zero bits before
2403        reaching the first one bit. When ``x`` is zero, returns the size of x
2404        in bits.
2405        "#,
2406            &formats.unary,
2407        )
2408        .operands_in(&[Operand::new("x", iB)])
2409        .operands_out(&[Operand::new("a", iB)]),
2410    );
2411
2412    ig.push(
2413        Inst::new(
2414            "bswap",
2415            r#"
2416        Reverse the byte order of an integer.
2417
2418        Reverses the bytes in ``x``.
2419        "#,
2420            &formats.unary,
2421        )
2422        .operands_in(&[Operand::new("x", iSwappable)])
2423        .operands_out(&[Operand::new("a", iSwappable)]),
2424    );
2425
2426    ig.push(
2427        Inst::new(
2428            "popcnt",
2429            r#"
2430        Population count
2431
2432        Count the number of one bits in ``x``.
2433        "#,
2434            &formats.unary,
2435        )
2436        .operands_in(&[Operand::new("x", Int)])
2437        .operands_out(&[Operand::new("a", Int)]),
2438    );
2439
2440    let Float = &TypeVar::new(
2441        "Float",
2442        "A scalar or vector floating point number",
2443        TypeSetBuilder::new()
2444            .floats(Interval::All)
2445            .simd_lanes(Interval::All)
2446            .dynamic_simd_lanes(Interval::All)
2447            .build(),
2448    );
2449
2450    ig.push(
2451        Inst::new(
2452            "fcmp",
2453            r#"
2454        Floating point comparison.
2455
2456        Two IEEE 754-2008 floating point numbers, `x` and `y`, relate to each
2457        other in exactly one of four ways:
2458
2459        ```text
2460        == ==========================================
2461        UN Unordered when one or both numbers is NaN.
2462        EQ When `x = y`. (And `0.0 = -0.0`).
2463        LT When `x < y`.
2464        GT When `x > y`.
2465        == ==========================================
2466        ```
2467
2468        The 14 `floatcc` condition codes each correspond to a subset of
2469        the four relations, except for the empty set which would always be
2470        false, and the full set which would always be true.
2471
2472        The condition codes are divided into 7 'ordered' conditions which don't
2473        include UN, and 7 unordered conditions which all include UN.
2474
2475        ```text
2476        +-------+------------+---------+------------+-------------------------+
2477        |Ordered             |Unordered             |Condition                |
2478        +=======+============+=========+============+=========================+
2479        |ord    |EQ | LT | GT|uno      |UN          |NaNs absent / present.   |
2480        +-------+------------+---------+------------+-------------------------+
2481        |eq     |EQ          |ueq      |UN | EQ     |Equal                    |
2482        +-------+------------+---------+------------+-------------------------+
2483        |one    |LT | GT     |ne       |UN | LT | GT|Not equal                |
2484        +-------+------------+---------+------------+-------------------------+
2485        |lt     |LT          |ult      |UN | LT     |Less than                |
2486        +-------+------------+---------+------------+-------------------------+
2487        |le     |LT | EQ     |ule      |UN | LT | EQ|Less than or equal       |
2488        +-------+------------+---------+------------+-------------------------+
2489        |gt     |GT          |ugt      |UN | GT     |Greater than             |
2490        +-------+------------+---------+------------+-------------------------+
2491        |ge     |GT | EQ     |uge      |UN | GT | EQ|Greater than or equal    |
2492        +-------+------------+---------+------------+-------------------------+
2493        ```
2494
2495        The standard C comparison operators, `<, <=, >, >=`, are all ordered,
2496        so they are false if either operand is NaN. The C equality operator,
2497        `==`, is ordered, and since inequality is defined as the logical
2498        inverse it is *unordered*. They map to the `floatcc` condition
2499        codes as follows:
2500
2501        ```text
2502        ==== ====== ============
2503        C    `Cond` Subset
2504        ==== ====== ============
2505        `==` eq     EQ
2506        `!=` ne     UN | LT | GT
2507        `<`  lt     LT
2508        `<=` le     LT | EQ
2509        `>`  gt     GT
2510        `>=` ge     GT | EQ
2511        ==== ====== ============
2512        ```
2513
2514        This subset of condition codes also corresponds to the WebAssembly
2515        floating point comparisons of the same name.
2516
2517        When this instruction compares floating point vectors, it returns a
2518        vector with the results of lane-wise comparisons.
2519
2520        When comparing scalars, the result is:
2521            - `1` if the condition holds.
2522            - `0` if the condition does not hold.
2523
2524        When comparing vectors, the result is:
2525            - `-1` (i.e. all ones) in each lane where the condition holds.
2526            - `0` in each lane where the condition does not hold.
2527        "#,
2528            &formats.float_compare,
2529        )
2530        .operands_in(&[
2531            Operand::new("Cond", &imm.floatcc),
2532            Operand::new("x", Float),
2533            Operand::new("y", Float),
2534        ])
2535        .operands_out(&[Operand::new("a", &Float.as_truthy())]),
2536    );
2537
2538    ig.push(
2539        Inst::new(
2540            "fadd",
2541            r#"
2542        Floating point addition.
2543        "#,
2544            &formats.binary,
2545        )
2546        .operands_in(&[Operand::new("x", Float), Operand::new("y", Float)])
2547        .operands_out(&[
2548            Operand::new("a", Float).with_doc("Result of applying operator to each lane")
2549        ]),
2550    );
2551
2552    ig.push(
2553        Inst::new(
2554            "fsub",
2555            r#"
2556        Floating point subtraction.
2557        "#,
2558            &formats.binary,
2559        )
2560        .operands_in(&[Operand::new("x", Float), Operand::new("y", Float)])
2561        .operands_out(&[
2562            Operand::new("a", Float).with_doc("Result of applying operator to each lane")
2563        ]),
2564    );
2565
2566    ig.push(
2567        Inst::new(
2568            "fmul",
2569            r#"
2570        Floating point multiplication.
2571        "#,
2572            &formats.binary,
2573        )
2574        .operands_in(&[Operand::new("x", Float), Operand::new("y", Float)])
2575        .operands_out(&[
2576            Operand::new("a", Float).with_doc("Result of applying operator to each lane")
2577        ]),
2578    );
2579
2580    ig.push(
2581        Inst::new(
2582            "fdiv",
2583            r#"
2584        Floating point division.
2585
2586        Unlike the integer division instructions ` and
2587        `udiv`, this can't trap. Division by zero is infinity or
2588        NaN, depending on the dividend.
2589        "#,
2590            &formats.binary,
2591        )
2592        .operands_in(&[Operand::new("x", Float), Operand::new("y", Float)])
2593        .operands_out(&[
2594            Operand::new("a", Float).with_doc("Result of applying operator to each lane")
2595        ]),
2596    );
2597
2598    ig.push(
2599        Inst::new(
2600            "sqrt",
2601            r#"
2602        Floating point square root.
2603        "#,
2604            &formats.unary,
2605        )
2606        .operands_in(&[Operand::new("x", Float)])
2607        .operands_out(&[
2608            Operand::new("a", Float).with_doc("Result of applying operator to each lane")
2609        ]),
2610    );
2611
2612    ig.push(
2613        Inst::new(
2614            "fma",
2615            r#"
2616        Floating point fused multiply-and-add.
2617
2618        Computes `a := xy+z` without any intermediate rounding of the
2619        product.
2620        "#,
2621            &formats.ternary,
2622        )
2623        .operands_in(&[
2624            Operand::new("x", Float),
2625            Operand::new("y", Float),
2626            Operand::new("z", Float),
2627        ])
2628        .operands_out(&[
2629            Operand::new("a", Float).with_doc("Result of applying operator to each lane")
2630        ]),
2631    );
2632
2633    ig.push(
2634        Inst::new(
2635            "fneg",
2636            r#"
2637        Floating point negation.
2638
2639        Note that this is a pure bitwise operation.
2640        "#,
2641            &formats.unary,
2642        )
2643        .operands_in(&[Operand::new("x", Float)])
2644        .operands_out(&[Operand::new("a", Float).with_doc("``x`` with its sign bit inverted")]),
2645    );
2646
2647    ig.push(
2648        Inst::new(
2649            "fabs",
2650            r#"
2651        Floating point absolute value.
2652
2653        Note that this is a pure bitwise operation.
2654        "#,
2655            &formats.unary,
2656        )
2657        .operands_in(&[Operand::new("x", Float)])
2658        .operands_out(&[Operand::new("a", Float).with_doc("``x`` with its sign bit cleared")]),
2659    );
2660
2661    ig.push(
2662        Inst::new(
2663            "fcopysign",
2664            r#"
2665        Floating point copy sign.
2666
2667        Note that this is a pure bitwise operation. The sign bit from ``y`` is
2668        copied to the sign bit of ``x``.
2669        "#,
2670            &formats.binary,
2671        )
2672        .operands_in(&[Operand::new("x", Float), Operand::new("y", Float)])
2673        .operands_out(&[
2674            Operand::new("a", Float).with_doc("``x`` with its sign bit changed to that of ``y``")
2675        ]),
2676    );
2677
2678    ig.push(
2679        Inst::new(
2680            "fmin",
2681            r#"
2682        Floating point minimum, propagating NaNs using the WebAssembly rules.
2683
2684        If either operand is NaN, this returns NaN with an unspecified sign. Furthermore, if
2685        each input NaN consists of a mantissa whose most significant bit is 1 and the rest is
2686        0, then the output has the same form. Otherwise, the output mantissa's most significant
2687        bit is 1 and the rest is unspecified.
2688        "#,
2689            &formats.binary,
2690        )
2691        .operands_in(&[Operand::new("x", Float), Operand::new("y", Float)])
2692        .operands_out(&[Operand::new("a", Float).with_doc("The smaller of ``x`` and ``y``")]),
2693    );
2694
2695    ig.push(
2696        Inst::new(
2697            "fmax",
2698            r#"
2699        Floating point maximum, propagating NaNs using the WebAssembly rules.
2700
2701        If either operand is NaN, this returns NaN with an unspecified sign. Furthermore, if
2702        each input NaN consists of a mantissa whose most significant bit is 1 and the rest is
2703        0, then the output has the same form. Otherwise, the output mantissa's most significant
2704        bit is 1 and the rest is unspecified.
2705        "#,
2706            &formats.binary,
2707        )
2708        .operands_in(&[Operand::new("x", Float), Operand::new("y", Float)])
2709        .operands_out(&[Operand::new("a", Float).with_doc("The larger of ``x`` and ``y``")]),
2710    );
2711
2712    ig.push(
2713        Inst::new(
2714            "ceil",
2715            r#"
2716        Round floating point round to integral, towards positive infinity.
2717        "#,
2718            &formats.unary,
2719        )
2720        .operands_in(&[Operand::new("x", Float)])
2721        .operands_out(&[Operand::new("a", Float).with_doc("``x`` rounded to integral value")]),
2722    );
2723
2724    ig.push(
2725        Inst::new(
2726            "floor",
2727            r#"
2728        Round floating point round to integral, towards negative infinity.
2729        "#,
2730            &formats.unary,
2731        )
2732        .operands_in(&[Operand::new("x", Float)])
2733        .operands_out(&[Operand::new("a", Float).with_doc("``x`` rounded to integral value")]),
2734    );
2735
2736    ig.push(
2737        Inst::new(
2738            "trunc",
2739            r#"
2740        Round floating point round to integral, towards zero.
2741        "#,
2742            &formats.unary,
2743        )
2744        .operands_in(&[Operand::new("x", Float)])
2745        .operands_out(&[Operand::new("a", Float).with_doc("``x`` rounded to integral value")]),
2746    );
2747
2748    ig.push(
2749        Inst::new(
2750            "nearest",
2751            r#"
2752        Round floating point round to integral, towards nearest with ties to
2753        even.
2754        "#,
2755            &formats.unary,
2756        )
2757        .operands_in(&[Operand::new("x", Float)])
2758        .operands_out(&[Operand::new("a", Float).with_doc("``x`` rounded to integral value")]),
2759    );
2760
2761    ig.push(
2762        Inst::new(
2763            "bitcast",
2764            r#"
2765        Reinterpret the bits in `x` as a different type.
2766
2767        The input and output types must be storable to memory and of the same
2768        size. A bitcast is equivalent to storing one type and loading the other
2769        type from the same address, both using the specified MemFlags.
2770
2771        Note that this operation only supports the `big` or `little` MemFlags.
2772        The specified byte order only affects the result in the case where
2773        input and output types differ in lane count/size.  In this case, the
2774        operation is only valid if a byte order specifier is provided.
2775        "#,
2776            &formats.load_no_offset,
2777        )
2778        .operands_in(&[
2779            Operand::new("MemFlags", &imm.memflags),
2780            Operand::new("x", Mem),
2781        ])
2782        .operands_out(&[Operand::new("a", MemTo).with_doc("Bits of `x` reinterpreted")]),
2783    );
2784
2785    ig.push(
2786        Inst::new(
2787            "scalar_to_vector",
2788            r#"
2789            Copies a scalar value to a vector value.  The scalar is copied into the
2790            least significant lane of the vector, and all other lanes will be zero.
2791            "#,
2792            &formats.unary,
2793        )
2794        .operands_in(&[Operand::new("s", &TxN.lane_of()).with_doc("A scalar value")])
2795        .operands_out(&[Operand::new("a", TxN).with_doc("A vector value")]),
2796    );
2797
2798    let Truthy = &TypeVar::new(
2799        "Truthy",
2800        "A scalar whose values are truthy",
2801        TypeSetBuilder::new().ints(Interval::All).build(),
2802    );
2803    let IntTo = &TypeVar::new(
2804        "IntTo",
2805        "An integer type",
2806        TypeSetBuilder::new().ints(Interval::All).build(),
2807    );
2808
2809    ig.push(
2810        Inst::new(
2811            "bmask",
2812            r#"
2813        Convert `x` to an integer mask.
2814
2815        Non-zero maps to all 1s and zero maps to all 0s.
2816        "#,
2817            &formats.unary,
2818        )
2819        .operands_in(&[Operand::new("x", Truthy)])
2820        .operands_out(&[Operand::new("a", IntTo)]),
2821    );
2822
2823    let Int = &TypeVar::new(
2824        "Int",
2825        "A scalar integer type",
2826        TypeSetBuilder::new().ints(Interval::All).build(),
2827    );
2828
2829    ig.push(
2830        Inst::new(
2831            "ireduce",
2832            r#"
2833        Convert `x` to a smaller integer type by discarding
2834        the most significant bits.
2835
2836        This is the same as reducing modulo `2^n`.
2837        "#,
2838            &formats.unary,
2839        )
2840        .operands_in(&[Operand::new("x", &Int.wider())
2841            .with_doc("A scalar integer type, wider than the controlling type")])
2842        .operands_out(&[Operand::new("a", Int)]),
2843    );
2844
2845    let I16or32or64xN = &TypeVar::new(
2846        "I16or32or64xN",
2847        "A SIMD vector type containing integer lanes 16, 32, or 64 bits wide",
2848        TypeSetBuilder::new()
2849            .ints(16..64)
2850            .simd_lanes(2..8)
2851            .dynamic_simd_lanes(2..8)
2852            .includes_scalars(false)
2853            .build(),
2854    );
2855
2856    ig.push(
2857        Inst::new(
2858            "snarrow",
2859            r#"
2860        Combine `x` and `y` into a vector with twice the lanes but half the integer width while
2861        saturating overflowing values to the signed maximum and minimum.
2862
2863        The lanes will be concatenated after narrowing. For example, when `x` and `y` are `i32x4`
2864        and `x = [x3, x2, x1, x0]` and `y = [y3, y2, y1, y0]`, then after narrowing the value
2865        returned is an `i16x8`: `a = [y3', y2', y1', y0', x3', x2', x1', x0']`.
2866            "#,
2867            &formats.binary,
2868        )
2869        .operands_in(&[
2870            Operand::new("x", I16or32or64xN),
2871            Operand::new("y", I16or32or64xN),
2872        ])
2873        .operands_out(&[Operand::new("a", &I16or32or64xN.split_lanes())]),
2874    );
2875
2876    ig.push(
2877        Inst::new(
2878            "unarrow",
2879            r#"
2880        Combine `x` and `y` into a vector with twice the lanes but half the integer width while
2881        saturating overflowing values to the unsigned maximum and minimum.
2882
2883        Note that all input lanes are considered signed: any negative lanes will overflow and be
2884        replaced with the unsigned minimum, `0x00`.
2885
2886        The lanes will be concatenated after narrowing. For example, when `x` and `y` are `i32x4`
2887        and `x = [x3, x2, x1, x0]` and `y = [y3, y2, y1, y0]`, then after narrowing the value
2888        returned is an `i16x8`: `a = [y3', y2', y1', y0', x3', x2', x1', x0']`.
2889            "#,
2890            &formats.binary,
2891        )
2892        .operands_in(&[
2893            Operand::new("x", I16or32or64xN),
2894            Operand::new("y", I16or32or64xN),
2895        ])
2896        .operands_out(&[Operand::new("a", &I16or32or64xN.split_lanes())]),
2897    );
2898
2899    ig.push(
2900        Inst::new(
2901            "uunarrow",
2902            r#"
2903        Combine `x` and `y` into a vector with twice the lanes but half the integer width while
2904        saturating overflowing values to the unsigned maximum and minimum.
2905
2906        Note that all input lanes are considered unsigned: any negative values will be interpreted as unsigned, overflowing and being replaced with the unsigned maximum.
2907
2908        The lanes will be concatenated after narrowing. For example, when `x` and `y` are `i32x4`
2909        and `x = [x3, x2, x1, x0]` and `y = [y3, y2, y1, y0]`, then after narrowing the value
2910        returned is an `i16x8`: `a = [y3', y2', y1', y0', x3', x2', x1', x0']`.
2911            "#,
2912            &formats.binary,
2913        )
2914        .operands_in(&[Operand::new("x", I16or32or64xN), Operand::new("y", I16or32or64xN)])
2915        .operands_out(&[Operand::new("a", &I16or32or64xN.split_lanes())]),
2916    );
2917
2918    let I8or16or32xN = &TypeVar::new(
2919        "I8or16or32xN",
2920        "A SIMD vector type containing integer lanes 8, 16, or 32 bits wide.",
2921        TypeSetBuilder::new()
2922            .ints(8..32)
2923            .simd_lanes(2..16)
2924            .dynamic_simd_lanes(2..16)
2925            .includes_scalars(false)
2926            .build(),
2927    );
2928
2929    ig.push(
2930        Inst::new(
2931            "swiden_low",
2932            r#"
2933        Widen the low lanes of `x` using signed extension.
2934
2935        This will double the lane width and halve the number of lanes.
2936            "#,
2937            &formats.unary,
2938        )
2939        .operands_in(&[Operand::new("x", I8or16or32xN)])
2940        .operands_out(&[Operand::new("a", &I8or16or32xN.merge_lanes())]),
2941    );
2942
2943    ig.push(
2944        Inst::new(
2945            "swiden_high",
2946            r#"
2947        Widen the high lanes of `x` using signed extension.
2948
2949        This will double the lane width and halve the number of lanes.
2950            "#,
2951            &formats.unary,
2952        )
2953        .operands_in(&[Operand::new("x", I8or16or32xN)])
2954        .operands_out(&[Operand::new("a", &I8or16or32xN.merge_lanes())]),
2955    );
2956
2957    ig.push(
2958        Inst::new(
2959            "uwiden_low",
2960            r#"
2961        Widen the low lanes of `x` using unsigned extension.
2962
2963        This will double the lane width and halve the number of lanes.
2964            "#,
2965            &formats.unary,
2966        )
2967        .operands_in(&[Operand::new("x", I8or16or32xN)])
2968        .operands_out(&[Operand::new("a", &I8or16or32xN.merge_lanes())]),
2969    );
2970
2971    ig.push(
2972        Inst::new(
2973            "uwiden_high",
2974            r#"
2975            Widen the high lanes of `x` using unsigned extension.
2976
2977            This will double the lane width and halve the number of lanes.
2978            "#,
2979            &formats.unary,
2980        )
2981        .operands_in(&[Operand::new("x", I8or16or32xN)])
2982        .operands_out(&[Operand::new("a", &I8or16or32xN.merge_lanes())]),
2983    );
2984
2985    ig.push(
2986        Inst::new(
2987            "iadd_pairwise",
2988            r#"
2989        Does lane-wise integer pairwise addition on two operands, putting the
2990        combined results into a single vector result. Here a pair refers to adjacent
2991        lanes in a vector, i.e. i*2 + (i*2+1) for i == num_lanes/2. The first operand
2992        pairwise add results will make up the low half of the resulting vector while
2993        the second operand pairwise add results will make up the upper half of the
2994        resulting vector.
2995            "#,
2996            &formats.binary,
2997        )
2998        .operands_in(&[
2999            Operand::new("x", I8or16or32xN),
3000            Operand::new("y", I8or16or32xN),
3001        ])
3002        .operands_out(&[Operand::new("a", I8or16or32xN)]),
3003    );
3004
3005    let I8x16 = &TypeVar::new(
3006        "I8x16",
3007        "A SIMD vector type consisting of 16 lanes of 8-bit integers",
3008        TypeSetBuilder::new()
3009            .ints(8..8)
3010            .simd_lanes(16..16)
3011            .includes_scalars(false)
3012            .build(),
3013    );
3014
3015    ig.push(
3016        Inst::new(
3017            "x86_pmaddubsw",
3018            r#"
3019        An instruction with equivalent semantics to `pmaddubsw` on x86.
3020
3021        This instruction will take signed bytes from the first argument and
3022        multiply them against unsigned bytes in the second argument. Adjacent
3023        pairs are then added, with saturating, to a 16-bit value and are packed
3024        into the result.
3025            "#,
3026            &formats.binary,
3027        )
3028        .operands_in(&[Operand::new("x", I8x16), Operand::new("y", I8x16)])
3029        .operands_out(&[Operand::new("a", I16x8)]),
3030    );
3031
3032    ig.push(
3033        Inst::new(
3034            "uextend",
3035            r#"
3036        Convert `x` to a larger integer type by zero-extending.
3037
3038        Each lane in `x` is converted to a larger integer type by adding
3039        zeroes. The result has the same numerical value as `x` when both are
3040        interpreted as unsigned integers.
3041
3042        The result type must have the same number of vector lanes as the input,
3043        and each lane must not have fewer bits that the input lanes. If the
3044        input and output types are the same, this is a no-op.
3045        "#,
3046            &formats.unary,
3047        )
3048        .operands_in(&[Operand::new("x", &Int.narrower())
3049            .with_doc("A scalar integer type, narrower than the controlling type")])
3050        .operands_out(&[Operand::new("a", Int)]),
3051    );
3052
3053    ig.push(
3054        Inst::new(
3055            "sextend",
3056            r#"
3057        Convert `x` to a larger integer type by sign-extending.
3058
3059        Each lane in `x` is converted to a larger integer type by replicating
3060        the sign bit. The result has the same numerical value as `x` when both
3061        are interpreted as signed integers.
3062
3063        The result type must have the same number of vector lanes as the input,
3064        and each lane must not have fewer bits that the input lanes. If the
3065        input and output types are the same, this is a no-op.
3066        "#,
3067            &formats.unary,
3068        )
3069        .operands_in(&[Operand::new("x", &Int.narrower())
3070            .with_doc("A scalar integer type, narrower than the controlling type")])
3071        .operands_out(&[Operand::new("a", Int)]),
3072    );
3073
3074    let FloatScalar = &TypeVar::new(
3075        "FloatScalar",
3076        "A scalar only floating point number",
3077        TypeSetBuilder::new().floats(Interval::All).build(),
3078    );
3079
3080    ig.push(
3081        Inst::new(
3082            "fpromote",
3083            r#"
3084        Convert `x` to a larger floating point format.
3085
3086        Each lane in `x` is converted to the destination floating point format.
3087        This is an exact operation.
3088
3089        Cranelift currently only supports two floating point formats
3090        - `f32` and `f64`. This may change in the future.
3091
3092        The result type must have the same number of vector lanes as the input,
3093        and the result lanes must not have fewer bits than the input lanes.
3094        "#,
3095            &formats.unary,
3096        )
3097        .operands_in(&[Operand::new("x", &FloatScalar.narrower())
3098            .with_doc("A scalar only floating point number, narrower than the controlling type")])
3099        .operands_out(&[Operand::new("a", FloatScalar)]),
3100    );
3101
3102    ig.push(
3103        Inst::new(
3104            "fdemote",
3105            r#"
3106        Convert `x` to a smaller floating point format.
3107
3108        Each lane in `x` is converted to the destination floating point format
3109        by rounding to nearest, ties to even.
3110
3111        Cranelift currently only supports two floating point formats
3112        - `f32` and `f64`. This may change in the future.
3113
3114        The result type must have the same number of vector lanes as the input,
3115        and the result lanes must not have more bits than the input lanes.
3116        "#,
3117            &formats.unary,
3118        )
3119        .operands_in(&[Operand::new("x", &FloatScalar.wider())
3120            .with_doc("A scalar only floating point number, wider than the controlling type")])
3121        .operands_out(&[Operand::new("a", FloatScalar)]),
3122    );
3123
3124    let F64x2 = &TypeVar::new(
3125        "F64x2",
3126        "A SIMD vector type consisting of 2 lanes of 64-bit floats",
3127        TypeSetBuilder::new()
3128            .floats(64..64)
3129            .simd_lanes(2..2)
3130            .includes_scalars(false)
3131            .build(),
3132    );
3133    let F32x4 = &TypeVar::new(
3134        "F32x4",
3135        "A SIMD vector type consisting of 4 lanes of 32-bit floats",
3136        TypeSetBuilder::new()
3137            .floats(32..32)
3138            .simd_lanes(4..4)
3139            .includes_scalars(false)
3140            .build(),
3141    );
3142
3143    ig.push(
3144        Inst::new(
3145            "fvdemote",
3146            r#"
3147                Convert `x` to a smaller floating point format.
3148
3149                Each lane in `x` is converted to the destination floating point format
3150                by rounding to nearest, ties to even.
3151
3152                Cranelift currently only supports two floating point formats
3153                - `f32` and `f64`. This may change in the future.
3154
3155                Fvdemote differs from fdemote in that with fvdemote it targets vectors.
3156                Fvdemote is constrained to having the input type being F64x2 and the result
3157                type being F32x4. The result lane that was the upper half of the input lane
3158                is initialized to zero.
3159                "#,
3160            &formats.unary,
3161        )
3162        .operands_in(&[Operand::new("x", F64x2)])
3163        .operands_out(&[Operand::new("a", F32x4)]),
3164    );
3165
3166    ig.push(
3167        Inst::new(
3168            "fvpromote_low",
3169            r#"
3170        Converts packed single precision floating point to packed double precision floating point.
3171
3172        Considering only the lower half of the register, the low lanes in `x` are interpreted as
3173        single precision floats that are then converted to a double precision floats.
3174
3175        The result type will have half the number of vector lanes as the input. Fvpromote_low is
3176        constrained to input F32x4 with a result type of F64x2.
3177        "#,
3178            &formats.unary,
3179        )
3180        .operands_in(&[Operand::new("a", F32x4)])
3181        .operands_out(&[Operand::new("x", F64x2)]),
3182    );
3183
3184    let IntTo = &TypeVar::new(
3185        "IntTo",
3186        "An scalar only integer type",
3187        TypeSetBuilder::new().ints(Interval::All).build(),
3188    );
3189
3190    ig.push(
3191        Inst::new(
3192            "fcvt_to_uint",
3193            r#"
3194        Converts floating point scalars to unsigned integer.
3195
3196        Only operates on `x` if it is a scalar. If `x` is NaN or if
3197        the unsigned integral value cannot be represented in the result
3198        type, this instruction traps.
3199
3200        "#,
3201            &formats.unary,
3202        )
3203        .operands_in(&[Operand::new("x", FloatScalar)])
3204        .operands_out(&[Operand::new("a", IntTo)])
3205        .can_trap()
3206        .side_effects_idempotent(),
3207    );
3208
3209    ig.push(
3210        Inst::new(
3211            "fcvt_to_sint",
3212            r#"
3213        Converts floating point scalars to signed integer.
3214
3215        Only operates on `x` if it is a scalar. If `x` is NaN or if
3216        the unsigned integral value cannot be represented in the result
3217        type, this instruction traps.
3218
3219        "#,
3220            &formats.unary,
3221        )
3222        .operands_in(&[Operand::new("x", FloatScalar)])
3223        .operands_out(&[Operand::new("a", IntTo)])
3224        .can_trap()
3225        .side_effects_idempotent(),
3226    );
3227
3228    let IntTo = &TypeVar::new(
3229        "IntTo",
3230        "A larger integer type with the same number of lanes",
3231        TypeSetBuilder::new()
3232            .ints(Interval::All)
3233            .simd_lanes(Interval::All)
3234            .build(),
3235    );
3236
3237    ig.push(
3238        Inst::new(
3239            "fcvt_to_uint_sat",
3240            r#"
3241        Convert floating point to unsigned integer as fcvt_to_uint does, but
3242        saturates the input instead of trapping. NaN and negative values are
3243        converted to 0.
3244        "#,
3245            &formats.unary,
3246        )
3247        .operands_in(&[Operand::new("x", Float)])
3248        .operands_out(&[Operand::new("a", IntTo)]),
3249    );
3250
3251    ig.push(
3252        Inst::new(
3253            "fcvt_to_sint_sat",
3254            r#"
3255        Convert floating point to signed integer as fcvt_to_sint does, but
3256        saturates the input instead of trapping. NaN values are converted to 0.
3257        "#,
3258            &formats.unary,
3259        )
3260        .operands_in(&[Operand::new("x", Float)])
3261        .operands_out(&[Operand::new("a", IntTo)]),
3262    );
3263
3264    ig.push(
3265        Inst::new(
3266            "x86_cvtt2dq",
3267            r#"
3268        A float-to-integer conversion instruction for vectors-of-floats which
3269        has the same semantics as `cvttp{s,d}2dq` on x86. This specifically
3270        returns `INT_MIN` for NaN or out-of-bounds lanes.
3271        "#,
3272            &formats.unary,
3273        )
3274        .operands_in(&[Operand::new("x", Float)])
3275        .operands_out(&[Operand::new("a", IntTo)]),
3276    );
3277
3278    let Int = &TypeVar::new(
3279        "Int",
3280        "A scalar or vector integer type",
3281        TypeSetBuilder::new()
3282            .ints(Interval::All)
3283            .simd_lanes(Interval::All)
3284            .build(),
3285    );
3286
3287    let FloatTo = &TypeVar::new(
3288        "FloatTo",
3289        "A scalar or vector floating point number",
3290        TypeSetBuilder::new()
3291            .floats(Interval::All)
3292            .simd_lanes(Interval::All)
3293            .build(),
3294    );
3295
3296    ig.push(
3297        Inst::new(
3298            "fcvt_from_uint",
3299            r#"
3300        Convert unsigned integer to floating point.
3301
3302        Each lane in `x` is interpreted as an unsigned integer and converted to
3303        floating point using round to nearest, ties to even.
3304
3305        The result type must have the same number of vector lanes as the input.
3306        "#,
3307            &formats.unary,
3308        )
3309        .operands_in(&[Operand::new("x", Int)])
3310        .operands_out(&[Operand::new("a", FloatTo)]),
3311    );
3312
3313    ig.push(
3314        Inst::new(
3315            "fcvt_from_sint",
3316            r#"
3317        Convert signed integer to floating point.
3318
3319        Each lane in `x` is interpreted as a signed integer and converted to
3320        floating point using round to nearest, ties to even.
3321
3322        The result type must have the same number of vector lanes as the input.
3323        "#,
3324            &formats.unary,
3325        )
3326        .operands_in(&[Operand::new("x", Int)])
3327        .operands_out(&[Operand::new("a", FloatTo)]),
3328    );
3329
3330    let WideInt = &TypeVar::new(
3331        "WideInt",
3332        "An integer type of width `i16` upwards",
3333        TypeSetBuilder::new().ints(16..128).build(),
3334    );
3335
3336    ig.push(
3337        Inst::new(
3338            "isplit",
3339            r#"
3340        Split an integer into low and high parts.
3341
3342        Vectors of integers are split lane-wise, so the results have the same
3343        number of lanes as the input, but the lanes are half the size.
3344
3345        Returns the low half of `x` and the high half of `x` as two independent
3346        values.
3347        "#,
3348            &formats.unary,
3349        )
3350        .operands_in(&[Operand::new("x", WideInt)])
3351        .operands_out(&[
3352            Operand::new("lo", &WideInt.half_width()).with_doc("The low bits of `x`"),
3353            Operand::new("hi", &WideInt.half_width()).with_doc("The high bits of `x`"),
3354        ]),
3355    );
3356
3357    ig.push(
3358        Inst::new(
3359            "iconcat",
3360            r#"
3361        Concatenate low and high bits to form a larger integer type.
3362
3363        Vectors of integers are concatenated lane-wise such that the result has
3364        the same number of lanes as the inputs, but the lanes are twice the
3365        size.
3366        "#,
3367            &formats.binary,
3368        )
3369        .operands_in(&[Operand::new("lo", NarrowInt), Operand::new("hi", NarrowInt)])
3370        .operands_out(&[Operand::new("a", &NarrowInt.double_width())
3371            .with_doc("The concatenation of `lo` and `hi`")]),
3372    );
3373
3374    // Instructions relating to atomic memory accesses and fences
3375    let AtomicMem = &TypeVar::new(
3376        "AtomicMem",
3377        "Any type that can be stored in memory, which can be used in an atomic operation",
3378        TypeSetBuilder::new().ints(8..128).build(),
3379    );
3380
3381    ig.push(
3382        Inst::new(
3383            "atomic_rmw",
3384            r#"
3385        Atomically read-modify-write memory at `p`, with second operand `x`.  The old value is
3386        returned.  `p` has the type of the target word size, and `x` may be any integer type; note
3387        that some targets require specific target features to be enabled in order to support 128-bit
3388        integer atomics.  The type of the returned value is the same as the type of `x`.  This
3389        operation is sequentially consistent and creates happens-before edges that order normal
3390        (non-atomic) loads and stores.
3391        "#,
3392            &formats.atomic_rmw,
3393        )
3394        .operands_in(&[
3395            Operand::new("MemFlags", &imm.memflags),
3396            Operand::new("AtomicRmwOp", &imm.atomic_rmw_op),
3397            Operand::new("p", iAddr),
3398            Operand::new("x", AtomicMem).with_doc("Value to be atomically stored"),
3399        ])
3400        .operands_out(&[Operand::new("a", AtomicMem).with_doc("Value atomically loaded")])
3401        .can_load()
3402        .can_store()
3403        .other_side_effects(),
3404    );
3405
3406    ig.push(
3407        Inst::new(
3408            "atomic_cas",
3409            r#"
3410        Perform an atomic compare-and-swap operation on memory at `p`, with expected value `e`,
3411        storing `x` if the value at `p` equals `e`.  The old value at `p` is returned,
3412        regardless of whether the operation succeeds or fails.  `p` has the type of the target
3413        word size, and `x` and `e` must have the same type and the same size, which may be any
3414        integer type; note that some targets require specific target features to be enabled in order
3415        to support 128-bit integer atomics.  The type of the returned value is the same as the type
3416        of `x` and `e`.  This operation is sequentially consistent and creates happens-before edges
3417        that order normal (non-atomic) loads and stores.
3418        "#,
3419            &formats.atomic_cas,
3420        )
3421        .operands_in(&[
3422            Operand::new("MemFlags", &imm.memflags),
3423            Operand::new("p", iAddr),
3424            Operand::new("e", AtomicMem).with_doc("Expected value in CAS"),
3425            Operand::new("x", AtomicMem).with_doc("Value to be atomically stored"),
3426        ])
3427        .operands_out(&[Operand::new("a", AtomicMem).with_doc("Value atomically loaded")])
3428        .can_load()
3429        .can_store()
3430        .other_side_effects(),
3431    );
3432
3433    ig.push(
3434        Inst::new(
3435            "atomic_load",
3436            r#"
3437        Atomically load from memory at `p`.
3438
3439        This is a polymorphic instruction that can load any value type which has a memory
3440        representation.  It can only be used for integer types; note that some targets require
3441        specific target features to be enabled in order to support 128-bit integer atomics. This
3442        operation is sequentially consistent and creates happens-before edges that order normal
3443        (non-atomic) loads and stores.
3444        "#,
3445            &formats.load_no_offset,
3446        )
3447        .operands_in(&[
3448            Operand::new("MemFlags", &imm.memflags),
3449            Operand::new("p", iAddr),
3450        ])
3451        .operands_out(&[Operand::new("a", AtomicMem).with_doc("Value atomically loaded")])
3452        .can_load()
3453        .other_side_effects(),
3454    );
3455
3456    ig.push(
3457        Inst::new(
3458            "atomic_store",
3459            r#"
3460        Atomically store `x` to memory at `p`.
3461
3462        This is a polymorphic instruction that can store any value type with a memory
3463        representation.  It can only be used for integer types; note that some targets require
3464        specific target features to be enabled in order to support 128-bit integer atomics This
3465        operation is sequentially consistent and creates happens-before edges that order normal
3466        (non-atomic) loads and stores.
3467        "#,
3468            &formats.store_no_offset,
3469        )
3470        .operands_in(&[
3471            Operand::new("MemFlags", &imm.memflags),
3472            Operand::new("x", AtomicMem).with_doc("Value to be atomically stored"),
3473            Operand::new("p", iAddr),
3474        ])
3475        .can_store()
3476        .other_side_effects(),
3477    );
3478
3479    ig.push(
3480        Inst::new(
3481            "fence",
3482            r#"
3483        A memory fence.  This must provide ordering to ensure that, at a minimum, neither loads
3484        nor stores of any kind may move forwards or backwards across the fence.  This operation
3485        is sequentially consistent.
3486        "#,
3487            &formats.nullary,
3488        )
3489        .other_side_effects(),
3490    );
3491
3492    let TxN = &TypeVar::new(
3493        "TxN",
3494        "A dynamic vector type",
3495        TypeSetBuilder::new()
3496            .ints(Interval::All)
3497            .floats(Interval::All)
3498            .dynamic_simd_lanes(Interval::All)
3499            .build(),
3500    );
3501
3502    ig.push(
3503        Inst::new(
3504            "extract_vector",
3505            r#"
3506        Return a fixed length sub vector, extracted from a dynamic vector.
3507        "#,
3508            &formats.binary_imm8,
3509        )
3510        .operands_in(&[
3511            Operand::new("x", TxN).with_doc("The dynamic vector to extract from"),
3512            Operand::new("y", &imm.uimm8).with_doc("128-bit vector index"),
3513        ])
3514        .operands_out(&[Operand::new("a", &TxN.dynamic_to_vector()).with_doc("New fixed vector")]),
3515    );
3516
3517    ig.push(
3518        Inst::new(
3519            "sequence_point",
3520            r#"
3521         A compiler barrier that acts as an immovable marker from IR input to machine-code output.
3522
3523         This "sequence point" can have debug tags attached to it, and these tags will be
3524         noted in the output `MachBuffer`.
3525
3526         It prevents motion of any other side-effects across this boundary.
3527         "#,
3528            &formats.nullary,
3529        )
3530        .other_side_effects(),
3531    );
3532}