From 0d50462a93671ae75561cdb491d2e0db01d7ab19 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Tue, 1 Oct 2019 10:18:11 +0200 Subject: [PATCH] Fixes #1091: Use match statements instead of HashMaps in x86 encodings; --- .../codegen/meta/src/isa/x86/encodings.rs | 104 +++++++++--------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/cranelift/codegen/meta/src/isa/x86/encodings.rs b/cranelift/codegen/meta/src/isa/x86/encodings.rs index 1e92940487..da08462e9a 100644 --- a/cranelift/codegen/meta/src/isa/x86/encodings.rs +++ b/cranelift/codegen/meta/src/isa/x86/encodings.rs @@ -1759,24 +1759,22 @@ pub(crate) fn define( } // SIMD insertlane - let mut x86_pinsr_mapping: HashMap)> = - HashMap::new(); - x86_pinsr_mapping.insert(8, (&PINSRB, Some(use_sse41_simd))); - x86_pinsr_mapping.insert(16, (&PINSRW, None)); - x86_pinsr_mapping.insert(32, (&PINSR, Some(use_sse41_simd))); - x86_pinsr_mapping.insert(64, (&PINSR, Some(use_sse41_simd))); - for ty in ValueType::all_lane_types().filter(allowed_simd_type) { - if let Some((opcode, isap)) = x86_pinsr_mapping.get(&ty.lane_bits()) { - let instruction = x86_pinsr.bind_vector_from_lane(ty, sse_vector_size); - let template = rec_r_ib_unsigned_r.opcodes(opcode); - if ty.lane_bits() < 64 { - e.enc_32_64_maybe_isap(instruction, template.nonrex(), isap.clone()); - } else { - // It turns out the 64-bit widths have REX/W encodings and only are available on - // x86_64. - e.enc64_maybe_isap(instruction, template.rex().w(), isap.clone()); - } + let (opcode, isap): (&[_], _) = match ty.lane_bits() { + 8 => (&PINSRB, Some(use_sse41_simd)), + 16 => (&PINSRW, None), + 32 | 64 => (&PINSR, Some(use_sse41_simd)), + _ => panic!("invalid size for SIMD insertlane"), + }; + + let instruction = x86_pinsr.bind_vector_from_lane(ty, sse_vector_size); + let template = rec_r_ib_unsigned_r.opcodes(opcode); + if ty.lane_bits() < 64 { + e.enc_32_64_maybe_isap(instruction, template.nonrex(), isap); + } else { + // It turns out the 64-bit widths have REX/W encodings and only are available on + // x86_64. + e.enc64_maybe_isap(instruction, template.rex().w(), isap); } } @@ -1802,23 +1800,22 @@ pub(crate) fn define( } // SIMD extractlane - let mut x86_pextr_mapping: HashMap = HashMap::new(); - x86_pextr_mapping.insert(8, &PEXTRB); - x86_pextr_mapping.insert(16, &PEXTRW); - x86_pextr_mapping.insert(32, &PEXTR); - x86_pextr_mapping.insert(64, &PEXTR); - for ty in ValueType::all_lane_types().filter(allowed_simd_type) { - if let Some(opcode) = x86_pextr_mapping.get(&ty.lane_bits()) { - let instruction = x86_pextr.bind_vector_from_lane(ty, sse_vector_size); - let template = rec_r_ib_unsigned_gpr.opcodes(opcode); - if ty.lane_bits() < 64 { - e.enc_32_64_maybe_isap(instruction, template.nonrex(), Some(use_sse41_simd)); - } else { - // It turns out the 64-bit widths have REX/W encodings and only are available on - // x86_64. - e.enc64_maybe_isap(instruction, template.rex().w(), Some(use_sse41_simd)); - } + let opcode = match ty.lane_bits() { + 8 => &PEXTRB, + 16 => &PEXTRW, + 32 | 64 => &PEXTR, + _ => panic!("invalid size for SIMD extractlane"), + }; + + let instruction = x86_pextr.bind_vector_from_lane(ty, sse_vector_size); + let template = rec_r_ib_unsigned_gpr.opcodes(opcode); + if ty.lane_bits() < 64 { + e.enc_32_64_maybe_isap(instruction, template.nonrex(), Some(use_sse41_simd)); + } else { + // It turns out the 64-bit widths have REX/W encodings and only are available on + // x86_64. + e.enc64_maybe_isap(instruction, template.rex().w(), Some(use_sse41_simd)); } } @@ -1996,27 +1993,28 @@ pub(crate) fn define( } // SIMD icmp using PCMPEQ* - let mut pcmpeq_mapping: HashMap)> = HashMap::new(); - pcmpeq_mapping.insert(8, (&PCMPEQB, None)); - pcmpeq_mapping.insert(16, (&PCMPEQW, None)); - pcmpeq_mapping.insert(32, (&PCMPEQD, None)); - pcmpeq_mapping.insert(64, (&PCMPEQQ, Some(use_sse41_simd))); for ty in ValueType::all_lane_types().filter(|t| t.is_int() && allowed_simd_type(t)) { - if let Some((opcodes, isa_predicate)) = pcmpeq_mapping.get(&ty.lane_bits()) { - let instruction = icmp.bind_vector_from_lane(ty, sse_vector_size); - let f_int_compare = formats.get(formats.by_name("IntCompare")); - let has_eq_condition_code = - InstructionPredicate::new_has_condition_code(f_int_compare, IntCC::Equal, "cond"); - let template = rec_icscc_fpr.nonrex().opcodes(*opcodes); - e.enc_32_64_func(instruction, template, |builder| { - let builder = builder.inst_predicate(has_eq_condition_code); - if let Some(p) = isa_predicate { - builder.isa_predicate(*p) - } else { - builder - } - }); - } + let (opcodes, isa_predicate): (&[_], _) = match ty.lane_bits() { + 8 => (&PCMPEQB, None), + 16 => (&PCMPEQW, None), + 32 => (&PCMPEQD, None), + 64 => (&PCMPEQQ, Some(use_sse41_simd)), + _ => panic!("invalid size for SIMD icmp"), + }; + + let instruction = icmp.bind_vector_from_lane(ty, sse_vector_size); + let f_int_compare = formats.get(formats.by_name("IntCompare")); + let has_eq_condition_code = + InstructionPredicate::new_has_condition_code(f_int_compare, IntCC::Equal, "cond"); + let template = rec_icscc_fpr.nonrex().opcodes(opcodes); + e.enc_32_64_func(instruction, template, |builder| { + let builder = builder.inst_predicate(has_eq_condition_code); + if let Some(p) = isa_predicate { + builder.isa_predicate(p) + } else { + builder + } + }); } // Reference type instructions