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