From 079fcafcb1b2d4bbfddd26b201d9df38012dbd25 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Fri, 14 Feb 2020 13:24:13 -0800 Subject: [PATCH] Expand x86 registers to include 32 XMM registers The EVEX encoding format (e.g. in AVX-512) allows addressing 32 registers instead of 16. The FPR register class currently defines 16 registers, `%xmm0`-`%xmm15`; that class is kept as-is with this change. A larger class, FPR32, is added as a super-class of FPR using a larger bank of registers, `%xmm0`-`%xmm31`. --- .../codegen/meta/src/isa/x86/registers.rs | 15 ++-- cranelift/codegen/src/isa/x86/registers.rs | 73 ++++++++++++------- 2 files changed, 56 insertions(+), 32 deletions(-) diff --git a/cranelift/codegen/meta/src/isa/x86/registers.rs b/cranelift/codegen/meta/src/isa/x86/registers.rs index 5c31401a3c..ca244b7446 100644 --- a/cranelift/codegen/meta/src/isa/x86/registers.rs +++ b/cranelift/codegen/meta/src/isa/x86/registers.rs @@ -3,6 +3,11 @@ use crate::cdsl::regs::{IsaRegs, IsaRegsBuilder, RegBankBuilder, RegClassBuilder pub(crate) fn define() -> IsaRegs { let mut regs = IsaRegsBuilder::new(); + let builder = RegBankBuilder::new("FloatRegs", "xmm") + .units(32) + .track_pressure(true); + let float_regs = regs.add_bank(builder); + let builder = RegBankBuilder::new("IntRegs", "r") .units(16) .names(vec!["rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"]) @@ -10,11 +15,6 @@ pub(crate) fn define() -> IsaRegs { .pinned_reg(15); let int_regs = regs.add_bank(builder); - let builder = RegBankBuilder::new("FloatRegs", "xmm") - .units(16) - .track_pressure(true); - let float_regs = regs.add_bank(builder); - let builder = RegBankBuilder::new("FlagRegs", "") .units(1) .names(vec!["rflags"]) @@ -24,7 +24,10 @@ pub(crate) fn define() -> IsaRegs { let builder = RegClassBuilder::new_toplevel("GPR", int_regs); let gpr = regs.add_class(builder); - let builder = RegClassBuilder::new_toplevel("FPR", float_regs); + let builder = RegClassBuilder::new_toplevel("FPR32", float_regs); + let fpr32 = regs.add_class(builder); + + let builder = RegClassBuilder::subclass_of("FPR", fpr32, 0, 16); let fpr = regs.add_class(builder); let builder = RegClassBuilder::new_toplevel("FLAG", flag_reg); diff --git a/cranelift/codegen/src/isa/x86/registers.rs b/cranelift/codegen/src/isa/x86/registers.rs index 130cf41d79..ac5ac37328 100644 --- a/cranelift/codegen/src/isa/x86/registers.rs +++ b/cranelift/codegen/src/isa/x86/registers.rs @@ -12,40 +12,61 @@ mod tests { #[test] fn unit_encodings() { + fn gpr(unit: usize) -> Option { + Some(GPR.unit(unit)) + } // The encoding of integer registers is not alphabetical. - assert_eq!(INFO.parse_regunit("rax"), Some(0)); - assert_eq!(INFO.parse_regunit("rbx"), Some(3)); - assert_eq!(INFO.parse_regunit("rcx"), Some(1)); - assert_eq!(INFO.parse_regunit("rdx"), Some(2)); - assert_eq!(INFO.parse_regunit("rsi"), Some(6)); - assert_eq!(INFO.parse_regunit("rdi"), Some(7)); - assert_eq!(INFO.parse_regunit("rbp"), Some(5)); - assert_eq!(INFO.parse_regunit("rsp"), Some(4)); - assert_eq!(INFO.parse_regunit("r8"), Some(8)); - assert_eq!(INFO.parse_regunit("r15"), Some(15)); + assert_eq!(INFO.parse_regunit("rax"), gpr(0)); + assert_eq!(INFO.parse_regunit("rbx"), gpr(3)); + assert_eq!(INFO.parse_regunit("rcx"), gpr(1)); + assert_eq!(INFO.parse_regunit("rdx"), gpr(2)); + assert_eq!(INFO.parse_regunit("rsi"), gpr(6)); + assert_eq!(INFO.parse_regunit("rdi"), gpr(7)); + assert_eq!(INFO.parse_regunit("rbp"), gpr(5)); + assert_eq!(INFO.parse_regunit("rsp"), gpr(4)); + assert_eq!(INFO.parse_regunit("r8"), gpr(8)); + assert_eq!(INFO.parse_regunit("r15"), gpr(15)); - assert_eq!(INFO.parse_regunit("xmm0"), Some(16)); - assert_eq!(INFO.parse_regunit("xmm15"), Some(31)); + fn fpr(unit: usize) -> Option { + Some(FPR.unit(unit)) + } + assert_eq!(INFO.parse_regunit("xmm0"), fpr(0)); + assert_eq!(INFO.parse_regunit("xmm15"), fpr(15)); + + fn fpr32(unit: usize) -> Option { + Some(FPR32.unit(unit)) + } + assert_eq!(INFO.parse_regunit("xmm0"), fpr32(0)); + assert_eq!(INFO.parse_regunit("xmm31"), fpr32(31)); } #[test] fn unit_names() { - fn uname(ru: RegUnit) -> String { - INFO.display_regunit(ru).to_string() + fn gpr(ru: RegUnit) -> String { + INFO.display_regunit(GPR.first + ru).to_string() } + assert_eq!(gpr(0), "%rax"); + assert_eq!(gpr(3), "%rbx"); + assert_eq!(gpr(1), "%rcx"); + assert_eq!(gpr(2), "%rdx"); + assert_eq!(gpr(6), "%rsi"); + assert_eq!(gpr(7), "%rdi"); + assert_eq!(gpr(5), "%rbp"); + assert_eq!(gpr(4), "%rsp"); + assert_eq!(gpr(8), "%r8"); + assert_eq!(gpr(15), "%r15"); - assert_eq!(uname(0), "%rax"); - assert_eq!(uname(3), "%rbx"); - assert_eq!(uname(1), "%rcx"); - assert_eq!(uname(2), "%rdx"); - assert_eq!(uname(6), "%rsi"); - assert_eq!(uname(7), "%rdi"); - assert_eq!(uname(5), "%rbp"); - assert_eq!(uname(4), "%rsp"); - assert_eq!(uname(8), "%r8"); - assert_eq!(uname(15), "%r15"); - assert_eq!(uname(16), "%xmm0"); - assert_eq!(uname(31), "%xmm15"); + fn fpr(ru: RegUnit) -> String { + INFO.display_regunit(FPR.first + ru).to_string() + } + assert_eq!(fpr(0), "%xmm0"); + assert_eq!(fpr(15), "%xmm15"); + + fn fpr32(ru: RegUnit) -> String { + INFO.display_regunit(FPR32.first + ru).to_string() + } + assert_eq!(fpr32(0), "%xmm0"); + assert_eq!(fpr32(31), "%xmm31"); } #[test]