1 //! Shared ISLE prelude implementation for optimization (mid-end) and
2 //! lowering (backend) ISLE environments.
3 
4 /// Helper macro to define methods in `prelude.isle` within `impl Context for
5 /// ...` for each backend. These methods are shared amongst all backends.
6 #[macro_export]
7 #[doc(hidden)]
8 macro_rules! isle_common_prelude_methods {
9     () => {
10         isle_numerics_methods!();
11 
12         /// We don't have a way of making a `()` value in isle directly.
13         #[inline]
14         fn unit(&mut self) -> Unit {
15             ()
16         }
17 
18         #[inline]
19         fn checked_add_with_type(&mut self, ty: Type, a: u64, b: u64) -> Option<u64> {
20             let c = a.checked_add(b)?;
21             let ty_mask = self.ty_mask(ty);
22             if (c & !ty_mask) == 0 { Some(c) } else { None }
23         }
24 
25         #[inline]
26         fn add_overflows_with_type(&mut self, ty: Type, a: u64, b: u64) -> bool {
27             self.checked_add_with_type(ty, a, b).is_none()
28         }
29 
30         #[inline]
31         fn imm64_clz(&mut self, ty: Type, a: Imm64) -> Imm64 {
32             let bits = ty.bits();
33             assert!(bits <= 64);
34             let clz_offset = 64 - bits;
35             let a_v: u64 = a.bits().cast_unsigned();
36             let lz = a_v.leading_zeros() - clz_offset;
37             Imm64::new(i64::from(lz))
38         }
39 
40         #[inline]
41         fn imm64_ctz(&mut self, ty: Type, a: Imm64) -> Imm64 {
42             let bits = ty.bits();
43             assert!(bits <= 64);
44             let a_v: u64 = a.bits().cast_unsigned();
45             if a_v == 0 {
46                 // ctz(0) is defined to be the number of bits in the type.
47                 Imm64::new(i64::from(bits))
48             } else {
49                 let lz = a_v.trailing_zeros();
50                 Imm64::new(i64::from(lz))
51             }
52         }
53 
54         #[inline]
55         fn imm64_sdiv(&mut self, ty: Type, x: Imm64, y: Imm64) -> Option<Imm64> {
56             // Sign extend `x` and `y`.
57             let type_width = ty.bits();
58             assert!(type_width <= 64);
59             let x = x.sign_extend_from_width(type_width).bits();
60             let y = y.sign_extend_from_width(type_width).bits();
61             let shift = 64 - type_width;
62 
63             // NB: We can't rely on `checked_div` to detect `ty::MIN / -1`
64             // (which overflows and should trap) because we are working with
65             // `i64` values here, and `i32::MIN != i64::MIN`, for
66             // example. Therefore, we have to explicitly check for this case
67             // ourselves.
68             let min = ((self.ty_smin(ty) as i64) << shift) >> shift;
69             if x == min && y == -1 {
70                 return None;
71             }
72 
73             let result = x.checked_div(y)?;
74             Some(Imm64::new(result).mask_to_width(type_width))
75         }
76 
77         #[inline]
78         fn imm64_srem(&mut self, ty: Type, x: Imm64, y: Imm64) -> Option<Imm64> {
79             // Sign extend `x` and `y`.
80             let type_width = ty.bits();
81             assert!(type_width <= 64);
82             let x = x.sign_extend_from_width(type_width).bits();
83             let y = y.sign_extend_from_width(type_width).bits();
84 
85             // iN::min % -1 is defined as 0 in wasm so no need
86             // to check for it
87 
88             let result = x.checked_rem(y)?;
89             Some(Imm64::new(result).mask_to_width(type_width))
90         }
91 
92         #[inline]
93         fn imm64_shl(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
94             // Mask off any excess shift bits.
95             let shift_mask = (ty.bits() - 1) as u64;
96             let y = (y.bits() as u64) & shift_mask;
97 
98             // Mask the result to `ty` bits.
99             let ty_mask = self.ty_mask(ty) as i64;
100             Imm64::new((x.bits() << y) & ty_mask)
101         }
102 
103         #[inline]
104         fn imm64_ushr(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
105             let ty_mask = self.ty_mask(ty);
106             let x = (x.bits() as u64) & ty_mask;
107 
108             // Mask off any excess shift bits.
109             let shift_mask = (ty.bits() - 1) as u64;
110             let y = (y.bits() as u64) & shift_mask;
111 
112             // NB: No need to mask off high bits because they are already zero.
113             Imm64::new((x >> y) as i64)
114         }
115 
116         #[inline]
117         fn imm64_sshr(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
118             // Sign extend `x` from `ty.bits()`-width to the full 64 bits.
119             let shift = u32::checked_sub(64, ty.bits()).unwrap_or(0);
120             let x = (x.bits() << shift) >> shift;
121 
122             // Mask off any excess shift bits.
123             let shift_mask = (ty.bits() - 1) as i64;
124             let y = y.bits() & shift_mask;
125 
126             // Mask off sign bits that aren't part of `ty`.
127             let ty_mask = self.ty_mask(ty) as i64;
128             Imm64::new((x >> y) & ty_mask)
129         }
130 
131         #[inline]
132         fn imm64_rotl(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
133             let bits = ty.bits();
134             assert!(bits <= 64);
135             // This holds for all Cranelift types ({u/i}{8,16,32,64})
136             debug_assert!(bits.is_power_of_two());
137 
138             let ty_mask = self.ty_mask(ty);
139             let x = (x.bits() as u64) & ty_mask;
140 
141             // Mask off any excess rotate bits so the rotate stays within `ty`.
142             let shift_mask = bits - 1;
143             let y = ((y.bits() as u64) & u64::from(shift_mask)) as u32;
144 
145             // In Rust, x >> 64 or x << 64 panics.
146             let result = if y == 0 {
147                 x
148             } else {
149                 (x << y) | (x >> (u32::from(bits) - y))
150             };
151 
152             Imm64::new((result & ty_mask) as i64)
153         }
154 
155         #[inline]
156         fn imm64_rotr(&mut self, ty: Type, x: Imm64, y: Imm64) -> Imm64 {
157             let bits = ty.bits();
158             assert!(bits <= 64);
159             debug_assert!(bits.is_power_of_two());
160 
161             let ty_mask = self.ty_mask(ty);
162             let x = (x.bits() as u64) & ty_mask;
163 
164             // Mask off any excess rotate bits so the rotate stays within `ty`.
165             let shift_mask = bits - 1;
166             let y = ((y.bits() as u64) & u64::from(shift_mask)) as u32;
167 
168             let result = if y == 0 {
169                 x
170             } else {
171                 (x >> y) | (x << (u32::from(bits) - y))
172             };
173 
174             Imm64::new((result & ty_mask) as i64)
175         }
176 
177         #[inline]
178         fn i64_sextend_u64(&mut self, ty: Type, x: u64) -> i64 {
179             let shift_amt = core::cmp::max(0, 64 - ty.bits());
180             ((x as i64) << shift_amt) >> shift_amt
181         }
182 
183         #[inline]
184         fn i64_sextend_imm64(&mut self, ty: Type, x: Imm64) -> i64 {
185             x.sign_extend_from_width(ty.bits()).bits()
186         }
187 
188         #[inline]
189         fn u64_uextend_imm64(&mut self, ty: Type, x: Imm64) -> u64 {
190             (x.bits() as u64) & self.ty_mask(ty)
191         }
192 
193         #[inline]
194         fn imm64_icmp(&mut self, ty: Type, cc: &IntCC, x: Imm64, y: Imm64) -> Imm64 {
195             let ux = self.u64_uextend_imm64(ty, x);
196             let uy = self.u64_uextend_imm64(ty, y);
197             let sx = self.i64_sextend_imm64(ty, x);
198             let sy = self.i64_sextend_imm64(ty, y);
199             let result = match cc {
200                 IntCC::Equal => ux == uy,
201                 IntCC::NotEqual => ux != uy,
202                 IntCC::UnsignedGreaterThanOrEqual => ux >= uy,
203                 IntCC::UnsignedGreaterThan => ux > uy,
204                 IntCC::UnsignedLessThanOrEqual => ux <= uy,
205                 IntCC::UnsignedLessThan => ux < uy,
206                 IntCC::SignedGreaterThanOrEqual => sx >= sy,
207                 IntCC::SignedGreaterThan => sx > sy,
208                 IntCC::SignedLessThanOrEqual => sx <= sy,
209                 IntCC::SignedLessThan => sx < sy,
210             };
211             Imm64::new(result.into())
212         }
213 
214         #[inline]
215         fn ty_bits(&mut self, ty: Type) -> u8 {
216             use core::convert::TryInto;
217             ty.bits().try_into().unwrap()
218         }
219 
220         #[inline]
221         fn ty_bits_u16(&mut self, ty: Type) -> u16 {
222             ty.bits() as u16
223         }
224 
225         #[inline]
226         fn ty_bits_u64(&mut self, ty: Type) -> u64 {
227             ty.bits() as u64
228         }
229 
230         #[inline]
231         fn ty_bytes(&mut self, ty: Type) -> u16 {
232             u16::try_from(ty.bytes()).unwrap()
233         }
234 
235         #[inline]
236         fn ty_mask(&mut self, ty: Type) -> u64 {
237             let ty_bits = ty.bits();
238             debug_assert_ne!(ty_bits, 0);
239             let shift = 64_u64
240                 .checked_sub(ty_bits.into())
241                 .expect("unimplemented for > 64 bits");
242             u64::MAX >> shift
243         }
244 
245         #[inline]
246         fn ty_lane_mask(&mut self, ty: Type) -> u64 {
247             let ty_lane_count = ty.lane_count();
248             debug_assert_ne!(ty_lane_count, 0);
249             let shift = 64_u64
250                 .checked_sub(ty_lane_count.into())
251                 .expect("unimplemented for > 64 bits");
252             u64::MAX >> shift
253         }
254 
255         #[inline]
256         fn ty_lane_count(&mut self, ty: Type) -> u64 {
257             ty.lane_count() as u64
258         }
259 
260         #[inline]
261         fn ty_umin(&mut self, _ty: Type) -> u64 {
262             0
263         }
264 
265         #[inline]
266         fn ty_umax(&mut self, ty: Type) -> u64 {
267             self.ty_mask(ty)
268         }
269 
270         #[inline]
271         fn ty_smin(&mut self, ty: Type) -> u64 {
272             let ty_bits = ty.bits();
273             debug_assert_ne!(ty_bits, 0);
274             let shift = 64_u64
275                 .checked_sub(ty_bits.into())
276                 .expect("unimplemented for > 64 bits");
277             (i64::MIN as u64) >> shift
278         }
279 
280         #[inline]
281         fn ty_smax(&mut self, ty: Type) -> u64 {
282             let ty_bits = ty.bits();
283             debug_assert_ne!(ty_bits, 0);
284             let shift = 64_u64
285                 .checked_sub(ty_bits.into())
286                 .expect("unimplemented for > 64 bits");
287             (i64::MAX as u64) >> shift
288         }
289 
290         fn fits_in_16(&mut self, ty: Type) -> Option<Type> {
291             if ty.bits() <= 16 && !ty.is_dynamic_vector() {
292                 Some(ty)
293             } else {
294                 None
295             }
296         }
297 
298         #[inline]
299         fn fits_in_32(&mut self, ty: Type) -> Option<Type> {
300             if ty.bits() <= 32 && !ty.is_dynamic_vector() {
301                 Some(ty)
302             } else {
303                 None
304             }
305         }
306 
307         #[inline]
308         fn lane_fits_in_32(&mut self, ty: Type) -> Option<Type> {
309             if !ty.is_vector() && !ty.is_dynamic_vector() {
310                 None
311             } else if ty.lane_type().bits() <= 32 {
312                 Some(ty)
313             } else {
314                 None
315             }
316         }
317 
318         #[inline]
319         fn fits_in_64(&mut self, ty: Type) -> Option<Type> {
320             if ty.bits() <= 64 && !ty.is_dynamic_vector() {
321                 Some(ty)
322             } else {
323                 None
324             }
325         }
326 
327         #[inline]
328         fn ty_int_ref_scalar_64(&mut self, ty: Type) -> Option<Type> {
329             if ty.bits() <= 64 && !ty.is_float() && !ty.is_vector() && !ty.is_dynamic_vector() {
330                 Some(ty)
331             } else {
332                 None
333             }
334         }
335 
336         #[inline]
337         fn ty_int_ref_scalar_64_extract(&mut self, ty: Type) -> Option<Type> {
338             self.ty_int_ref_scalar_64(ty)
339         }
340 
341         #[inline]
342         fn ty_16(&mut self, ty: Type) -> Option<Type> {
343             if ty.bits() == 16 { Some(ty) } else { None }
344         }
345 
346         #[inline]
347         fn ty_32(&mut self, ty: Type) -> Option<Type> {
348             if ty.bits() == 32 { Some(ty) } else { None }
349         }
350 
351         #[inline]
352         fn ty_64(&mut self, ty: Type) -> Option<Type> {
353             if ty.bits() == 64 { Some(ty) } else { None }
354         }
355 
356         #[inline]
357         fn ty_128(&mut self, ty: Type) -> Option<Type> {
358             if ty.bits() == 128 { Some(ty) } else { None }
359         }
360 
361         #[inline]
362         fn ty_32_or_64(&mut self, ty: Type) -> Option<Type> {
363             if ty.bits() == 32 || ty.bits() == 64 {
364                 Some(ty)
365             } else {
366                 None
367             }
368         }
369 
370         #[inline]
371         fn ty_8_or_16(&mut self, ty: Type) -> Option<Type> {
372             if ty.bits() == 8 || ty.bits() == 16 {
373                 Some(ty)
374             } else {
375                 None
376             }
377         }
378 
379         #[inline]
380         fn ty_16_or_32(&mut self, ty: Type) -> Option<Type> {
381             if ty.bits() == 16 || ty.bits() == 32 {
382                 Some(ty)
383             } else {
384                 None
385             }
386         }
387 
388         #[inline]
389         fn int_fits_in_32(&mut self, ty: Type) -> Option<Type> {
390             match ty {
391                 I8 | I16 | I32 => Some(ty),
392                 _ => None,
393             }
394         }
395 
396         #[inline]
397         fn ty_int_ref_64(&mut self, ty: Type) -> Option<Type> {
398             match ty {
399                 I64 => Some(ty),
400                 _ => None,
401             }
402         }
403 
404         #[inline]
405         fn ty_int_ref_16_to_64(&mut self, ty: Type) -> Option<Type> {
406             match ty {
407                 I16 | I32 | I64 => Some(ty),
408                 _ => None,
409             }
410         }
411 
412         #[inline]
413         fn ty_int(&mut self, ty: Type) -> Option<Type> {
414             ty.is_int().then(|| ty)
415         }
416 
417         #[inline]
418         fn ty_scalar(&mut self, ty: Type) -> Option<Type> {
419             if ty.lane_count() == 1 { Some(ty) } else { None }
420         }
421 
422         #[inline]
423         fn ty_scalar_float(&mut self, ty: Type) -> Option<Type> {
424             if ty.is_float() { Some(ty) } else { None }
425         }
426 
427         #[inline]
428         fn ty_float_or_vec(&mut self, ty: Type) -> Option<Type> {
429             if ty.is_float() || ty.is_vector() {
430                 Some(ty)
431             } else {
432                 None
433             }
434         }
435 
436         fn ty_vector_float(&mut self, ty: Type) -> Option<Type> {
437             if ty.is_vector() && ty.lane_type().is_float() {
438                 Some(ty)
439             } else {
440                 None
441             }
442         }
443 
444         #[inline]
445         fn ty_vector_not_float(&mut self, ty: Type) -> Option<Type> {
446             if ty.is_vector() && !ty.lane_type().is_float() {
447                 Some(ty)
448             } else {
449                 None
450             }
451         }
452 
453         #[inline]
454         fn ty_vec64_ctor(&mut self, ty: Type) -> Option<Type> {
455             if ty.is_vector() && ty.bits() == 64 {
456                 Some(ty)
457             } else {
458                 None
459             }
460         }
461 
462         #[inline]
463         fn ty_vec64(&mut self, ty: Type) -> Option<Type> {
464             if ty.is_vector() && ty.bits() == 64 {
465                 Some(ty)
466             } else {
467                 None
468             }
469         }
470 
471         #[inline]
472         fn ty_vec128(&mut self, ty: Type) -> Option<Type> {
473             if ty.is_vector() && ty.bits() == 128 {
474                 Some(ty)
475             } else {
476                 None
477             }
478         }
479 
480         #[inline]
481         fn ty_dyn_vec64(&mut self, ty: Type) -> Option<Type> {
482             if ty.is_dynamic_vector() && dynamic_to_fixed(ty).bits() == 64 {
483                 Some(ty)
484             } else {
485                 None
486             }
487         }
488 
489         #[inline]
490         fn ty_dyn_vec128(&mut self, ty: Type) -> Option<Type> {
491             if ty.is_dynamic_vector() && dynamic_to_fixed(ty).bits() == 128 {
492                 Some(ty)
493             } else {
494                 None
495             }
496         }
497 
498         #[inline]
499         fn ty_vec64_int(&mut self, ty: Type) -> Option<Type> {
500             if ty.is_vector() && ty.bits() == 64 && ty.lane_type().is_int() {
501                 Some(ty)
502             } else {
503                 None
504             }
505         }
506 
507         #[inline]
508         fn ty_vec128_int(&mut self, ty: Type) -> Option<Type> {
509             if ty.is_vector() && ty.bits() == 128 && ty.lane_type().is_int() {
510                 Some(ty)
511             } else {
512                 None
513             }
514         }
515 
516         #[inline]
517         fn ty_addr64(&mut self, ty: Type) -> Option<Type> {
518             match ty {
519                 I64 => Some(ty),
520                 _ => None,
521             }
522         }
523 
524         #[inline]
525         fn u64_from_imm64(&mut self, imm: Imm64) -> u64 {
526             imm.bits() as u64
527         }
528 
529         #[inline]
530         fn imm64_power_of_two(&mut self, x: Imm64) -> Option<u64> {
531             let x = i64::from(x);
532             let x = u64::try_from(x).ok()?;
533             if x.is_power_of_two() {
534                 Some(x.trailing_zeros().into())
535             } else {
536                 None
537             }
538         }
539 
540         #[inline]
541         fn u64_from_bool(&mut self, b: bool) -> u64 {
542             if b { u64::MAX } else { 0 }
543         }
544 
545         #[inline]
546         fn multi_lane(&mut self, ty: Type) -> Option<(u32, u32)> {
547             if ty.lane_count() > 1 {
548                 Some((ty.lane_bits(), ty.lane_count()))
549             } else {
550                 None
551             }
552         }
553 
554         #[inline]
555         fn dynamic_lane(&mut self, ty: Type) -> Option<(u32, u32)> {
556             if ty.is_dynamic_vector() {
557                 Some((ty.lane_bits(), ty.min_lane_count()))
558             } else {
559                 None
560             }
561         }
562 
563         #[inline]
564         fn ty_dyn64_int(&mut self, ty: Type) -> Option<Type> {
565             if ty.is_dynamic_vector() && ty.min_bits() == 64 && ty.lane_type().is_int() {
566                 Some(ty)
567             } else {
568                 None
569             }
570         }
571 
572         #[inline]
573         fn ty_dyn128_int(&mut self, ty: Type) -> Option<Type> {
574             if ty.is_dynamic_vector() && ty.min_bits() == 128 && ty.lane_type().is_int() {
575                 Some(ty)
576             } else {
577                 None
578             }
579         }
580 
581         fn u16_from_ieee16(&mut self, val: Ieee16) -> u16 {
582             val.bits()
583         }
584 
585         fn u32_from_ieee32(&mut self, val: Ieee32) -> u32 {
586             val.bits()
587         }
588 
589         fn u64_from_ieee64(&mut self, val: Ieee64) -> u64 {
590             val.bits()
591         }
592 
593         fn u8_from_uimm8(&mut self, val: Uimm8) -> u8 {
594             val
595         }
596 
597         fn not_vec32x2(&mut self, ty: Type) -> Option<Type> {
598             if ty.lane_bits() == 32 && ty.lane_count() == 2 {
599                 None
600             } else {
601                 Some(ty)
602             }
603         }
604 
605         fn not_i64x2(&mut self, ty: Type) -> Option<()> {
606             if ty == I64X2 { None } else { Some(()) }
607         }
608 
609         fn trap_code_division_by_zero(&mut self) -> TrapCode {
610             TrapCode::INTEGER_DIVISION_BY_ZERO
611         }
612 
613         fn trap_code_integer_overflow(&mut self) -> TrapCode {
614             TrapCode::INTEGER_OVERFLOW
615         }
616 
617         fn trap_code_bad_conversion_to_integer(&mut self) -> TrapCode {
618             TrapCode::BAD_CONVERSION_TO_INTEGER
619         }
620 
621         fn nonzero_u64_from_imm64(&mut self, val: Imm64) -> Option<u64> {
622             match val.bits() {
623                 0 => None,
624                 n => Some(n as u64),
625             }
626         }
627 
628         #[inline]
629         fn u32_nonnegative(&mut self, x: u32) -> Option<u32> {
630             if (x as i32) >= 0 { Some(x) } else { None }
631         }
632 
633         #[inline]
634         fn imm64(&mut self, x: u64) -> Imm64 {
635             Imm64::new(x as i64)
636         }
637 
638         #[inline]
639         fn imm64_masked(&mut self, ty: Type, x: u64) -> Imm64 {
640             Imm64::new((x & self.ty_mask(ty)) as i64)
641         }
642 
643         #[inline]
644         fn offset32(&mut self, x: Offset32) -> i32 {
645             x.into()
646         }
647 
648         #[inline]
649         fn lane_type(&mut self, ty: Type) -> Type {
650             ty.lane_type()
651         }
652 
653         #[inline]
654         fn ty_half_lanes(&mut self, ty: Type) -> Option<Type> {
655             if ty.lane_count() == 1 {
656                 None
657             } else {
658                 ty.lane_type().by(ty.lane_count() / 2)
659             }
660         }
661 
662         #[inline]
663         fn ty_half_width(&mut self, ty: Type) -> Option<Type> {
664             ty.half_width()
665         }
666 
667         #[inline]
668         fn ty_equal(&mut self, lhs: Type, rhs: Type) -> bool {
669             lhs == rhs
670         }
671 
672         #[inline]
673         fn offset32_to_i32(&mut self, offset: Offset32) -> i32 {
674             offset.into()
675         }
676 
677         #[inline]
678         fn i32_to_offset32(&mut self, offset: i32) -> Offset32 {
679             Offset32::new(offset)
680         }
681 
682         #[inline]
683         fn mem_flags_trusted(&mut self) -> MemFlags {
684             MemFlags::trusted()
685         }
686 
687         #[inline]
688         fn little_or_native_endian(&mut self, flags: MemFlags) -> Option<MemFlags> {
689             match flags.explicit_endianness() {
690                 Some(crate::ir::Endianness::Little) | None => Some(flags),
691                 Some(crate::ir::Endianness::Big) => None,
692             }
693         }
694 
695         #[inline]
696         fn intcc_unsigned(&mut self, x: &IntCC) -> IntCC {
697             x.unsigned()
698         }
699 
700         #[inline]
701         fn signed_cond_code(&mut self, cc: &IntCC) -> Option<IntCC> {
702             match cc {
703                 IntCC::Equal
704                 | IntCC::UnsignedGreaterThanOrEqual
705                 | IntCC::UnsignedGreaterThan
706                 | IntCC::UnsignedLessThanOrEqual
707                 | IntCC::UnsignedLessThan
708                 | IntCC::NotEqual => None,
709                 IntCC::SignedGreaterThanOrEqual
710                 | IntCC::SignedGreaterThan
711                 | IntCC::SignedLessThanOrEqual
712                 | IntCC::SignedLessThan => Some(*cc),
713             }
714         }
715 
716         #[inline]
717         fn intcc_swap_args(&mut self, cc: &IntCC) -> IntCC {
718             cc.swap_args()
719         }
720 
721         #[inline]
722         fn intcc_complement(&mut self, cc: &IntCC) -> IntCC {
723             cc.complement()
724         }
725 
726         #[inline]
727         fn intcc_without_eq(&mut self, x: &IntCC) -> IntCC {
728             x.without_equal()
729         }
730 
731         #[inline]
732         fn floatcc_swap_args(&mut self, cc: &FloatCC) -> FloatCC {
733             cc.swap_args()
734         }
735 
736         #[inline]
737         fn floatcc_complement(&mut self, cc: &FloatCC) -> FloatCC {
738             cc.complement()
739         }
740 
741         fn floatcc_unordered(&mut self, cc: &FloatCC) -> bool {
742             match *cc {
743                 FloatCC::Unordered
744                 | FloatCC::UnorderedOrEqual
745                 | FloatCC::UnorderedOrLessThan
746                 | FloatCC::UnorderedOrLessThanOrEqual
747                 | FloatCC::UnorderedOrGreaterThan
748                 | FloatCC::UnorderedOrGreaterThanOrEqual => true,
749                 _ => false,
750             }
751         }
752 
753         #[inline]
754         fn unpack_value_array_2(&mut self, arr: &ValueArray2) -> (Value, Value) {
755             let [a, b] = *arr;
756             (a, b)
757         }
758 
759         #[inline]
760         fn pack_value_array_2(&mut self, a: Value, b: Value) -> ValueArray2 {
761             [a, b]
762         }
763 
764         #[inline]
765         fn unpack_value_array_3(&mut self, arr: &ValueArray3) -> (Value, Value, Value) {
766             let [a, b, c] = *arr;
767             (a, b, c)
768         }
769 
770         #[inline]
771         fn pack_value_array_3(&mut self, a: Value, b: Value, c: Value) -> ValueArray3 {
772             [a, b, c]
773         }
774 
775         #[inline]
776         fn unpack_block_array_2(&mut self, arr: &BlockArray2) -> (BlockCall, BlockCall) {
777             let [a, b] = *arr;
778             (a, b)
779         }
780 
781         #[inline]
782         fn pack_block_array_2(&mut self, a: BlockCall, b: BlockCall) -> BlockArray2 {
783             [a, b]
784         }
785 
786         fn u128_replicated_u64(&mut self, val: u128) -> Option<u64> {
787             let low64 = val as u64 as u128;
788             if (low64 | (low64 << 64)) == val {
789                 Some(low64 as u64)
790             } else {
791                 None
792             }
793         }
794 
795         fn u64_replicated_u32(&mut self, val: u64) -> Option<u64> {
796             let low32 = val as u32 as u64;
797             if (low32 | (low32 << 32)) == val {
798                 Some(low32)
799             } else {
800                 None
801             }
802         }
803 
804         fn u32_replicated_u16(&mut self, val: u64) -> Option<u64> {
805             let val = val as u32;
806             let low16 = val as u16 as u32;
807             if (low16 | (low16 << 16)) == val {
808                 Some(low16.into())
809             } else {
810                 None
811             }
812         }
813 
814         fn u16_replicated_u8(&mut self, val: u64) -> Option<u8> {
815             let val = val as u16;
816             let low8 = val as u8 as u16;
817             if (low8 | (low8 << 8)) == val {
818                 Some(low8 as u8)
819             } else {
820                 None
821             }
822         }
823 
824         fn u128_low_bits(&mut self, val: u128) -> u64 {
825             val as u64
826         }
827 
828         fn u128_high_bits(&mut self, val: u128) -> u64 {
829             (val >> 64) as u64
830         }
831 
832         fn f16_min(&mut self, a: Ieee16, b: Ieee16) -> Option<Ieee16> {
833             a.minimum(b).non_nan()
834         }
835 
836         fn f16_max(&mut self, a: Ieee16, b: Ieee16) -> Option<Ieee16> {
837             a.maximum(b).non_nan()
838         }
839 
840         fn f16_neg(&mut self, n: Ieee16) -> Ieee16 {
841             -n
842         }
843 
844         fn f16_abs(&mut self, n: Ieee16) -> Ieee16 {
845             n.abs()
846         }
847 
848         fn f16_copysign(&mut self, a: Ieee16, b: Ieee16) -> Ieee16 {
849             a.copysign(b)
850         }
851 
852         fn f32_add(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> {
853             (lhs + rhs).non_nan()
854         }
855 
856         fn f32_sub(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> {
857             (lhs - rhs).non_nan()
858         }
859 
860         fn f32_mul(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> {
861             (lhs * rhs).non_nan()
862         }
863 
864         fn f32_div(&mut self, lhs: Ieee32, rhs: Ieee32) -> Option<Ieee32> {
865             (lhs / rhs).non_nan()
866         }
867 
868         fn f32_sqrt(&mut self, n: Ieee32) -> Option<Ieee32> {
869             n.sqrt().non_nan()
870         }
871 
872         fn f32_ceil(&mut self, n: Ieee32) -> Option<Ieee32> {
873             n.ceil().non_nan()
874         }
875 
876         fn f32_floor(&mut self, n: Ieee32) -> Option<Ieee32> {
877             n.floor().non_nan()
878         }
879 
880         fn f32_trunc(&mut self, n: Ieee32) -> Option<Ieee32> {
881             n.trunc().non_nan()
882         }
883 
884         fn f32_nearest(&mut self, n: Ieee32) -> Option<Ieee32> {
885             n.round_ties_even().non_nan()
886         }
887 
888         fn f32_min(&mut self, a: Ieee32, b: Ieee32) -> Option<Ieee32> {
889             a.minimum(b).non_nan()
890         }
891 
892         fn f32_max(&mut self, a: Ieee32, b: Ieee32) -> Option<Ieee32> {
893             a.maximum(b).non_nan()
894         }
895 
896         fn f32_neg(&mut self, n: Ieee32) -> Ieee32 {
897             -n
898         }
899 
900         fn f32_abs(&mut self, n: Ieee32) -> Ieee32 {
901             n.abs()
902         }
903 
904         fn f32_copysign(&mut self, a: Ieee32, b: Ieee32) -> Ieee32 {
905             a.copysign(b)
906         }
907 
908         fn f64_add(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> {
909             (lhs + rhs).non_nan()
910         }
911 
912         fn f64_sub(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> {
913             (lhs - rhs).non_nan()
914         }
915 
916         fn f64_mul(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> {
917             (lhs * rhs).non_nan()
918         }
919 
920         fn f64_div(&mut self, lhs: Ieee64, rhs: Ieee64) -> Option<Ieee64> {
921             (lhs / rhs).non_nan()
922         }
923 
924         fn f64_sqrt(&mut self, n: Ieee64) -> Option<Ieee64> {
925             n.sqrt().non_nan()
926         }
927 
928         fn f64_ceil(&mut self, n: Ieee64) -> Option<Ieee64> {
929             n.ceil().non_nan()
930         }
931 
932         fn f64_floor(&mut self, n: Ieee64) -> Option<Ieee64> {
933             n.floor().non_nan()
934         }
935 
936         fn f64_trunc(&mut self, n: Ieee64) -> Option<Ieee64> {
937             n.trunc().non_nan()
938         }
939 
940         fn f64_nearest(&mut self, n: Ieee64) -> Option<Ieee64> {
941             n.round_ties_even().non_nan()
942         }
943 
944         fn f64_min(&mut self, a: Ieee64, b: Ieee64) -> Option<Ieee64> {
945             a.minimum(b).non_nan()
946         }
947 
948         fn f64_max(&mut self, a: Ieee64, b: Ieee64) -> Option<Ieee64> {
949             a.maximum(b).non_nan()
950         }
951 
952         fn f64_neg(&mut self, n: Ieee64) -> Ieee64 {
953             -n
954         }
955 
956         fn f64_abs(&mut self, n: Ieee64) -> Ieee64 {
957             n.abs()
958         }
959 
960         fn f64_copysign(&mut self, a: Ieee64, b: Ieee64) -> Ieee64 {
961             a.copysign(b)
962         }
963 
964         fn f128_min(&mut self, a: Ieee128, b: Ieee128) -> Option<Ieee128> {
965             a.minimum(b).non_nan()
966         }
967 
968         fn f128_max(&mut self, a: Ieee128, b: Ieee128) -> Option<Ieee128> {
969             a.maximum(b).non_nan()
970         }
971 
972         fn f128_neg(&mut self, n: Ieee128) -> Ieee128 {
973             -n
974         }
975 
976         fn f128_abs(&mut self, n: Ieee128) -> Ieee128 {
977             n.abs()
978         }
979 
980         fn f128_copysign(&mut self, a: Ieee128, b: Ieee128) -> Ieee128 {
981             a.copysign(b)
982         }
983 
984         #[inline]
985         fn def_inst(&mut self, val: Value) -> Option<Inst> {
986             self.dfg().value_def(val).inst()
987         }
988     };
989 }
990